Search in sources :

Example 1 with IllegalLRAStateException

use of io.narayana.lra.client.IllegalLRAStateException in project narayana by jbosstm.

the class LRAService method endLRA.

public LRAStatus endLRA(URL lraId, boolean compensate, boolean fromHierarchy) {
    lraTrace(lraId, "end LRA");
    Transaction transaction = getTransaction(lraId);
    if (!transaction.isActive() && !transaction.isRecovering() && transaction.isTopLevel())
        throw new IllegalLRAStateException(lraId.toString(), "LRA is closing or closed", "endLRA");
    transaction.end(compensate);
    if (transaction.currentLRA() != null)
        if (LRALogger.logger.isInfoEnabled())
            LRALogger.logger.infof("LRAServicve.endLRA LRA %s ended but is still associated with %s%n", lraId, transaction.currentLRA().get_uid().fileStringForm());
    finished(transaction, fromHierarchy);
    if (transaction.isTopLevel()) {
        // forget any nested LRAs
        // instruct compensators to clean up
        transaction.forgetAllParticipants();
    }
    return new LRAStatus(transaction);
}
Also used : Transaction(io.narayana.lra.coordinator.domain.model.Transaction) LRAStatus(io.narayana.lra.coordinator.domain.model.LRAStatus) IllegalLRAStateException(io.narayana.lra.client.IllegalLRAStateException)

Example 2 with IllegalLRAStateException

use of io.narayana.lra.client.IllegalLRAStateException 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 3 with IllegalLRAStateException

use of io.narayana.lra.client.IllegalLRAStateException in project narayana by jbosstm.

the class Coordinator method getNestedLRAStatus.

@GET
@Path("{NestedLraId}/status")
public Response getNestedLRAStatus(@PathParam("NestedLraId") String nestedLraId) {
    if (!lraService.hasTransaction(nestedLraId)) {
        // it must have compensated TODO maybe it's better to keep nested LRAs in separate collection
        return Response.ok(CompensatorStatus.Compensated.name()).build();
    }
    Transaction lra = lraService.getTransaction(toURL(nestedLraId));
    CompensatorStatus status = lra.getLRAStatus();
    if (status == null || lra.getLRAStatus() == null) {
        LRALogger.i18NLogger.error_cannotGetStatusOfNestedLra(nestedLraId, lra.getId());
        throw new IllegalLRAStateException(nestedLraId, "The LRA is still active", "getNestedLRAStatus");
    }
    return Response.ok(lra.getLRAStatus().name()).build();
}
Also used : Transaction(io.narayana.lra.coordinator.domain.model.Transaction) IllegalLRAStateException(io.narayana.lra.client.IllegalLRAStateException) CompensatorStatus(io.narayana.lra.annotation.CompensatorStatus) Path(javax.ws.rs.Path) GET(javax.ws.rs.GET)

Example 4 with IllegalLRAStateException

use of io.narayana.lra.client.IllegalLRAStateException in project narayana by jbosstm.

the class ActivityController method status.

/**
 *     Performing a GET on the participant URL will return the current status of the participant {@link CompensatorStatus}, or 404 if the participant is no longer present.
 */
@GET
@Path("/status")
@Produces(MediaType.APPLICATION_JSON)
@Status
@LRA(LRA.Type.NOT_SUPPORTED)
public Response status(@PathParam("LraUrl") String lraUrl, @HeaderParam(LRA_HTTP_HEADER) String lraId) throws NotFoundException {
    String txId = NarayanaLRAClient.getLRAId(lraId);
    Activity activity = activityService.getActivity(txId);
    if (activity.status == null)
        throw new IllegalLRAStateException(lraId, "LRA is not active", "getStatus");
    if (activity.getAndDecrementAcceptCount() <= 0) {
        if (activity.status == CompensatorStatus.Completing)
            activity.status = CompensatorStatus.Completed;
        else if (activity.status == CompensatorStatus.Compensating)
            activity.status = CompensatorStatus.Compensated;
    }
    return Response.ok(activity.status.name()).build();
}
Also used : Activity(io.narayana.lra.participant.model.Activity) IllegalLRAStateException(io.narayana.lra.client.IllegalLRAStateException) Path(javax.ws.rs.Path) Status(io.narayana.lra.annotation.Status) CompensatorStatus(io.narayana.lra.annotation.CompensatorStatus) Produces(javax.ws.rs.Produces) GET(javax.ws.rs.GET) LRA(io.narayana.lra.annotation.LRA) NestedLRA(io.narayana.lra.annotation.NestedLRA)

Aggregations

IllegalLRAStateException (io.narayana.lra.client.IllegalLRAStateException)4 CompensatorStatus (io.narayana.lra.annotation.CompensatorStatus)2 LRA (io.narayana.lra.annotation.LRA)2 NestedLRA (io.narayana.lra.annotation.NestedLRA)2 Status (io.narayana.lra.annotation.Status)2 Transaction (io.narayana.lra.coordinator.domain.model.Transaction)2 GET (javax.ws.rs.GET)2 Path (javax.ws.rs.Path)2 Forget (io.narayana.lra.annotation.Forget)1 Leave (io.narayana.lra.annotation.Leave)1 GenericLRAException (io.narayana.lra.client.GenericLRAException)1 LRAStatus (io.narayana.lra.coordinator.domain.model.LRAStatus)1 Activity (io.narayana.lra.participant.model.Activity)1 Annotation (java.lang.annotation.Annotation)1 Method (java.lang.reflect.Method)1 URI (java.net.URI)1 URL (java.net.URL)1 Produces (javax.ws.rs.Produces)1 WebApplicationException (javax.ws.rs.WebApplicationException)1 Response (javax.ws.rs.core.Response)1