Repository: eclipse/microprofile-lra (java)

Issue:
Add TCK for deployment failure when LRA is not combined with either Compensate or AfterLRA
#244 introduced requirement for Compensate or AfterLRA to be present in each class which has an LRA method. This requirement is supported by the deployment failure [1]. We need to add TCK for this use-case.

[1] https://github.com/eclipse/microprofile-lra/blob/master/api/src/main/java/org/eclipse/microprofile/lra/annotation/ws/rs/LRA.java#L44

Pull request:
Issue272 Add TCK for deployment failure when LRA is not combined with either Compensate or AfterLRA
resolves #272 

* add a new TCK test - `TckInvalidSignaturesTests#invalidLRAResourceWithoutCompensateOrAfterLRATest`
* fix other TCK LRA resources which do not contain any of the Compensate of AfterLRA methods
* ignore TckTests#mixedMultiLevelNestedActivity because it collides with the above requirement (will be reported in the new issue - https://github.com/eclipse/microprofile-lra/issues/274)

Patch:
diff --git a/tck/src/main/java/org/eclipse/microprofile/lra/tck/participant/api/LRATypeTckInterface.java b/tck/src/main/java/org/eclipse/microprofile/lra/tck/participant/api/LRATypeTckInterface.java
index a8a12d4..dddbfdc 100644
--- a/tck/src/main/java/org/eclipse/microprofile/lra/tck/participant/api/LRATypeTckInterface.java
+++ b/tck/src/main/java/org/eclipse/microprofile/lra/tck/participant/api/LRATypeTckInterface.java
@@ -19,6 +19,8 @@
  *******************************************************************************/
 package org.eclipse.microprofile.lra.tck.participant.api;
 
+import org.eclipse.microprofile.lra.annotation.AfterLRA;
+import org.eclipse.microprofile.lra.annotation.LRAStatus;
 import org.eclipse.microprofile.lra.annotation.ws.rs.LRA;
 
 import javax.ws.rs.GET;
@@ -105,4 +107,6 @@ public interface LRATypeTckInterface {
     @LRA(value = LRA.Type.NEVER, end = false)
     Response neverEndLRA(@HeaderParam(LRA_HTTP_CONTEXT_HEADER) URI lraId);
 
+    @AfterLRA
+    void afterLRA(URI lraId, LRAStatus status);
 }
diff --git a/tck/src/main/java/org/eclipse/microprofile/lra/tck/participant/api/LRATypeTckInterfaceResource.java b/tck/src/main/java/org/eclipse/microprofile/lra/tck/participant/api/LRATypeTckInterfaceResource.java
index 6a03de2..5a9e549 100644
--- a/tck/src/main/java/org/eclipse/microprofile/lra/tck/participant/api/LRATypeTckInterfaceResource.java
+++ b/tck/src/main/java/org/eclipse/microprofile/lra/tck/participant/api/LRATypeTckInterfaceResource.java
@@ -19,6 +19,8 @@
  *******************************************************************************/
 package org.eclipse.microprofile.lra.tck.participant.api;
 
+import org.eclipse.microprofile.lra.annotation.LRAStatus;
+
 import javax.ws.rs.Path;
 import javax.ws.rs.core.Response;
 import java.net.URI;
@@ -75,4 +77,9 @@ public class LRATypeTckInterfaceResource implements LRATypeTckInterface {
     public Response neverEndLRA(URI lraId) {
         return Response.ok(lraId).build();
     }
+
+    public void afterLRA(URI lraId, LRAStatus status) {
+        // no-op, required by the specification (see https://github.com/eclipse/microprofile-lra/pull/265)
+    }
+
 }
