Search in sources :

Example 1 with LRA

use of io.narayana.lra.annotation.LRA in project narayana by jbosstm.

the class ActivityController method subActivity.

@PUT
@Path("/startViaApi")
@LRA(LRA.Type.NOT_SUPPORTED)
public Response subActivity(@HeaderParam(LRA_HTTP_HEADER) String lraId) {
    if (lraId != null)
        throw new WebApplicationException(Response.Status.NOT_ACCEPTABLE);
    // manually start an LRA via the injection LRAClient api
    URL lra = lraClient.startLRA("subActivity", 0L);
    lraId = lra.toString();
    addWork(lraId, null);
    // invoke a method that SUPPORTS LRAs. The filters should detect the LRA we just started via the injected client
    // and add it as a header before calling the method at path /supports (ie supportsLRACall()).
    // The supportsLRACall method will return LRA id in the body if it is present.
    String id = restPutInvocation("supports", "");
    // check that the invoked method saw the LRA
    if (lraId == null || id == null || !lraId.equals(id))
        return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(Entity.text("Unequal LRA ids")).build();
    return Response.ok(id).build();
}
Also used : WebApplicationException(javax.ws.rs.WebApplicationException) URL(java.net.URL) Path(javax.ws.rs.Path) LRA(io.narayana.lra.annotation.LRA) NestedLRA(io.narayana.lra.annotation.NestedLRA) PUT(javax.ws.rs.PUT)

Example 2 with LRA

use of io.narayana.lra.annotation.LRA in project narayana by jbosstm.

the class ActivityController method acceptWork.

@PUT
@Path(ACCEPT_WORK)
@LRA(LRA.Type.REQUIRED)
public Response acceptWork(@HeaderParam(LRA_HTTP_RECOVERY_HEADER) String rcvId, @HeaderParam(LRA_HTTP_HEADER) String lraId) {
    assert lraId != null;
    Activity activity = addWork(lraId, rcvId);
    if (activity == null)
        return Response.status(Response.Status.EXPECTATION_FAILED).entity("Missing lra data").build();
    // tests that it is possible to asynchronously complete
    activity.setAcceptedCount(1);
    return Response.ok(lraId).build();
}
Also used : Activity(io.narayana.lra.participant.model.Activity) Path(javax.ws.rs.Path) LRA(io.narayana.lra.annotation.LRA) NestedLRA(io.narayana.lra.annotation.NestedLRA) PUT(javax.ws.rs.PUT)

Example 3 with LRA

use of io.narayana.lra.annotation.LRA in project narayana by jbosstm.

the class ServerLRAFilter method filter.

