diff --git a/rts/lra/lra-client/src/main/java/io/narayana/lra/client/GenericLRAExceptionMapper.java b/rts/lra/lra-client/src/main/java/io/narayana/lra/client/GenericLRAExceptionMapper.java index 5a97f33161..bb684720b5 100644 --- a/rts/lra/lra-client/src/main/java/io/narayana/lra/client/GenericLRAExceptionMapper.java +++ b/rts/lra/lra-client/src/main/java/io/narayana/lra/client/GenericLRAExceptionMapper.java @@ -21,7 +21,7 @@ */ package io.narayana.lra.client; -import org.eclipse.microprofile.lra.client.GenericLRAException; +import io.narayana.lra.GenericLRAException; import javax.ws.rs.core.Response; import javax.ws.rs.ext.ExceptionMapper; diff --git a/rts/lra/lra-client/src/main/java/io/narayana/lra/client/IllegalLRAStateExceptionMapper.java b/rts/lra/lra-client/src/main/java/io/narayana/lra/client/IllegalLRAStateExceptionMapper.java index b64a9cd347..aa978a9a9e 100644 --- a/rts/lra/lra-client/src/main/java/io/narayana/lra/client/IllegalLRAStateExceptionMapper.java +++ b/rts/lra/lra-client/src/main/java/io/narayana/lra/client/IllegalLRAStateExceptionMapper.java @@ -21,7 +21,7 @@ */ package io.narayana.lra.client; -import org.eclipse.microprofile.lra.client.IllegalLRAStateException; +import io.narayana.lra.IllegalLRAStateException; import javax.ws.rs.core.Response; import javax.ws.rs.ext.ExceptionMapper; diff --git a/rts/lra/lra-client/src/main/java/io/narayana/lra/client/InvalidLRAIdExceptionMapper.java b/rts/lra/lra-client/src/main/java/io/narayana/lra/client/InvalidLRAIdExceptionMapper.java index 2c86155f0e..34c1bd1921 100644 --- a/rts/lra/lra-client/src/main/java/io/narayana/lra/client/InvalidLRAIdExceptionMapper.java +++ b/rts/lra/lra-client/src/main/java/io/narayana/lra/client/InvalidLRAIdExceptionMapper.java @@ -21,7 +21,7 @@ */ package io.narayana.lra.client; -import org.eclipse.microprofile.lra.client.InvalidLRAIdException; +import io.narayana.lra.InvalidLRAIdException; import javax.ws.rs.core.Response; import javax.ws.rs.ext.ExceptionMapper; diff --git a/rts/lra/lra-client/src/main/java/io/narayana/lra/client/NarayanaLRAClient.java b/rts/lra/lra-client/src/main/java/io/narayana/lra/client/NarayanaLRAClient.java index 6c09ce33ce..7ae43e5bac 100644 --- a/rts/lra/lra-client/src/main/java/io/narayana/lra/client/NarayanaLRAClient.java +++ b/rts/lra/lra-client/src/main/java/io/narayana/lra/client/NarayanaLRAClient.java @@ -64,6 +64,8 @@ import javax.ws.rs.core.Response; import io.narayana.lra.Current; +import io.narayana.lra.GenericLRAException; +import io.narayana.lra.IllegalLRAStateException; import org.eclipse.microprofile.lra.annotation.Compensate; import io.narayana.lra.logging.LRALogger; @@ -72,10 +74,8 @@ import org.eclipse.microprofile.lra.annotation.LRAStatus; import org.eclipse.microprofile.lra.annotation.ws.rs.Leave; import org.eclipse.microprofile.lra.annotation.Status; -import org.eclipse.microprofile.lra.client.GenericLRAException; -import org.eclipse.microprofile.lra.client.IllegalLRAStateException; -import static org.eclipse.microprofile.lra.annotation.ws.rs.LRA.LRA_HTTP_HEADER; +import static org.eclipse.microprofile.lra.annotation.ws.rs.LRA.LRA_HTTP_CONTEXT_HEADER; /** * A utility class for controlling the lifecycle of Long Running Actions (LRAs) but the prefered mechanism is to use @@ -286,7 +286,7 @@ public URI startLRA(URI parentLRA, String clientID, Long timeout, ChronoUnit uni } // validate that there is an LRAInfo response header holding the LRAInfo id - Object lraObject = Current.getLast(response.getHeaders().get(LRA_HTTP_HEADER)); + Object lraObject = Current.getLast(response.getHeaders().get(LRA_HTTP_CONTEXT_HEADER)); if (lraObject == null) { LRALogger.i18NLogger.error_nullLraOnCreation(response); @@ -358,7 +358,7 @@ public void leaveLRA(URI lraId, String body) throws GenericLRAException { response = getTarget().path(String.format(leaveFormat, getLRAId(lraId.toString()))) .request() - .header(LRA_HTTP_HEADER, lraId) + .header(LRA_HTTP_CONTEXT_HEADER, lraId) .put(Entity.entity(body, MediaType.TEXT_PLAIN)); if (Response.Status.OK.getStatusCode() != response.getStatus()) { @@ -636,7 +636,7 @@ private URI enlistCompensator(URI uri, long timelimit, String linkHeader, String .queryParam(TIMELIMIT_PARAM_NAME, timelimit) .request() .header(LINK_TEXT, linkHeader) - .header(LRA_HTTP_HEADER, lraId) + .header(LRA_HTTP_CONTEXT_HEADER, lraId) .put(Entity.entity(compensatorData == null ? linkHeader : compensatorData, MediaType.TEXT_PLAIN)); if (response.getStatus() == Response.Status.PRECONDITION_FAILED.getStatusCode()) { diff --git a/rts/lra/lra-coordinator/src/main/java/io/narayana/lra/coordinator/api/Coordinator.java b/rts/lra/lra-coordinator/src/main/java/io/narayana/lra/coordinator/api/Coordinator.java index c59263e262..a16ffb1f87 100644 --- a/rts/lra/lra-coordinator/src/main/java/io/narayana/lra/coordinator/api/Coordinator.java +++ b/rts/lra/lra-coordinator/src/main/java/io/narayana/lra/coordinator/api/Coordinator.java @@ -23,6 +23,9 @@ package io.narayana.lra.coordinator.api; import io.narayana.lra.Current; +import io.narayana.lra.GenericLRAException; +import io.narayana.lra.IllegalLRAStateException; +import io.narayana.lra.InvalidLRAIdException; import io.narayana.lra.coordinator.domain.model.LRAData; import io.narayana.lra.coordinator.domain.model.LRAStatusHolder; import io.narayana.lra.coordinator.domain.model.Transaction; @@ -69,9 +72,6 @@ import java.util.Map; import org.eclipse.microprofile.lra.annotation.LRAStatus; -import org.eclipse.microprofile.lra.client.GenericLRAException; -import org.eclipse.microprofile.lra.client.IllegalLRAStateException; -import org.eclipse.microprofile.lra.client.InvalidLRAIdException; import static io.narayana.lra.LRAConstants.CLIENT_ID_PARAM_NAME; import static io.narayana.lra.LRAConstants.COMPENSATE; @@ -84,7 +84,7 @@ import static io.narayana.lra.LRAConstants.TIMELIMIT_PARAM_NAME; import static java.util.stream.Collectors.toList; import static javax.ws.rs.core.Response.Status.BAD_REQUEST; -import static org.eclipse.microprofile.lra.annotation.ws.rs.LRA.LRA_HTTP_HEADER; +import static org.eclipse.microprofile.lra.annotation.ws.rs.LRA.LRA_HTTP_CONTEXT_HEADER; import static org.eclipse.microprofile.lra.annotation.ws.rs.LRA.LRA_HTTP_RECOVERY_HEADER; @ApplicationScoped @@ -238,7 +238,7 @@ public Response startLRA( @QueryParam(TIMELIMIT_PARAM_NAME) @DefaultValue("0") Long timelimit, @ApiParam(value = "The enclosing LRA if this new LRA is nested", required = false) @QueryParam(PARENT_LRA_PARAM_NAME) @DefaultValue("") String parentLRA, - @HeaderParam(LRA_HTTP_HEADER) String parentId) throws WebApplicationException, InvalidLRAIdException { + @HeaderParam(LRA_HTTP_CONTEXT_HEADER) String parentId) throws WebApplicationException, InvalidLRAIdException { URI parentLRAUrl = null; @@ -280,7 +280,7 @@ public Response startLRA( return Response.status(Response.Status.CREATED) .entity(lraId) - .header(LRA_HTTP_HEADER, Current.getContexts()) + .header(LRA_HTTP_CONTEXT_HEADER, Current.getContexts()) .build(); } diff --git a/rts/lra/lra-coordinator/src/main/java/io/narayana/lra/coordinator/api/CoordinatorContainerFilter.java b/rts/lra/lra-coordinator/src/main/java/io/narayana/lra/coordinator/api/CoordinatorContainerFilter.java index d6d30dba0e..9a613b96d1 100644 --- a/rts/lra/lra-coordinator/src/main/java/io/narayana/lra/coordinator/api/CoordinatorContainerFilter.java +++ b/rts/lra/lra-coordinator/src/main/java/io/narayana/lra/coordinator/api/CoordinatorContainerFilter.java @@ -22,7 +22,7 @@ package io.narayana.lra.coordinator.api; import io.narayana.lra.Current; -import org.eclipse.microprofile.lra.client.GenericLRAException; +import io.narayana.lra.GenericLRAException; import javax.ws.rs.container.ContainerRequestContext; import javax.ws.rs.container.ContainerRequestFilter; @@ -35,7 +35,7 @@ import java.net.URI; import java.net.URISyntaxException; -import static org.eclipse.microprofile.lra.annotation.ws.rs.LRA.LRA_HTTP_HEADER; +import static org.eclipse.microprofile.lra.annotation.ws.rs.LRA.LRA_HTTP_CONTEXT_HEADER; @Provider public class CoordinatorContainerFilter implements ContainerRequestFilter, ContainerResponseFilter { @@ -44,19 +44,19 @@ public void filter(ContainerRequestContext requestContext) throws IOException { MultivaluedMap headers = requestContext.getHeaders(); URI lraId = null; - if (headers.containsKey(LRA_HTTP_HEADER)) { + if (headers.containsKey(LRA_HTTP_CONTEXT_HEADER)) { try { - lraId = new URI(Current.getLast(headers.get(LRA_HTTP_HEADER))); + lraId = new URI(Current.getLast(headers.get(LRA_HTTP_CONTEXT_HEADER))); } catch (URISyntaxException e) { String msg = String.format("header %s contains an invalid URL %s", - LRA_HTTP_HEADER, Current.getLast(headers.get(LRA_HTTP_HEADER))); + LRA_HTTP_CONTEXT_HEADER, Current.getLast(headers.get(LRA_HTTP_CONTEXT_HEADER))); throw new GenericLRAException(null, Response.Status.PRECONDITION_FAILED.getStatusCode(), msg, e); } } - if (!headers.containsKey(LRA_HTTP_HEADER)) { - Object lraContext = requestContext.getProperty(LRA_HTTP_HEADER); + if (!headers.containsKey(LRA_HTTP_CONTEXT_HEADER)) { + Object lraContext = requestContext.getProperty(LRA_HTTP_CONTEXT_HEADER); if (lraContext != null) { lraId = (URI) lraContext; diff --git a/rts/lra/lra-coordinator/src/main/java/io/narayana/lra/coordinator/api/RecoveryCoordinator.java b/rts/lra/lra-coordinator/src/main/java/io/narayana/lra/coordinator/api/RecoveryCoordinator.java index a9b7ba1920..b679632125 100644 --- a/rts/lra/lra-coordinator/src/main/java/io/narayana/lra/coordinator/api/RecoveryCoordinator.java +++ b/rts/lra/lra-coordinator/src/main/java/io/narayana/lra/coordinator/api/RecoveryCoordinator.java @@ -21,6 +21,7 @@ */ package io.narayana.lra.coordinator.api; +import io.narayana.lra.GenericLRAException; import io.narayana.lra.coordinator.domain.model.LRAStatusHolder; import io.narayana.lra.coordinator.domain.service.LRAService; import io.narayana.lra.logging.LRALogger; @@ -29,7 +30,6 @@ import io.swagger.annotations.ApiParam; import io.swagger.annotations.ApiResponse; import io.swagger.annotations.ApiResponses; -import org.eclipse.microprofile.lra.client.GenericLRAException; import org.jboss.logging.Logger; import javax.enterprise.context.ApplicationScoped; diff --git a/rts/lra/lra-coordinator/src/main/java/io/narayana/lra/coordinator/domain/model/LRARecord.java b/rts/lra/lra-coordinator/src/main/java/io/narayana/lra/coordinator/domain/model/LRARecord.java index d800ff3be6..7572d72c95 100644 --- a/rts/lra/lra-coordinator/src/main/java/io/narayana/lra/coordinator/domain/model/LRARecord.java +++ b/rts/lra/lra-coordinator/src/main/java/io/narayana/lra/coordinator/domain/model/LRARecord.java @@ -29,11 +29,12 @@ import com.arjuna.ats.arjuna.state.OutputObjectState; import io.narayana.lra.Current; +import io.narayana.lra.GenericLRAException; +import io.narayana.lra.InvalidLRAIdException; import io.narayana.lra.coordinator.domain.service.LRAService; import io.narayana.lra.logging.LRALogger; import org.eclipse.microprofile.lra.annotation.LRAStatus; -import org.eclipse.microprofile.lra.client.GenericLRAException; -import org.eclipse.microprofile.lra.client.InvalidLRAIdException; +import org.eclipse.microprofile.lra.annotation.ParticipantStatus; import javax.ws.rs.client.Client; import javax.ws.rs.client.ClientBuilder; @@ -58,7 +59,7 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.ReentrantLock; -import static org.eclipse.microprofile.lra.annotation.ws.rs.LRA.LRA_HTTP_HEADER; +import static org.eclipse.microprofile.lra.annotation.ws.rs.LRA.LRA_HTTP_CONTEXT_HEADER; import static org.eclipse.microprofile.lra.annotation.ws.rs.LRA.LRA_HTTP_RECOVERY_HEADER; public class LRARecord extends AbstractRecord implements Comparable { @@ -82,7 +83,7 @@ public class LRARecord extends AbstractRecord implements Comparable scheduledAbort; private LRAService lraService; - private LRAStatus status; + private ParticipantStatus status; boolean accepted; public LRARecord() { @@ -106,6 +107,8 @@ public LRARecord() { if (parseException[0] != null) { throw new InvalidLRAIdException(lraId, "Invalid link URI", parseException[0]); + } else if (compensateURI == null) { + throw new InvalidLRAIdException(lraId, "Invalid link URI: missing compensator"); } } else { this.compensateURI = new URI(String.format("%s/compensate", linkURI)); @@ -253,7 +256,7 @@ private int tryDoEnd(boolean compensate) { scheduledAbort = null; } - if (LRAStatus.Cancelling.equals(status)) { + if (ParticipantStatus.Compensating.equals(status)) { compensate = true; } @@ -263,16 +266,16 @@ private int tryDoEnd(boolean compensate) { } endPath = compensateURI; // we are going to ask the participant to compensate - status = LRAStatus.Cancelling; + status = ParticipantStatus.Compensating; } else { if (isCompelete() || completeURI == null) { - status = LRAStatus.Closed; + status = ParticipantStatus.Completed; return TwoPhaseOutcome.FINISH_OK; // the participant has already completed } endPath = completeURI; // we are going to ask the participant to complete - status = LRAStatus.Closing; + status = ParticipantStatus.Completing; } // NB trying to compensate when already completed is allowed (for nested LRAs) @@ -300,9 +303,9 @@ private int tryDoEnd(boolean compensate) { try { // ask the participant to complete or compensate Future asyncResponse = target.request() - .header(LRA_HTTP_HEADER, lraId.toASCIIString()) + .header(LRA_HTTP_CONTEXT_HEADER, lraId.toASCIIString()) .header(LRA_HTTP_RECOVERY_HEADER, recoveryURI.toASCIIString()) - .property(LRA_HTTP_HEADER, lraId) // make the context available to the jaxrs filters + .property(LRA_HTTP_CONTEXT_HEADER, lraId) // make the context available to the jaxrs filters .async() .put(Entity.entity(compensatorData, MediaType.APPLICATION_JSON)); // the catch block below catches any Timeout exception @@ -365,7 +368,7 @@ private int tryDoEnd(boolean compensate) { } if (compensate) { - status = LRAStatus.Cancelling; // recovery will figure out the status via the status url + status = ParticipantStatus.Compensating; // recovery will figure out the status via the status url /* * We are mapping compensate onto Abort. TwoPhaseCoordinator uses presumed abort @@ -375,7 +378,7 @@ private int tryDoEnd(boolean compensate) { return TwoPhaseOutcome.HEURISTIC_HAZARD; } - status = LRAStatus.Closing; // recovery will figure out the status via the status url + status = ParticipantStatus.Completing; // recovery will figure out the status via the status url return TwoPhaseOutcome.FINISH_ERROR; } @@ -388,14 +391,14 @@ private int tryDoEnd(boolean compensate) { private void updateStatus(boolean compensate) { if (compensate) { - status = accepted ? LRAStatus.Cancelling : LRAStatus.Cancelled; + status = accepted ? ParticipantStatus.Compensating : ParticipantStatus.Compensated; } else { - status = accepted ? LRAStatus.Closing : LRAStatus.Closed; + status = accepted ? ParticipantStatus.Completing : ParticipantStatus.Completed; } } private int reportFailure(boolean compensate, String endPath) { - status = compensate ? LRAStatus.FailedToCancel : LRAStatus.FailedToClose; + status = compensate ? ParticipantStatus.FailedToCompensate : ParticipantStatus.FailedToComplete; LRALogger.logger.warnf("LRARecord: participant %s reported a failure to %s", endPath, compensate ? COMPENSATE_REL : COMPLETE_REL); @@ -449,9 +452,9 @@ private int retryGetEndStatus(URI endPath, boolean compensate) { // since this method is called from the recovery thread do not block Future asyncResponse = target.request() - .header(LRA_HTTP_HEADER, lraId.toASCIIString()) + .header(LRA_HTTP_CONTEXT_HEADER, lraId.toASCIIString()) .header(LRA_HTTP_RECOVERY_HEADER, recoveryURI.toASCIIString()) - .property(LRA_HTTP_HEADER, lraId) // make the context available to the jaxrs filters + .property(LRA_HTTP_CONTEXT_HEADER, lraId) // make the context available to the jaxrs filters .async() .get(); @@ -468,35 +471,31 @@ private int retryGetEndStatus(URI endPath, boolean compensate) { // the participant is available again and has reported its status String s = response.readEntity(String.class); - status = LRAStatus.valueOf(s); + status = ParticipantStatus.valueOf(s); switch (status) { - case Closed: - case Cancelled: + case Completed: + case Compensated: return TwoPhaseOutcome.FINISH_OK; - case Closing: - case Cancelling: + case Completing: + case Compensating: // still in progress - make sure recovery keeps retrying it return TwoPhaseOutcome.HEURISTIC_HAZARD; - case FailedToCancel: - case FailedToClose: + case FailedToCompensate: + case FailedToComplete: // the participant could not finish - log a warning and forget LRALogger.logger.warnf( "LRARecord.doEnd(compensate %b) get status %s did not finish: %s: WILL NOT RETRY", compensate, target.getUri(), status); - if (forgetURI != null) { - forgetURI = statusURI; // forget is equivalent to HTTP delete on the status URI - } - if (forgetURI != null) { try { // let the participant know he can clean up WebTarget target2 = client.target(forgetURI); Future asyncResponse2 = target2.request() - .header(LRA_HTTP_HEADER, lraId.toASCIIString()) + .header(LRA_HTTP_CONTEXT_HEADER, lraId.toASCIIString()) .header(LRA_HTTP_RECOVERY_HEADER, recoveryURI.toASCIIString()) - .property(LRA_HTTP_HEADER, lraId) // make the context available to the jaxrs filters + .property(LRA_HTTP_CONTEXT_HEADER, lraId) // make the context available to the jaxrs filters .async() .delete(); @@ -612,11 +611,11 @@ boolean forget() { } private boolean isCompelete() { - return status != null && status == LRAStatus.Closed; + return status != null && status == ParticipantStatus.Completed; } private boolean isCompensated() { - return status != null && status == LRAStatus.Cancelled; + return status != null && status == ParticipantStatus.Compensated; } String getResponseData() { @@ -657,7 +656,7 @@ public boolean restore_state(InputObjectState os, int t) { unpackStatus(os); participantPath = os.unpackString(); compensatorData = os.unpackString(); - accepted = status == LRAStatus.Closing || status == LRAStatus.Cancelling; + accepted = status == ParticipantStatus.Completing || status == ParticipantStatus.Compensating; } catch (IOException | URISyntaxException e) { return false; } @@ -676,7 +675,7 @@ private void packStatus(OutputObjectState os) throws IOException { } private void unpackStatus(InputObjectState os) throws IOException { - status = os.unpackBoolean() ? LRAStatus.values()[os.unpackInt()] : null; + status = os.unpackBoolean() ? ParticipantStatus.values()[os.unpackInt()] : null; } private void packURI(OutputObjectState os, URI url) throws IOException { diff --git a/rts/lra/lra-coordinator/src/main/java/io/narayana/lra/coordinator/domain/model/Transaction.java b/rts/lra/lra-coordinator/src/main/java/io/narayana/lra/coordinator/domain/model/Transaction.java index 4647d61e26..c1d50d0829 100644 --- a/rts/lra/lra-coordinator/src/main/java/io/narayana/lra/coordinator/domain/model/Transaction.java +++ b/rts/lra/lra-coordinator/src/main/java/io/narayana/lra/coordinator/domain/model/Transaction.java @@ -30,6 +30,7 @@ import com.arjuna.ats.arjuna.coordinator.RecordList; import com.arjuna.ats.arjuna.coordinator.RecordListIterator; import com.arjuna.ats.arjuna.coordinator.RecordType; +import io.narayana.lra.InvalidLRAIdException; import io.narayana.lra.logging.LRALogger; import com.arjuna.ats.arjuna.state.InputObjectState; import com.arjuna.ats.arjuna.state.OutputObjectState; @@ -37,7 +38,6 @@ import io.narayana.lra.coordinator.domain.service.LRAService; import org.eclipse.microprofile.lra.annotation.LRAStatus; -import org.eclipse.microprofile.lra.client.InvalidLRAIdException; import javax.ws.rs.core.Response; import javax.ws.rs.core.Response.Status; @@ -551,7 +551,7 @@ private LRARecord findLRAParticipant(String participantUrl, boolean remove) { } catch (MalformedURLException | URISyntaxException ignore) { String pUrl = LRARecord.extractCompensator(id, participantUrl); - rec = findLRAParticipant(pUrl, remove, pendingList, pendingList, preparedList, heuristicList, failedList); + rec = findLRAParticipant(pUrl, remove, pendingList, preparedList, heuristicList, failedList); } return rec; diff --git a/rts/lra/lra-coordinator/src/main/java/io/narayana/lra/coordinator/domain/service/LRAService.java b/rts/lra/lra-coordinator/src/main/java/io/narayana/lra/coordinator/domain/service/LRAService.java index 3dfa7210a2..5dfa32068e 100644 --- a/rts/lra/lra-coordinator/src/main/java/io/narayana/lra/coordinator/domain/service/LRAService.java +++ b/rts/lra/lra-coordinator/src/main/java/io/narayana/lra/coordinator/domain/service/LRAService.java @@ -23,6 +23,8 @@ import com.arjuna.ats.arjuna.AtomicAction; import com.arjuna.ats.arjuna.coordinator.ActionStatus; +import io.narayana.lra.IllegalLRAStateException; +import io.narayana.lra.InvalidLRAIdException; import io.narayana.lra.coordinator.domain.model.LRAData; import io.narayana.lra.logging.LRALogger; import com.arjuna.ats.arjuna.recovery.RecoveryManager; @@ -34,8 +36,6 @@ import io.narayana.lra.coordinator.domain.model.Transaction; import org.eclipse.microprofile.lra.annotation.LRAStatus; -import org.eclipse.microprofile.lra.client.IllegalLRAStateException; -import org.eclipse.microprofile.lra.client.InvalidLRAIdException; import javax.enterprise.context.ApplicationScoped; import javax.enterprise.context.Destroyed; diff --git a/rts/lra/lra-filters/src/main/java/io/narayana/lra/filter/ClientLRARequestFilter.java b/rts/lra/lra-filters/src/main/java/io/narayana/lra/filter/ClientLRARequestFilter.java index 680b46daee..62c6ec75bb 100644 --- a/rts/lra/lra-filters/src/main/java/io/narayana/lra/filter/ClientLRARequestFilter.java +++ b/rts/lra/lra-filters/src/main/java/io/narayana/lra/filter/ClientLRARequestFilter.java @@ -26,9 +26,14 @@ import javax.ws.rs.client.ClientRequestContext; import javax.ws.rs.client.ClientRequestFilter; +import static org.eclipse.microprofile.lra.annotation.ws.rs.LRA.LRA_HTTP_CONTEXT_HEADER; + public class ClientLRARequestFilter implements ClientRequestFilter { @Override public void filter(ClientRequestContext context) { + if (Current.peek() != null) { + context.setProperty(LRA_HTTP_CONTEXT_HEADER, Current.peek()); + } Current.updateLRAContext(context); } } diff --git a/rts/lra/lra-filters/src/main/java/io/narayana/lra/filter/ClientLRAResponseFilter.java b/rts/lra/lra-filters/src/main/java/io/narayana/lra/filter/ClientLRAResponseFilter.java index e8e16fd329..ece74f0101 100644 --- a/rts/lra/lra-filters/src/main/java/io/narayana/lra/filter/ClientLRAResponseFilter.java +++ b/rts/lra/lra-filters/src/main/java/io/narayana/lra/filter/ClientLRAResponseFilter.java @@ -30,9 +30,8 @@ import javax.ws.rs.core.Context; import java.io.IOException; import java.net.URI; -import java.net.URISyntaxException; -import static org.eclipse.microprofile.lra.annotation.ws.rs.LRA.LRA_HTTP_HEADER; +import static org.eclipse.microprofile.lra.annotation.ws.rs.LRA.LRA_HTTP_CONTEXT_HEADER; public class ClientLRAResponseFilter implements ClientResponseFilter { @Context @@ -40,31 +39,10 @@ public class ClientLRAResponseFilter implements ClientResponseFilter { @Override public void filter(ClientRequestContext requestContext, ClientResponseContext responseContext) throws IOException { - Object incomingLRA = Current.getLast(responseContext.getHeaders().get(LRA_HTTP_HEADER)); + Object callingContext = requestContext.getProperty(LRA_HTTP_CONTEXT_HEADER); - if (incomingLRA == null) { - incomingLRA = requestContext.getProperty(LRA_HTTP_HEADER); - } - - /* - * if the incoming response contains a context make it the current one - * (note we never popped the context in the request filter so we don't need to push outgoingLRA - */ - if (incomingLRA != null) { - try { - Current.push(new URI(incomingLRA.toString())); - } catch (URISyntaxException e) { - throw new IOException( - String.format("The JAX-RS '%s' filter for method '%s'#'%s' contained an invalid LRA context ('%s')", - ClientLRAResponseFilter.class.getName(), - resourceInfo.getResourceClass().getName(), - resourceInfo.getResourceMethod().getName(), - incomingLRA.toString()), e); - } - } else { - // any previous context must have been ended by the invoked service otherwise incomingLRA - // would have been present - Current.pop(); + if (callingContext != null) { + Current.push((URI) callingContext); } } } diff --git a/rts/lra/lra-filters/src/main/java/io/narayana/lra/filter/ServerLRAFilter.java b/rts/lra/lra-filters/src/main/java/io/narayana/lra/filter/ServerLRAFilter.java index 62042af32e..b675bd246a 100644 --- a/rts/lra/lra-filters/src/main/java/io/narayana/lra/filter/ServerLRAFilter.java +++ b/rts/lra/lra-filters/src/main/java/io/narayana/lra/filter/ServerLRAFilter.java @@ -22,6 +22,8 @@ package io.narayana.lra.filter; import io.narayana.lra.Current; +import io.narayana.lra.GenericLRAException; +import io.narayana.lra.IllegalLRAStateException; import io.narayana.lra.client.NarayanaLRAClient; import io.narayana.lra.logging.LRALogger; import org.eclipse.microprofile.lra.annotation.Compensate; @@ -31,8 +33,6 @@ import org.eclipse.microprofile.lra.annotation.ws.rs.Leave; import org.eclipse.microprofile.lra.annotation.ws.rs.NestedLRA; import org.eclipse.microprofile.lra.annotation.Status; -import org.eclipse.microprofile.lra.client.GenericLRAException; -import org.eclipse.microprofile.lra.client.IllegalLRAStateException; import javax.inject.Inject; import javax.ws.rs.NotFoundException; @@ -62,7 +62,7 @@ import static io.narayana.lra.LRAConstants.LEAVE; import static io.narayana.lra.LRAConstants.STATUS; import static io.narayana.lra.LRAConstants.TIMELIMIT_PARAM_NAME; -import static org.eclipse.microprofile.lra.annotation.ws.rs.LRA.LRA_HTTP_HEADER; +import static org.eclipse.microprofile.lra.annotation.ws.rs.LRA.LRA_HTTP_CONTEXT_HEADER; import static org.eclipse.microprofile.lra.annotation.ws.rs.LRA.LRA_HTTP_RECOVERY_HEADER; @Provider @@ -169,17 +169,27 @@ public void filter(ContainerRequestContext containerRequestContext) throws IOExc || method.isAnnotationPresent(Status.class) || method.isAnnotationPresent(Forget.class); - if (headers.containsKey(LRA_HTTP_HEADER)) { + if (headers.containsKey(LRA_HTTP_CONTEXT_HEADER)) { try { - incommingLRA = new URI(Current.getLast(headers.get(LRA_HTTP_HEADER)).toString()); + incommingLRA = new URI(Current.getLast(headers.get(LRA_HTTP_CONTEXT_HEADER)).toString()); } catch (URISyntaxException e) { String msg = String.format("header %s contains an invalid URL %s", - LRA_HTTP_HEADER, Current.getLast(headers.get(LRA_HTTP_HEADER))); + LRA_HTTP_CONTEXT_HEADER, Current.getLast(headers.get(LRA_HTTP_CONTEXT_HEADER))); throw new GenericLRAException(null, Response.Status.PRECONDITION_FAILED.getStatusCode(), msg, e); } } + if (method.isAnnotationPresent(Leave.class)) { + // leave the LRA + String compensatorId = getCompensatorId(incommingLRA, containerRequestContext.getUriInfo().getBaseUri()); + + lraTrace(containerRequestContext, incommingLRA, "leaving LRA"); + lraClient.leaveLRA(incommingLRA, compensatorId); + + // let the participant know which lra he left by leaving the header intact + } + if (type == null) { if (!endAnnotation) { Current.clearContext(headers); @@ -194,8 +204,8 @@ public void filter(ContainerRequestContext containerRequestContext) throws IOExc } // check the incomming request for an LRA context - if (!headers.containsKey(LRA_HTTP_HEADER)) { - Object lraContext = containerRequestContext.getProperty(LRA_HTTP_HEADER); + if (!headers.containsKey(LRA_HTTP_CONTEXT_HEADER)) { + Object lraContext = containerRequestContext.getProperty(LRA_HTTP_CONTEXT_HEADER); if (lraContext != null) { incommingLRA = (URI) lraContext; @@ -327,6 +337,8 @@ public void filter(ContainerRequestContext containerRequestContext) throws IOExc containerRequestContext.setProperty(NEW_LRA_PROP, newLRA); } + Current.push(lraId); + lraTrace(containerRequestContext, lraId, "ServerLRAFilter before: making LRA available to injected NarayanaLRAClient"); lraClient.setCurrentLRA(lraId); // make the current LRA available to the called method @@ -367,16 +379,6 @@ public void filter(ContainerRequestContext containerRequestContext) throws IOExc } } - 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"); } @@ -402,9 +404,9 @@ public void filter(ContainerRequestContext requestContext, ContainerResponseCont // or completed (if the intercepted method caused it to complete) } finally { if (current.toASCIIString().equals( - Current.getLast(requestContext.getHeaders().get(LRA_HTTP_HEADER)))) { + Current.getLast(requestContext.getHeaders().get(LRA_HTTP_CONTEXT_HEADER)))) { // the callers context was ended so invalidate it - requestContext.getHeaders().remove(LRA_HTTP_HEADER); + requestContext.getHeaders().remove(LRA_HTTP_CONTEXT_HEADER); } if (toClose != null && toClose.toASCIIString().equals(current.toASCIIString())) { @@ -420,12 +422,12 @@ public void filter(ContainerRequestContext requestContext, ContainerResponseCont // must already be cancelled (if the intercepted method caused it to cancel) // or completed (if the intercepted method caused it to complete } finally { - requestContext.getHeaders().remove(LRA_HTTP_HEADER); + requestContext.getHeaders().remove(LRA_HTTP_CONTEXT_HEADER); if (toClose.toASCIIString().equals( - Current.getLast(requestContext.getHeaders().get(LRA_HTTP_HEADER)))) { + Current.getLast(requestContext.getHeaders().get(LRA_HTTP_CONTEXT_HEADER)))) { // the callers context was ended so invalidate it - requestContext.getHeaders().remove(LRA_HTTP_HEADER); + requestContext.getHeaders().remove(LRA_HTTP_CONTEXT_HEADER); } } } diff --git a/rts/lra/lra-service-base/src/main/java/io/narayana/lra/Current.java b/rts/lra/lra-service-base/src/main/java/io/narayana/lra/Current.java index f6855c7537..9507ee71fa 100644 --- a/rts/lra/lra-service-base/src/main/java/io/narayana/lra/Current.java +++ b/rts/lra/lra-service-base/src/main/java/io/narayana/lra/Current.java @@ -31,7 +31,7 @@ import java.util.Map; import java.util.Stack; -import static org.eclipse.microprofile.lra.annotation.ws.rs.LRA.LRA_HTTP_HEADER; +import static org.eclipse.microprofile.lra.annotation.ws.rs.LRA.LRA_HTTP_CONTEXT_HEADER; public class Current { private static final ThreadLocal lraContexts = new ThreadLocal<>(); @@ -154,14 +154,14 @@ public static void updateLRAContext(ContainerResponseContext responseContext) { URI lraId = Current.peek(); if (lraId != null) { - responseContext.getHeaders().put(LRA_HTTP_HEADER, getContexts()); + responseContext.getHeaders().put(LRA_HTTP_CONTEXT_HEADER, getContexts()); } else { - responseContext.getHeaders().remove(LRA_HTTP_HEADER); + responseContext.getHeaders().remove(LRA_HTTP_CONTEXT_HEADER); } } public static void updateLRAContext(URI lraId, MultivaluedMap headers) { - headers.putSingle(LRA_HTTP_HEADER, lraId.toString()); + headers.putSingle(LRA_HTTP_CONTEXT_HEADER, lraId.toString()); push(lraId); } @@ -174,7 +174,7 @@ public static void updateLRAContext(URI lraId, MultivaluedMap he public static void updateLRAContext(ClientRequestContext context) { MultivaluedMap headers = context.getHeaders(); - if (headers.containsKey(LRA_HTTP_HEADER)) { + if (headers.containsKey(LRA_HTTP_CONTEXT_HEADER)) { // LRA context is explicitly set return; } @@ -182,14 +182,14 @@ public static void updateLRAContext(ClientRequestContext context) { URI lraId = Current.peek(); if (lraId != null) { - headers.putSingle(LRA_HTTP_HEADER, lraId); + headers.putSingle(LRA_HTTP_CONTEXT_HEADER, lraId); } else { - Object lraContext = context.getProperty(LRA_HTTP_HEADER); + Object lraContext = context.getProperty(LRA_HTTP_CONTEXT_HEADER); if (lraContext != null) { - headers.putSingle(LRA_HTTP_HEADER, lraContext); + headers.putSingle(LRA_HTTP_CONTEXT_HEADER, lraContext); } else { - headers.remove(LRA_HTTP_HEADER); + headers.remove(LRA_HTTP_CONTEXT_HEADER); } } } @@ -199,7 +199,7 @@ public static void popAll() { } public static void clearContext(MultivaluedMap headers) { - headers.remove(LRA_HTTP_HEADER); + headers.remove(LRA_HTTP_CONTEXT_HEADER); popAll(); } diff --git a/rts/lra/lra-service-base/src/main/java/io/narayana/lra/GenericLRAException.java b/rts/lra/lra-service-base/src/main/java/io/narayana/lra/GenericLRAException.java new file mode 100644 index 0000000000..fab52a7d8b --- /dev/null +++ b/rts/lra/lra-service-base/src/main/java/io/narayana/lra/GenericLRAException.java @@ -0,0 +1,47 @@ +/* + ******************************************************************************* + * Copyright (c) 2018 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *******************************************************************************/ + +package io.narayana.lra; + +import javax.ws.rs.WebApplicationException; +import java.net.URI; + +public class GenericLRAException extends WebApplicationException { + private static final long serialVersionUID = 1L; + + private URI lraId; + private int statusCode; + + public int getStatusCode() { + return statusCode; + } + + public URI getLraId() { + return lraId; + } + + public GenericLRAException(URI lraId, int statusCode, String message, + Throwable cause) { + super(String.format("%s: %s", lraId, message), cause); + + this.lraId = lraId; + this.statusCode = statusCode; + } +} diff --git a/rts/lra/lra-service-base/src/main/java/io/narayana/lra/IllegalLRAStateException.java b/rts/lra/lra-service-base/src/main/java/io/narayana/lra/IllegalLRAStateException.java new file mode 100644 index 0000000000..f55ed83e75 --- /dev/null +++ b/rts/lra/lra-service-base/src/main/java/io/narayana/lra/IllegalLRAStateException.java @@ -0,0 +1,49 @@ +/* + ******************************************************************************* + * Copyright (c) 2018 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *******************************************************************************/ +package io.narayana.lra; + +import javax.ws.rs.WebApplicationException; + +public class IllegalLRAStateException extends WebApplicationException { + private final String lraId; + private final String operation; + + /** + * Creation of LRA state exception. + * + * @param lraId LRA id that is behind this exception + * @param operation the java method that generated the exception + * @param message error message of this exception + */ + public IllegalLRAStateException(String lraId, String operation, String message) { + super(String.format("%s, lra id: %s", message, lraId)); + + this.lraId = lraId; + this.operation = operation; + } + + public String getLraId() { + return this.lraId; + } + + public String getOperation() { + return this.operation; + } +} diff --git a/rts/lra/lra-service-base/src/main/java/io/narayana/lra/InvalidLRAIdException.java b/rts/lra/lra-service-base/src/main/java/io/narayana/lra/InvalidLRAIdException.java new file mode 100644 index 0000000000..b9c7e2392e --- /dev/null +++ b/rts/lra/lra-service-base/src/main/java/io/narayana/lra/InvalidLRAIdException.java @@ -0,0 +1,56 @@ +/* + ******************************************************************************* + * Copyright (c) 2018 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *******************************************************************************/ +package io.narayana.lra; + +import javax.ws.rs.WebApplicationException; + +public class InvalidLRAIdException extends WebApplicationException { + private static final long serialVersionUID = 1271422145863321852L; + private final String lraId; + + /** + * Invalid LRA id exception. + * + * @param lraId LRA id that is behind this exception + * @param message error message of this exception + * @param cause cause exception + */ + public InvalidLRAIdException(String lraId, String message, Throwable cause) { + super(String.format("%s, LRA id: %s", message, lraId), cause); + + this.lraId = lraId; + } + + /** + * Invalid LRA id exception. + * + * @param lraId LRA id that is behind this exception + * @param message error message of this exception + */ + public InvalidLRAIdException(String lraId, String message) { + super(String.format("%s, LRA id: %s", message, lraId)); + + this.lraId = lraId; + } + + public String getLraId() { + return this.lraId; + } +} diff --git a/rts/lra/lra-service-base/src/main/java/io/narayana/lra/UnknowableException.java b/rts/lra/lra-service-base/src/main/java/io/narayana/lra/UnknowableException.java new file mode 100644 index 0000000000..739a6f20e5 --- /dev/null +++ b/rts/lra/lra-service-base/src/main/java/io/narayana/lra/UnknowableException.java @@ -0,0 +1,31 @@ +/* + ******************************************************************************* + * Copyright (c) 2019 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *******************************************************************************/ +package io.narayana.lra; + +import java.net.URI; + +/** + * An exception type to indicate that a requested operation can never be completed. + */ +public class UnknowableException extends GenericLRAException { + public UnknowableException(URI lraId, int statusCode, String message, Throwable cause) { + super(lraId, statusCode, message, cause); + } +} diff --git a/rts/lra/lra-test/tck/src/test/java/io/narayana/lra/tck/arquillian/ConfigAuxiliaryArchiveAppender.java b/rts/lra/lra-test/tck/src/test/java/io/narayana/lra/tck/arquillian/ConfigAuxiliaryArchiveAppender.java index 712a391dd0..bcb3dae73b 100644 --- a/rts/lra/lra-test/tck/src/test/java/io/narayana/lra/tck/arquillian/ConfigAuxiliaryArchiveAppender.java +++ b/rts/lra/lra-test/tck/src/test/java/io/narayana/lra/tck/arquillian/ConfigAuxiliaryArchiveAppender.java @@ -40,7 +40,7 @@ public Archive createAuxiliaryArchive() { JavaArchive archive = ShrinkWrap.create(JavaArchive.class) // adding LRA spec interfaces under the WildFly Swarm deployment .addPackages(true, org.eclipse.microprofile.lra.annotation.Compensate.class.getPackage()) - .addPackages(true, org.eclipse.microprofile.lra.client.InvalidLRAIdException.class.getPackage()) + .addPackages(true, io.narayana.lra.InvalidLRAIdException.class.getPackage()) .addPackages(true, org.eclipse.microprofile.lra.participant.LRAParticipant.class.getPackage()); // adding Narayana LRA implementation under the WildFly Swarm deployment archive.addPackages(true, io.narayana.lra.client.NarayanaLRAClient.class.getPackage()) diff --git a/rts/lra/pom.xml b/rts/lra/pom.xml index 381897fc83..45e2ca8c5f 100644 --- a/rts/lra/pom.xml +++ b/rts/lra/pom.xml @@ -33,8 +33,8 @@ 4.12 1.2.1.Final - 1.0-20190329.061214-321 - 1.0-20190329.061215-321 + 1.0-20190418.101203-346 + 1.0-20190418.101205-346 UTF-8