diff --git a/tck/src/main/java/org/eclipse/microprofile/lra/tck/participant/api/LRATypeTckResource.java b/tck/src/main/java/org/eclipse/microprofile/lra/tck/participant/api/LRATypeTckResource.java
index 688aa7f..ce9bb19 100644
--- a/tck/src/main/java/org/eclipse/microprofile/lra/tck/participant/api/LRATypeTckResource.java
+++ b/tck/src/main/java/org/eclipse/microprofile/lra/tck/participant/api/LRATypeTckResource.java
@@ -19,6 +19,8 @@
  *******************************************************************************/
 package org.eclipse.microprofile.lra.tck.participant.api;
 
+import org.eclipse.microprofile.lra.annotation.AfterLRA;
+import org.eclipse.microprofile.lra.annotation.LRAStatus;
 import org.eclipse.microprofile.lra.annotation.ws.rs.LRA;
 
 import javax.enterprise.context.ApplicationScoped;
@@ -138,4 +140,9 @@ public class LRATypeTckResource {
     public Response neverEndLRA(@HeaderParam(LRA_HTTP_CONTEXT_HEADER) URI lraId) {
         return Response.ok(lraId).build();
     }
+
+    @AfterLRA
+    public void afterLRA(URI lraId, LRAStatus status) {
+        // no-op, required by the specification (see https://github.com/eclipse/microprofile-lra/pull/265)
+    }
 }
diff --git a/tck/src/main/java/org/eclipse/microprofile/lra/tck/participant/api/LRATypeTckSuperclass.java b/tck/src/main/java/org/eclipse/microprofile/lra/tck/participant/api/LRATypeTckSuperclass.java
index 28be8ed..60e3859 100644
--- a/tck/src/main/java/org/eclipse/microprofile/lra/tck/participant/api/LRATypeTckSuperclass.java
+++ b/tck/src/main/java/org/eclipse/microprofile/lra/tck/participant/api/LRATypeTckSuperclass.java
@@ -19,6 +19,8 @@
  *******************************************************************************/
 package org.eclipse.microprofile.lra.tck.participant.api;
 
+import org.eclipse.microprofile.lra.annotation.AfterLRA;
+import org.eclipse.microprofile.lra.annotation.LRAStatus;
 import org.eclipse.microprofile.lra.annotation.ws.rs.LRA;
 
 import javax.ws.rs.GET;
@@ -105,4 +107,8 @@ public abstract class LRATypeTckSuperclass {
     @LRA(value = LRA.Type.NEVER, end = false)
     public abstract Response neverEndLRA(@HeaderParam(LRA_HTTP_CONTEXT_HEADER) URI lraId);
 
+    @AfterLRA
+    public void afterLRA(URI lraId, LRAStatus status) {
+        // no-op, required by the specification (see https://github.com/eclipse/microprofile-lra/pull/265)
+    }
 }
diff --git a/tck/src/main/java/org/eclipse/microprofile/lra/tck/participant/api/LRATypeTckSuperclassResource.java b/tck/src/main/java/org/eclipse/microprofile/lra/tck/participant/api/LRATypeTckSuperclassResource.java
index 221380a..a3fd819 100644
--- a/tck/src/main/java/org/eclipse/microprofile/lra/tck/participant/api/LRATypeTckSuperclassResource.java
+++ b/tck/src/main/java/org/eclipse/microprofile/lra/tck/participant/api/LRATypeTckSuperclassResource.java
@@ -19,6 +19,8 @@
  *******************************************************************************/
 package org.eclipse.microprofile.lra.tck.participant.api;
 
+import org.eclipse.microprofile.lra.annotation.LRAStatus;
+
 import javax.ws.rs.Path;
 import javax.ws.rs.core.Response;
 import java.net.URI;
@@ -75,4 +77,8 @@ public class LRATypeTckSuperclassResource extends LRATypeTckSuperclass {
     public Response neverEndLRA(URI lraId) {
         return Response.ok(lraId).build();
     }
+
+    public void afterLRA(URI lraId, LRAStatus status) {
+        // no-op, required by the specification (see https://github.com/eclipse/microprofile-lra/pull/265)
+    }
 }