@Override
public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) throws IOException {
    // a request is leaving the container so clear any context on the thread and fix up the LRA response header
    Object suspendedLRA = Current.getState("suspendedLRA");
    Object newLRA = Current.getState("newLRA");
    URL current = Current.peek();
    try {
        if (current != null) {
            int status = responseContext.getStatus();
            Response.Status.Family[] cancel0nFamily = (Response.Status.Family[]) requestContext.getProperty(CANCEL_ON_FAMILY_PROP);
            Response.Status[] cancel0n = (Response.Status[]) requestContext.getProperty(CANCEL_ON_PROP);
            Boolean closeCurrent = (Boolean) requestContext.getProperty(TERMINAL_LRA_PROP);
            if (closeCurrent == null)
                closeCurrent = false;
            if (cancel0nFamily != null)
                if (Arrays.stream(cancel0nFamily).anyMatch(f -> Response.Status.Family.familyOf(status) == f))
                    closeCurrent = true;
            if (cancel0n != null && !closeCurrent)
                if (Arrays.stream(cancel0n).anyMatch(f -> status == f.getStatusCode()))
                    closeCurrent = true;
            if (closeCurrent) {
                lraTrace(requestContext, (URL) newLRA, "ServerLRAFilter after: closing LRA becasue http status is " + status);
                lraClient.cancelLRA(current);
                if (current.equals(newLRA))
                    // don't try to cancle newKRA twice
                    newLRA = null;
            }
        }
        if (newLRA != null) {
            lraTrace(requestContext, (URL) newLRA, "ServerLRAFilter after: closing LRA");
            lraClient.closeLRA((URL) newLRA);
        }
        if (responseContext.getStatus() == Response.Status.OK.getStatusCode() && NarayanaLRAClient.isAsyncCompletion(resourceInfo.getResourceMethod())) {
            LRALogger.i18NLogger.warn_lraParticipantqForAsync(resourceInfo.getResourceMethod().getDeclaringClass().getName(), resourceInfo.getResourceMethod().getName(), Response.Status.ACCEPTED.getStatusCode(), Response.Status.OK.getStatusCode());
        }
    } finally {
        if (suspendedLRA != null)
            Current.push((URL) suspendedLRA);
        Current.updateLRAContext(responseContext.getHeaders());
        Current.popAll();
    }
}
Also used : Response(javax.ws.rs.core.Response) Status(io.narayana.lra.annotation.Status) LEAVE(io.narayana.lra.client.NarayanaLRAClient.LEAVE) Arrays(java.util.Arrays) COMPENSATE(io.narayana.lra.client.NarayanaLRAClient.COMPENSATE) Provider(javax.ws.rs.ext.Provider) URL(java.net.URL) IllegalLRAStateException(io.narayana.lra.client.IllegalLRAStateException) GenericLRAException(io.narayana.lra.client.GenericLRAException) Complete(io.narayana.lra.annotation.Complete) ContainerRequestFilter(javax.ws.rs.container.ContainerRequestFilter) LRA_HTTP_HEADER(io.narayana.lra.client.NarayanaLRAClient.LRA_HTTP_HEADER) Compensate(io.narayana.lra.annotation.Compensate) Forget(io.narayana.lra.annotation.Forget) ContainerResponseFilter(javax.ws.rs.container.ContainerResponseFilter) ContainerRequestContext(javax.ws.rs.container.ContainerRequestContext) Inject(javax.inject.Inject) Leave(io.narayana.lra.annotation.Leave) ResourceInfo(javax.ws.rs.container.ResourceInfo) Current(io.narayana.lra.client.Current) Map(java.util.Map) FORGET(io.narayana.lra.client.NarayanaLRAClient.FORGET) Status(io.narayana.lra.annotation.Status) URI(java.net.URI) LRA(io.narayana.lra.annotation.LRA) Method(java.lang.reflect.Method) STATUS(io.narayana.lra.client.NarayanaLRAClient.STATUS) Context(javax.ws.rs.core.Context) TimeLimit(io.narayana.lra.annotation.TimeLimit) MalformedURLException(java.net.MalformedURLException) IOException(java.io.IOException) NestedLRA(io.narayana.lra.annotation.NestedLRA) MultivaluedMap(javax.ws.rs.core.MultivaluedMap) TimeUnit(java.util.concurrent.TimeUnit) NarayanaLRAClient(io.narayana.lra.client.NarayanaLRAClient) COMPLETE(io.narayana.lra.client.NarayanaLRAClient.COMPLETE) Response(javax.ws.rs.core.Response) Annotation(java.lang.annotation.Annotation) WebApplicationException(javax.ws.rs.WebApplicationException) LRALogger(io.narayana.lra.logging.LRALogger) ContainerResponseContext(javax.ws.rs.container.ContainerResponseContext) LRA_HTTP_RECOVERY_HEADER(io.narayana.lra.client.NarayanaLRAClient.LRA_HTTP_RECOVERY_HEADER) URL(java.net.URL)

Example 4 with LRA

use of io.narayana.lra.annotation.LRA 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");
}
Also used : Status(io.narayana.lra.annotation.Status) WebApplicationException(javax.ws.rs.WebApplicationException) Leave(io.narayana.lra.annotation.Leave) Forget(io.narayana.lra.annotation.Forget) NestedLRA(io.narayana.lra.annotation.NestedLRA) IllegalLRAStateException(io.narayana.lra.client.IllegalLRAStateException) Method(java.lang.reflect.Method) URI(java.net.URI) Annotation(java.lang.annotation.Annotation) URL(java.net.URL) Response(javax.ws.rs.core.Response) LRA(io.narayana.lra.annotation.LRA) NestedLRA(io.narayana.lra.annotation.NestedLRA) GenericLRAException(io.narayana.lra.client.GenericLRAException)

Example 5 with LRA

use of io.narayana.lra.annotation.LRA in project narayana by jbosstm.

the class LraAnnotationProcessingExtension method processLraAnnotatedType.

