use of org.eclipse.microprofile.lra.annotation.Forget in project narayana by jbosstm.
the class LRATest method multiLevelNestedActivity.
private void multiLevelNestedActivity(CompletionType how, int nestedCnt) throws WebApplicationException, URISyntaxException {
WebTarget resourcePath = client.target(TestPortProvider.generateURL("/base/test/multiLevelNestedActivity"));
if (how == CompletionType.mixed && nestedCnt <= 1) {
how = CompletionType.complete;
}
URI lra = new URI(client.target(TestPortProvider.generateURL("/base/test/start")).request().get(String.class));
Response response = resourcePath.queryParam("nestedCnt", nestedCnt).request().header(LRA_HTTP_CONTEXT_HEADER, lra).put(Entity.text(""));
// the response is a comma separated list of URIs (parent, children)
String lraStr = response.readEntity(String.class);
assertNotNull("expecting a LRA string returned from " + resourcePath.getUri(), lraStr);
URI[] uris = Arrays.stream(lraStr.split(",")).map(s -> {
try {
return new URI(s);
} catch (URISyntaxException e) {
fail(e.getMessage());
return null;
}
}).toArray(URI[]::new);
// check that the multiLevelNestedActivity method returned the mandatory LRA followed by any nested LRAs
assertEquals("multiLevelNestedActivity: step 1 (the test call went to " + resourcePath.getUri() + ")", nestedCnt + 1, uris.length);
// first element should be the mandatory LRA
assertEquals("multiLevelNestedActivity: step 2 (the test call went to " + resourcePath.getUri() + ")", lra, uris[0]);
// and the mandatory lra seen by the multiLevelNestedActivity method
assertFalse("multiLevelNestedActivity: top level LRA should be active (path called " + resourcePath.getUri() + ")", isFinished(uris[0]));
// check that all nested activities were told to complete
assertEquals("multiLevelNestedActivity: step 3 (called test path " + resourcePath.getUri() + ")", nestedCnt, completeCount.get());
assertEquals("multiLevelNestedActivity: step 4 (called test path " + resourcePath.getUri() + ")", 0, compensateCount.get());
// close the LRA
if (how == CompletionType.compensate) {
lraClient.cancelLRA(lra);
// validate that the top level and nested LRAs are gone
assertAllFinished(uris);
/*
* the test starts LRA1 calls a @Mandatory method multiLevelNestedActivity which enlists in LRA1
* multiLevelNestedActivity then calls an @Nested method which starts L2 and enlists another participant
* when the method returns the nested participant is completed (ie completed count is incremented)
* Canceling L1 should then compensate the L1 enlistment (ie compensate count is incremented)
* which will then tell L2 to compensate (ie the compensate count is incremented again)
*/
// each nested participant should have completed (the +nestedCnt)
assertEquals("multiLevelNestedActivity: step 7 (called test path " + resourcePath.getUri() + ")", nestedCnt, completeCount.get());
// each nested participant should have compensated. The top level enlistment should have compensated (the +1)
assertEquals("multiLevelNestedActivity: step 8 (called test path " + resourcePath.getUri() + ")", nestedCnt + 1, compensateCount.get());
} else if (how == CompletionType.complete) {
lraClient.closeLRA(lra);
// validate that the top level and nested LRAs are gone
assertAllFinished(uris);
// each nested participant and the top level participant should have completed (nestedCnt + 1) at least once
assertTrue("multiLevelNestedActivity: step 5a (called test path " + resourcePath.getUri() + ")", completeCount.get() >= nestedCnt + 1);
// each nested participant should have been told to forget
assertEquals("multiLevelNestedActivity: step 5b (called test path " + resourcePath.getUri() + ")", forgetCount.get(), nestedCnt);
// and that neither were still not told to compensate
assertEquals("multiLevelNestedActivity: step 6 (called test path " + resourcePath.getUri() + ")", 0, compensateCount.get());
} else {
// compensate the first nested LRA in the enlisted resource
try (Response r = client.target(TestPortProvider.generateURL("/base/test/end")).queryParam("cancel", true).request().header(LRA_HTTP_CONTEXT_HEADER, uris[1]).put(Entity.text(""))) {
assertEquals("compensate the first nested LRA", 500, r.getStatus());
}
// should not complete any nested LRAs (since they have already completed via the interceptor)
lraClient.closeLRA(lra);
/*
* Expect nestedCnt + 1 completions, 1 for the top level and one for each nested LRA
* (NB the first nested LRA is completed and compensated)
* Note that the top level complete should not call complete again on the nested LRA
*/
assertEquals("multiLevelNestedActivity: step 10 (called test path " + resourcePath.getUri() + ")", nestedCnt + 1, completeCount.get());
/*
* The test is calling for a mixed outcome:
* - the top level LRA was closed
* - one of the nested LRAs was compensated the rest should have been completed
*/
// there should be just 1 compensation (the first nested LRA)
assertEquals("multiLevelNestedActivity: step 9 (called test path " + resourcePath.getUri() + ")", 1, compensateCount.get());
}
}
use of org.eclipse.microprofile.lra.annotation.Forget in project narayana by jbosstm.
the class NarayanaLRAClient method getTerminationUris.
/**
* For particular compensator class it returns termination uris based on the provided base uri.
* You get map of string and URI.
*
* @param compensatorClass compensator class to examine
* @param uriInfo the uri that triggered this join request.
* @return map of URI
*/
public static Map<String, String> getTerminationUris(Class<?> compensatorClass, UriInfo uriInfo, Long timeout) {
Map<String, String> paths = new HashMap<>();
final boolean[] asyncTermination = { false };
URI baseUri = uriInfo.getBaseUri();
/*
* Calculate which path to prepend to the LRA participant methods. If there is more than one matching URI
* then the second matched URI comes from either the class level Path annotation or from a sub-resource locator.
* In both cases the second matched URI can be used as a prefix for the LRA participant URIs:
*/
List<String> matchedURIs = uriInfo.getMatchedURIs();
int matchedURI = (matchedURIs.size() > 1 ? 1 : 0);
final String uriPrefix = baseUri + matchedURIs.get(matchedURI);
String timeoutValue = timeout != null ? Long.toString(timeout) : "0";
Arrays.stream(compensatorClass.getMethods()).forEach(method -> {
Path pathAnnotation = method.getAnnotation(Path.class);
if (pathAnnotation != null) {
if (checkMethod(paths, method, COMPENSATE, pathAnnotation, method.getAnnotation(Compensate.class), uriPrefix) != 0) {
paths.put(TIMELIMIT_PARAM_NAME, timeoutValue);
if (isAsyncCompletion(method)) {
asyncTermination[0] = true;
}
}
if (checkMethod(paths, method, COMPLETE, pathAnnotation, method.getAnnotation(Complete.class), uriPrefix) != 0) {
paths.put(TIMELIMIT_PARAM_NAME, timeoutValue);
if (isAsyncCompletion(method)) {
asyncTermination[0] = true;
}
}
checkMethod(paths, method, STATUS, pathAnnotation, method.getAnnotation(Status.class), uriPrefix);
checkMethod(paths, method, FORGET, pathAnnotation, method.getAnnotation(Forget.class), uriPrefix);
checkMethod(paths, method, LEAVE, pathAnnotation, method.getAnnotation(Leave.class), uriPrefix);
checkMethod(paths, method, AFTER, pathAnnotation, method.getAnnotation(AfterLRA.class), uriPrefix);
}
});
if (asyncTermination[0] && !paths.containsKey(STATUS) && !paths.containsKey(FORGET)) {
String logMsg = LRALogger.i18nLogger.error_asyncTerminationBeanMissStatusAndForget(compensatorClass);
LRALogger.logger.warn(logMsg);
throw new WebApplicationException(Response.status(BAD_REQUEST).entity(logMsg).build());
}
StringBuilder linkHeaderValue = new StringBuilder();
if (paths.size() != 0) {
paths.forEach((k, v) -> makeLink(linkHeaderValue, null, k, v));
paths.put(LINK_TEXT, linkHeaderValue.toString());
}
return paths;
}
Aggregations