diff --git a/tck/src/main/java/org/eclipse/microprofile/lra/tck/participant/api/NonParticipatingTckResource.java b/tck/src/main/java/org/eclipse/microprofile/lra/tck/participant/api/NonParticipatingTckResource.java
index 274aed9..284efb1 100644
--- a/tck/src/main/java/org/eclipse/microprofile/lra/tck/participant/api/NonParticipatingTckResource.java
+++ b/tck/src/main/java/org/eclipse/microprofile/lra/tck/participant/api/NonParticipatingTckResource.java
@@ -19,6 +19,8 @@
  *******************************************************************************/
 package org.eclipse.microprofile.lra.tck.participant.api;
 
+import org.eclipse.microprofile.lra.annotation.AfterLRA;
+import org.eclipse.microprofile.lra.annotation.LRAStatus;
 import org.eclipse.microprofile.lra.annotation.ws.rs.LRA;
 import org.eclipse.microprofile.lra.tck.LRAClientOps;
 
@@ -82,7 +84,7 @@ public class NonParticipatingTckResource {
 
     @PUT
     @Path(SUPPORTS_PATH)
-    @LRA(value = LRA.Type.SUPPORTS)
+    @LRA(value = LRA.Type.SUPPORTS, end = false)
     public Response supports(@HeaderParam(LRA_HTTP_CONTEXT_HEADER) URI lraId) {
         return Response.ok(lraId).build();
     }
@@ -139,6 +141,11 @@ public class NonParticipatingTckResource {
                 200)).build();
     }
 
