use of io.narayana.lra.client.GenericLRAException in project narayana by jbosstm.
the class RecoveryCoordinator method replaceCompensator.
// Performing a PUT on the recovery URL will overwrite the old <compensor URL> with the new one supplied
// and return the old url
@PUT
@Path("{LRAId}/{RecCoordId}")
@Produces(MediaType.APPLICATION_JSON)
@ApiOperation(value = "Update the endpoint that a participant is prepared to accept requests on.", notes = "Performing a PUT on the recovery URL will overwrite the old <compensor URL> with the new one supplied" + " and return the old url. The old value is returned." + "The full URL was returned when the participant first joined the LRA.", response = String.class)
@ApiResponses({ @ApiResponse(code = 404, message = "The coordinator has no knowledge of this participant"), @ApiResponse(code = 200, message = "The coordinator has replaced the old participant with the new one ") })
public String replaceCompensator(@ApiParam(value = "Identifies the LRAId that the participant joined", required = true) @PathParam("LRAId") String lraId, @ApiParam(value = "An identifier that was returned by the coordinator when a participant joined the LRA", required = true) @PathParam("RecCoordId") String rcvCoordId, String newCompensatorUrl) throws NotFoundException {
String compensatorUrl = lraService.getParticipant(rcvCoordId);
if (compensatorUrl != null) {
URL lra = null;
try {
lra = new URL(lraId);
} catch (MalformedURLException e) {
LRALogger.i18NLogger.error_invalidFormatOfLraIdReplacingCompensator(lraId, compensatorUrl, e);
throw new GenericLRAException(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e.getMessage(), e.getCause());
}
lraService.updateRecoveryURL(lra, newCompensatorUrl, rcvCoordId, true);
try {
return context.getRequestUri().toURL().toExternalForm();
} catch (MalformedURLException e) {
// cannot happen
LRALogger.i18NLogger.error_invalidFormatOfRequestUri(context.getRequestUri(), lraId, compensatorUrl, e);
throw new GenericLRAException(lra, Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e.getMessage(), e.getCause());
}
}
LRALogger.i18NLogger.error_cannotFoundCompensatorUrl(compensatorUrl, lraId);
throw new NotFoundException(rcvCoordId);
}
use of io.narayana.lra.client.GenericLRAException in project narayana by jbosstm.
the class ServerLRAFilter method filter.
// // TODO figure out how to disable the filters for the coordinator since they are required
// private boolean isCoordinator() {
// return resourceInfo.getResourceClass().getName().equals("io.narayana.lra.coordinator.api.Coordinator")
// }
@Override
public void filter(ContainerRequestContext containerRequestContext) throws IOException {
Method method = resourceInfo.getResourceMethod();
MultivaluedMap<String, String> headers = containerRequestContext.getHeaders();
LRA.Type type = null;
Annotation transactional = method.getDeclaredAnnotation(LRA.class);
URL lraId;
URL newLRA = null;
URL suspendedLRA = null;
URL incommingLRA = null;
String recoveryUrl = null;
boolean nested;
boolean isLongRunning = false;
boolean enlist;
if (transactional == null)
transactional = method.getDeclaringClass().getDeclaredAnnotation(LRA.class);
if (transactional != null) {
type = ((LRA) transactional).value();
isLongRunning = ((LRA) transactional).delayClose();
Response.Status.Family[] cancel0nFamily = ((LRA) transactional).cancelOnFamily();
Response.Status[] cancel0n = ((LRA) transactional).cancelOn();
if (((LRA) transactional).terminal())
containerRequestContext.setProperty(TERMINAL_LRA_PROP, Boolean.TRUE);
if (cancel0nFamily.length != 0)
containerRequestContext.setProperty(CANCEL_ON_FAMILY_PROP, cancel0nFamily);
if (cancel0n.length != 0)
containerRequestContext.setProperty(CANCEL_ON_PROP, cancel0n);
}
boolean endAnnotation = method.isAnnotationPresent(Complete.class) || method.isAnnotationPresent(Compensate.class) || method.isAnnotationPresent(Leave.class) || method.isAnnotationPresent(Status.class) || method.isAnnotationPresent(Forget.class);
if (type == null) {
if (!endAnnotation)
Current.clearContext(headers);
// not transactional
return;
}
if (headers.containsKey(LRA_HTTP_HEADER))
// TODO filters for asynchronous JAX-RS motheods should not throw exceptions
incommingLRA = new URL(headers.getFirst(LRA_HTTP_HEADER));
if (endAnnotation && incommingLRA == null)
return;
enlist = ((LRA) transactional).join();
nested = resourceInfo.getResourceMethod().isAnnotationPresent(NestedLRA.class);
switch(type) {
case // a txn must be present
MANDATORY:
checkForTx(type, incommingLRA, true);
if (nested) {
// a new LRA is nested under the incomming LRA
suspendedLRA = incommingLRA;
lraTrace(containerRequestContext, suspendedLRA, "ServerLRAFilter before: MANDATORY start new LRA");
newLRA = lraId = startLRA(incommingLRA, method, getTimeOut(method));
} else {
lraId = incommingLRA;
// txId is not null
resumeTransaction(incommingLRA);
}
break;
case // a txn must not be present
NEVER:
checkForTx(type, incommingLRA, false);
if (nested) {
// nested does not make sense
throw new GenericLRAException(Response.Status.PRECONDITION_FAILED.getStatusCode(), type.name() + " but found Nested annnotation");
}
enlist = false;
lraId = null;
break;
case NOT_SUPPORTED:
if (nested) {
// nested does not make sense
throw new GenericLRAException(Response.Status.PRECONDITION_FAILED.getStatusCode(), type.name() + " but found Nested annnotation");
}
enlist = false;
suspendedLRA = incommingLRA;
lraId = null;
break;
case REQUIRED:
if (incommingLRA != null) {
if (nested) {
// if there is an LRA present nest a new LRA under it
suspendedLRA = incommingLRA;
lraTrace(containerRequestContext, suspendedLRA, "ServerLRAFilter before: REQUIRED start new LRA");
newLRA = lraId = startLRA(incommingLRA, method, getTimeOut(method));
} else {
lraId = incommingLRA;
resumeTransaction(incommingLRA);
}
} else {
lraTrace(containerRequestContext, null, "ServerLRAFilter before: REQUIRED start new LRA");
newLRA = lraId = startLRA(null, method, getTimeOut(method));
}
break;
case REQUIRES_NEW:
// previous = AtomicAction.suspend();
suspendedLRA = incommingLRA;
lraTrace(containerRequestContext, suspendedLRA, "ServerLRAFilter before: REQUIRES_NEW start new LRA");
newLRA = lraId = startLRA(incommingLRA, method, getTimeOut(method));
break;
case SUPPORTS:
lraId = incommingLRA;
if (nested) {
// if there is an LRA present a new LRA is nested under it otherwise a new top level LRA is begun
if (incommingLRA != null)
suspendedLRA = incommingLRA;
lraTrace(containerRequestContext, incommingLRA, "ServerLRAFilter before: SUPPORTS start new LRA");
newLRA = lraId = startLRA(incommingLRA, method, getTimeOut(method));
} else if (incommingLRA != null) {
resumeTransaction(incommingLRA);
}
break;
default:
lraId = incommingLRA;
}
if (lraId == null) {
lraTrace(containerRequestContext, null, "ServerLRAFilter before: removing header");
// the method call needs to run without a transaction
Current.clearContext(headers);
// non transactional
return;
} else {
lraTrace(containerRequestContext, lraId, "ServerLRAFilter before: adding header");
if (lraId.toExternalForm().contains("recovery-coordi"))
lraWarn(containerRequestContext, lraId, "wrong lra id");
}
if (isLongRunning)
newLRA = null;
// store state with the current thread. TODO for the async version use containerRequestContext.setProperty("lra", Current.peek());
// make the current LRA available to the called method
Current.updateLRAContext(lraId, headers);
if (newLRA != null) {
if (suspendedLRA != null)
Current.putState("suspendedLRA", suspendedLRA);
Current.putState("newLRA", newLRA);
}
lraTrace(containerRequestContext, lraId, "ServerLRAFilter before: making LRA available to injected LRAClient");
// make the current LRA available to the called method
lraClient.setCurrentLRA(lraId);
// TODO make sure it is possible to do compensations inside a new LRA
if (!endAnnotation && enlist) {
// don't enlist for methods marked with Compensate, Complete or Leave
URI baseUri = containerRequestContext.getUriInfo().getBaseUri();
Map<String, String> terminateURIs = NarayanaLRAClient.getTerminationUris(resourceInfo.getResourceClass(), baseUri);
String timeLimitStr = terminateURIs.get(NarayanaLRAClient.TIMELIMIT_PARAM_NAME);
long timeLimit = timeLimitStr == null ? NarayanaLRAClient.DEFAULT_TIMEOUT_MILLIS : Long.valueOf(timeLimitStr);
if (terminateURIs.containsKey("Link")) {
try {
recoveryUrl = lraClient.joinLRA(lraId, timeLimit, toURL(terminateURIs.get(COMPENSATE)), toURL(terminateURIs.get(COMPLETE)), toURL(terminateURIs.get(FORGET)), toURL(terminateURIs.get(LEAVE)), toURL(terminateURIs.get(STATUS)), null);
} catch (IllegalLRAStateException e) {
lraTrace(containerRequestContext, lraId, "ServerLRAFilter before: aborting with " + e.getMessage());
throw e;
} catch (WebApplicationException e) {
lraTrace(containerRequestContext, lraId, "ServerLRAFilter before: aborting with " + e.getMessage());
throw new GenericLRAException(lraId, e.getResponse().getStatus(), e.getMessage(), e);
}
headers.putSingle(LRA_HTTP_RECOVERY_HEADER, recoveryUrl);
} else {
lraTrace(containerRequestContext, lraId, "ServerLRAFilter: skipping resource " + method.getDeclaringClass().getName() + " - no participant annotations");
}
}
if (method.isAnnotationPresent(Leave.class)) {
// leave the LRA
String compensatorId = getCompensatorId(lraId, containerRequestContext.getUriInfo().getBaseUri());
lraTrace(containerRequestContext, lraId, "leaving LRA");
lraClient.leaveLRA(lraId, compensatorId);
// let the participant know which lra he left by leaving the header intact
}
lraTrace(containerRequestContext, lraId, "ServerLRAFilter before: making LRA available as a thread local");
}
use of io.narayana.lra.client.GenericLRAException in project narayana by jbosstm.
the class Coordinator method joinLRA.
private Response joinLRA(URL lraId, long timeLimit, String compensatorUrl, String linkHeader, String userData) throws NotFoundException {
final String recoveryUrlBase = String.format("http://%s/%s/", context.getRequestUri().getAuthority(), NarayanaLRAClient.RECOVERY_COORDINATOR_PATH_NAME);
StringBuilder recoveryUrl = new StringBuilder();
int status = lraService.joinLRA(recoveryUrl, lraId, timeLimit, compensatorUrl, linkHeader, recoveryUrlBase, userData);
try {
return Response.status(status).entity(recoveryUrl).location(new URI(recoveryUrl.toString())).header(LRA_HTTP_RECOVERY_HEADER, recoveryUrl).build();
} catch (URISyntaxException e) {
LRALogger.i18NLogger.error_invalidRecoveryUrlToJoinLRA(recoveryUrl.toString(), lraId);
throw new GenericLRAException(lraId, Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), "Invalid recovery URL", e);
}
}
Aggregations