<X> void processLraAnnotatedType(@Observes @WithAnnotations({ LRA.class }) ProcessAnnotatedType<X> classAnnotatedWithLra) {
    // All compulsory LRA annotations are available at the class
    Supplier<Stream<AnnotatedMethod<? super X>>> sup = () -> classAnnotatedWithLra.getAnnotatedType().getMethods().stream();
    Set<Class<? extends Annotation>> missing = new HashSet<>();
    if (!sup.get().anyMatch(m -> m.isAnnotationPresent(Compensate.class)))
        missing.add(Compensate.class);
    // gathering all LRA annotations in the class
    List<LRA> lraAnnotations = new ArrayList<>();
    LRA classLraAnnotation = classAnnotatedWithLra.getAnnotatedType().getAnnotation(LRA.class);
    if (classLraAnnotation != null)
        lraAnnotations.add(classLraAnnotation);
    List<LRA> methodlraAnnotations = sup.get().filter(m -> m.isAnnotationPresent(LRA.class)).map(m -> m.getAnnotation(LRA.class)).collect(Collectors.toList());
    lraAnnotations.addAll(methodlraAnnotations);
    // when LRA annotations expect no context then they are not part of the LRA and no handling
    // of the completion or compensation is needed
    boolean isNoLRAContext = lraAnnotations.stream().allMatch(lraAnn -> (lraAnn.value() == LRA.Type.NEVER || lraAnn.value() == LRA.Type.NOT_SUPPORTED));
    if (isNoLRAContext)
        return;
    // if any of the LRA annotations have set the join attribute to true (join to be true means
    // handling it as full LRA participant which needs to be completed, compensated...)
    // then have to process checks for compulsory LRA annotations
    boolean isJoin = lraAnnotations.stream().anyMatch(lraAnn -> lraAnn.join());
    final String classAnnotatedWithLraName = classAnnotatedWithLra.getAnnotatedType().getJavaClass().getName();
    if (!missing.isEmpty() && isJoin) {
        FailureCatalog.INSTANCE.add("Class " + classAnnotatedWithLraName + " uses " + LRA.class.getName() + " which requires methods handling LRA events. Missing annotations in the class: " + missing);
    }
    // Only one of each LRA annotation is placed in the class
    List<AnnotatedMethod<? super X>> methodsWithCompensate = sup.get().filter(m -> m.isAnnotationPresent(Compensate.class)).collect(Collectors.toList());
    List<AnnotatedMethod<? super X>> methodsWithComplete = sup.get().filter(m -> m.isAnnotationPresent(Complete.class)).collect(Collectors.toList());
    List<AnnotatedMethod<? super X>> methodsWithStatus = sup.get().filter(m -> m.isAnnotationPresent(Status.class)).collect(Collectors.toList());
    List<AnnotatedMethod<? super X>> methodsWithLeave = sup.get().filter(m -> m.isAnnotationPresent(Leave.class)).collect(Collectors.toList());
    List<AnnotatedMethod<? super X>> methodsWithForget = sup.get().filter(m -> m.isAnnotationPresent(Forget.class)).collect(Collectors.toList());
    BiFunction<Class<?>, List<AnnotatedMethod<? super X>>, String> errorMsg = (clazz, methods) -> String.format("There are used multiple annotations '%s' in the class '%s' on methods %s. Only one per the class is expected.", clazz.getName(), classAnnotatedWithLraName, methods.stream().map(a -> a.getJavaMember().getName()).collect(Collectors.toList()));
    if (methodsWithCompensate.size() > 1) {
        FailureCatalog.INSTANCE.add(errorMsg.apply(Compensate.class, methodsWithCompensate));
    }
    if (methodsWithComplete.size() > 1) {
        FailureCatalog.INSTANCE.add(errorMsg.apply(Complete.class, methodsWithComplete));
    }
    if (methodsWithStatus.size() > 1) {
        FailureCatalog.INSTANCE.add(errorMsg.apply(Status.class, methodsWithStatus));
    }
    if (methodsWithLeave.size() > 1) {
        FailureCatalog.INSTANCE.add(errorMsg.apply(Leave.class, methodsWithLeave));
    }
    if (methodsWithForget.size() > 1) {
        FailureCatalog.INSTANCE.add(errorMsg.apply(Forget.class, methodsWithForget));
    }
    if (methodsWithCompensate.size() > 0) {
        // Each method annotated with LRA-style annotations contain all necessary REST annotations
        // @Compensate - requires @Path and @PUT
        final AnnotatedMethod<? super X> methodWithCompensate = methodsWithCompensate.get(0);
        Function<Class<?>, String> getCompensateMissingErrMsg = (wrongAnnotation) -> getMissingAnnotationError(methodWithCompensate, classAnnotatedWithLra, Compensate.class, wrongAnnotation);
        boolean isCompensateContainsPathAnnotation = methodWithCompensate.getAnnotations().stream().anyMatch(a -> a.annotationType().equals(Path.class));
        if (!isCompensateContainsPathAnnotation) {
            FailureCatalog.INSTANCE.add(getCompensateMissingErrMsg.apply(Path.class));
        }
        boolean isCompensateContainsPutAnnotation = methodWithCompensate.getAnnotations().stream().anyMatch(a -> a.annotationType().equals(PUT.class));
        if (!isCompensateContainsPutAnnotation) {
            FailureCatalog.INSTANCE.add(getCompensateMissingErrMsg.apply(PUT.class));
        }
        boolean isCompensateParametersContainsSuspended = methodWithCompensate.getParameters().stream().flatMap(p -> p.getAnnotations().stream()).anyMatch(a -> a.annotationType().equals(Suspended.class));
        if (isCompensateParametersContainsSuspended) {
            if (methodsWithStatus.size() == 0 || methodsWithForget.size() == 0) {
                FailureCatalog.INSTANCE.add(getMissingAnnotationsForAsynchHandling(methodWithCompensate, classAnnotatedWithLra, Compensate.class));
            }
        }
    }
    if (methodsWithComplete.size() > 0) {
        // @Complete - requires @Path and @PUT
        final AnnotatedMethod<? super X> methodWithComplete = methodsWithComplete.get(0);
        Function<Class<?>, String> getCompleteMissingErrMsg = (wrongAnnotation) -> getMissingAnnotationError(methodWithComplete, classAnnotatedWithLra, Complete.class, wrongAnnotation);
        boolean isCompleteContainsPathAnnotation = methodWithComplete.getAnnotations().stream().anyMatch(a -> a.annotationType().equals(Path.class));
        if (!isCompleteContainsPathAnnotation) {
            FailureCatalog.INSTANCE.add(getCompleteMissingErrMsg.apply(Path.class));
        }
        boolean isCompleteContainsPutAnnotation = methodWithComplete.getAnnotations().stream().anyMatch(a -> a.annotationType().equals(PUT.class));
        if (!isCompleteContainsPutAnnotation) {
            FailureCatalog.INSTANCE.add(getCompleteMissingErrMsg.apply(PUT.class));
        }
        boolean isCompleteParametersContainsSuspended = methodWithComplete.getParameters().stream().flatMap(p -> p.getAnnotations().stream()).anyMatch(a -> a.annotationType().equals(Suspended.class));
        if (isCompleteParametersContainsSuspended) {
            if (methodsWithStatus.size() == 0 || methodsWithForget.size() == 0) {
                FailureCatalog.INSTANCE.add(getMissingAnnotationsForAsynchHandling(methodWithComplete, classAnnotatedWithLra, Complete.class));
            }
        }
    }
    if (methodsWithStatus.size() > 0) {
        // @Status - requires @Path and @GET
        final AnnotatedMethod<? super X> methodWithStatus = methodsWithStatus.get(0);
        Function<Class<?>, String> getStatusMissingErrMsg = (wrongAnnotation) -> getMissingAnnotationError(methodWithStatus, classAnnotatedWithLra, Status.class, wrongAnnotation);
        boolean isStatusContainsPathAnnotation = methodWithStatus.getAnnotations().stream().anyMatch(a -> a.annotationType().equals(Path.class));
        if (!isStatusContainsPathAnnotation) {
            FailureCatalog.INSTANCE.add(getStatusMissingErrMsg.apply(Path.class));
        }
        boolean isStatusContainsGetAnnotation = methodWithStatus.getAnnotations().stream().anyMatch(a -> a.annotationType().equals(GET.class));
        if (!isStatusContainsGetAnnotation) {
            FailureCatalog.INSTANCE.add(getStatusMissingErrMsg.apply(GET.class));
        }
    }
    if (methodsWithLeave.size() > 0) {
        // @Leave - requires @PUT
        final AnnotatedMethod<? super X> methodWithLeave = methodsWithLeave.get(0);
        boolean isLeaveContainsPutAnnotation = methodWithLeave.getAnnotations().stream().anyMatch(a -> a.annotationType().equals(PUT.class));
        if (!isLeaveContainsPutAnnotation) {
            FailureCatalog.INSTANCE.add(getMissingAnnotationError(methodWithLeave, classAnnotatedWithLra, Leave.class, PUT.class));
        }
    }
    if (methodsWithForget.size() > 0) {
        // @Forget - requires @DELETE
        final AnnotatedMethod<? super X> methodWithForget = methodsWithForget.get(0);
        boolean isForgetContainsPutAnnotation = methodWithForget.getAnnotations().stream().anyMatch(a -> a.annotationType().equals(DELETE.class));
        if (!isForgetContainsPutAnnotation) {
            FailureCatalog.INSTANCE.add(getMissingAnnotationError(methodWithForget, classAnnotatedWithLra, Forget.class, DELETE.class));
        }
    }
}
Also used : GET(javax.ws.rs.GET) BiFunction(java.util.function.BiFunction) Path(javax.ws.rs.Path) Complete(io.narayana.lra.annotation.Complete) Function(java.util.function.Function) Supplier(java.util.function.Supplier) Compensate(io.narayana.lra.annotation.Compensate) Forget(io.narayana.lra.annotation.Forget) ArrayList(java.util.ArrayList) HashSet(java.util.HashSet) Leave(io.narayana.lra.annotation.Leave) Observes(javax.enterprise.event.Observes) Status(io.narayana.lra.annotation.Status) LRA(io.narayana.lra.annotation.LRA) DELETE(javax.ws.rs.DELETE) FailureCatalog(io.narayana.lra.checker.FailureCatalog) Extension(javax.enterprise.inject.spi.Extension) ProcessAnnotatedType(javax.enterprise.inject.spi.ProcessAnnotatedType) Set(java.util.Set) WithAnnotations(javax.enterprise.inject.spi.WithAnnotations) Collectors(java.util.stream.Collectors) Suspended(javax.ws.rs.container.Suspended) List(java.util.List) Stream(java.util.stream.Stream) Annotation(java.lang.annotation.Annotation) PUT(javax.ws.rs.PUT) AnnotatedMethod(javax.enterprise.inject.spi.AnnotatedMethod) AnnotatedMethod(javax.enterprise.inject.spi.AnnotatedMethod) Complete(io.narayana.lra.annotation.Complete) ArrayList(java.util.ArrayList) Leave(io.narayana.lra.annotation.Leave) Forget(io.narayana.lra.annotation.Forget) Compensate(io.narayana.lra.annotation.Compensate) DELETE(javax.ws.rs.DELETE) Stream(java.util.stream.Stream) ArrayList(java.util.ArrayList) List(java.util.List) Suspended(javax.ws.rs.container.Suspended) HashSet(java.util.HashSet) Status(io.narayana.lra.annotation.Status) Path(javax.ws.rs.Path) Annotation(java.lang.annotation.Annotation) PUT(javax.ws.rs.PUT) GET(javax.ws.rs.GET) LRA(io.narayana.lra.annotation.LRA)

Aggregations

LRA (io.narayana.lra.annotation.LRA)8 NestedLRA (io.narayana.lra.annotation.NestedLRA)7 Path (javax.ws.rs.Path)6 Status (io.narayana.lra.annotation.Status)4 Activity (io.narayana.lra.participant.model.Activity)4 PUT (javax.ws.rs.PUT)4 Forget (io.narayana.lra.annotation.Forget)3 Leave (io.narayana.lra.annotation.Leave)3 IllegalLRAStateException (io.narayana.lra.client.IllegalLRAStateException)3 Annotation (java.lang.annotation.Annotation)3 URL (java.net.URL)3 GET (javax.ws.rs.GET)3 WebApplicationException (javax.ws.rs.WebApplicationException)3 Compensate (io.narayana.lra.annotation.Compensate)2 Complete (io.narayana.lra.annotation.Complete)2 TimeLimit (io.narayana.lra.annotation.TimeLimit)2 GenericLRAException (io.narayana.lra.client.GenericLRAException)2 Method (java.lang.reflect.Method)2 URI (java.net.URI)2 Produces (javax.ws.rs.Produces)2