+    @AfterLRA
+    public void afterLRA(URI lraId, LRAStatus status) {
+        // no-op, required by the specification (see https://github.com/eclipse/microprofile-lra/pull/265)
+    }
+
     private String invokeRestEndpoint(URI lra, String basePath, String path, int coerceResponse) {
         Client client = ClientBuilder.newClient();
 
diff --git a/tck/src/main/java/org/eclipse/microprofile/lra/tck/participant/invalid/LRAResourceWithoutCompensateOrAfteRLRA.java b/tck/src/main/java/org/eclipse/microprofile/lra/tck/participant/invalid/LRAResourceWithoutCompensateOrAfteRLRA.java
new file mode 100644
index 0000000..fdc257e
--- /dev/null
+++ b/tck/src/main/java/org/eclipse/microprofile/lra/tck/participant/invalid/LRAResourceWithoutCompensateOrAfteRLRA.java
@@ -0,0 +1,54 @@
+/*
+ *******************************************************************************
+ * Copyright (c) 2020 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 org.eclipse.microprofile.lra.tck.participant.invalid;
+
+import org.eclipse.microprofile.lra.annotation.Complete;
+import org.eclipse.microprofile.lra.annotation.ws.rs.LRA;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.HeaderParam;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.Response;
+import java.net.URI;
+
+@Path(LRAResourceWithoutCompensateOrAfteRLRA.INVALID_LRA_RESOURCE_PATH)
+public class LRAResourceWithoutCompensateOrAfteRLRA {
+
+    public static final String INVALID_LRA_RESOURCE_PATH = "/invalid-lra-resource-path";
+
+    @GET
+    @Path("/lra")
+    @LRA(value = LRA.Type.REQUIRES_NEW)
+    public Response doInLRA(@HeaderParam(LRA.LRA_HTTP_CONTEXT_HEADER) URI lraId) {
+        return Response.ok(lraId).build();
+    }
+
+    // intentionally don't include any of Compensate or AfterLRA methods which should fail the deployment
+
+    @PUT
+    @Path("/complete")
+    @Complete
+    public Response complete() {
+        throw new WebApplicationException(500);
+    }
+
+}


Test patch:
diff --git a/tck/src/main/java/org/eclipse/microprofile/lra/tck/TckInvalidSignaturesTests.java b/tck/src/main/java/org/eclipse/microprofile/lra/tck/TckInvalidSignaturesTests.java
index d7018a1..95c0b39 100644
--- a/tck/src/main/java/org/eclipse/microprofile/lra/tck/TckInvalidSignaturesTests.java
+++ b/tck/src/main/java/org/eclipse/microprofile/lra/tck/TckInvalidSignaturesTests.java
@@ -19,6 +19,7 @@
  *******************************************************************************/
 package org.eclipse.microprofile.lra.tck;
 
+import org.eclipse.microprofile.lra.tck.participant.invalid.LRAResourceWithoutCompensateOrAfteRLRA;
 import org.eclipse.microprofile.lra.tck.participant.nonjaxrs.InvalidAfterLRASignatureListener;
 import org.eclipse.microprofile.lra.tck.participant.nonjaxrs.InvalidArgumentTypesParticipant;
 import org.eclipse.microprofile.lra.tck.participant.nonjaxrs.InvalidReturnTypeParticipant;
@@ -55,6 +56,7 @@ public class TckInvalidSignaturesTests {
     private static final String TOO_MANY_ARGS_DEPLOYMENT = "too-many-args-deploy";
     private static final String INVALID_ARGUMENT_TYPE_DEPLOYMENT = "nonjaxrs-argument-type-deploy";
     private static final String INVALID_AFTER_LRA_SIGNATURE_DEPLOYMENT = "invalid-after-lra-deploy";
+    private static final String INVALID_LRA_RESOURCE_DEPLOYMENT = "invalid-lra-resource-deploy";
 
     @Rule
     public ExpectedException expectedException = ExpectedException.none();
@@ -85,6 +87,11 @@ public class TckInvalidSignaturesTests {
         return createArchive(InvalidAfterLRASignatureListener.class);
     }
 
+    @Deployment(name = INVALID_LRA_RESOURCE_DEPLOYMENT, managed = false)
+    public static WebArchive deployInvalidLRAResource() {
+        return createArchive(LRAResourceWithoutCompensateOrAfteRLRA.class);
+    }
+
     private static WebArchive createArchive(Class<?> resourceClass) {
         String archiveName = resourceClass.getSimpleName();
         return ShrinkWrap
@@ -130,6 +137,14 @@ public class TckInvalidSignaturesTests {
         testInvalidDeployment(INVALID_AFTER_LRA_SIGNATURE_DEPLOYMENT);
     }
 
+    /**
+     * Verify that invalid LRA resource which does not contain any of @Compensate or @AfterLRA methods is detected
+     */
+    @Test
+    public void invalidLRAResourceWithoutCompensateOrAfterLRATest() {
+        testInvalidDeployment(INVALID_LRA_RESOURCE_DEPLOYMENT);
+    }
+
     private void testInvalidDeployment(String deploymentName) {
         deploymentNameRule.deploymentName = deploymentName;
         expectedException.expect(DeploymentException.class);
diff --git a/tck/src/main/java/org/eclipse/microprofile/lra/tck/TckTests.java b/tck/src/main/java/org/eclipse/microprofile/lra/tck/TckTests.java
index 44a7df3..b5813da 100644
--- a/tck/src/main/java/org/eclipse/microprofile/lra/tck/TckTests.java
+++ b/tck/src/main/java/org/eclipse/microprofile/lra/tck/TckTests.java
@@ -64,6 +64,7 @@ import org.jboss.arquillian.container.test.api.Deployment;
 import org.jboss.arquillian.junit.Arquillian;
 import org.jboss.shrinkwrap.api.spec.WebArchive;
 import org.junit.Before;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
@@ -177,6 +178,7 @@ public class TckTests extends TckTestBase {
     }
 
     @Test
+    @Ignore("https://github.com/eclipse/microprofile-lra/issues/274")
     public void mixedMultiLevelNestedActivity() throws WebApplicationException {
         multiLevelNestedActivity(CompletionType.mixed, 2);
     }