Repository: eclipse/microprofile-lra (java)

Issue:
Add a TCK test which ensures the compensate may called before the participant's business method finishes
The goal of this issue is to create a new TCK test case which ensures that the implementation permits the call of the compensate method being processed before the `@LRA` business method ends.
In other words, the test should show that if the business method takes a long time and meanwhile the LRA is cancelled then the `@Compensate` method will be invoked. The business method may still be in progress. The `@Compensate` method could be, for example, used for interruption of the tasks being done in the business method.

This issue was created as a result of discussion at https://github.com/eclipse/microprofile-lra/issues/301. The issue #301 wrongly assumed the behaviour expected by the spec.

The test would consist (approximately) this scenario:

* LRA is started
* Aarticipant's `@LRA` business method is invoked with context of the started LRA
* The invocation of the business `@LRA` method causes the participant is registered with the started LRA
* The participant starts some business processing inside of the invoked method. This is long running action which is ensured not being finished until LRA is cancelled.
* The LRA is meanwhile cancelled. The LRA implementation has to call the compensate callback at the enlisted participant
* The `@Compensate` method has to be invoked and only after that the LRA participant business method may be finished by the test


Pull request description:
#305 Add a TCK test which ensures compensate may called before the participant's business method finishes. 
resolves #305

   - add a new TCK test (as described in the title) `TckParticipantTests#cancelLraDuringBusinessMethod` and an auxiliary participant `LongBusinessMethodParticipant` used in this test.

Patch:
diff --git a/tck/running_the_tck.asciidoc b/tck/running_the_tck.asciidoc
index 3b2a458..0304ae9 100644
--- a/tck/running_the_tck.asciidoc
+++ b/tck/running_the_tck.asciidoc
@@ -37,7 +37,6 @@ The LRA TCK suite can be parametrized by following properties, handled in the su
   When set-up lower then the timeouts will be shorter.
   Thus on slower machines it's expected longer timeouts will be needed. For example if test expects
   some waiting time to be 10 seconds and this factor is set to `1.5` then the result waiting time is 15 seconds.
-  The timeout factor must be configured as system property because of the test limitations.
 `lra.http.recovery.host`, `lra.http.recovery.port`, `lra.http.recovery.path`::
   Hostname, port and path for the recovery endpoint that will be contacted in tests checking recovery capabilities.
 
diff --git a/tck/src/main/java/org/eclipse/microprofile/lra/tck/LraTckConfigBean.java b/tck/src/main/java/org/eclipse/microprofile/lra/tck/LraTckConfigBean.java
index 90a2e83..6c58166 100644
--- a/tck/src/main/java/org/eclipse/microprofile/lra/tck/LraTckConfigBean.java
+++ b/tck/src/main/java/org/eclipse/microprofile/lra/tck/LraTckConfigBean.java
@@ -20,11 +20,11 @@
 
 package org.eclipse.microprofile.lra.tck;
 
-import org.eclipse.microprofile.config.inject.ConfigProperty;
-
 import javax.enterprise.context.ApplicationScoped;
 import javax.inject.Inject;
 
+import org.eclipse.microprofile.config.inject.ConfigProperty;
+
 @ApplicationScoped
 public class LraTckConfigBean {
 
@@ -32,19 +32,7 @@ public class LraTckConfigBean {
      * Definition of LRA default timeout which should be used
      * by any method which needs to work with timeout
      */
-    private static final Long LRA_TIMEOUT_MILLIS = 50000L;
-
-    /**
-     * Name of the config property that is used as factor adjusting timeout values
-     * used in the testsuite.
-     */
-    public static final String LRA_TCK_TIMEOUT_FACTOR_PROPETY_NAME = "lra.tck.timeout.factor";
-
-    /**
-     * Name of the config property which is used to configure the TCK base url.
-     * See {@link LraTckConfigBean#tckSuiteBaseUrl}.
-     */
-    public static final String LRA_TCK_BASE_URL_PROPERTY_NAME = "lra.tck.base.url";
+    public static final Long LRA_TIMEOUT_MILLIS = 50000L;
 
     /**
      * <p>
@@ -57,7 +45,7 @@ public class LraTckConfigBean {
      * If you wish the test waits shorter time than designed
      * or the timeout is elapsed faster then set the value less than <code>1.0</code>
      */
-    @Inject @ConfigProperty(name = LRA_TCK_TIMEOUT_FACTOR_PROPETY_NAME, defaultValue = "1.0")
+    @Inject @ConfigProperty(name = "lra.tck.timeout.factor", defaultValue = "1.0")
     private double timeoutFactor;
 
     /**
@@ -66,35 +54,12 @@ public class LraTckConfigBean {
      * <p>
      * The default base URL where TCK suite is expected to be started is <code>http://localhost:8180/</code>.
      */
-    @Inject @ConfigProperty(name = LRA_TCK_BASE_URL_PROPERTY_NAME, defaultValue = "http://localhost:8180/")
+    @Inject @ConfigProperty(name = "lra.tck.base.url", defaultValue = "http://localhost:8180/")
     private String tckSuiteBaseUrl;
 
-    /**
-     * Adjusting the default timeout by the specified timeout factor which can be defined by user
-     * when property {@code #LRA_TCK_TIMEOUT_FACTOR_PROPETY_NAME} is defined.
-     *
-     * @return default timeout adjusted with timeout factor
-     */
-    public long getDefaultTimeout() {
-        return adjustTimeout(LraTckConfigBean.LRA_TIMEOUT_MILLIS);
-    }
-
-    /**
-     * Adjusting the provided value by timeout factor defined for the TCK suite.
-     *
-     * @param timeout timeout value to be adjusted by {@code #LRA_TCK_TIMEOUT_FACTOR_PROPETY_NAME}
-     * @return value of adjusted timeout
-     */
-    public long adjustTimeout(long timeout) {
-        return adjustTimeout(timeout, timeoutFactor);
-    }
 
-    private long adjustTimeout(long timeout, double timeoutFactor) {
-        if (timeout < 0 || timeoutFactor < 0)  {
-            throw new IllegalArgumentException(String.format(
-                    "Provided arguments (timeout=%d, timeoutFactor=%.2f) have to be positive", timeout, timeoutFactor));
-        }
-        return (long) Math.ceil(timeout * timeoutFactor);
+    public double timeoutFactor() {
+        return timeoutFactor;
     }
 
 }
diff --git a/tck/src/main/java/org/eclipse/microprofile/lra/tck/participant/api/LraCancelOnResource.java b/tck/src/main/java/org/eclipse/microprofile/lra/tck/participant/api/LraCancelOnResource.java
index d1d5b7f..4942e5f 100644
--- a/tck/src/main/java/org/eclipse/microprofile/lra/tck/participant/api/LraCancelOnResource.java
+++ b/tck/src/main/java/org/eclipse/microprofile/lra/tck/participant/api/LraCancelOnResource.java
@@ -143,7 +143,6 @@ public class LraCancelOnResource {
      * will be called only once for the test invocation.
      * </p>
      * @param lraId The LRA id generated for this action
-     * @param uriInfo as context provided by JAX-RS to find base service URI
      * @return JAX-RS response
      */
     @GET
diff --git a/tck/src/main/java/org/eclipse/microprofile/lra/tck/participant/api/LraResource.java b/tck/src/main/java/org/eclipse/microprofile/lra/tck/participant/api/LraResource.java
index dde3849..9e0cda5 100644
--- a/tck/src/main/java/org/eclipse/microprofile/lra/tck/participant/api/LraResource.java
+++ b/tck/src/main/java/org/eclipse/microprofile/lra/tck/participant/api/LraResource.java
@@ -21,7 +21,6 @@ package org.eclipse.microprofile.lra.tck.participant.api;
 
 import org.eclipse.microprofile.lra.annotation.Forget;
 import org.eclipse.microprofile.lra.tck.LRAClientOps;
-import org.eclipse.microprofile.lra.tck.LraTckConfigBean;
 import org.eclipse.microprofile.lra.tck.participant.activity.Activity;
 import org.eclipse.microprofile.lra.tck.participant.activity.ActivityStorage;
 import org.eclipse.microprofile.lra.annotation.ws.rs.LRA;
@@ -89,9 +88,6 @@ public class LraResource {
     @Inject
     private LRAMetricService lraMetricService;
 
-    @Inject
-    private LraTckConfigBean configBean;
-
     @Inject
     LRATestService lraTestService;
     /**
@@ -419,15 +415,14 @@ public class LraResource {
     @GET
     @Path(TIME_LIMIT)
     @Produces(MediaType.APPLICATION_JSON)
-    @LRA(value = LRA.Type.REQUIRED, timeLimit = 500, timeUnit = ChronoUnit.MILLIS)
+    @LRA(value = LRA.Type.REQUIRED, timeLimit = 100, timeUnit = ChronoUnit.MILLIS)
     public Response timeLimit(@HeaderParam(LRA_HTTP_CONTEXT_HEADER) URI lraId) {
         assertHeaderPresent(lraId, LRA_HTTP_CONTEXT_HEADER);
 
         activityStore.add(new Activity(lraId));
 
         try {
-            // sleep longer time than specified in the attribute 'timeLimit'
-            Thread.sleep(configBean.adjustTimeout(1000));
+            Thread.sleep(300); // sleep for longer than specified in the timeLimit annotation attribute
         } catch (InterruptedException e) {
             LOGGER.log(Level.FINE, "Interrupted because time limit elapsed", e);
         }
@@ -447,7 +442,7 @@ public class LraResource {
         activityStore.add(new Activity(lraId));
 
         try {
-            Thread.sleep(configBean.adjustTimeout(1000)); // sleep for longer than specified in the timeLimit annotation attribute
+            Thread.sleep(1000); // sleep for longer than specified in the timeLimit annotation attribute
             // force the implementation to notice that the LRA should have timed out
             lraTestService.waitForCallbacks(lraId);
             // the next request should fail with a 412 code since the LRA should no longer be active
diff --git a/tck/src/main/java/org/eclipse/microprofile/lra/tck/participant/api/RecoveryResource.java b/tck/src/main/java/org/eclipse/microprofile/lra/tck/participant/api/RecoveryResource.java
index ae56121..c3f2614 100644
--- a/tck/src/main/java/org/eclipse/microprofile/lra/tck/participant/api/RecoveryResource.java
+++ b/tck/src/main/java/org/eclipse/microprofile/lra/tck/participant/api/RecoveryResource.java
@@ -23,16 +23,23 @@ import org.eclipse.microprofile.lra.annotation.AfterLRA;
 import org.eclipse.microprofile.lra.annotation.Compensate;
 import org.eclipse.microprofile.lra.annotation.LRAStatus;
 import org.eclipse.microprofile.lra.annotation.ws.rs.LRA;
+import org.eclipse.microprofile.lra.tck.TckRecoveryTests;
 import org.eclipse.microprofile.lra.tck.service.LRAMetricService;
 import org.eclipse.microprofile.lra.tck.service.LRAMetricType;
+import org.eclipse.microprofile.lra.tck.service.LRATestService;
 
 import javax.enterprise.context.ApplicationScoped;
 import javax.inject.Inject;
+import javax.ws.rs.DefaultValue;
+import javax.ws.rs.GET;
 import javax.ws.rs.HeaderParam;
 import javax.ws.rs.PUT;
 import javax.ws.rs.Path;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.client.Entity;
 import javax.ws.rs.core.Response;
 import java.net.URI;
+import java.net.URL;
 import java.time.temporal.ChronoUnit;
 
 import static org.eclipse.microprofile.lra.annotation.ws.rs.LRA.LRA_HTTP_CONTEXT_HEADER;
@@ -42,13 +49,93 @@ import static org.eclipse.microprofile.lra.annotation.ws.rs.LRA.LRA_HTTP_CONTEXT
 public class RecoveryResource {
 
     public static final String RECOVERY_RESOURCE_PATH = "recovery-resource";
-    public static final String REQUIRED_PATH = "required";
-    public static final String REQUIRED_TIMEOUT_PATH = "required-timeout";
+    public static final String PHASE_1 = "phase-1";
+    public static final String PHASE_2 = "phase-2";
+    public static final String LRA_HEADER = "LRA";
+    public static final String TRIGGER_RECOVERY = "triggerRecovery";
     public static final long LRA_TIMEOUT = 500;
+    private static final String REQUIRED_PATH = "required";
+    private static final String REQUIRED_TIMEOUT_PATH = "required-timeout";
 
     @Inject
     LRAMetricService lraMetricService;
 
+    @Inject
+    LRATestService lraTestService;
+
+    /**
+     * Starts a new LRA and enlists an instance of this class with it as a participant
+     *
+     * @param timeout whether or not the LRA should time out after 500 milliseconds
+     * @return response containing the LRA id of the newly started LRA
+     */
+    @GET
+    @Path(PHASE_1)
+    public Response phase1(@QueryParam("timeout") @DefaultValue("false") boolean timeout,
+                           @HeaderParam(TckRecoveryTests.LRA_TCK_DEPLOYMENT_URL) URL deploymentURL) {
+        
+        lraTestService.start(deploymentURL);
+        
+        // start a new LRA and join it with this resource
+        URI lra;
+        Response response;
+        
+
+        response = lraTestService.getTCKSuiteTarget().path(RecoveryResource.RECOVERY_RESOURCE_PATH)
+                .path(timeout ? RecoveryResource.REQUIRED_TIMEOUT_PATH : RecoveryResource.REQUIRED_PATH)
+                .request().put(Entity.text(""));
+
+        lra = URI.create(response.readEntity(String.class));
+
+        Response.ResponseBuilder responseBuilder = Response.ok(lra);
+        
+        return responseBuilder.build();
+    }
+
+    /**
+     * Cancels the supplied LRA and verifies that all required actions have been performed
+     * 
+     * @param lraId lra id of the LRA to be cancelled
+     * @return a {@link Response} object containing the optional error message 
+     */
+    @GET
+    @Path(PHASE_2)
+    public Response phase2(@HeaderParam(LRA_HEADER) URI lraId,
+                           @HeaderParam(TckRecoveryTests.LRA_TCK_DEPLOYMENT_URL) URL deploymentURL) {
+        lraTestService.start(deploymentURL);
+        lraTestService.getLRAClient().cancelLRA(lraId);
+        lraTestService.waitForCallbacks(lraId);
+
+        // assert compensate has been called
+        int compensations = lraMetricService.getMetric(LRAMetricType.Compensated, lraId, RecoveryResource.class.getName());
+        if (compensations < 1) {
+            return assertFailedResponse("Compensate on restarted service should have been called. Was " + compensations);
+        }
+
+        // assert after LRA has been called
+        int afterLRACalls = lraMetricService.getMetric(LRAMetricType.Cancelled, lraId, RecoveryResource.class.getName());
+        if (afterLRACalls < 1) {
+            return assertFailedResponse("After LRA with Cancelled status should have been called. Was " + afterLRACalls);
+        }
+
+        return Response.ok().build();
+    }
+
+    private Response assertFailedResponse(String message) {
+        return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(message).build();
+    }
+
+    @GET
+    @Path(TRIGGER_RECOVERY)
+    public Response triggerRecovery(@HeaderParam(LRA_HEADER) URI lraId,
+                                    @HeaderParam(TckRecoveryTests.LRA_TCK_DEPLOYMENT_URL) URL deploymentURL) {
+        lraTestService.start(deploymentURL);
+        lraTestService.waitForRecovery(lraId);
+        return Response.ok().build();
+    } 
+
+    // LRA participant methods
+
     @PUT
     @Path(REQUIRED_PATH)
     @LRA(value = LRA.Type.REQUIRED, end = false)
diff --git a/tck/src/main/java/org/eclipse/microprofile/lra/tck/participant/nonjaxrs/valid/LongBusinessMethodParticipant.java b/tck/src/main/java/org/eclipse/microprofile/lra/tck/participant/nonjaxrs/valid/LongBusinessMethodParticipant.java
new file mode 100644
index 0000000..6b734ec
--- /dev/null
+++ b/tck/src/main/java/org/eclipse/microprofile/lra/tck/participant/nonjaxrs/valid/LongBusinessMethodParticipant.java
@@ -0,0 +1,89 @@
+/*
+ *******************************************************************************
+ * 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.nonjaxrs.valid;
+
+import java.net.URI;
+import java.util.concurrent.CountDownLatch;
+import java.util.logging.Logger;
+
+import javax.enterprise.context.ApplicationScoped;
+import javax.inject.Inject;
+import javax.ws.rs.HeaderParam;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.core.Response;
+
+import org.eclipse.microprofile.lra.annotation.Compensate;
+import org.eclipse.microprofile.lra.annotation.ws.rs.LRA;
+import org.eclipse.microprofile.lra.tck.service.LRAMetricService;
+import org.eclipse.microprofile.lra.tck.service.LRAMetricType;
+
+@ApplicationScoped
+@Path(LongBusinessMethodParticipant.ROOT_PATH)
+public class LongBusinessMethodParticipant {
+
+    public static final String ROOT_PATH = "long-business-participant";
+    public static final String BUSINESS_METHOD = "business-method";
+    public static final String SYNC_METHOD = "sync-method";
+
+    private static final Logger LOGGER = Logger.getLogger(LongBusinessMethodParticipant.class.getName());
+
+    private CountDownLatch businessLatch = new CountDownLatch(1);
+    private CountDownLatch syncLatch = new CountDownLatch(1);
+
+    @Inject
+    private LRAMetricService lraMetricService;
+
+    @Compensate
+    public void compensate(URI lraId) {
+        assert lraId != null;
+        if(businessLatch.getCount() > 0) {
+            businessLatch.countDown();
+        }
+        lraMetricService.incrementMetric(LRAMetricType.Compensated, lraId, LongBusinessMethodParticipant.class.getName());
+    }
+
+    @PUT
+    @Path(BUSINESS_METHOD)
+    @LRA(value = LRA.Type.MANDATORY)
+    public Response enlistWithLongLatency(@HeaderParam(LRA.LRA_HTTP_CONTEXT_HEADER) URI lraId) {
+        LOGGER.info("call of enlistWithLongLatency");
+        try {
+            syncLatch.countDown();
+            // await for compensation
+            businessLatch.await();
+            return Response.ok(lraId).build();
+        } catch (InterruptedException ex) {
+            return Response.serverError().build();
+        }
+    }
+
+    @PUT
+    @Path(SYNC_METHOD)
+    public Response sync() {
+        LOGGER.info("call of sync method");
+        try {
+            syncLatch.await();
+        } catch (Exception e) {
+            throw new IllegalStateException("Expecting the latch will be succesfully released on long latency LRA is in progress");
+        }
+        return Response.ok().build();
+    }
+}
diff --git a/tck/src/main/java/org/eclipse/microprofile/lra/tck/service/LRAMetricRest.java b/tck/src/main/java/org/eclipse/microprofile/lra/tck/service/LRAMetricRest.java
deleted file mode 100644
index 92e65cf..0000000
--- a/tck/src/main/java/org/eclipse/microprofile/lra/tck/service/LRAMetricRest.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- *******************************************************************************
- * 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.service;
-
-import javax.inject.Inject;
-import javax.ws.rs.GET;
-import javax.ws.rs.Path;
-import javax.ws.rs.Produces;
-import javax.ws.rs.QueryParam;
-import javax.ws.rs.core.MediaType;
-import java.net.URI;
-
-/**
- * JAX-RS endpoints for the {@link LRAMetricService}.
- */
-@Path(LRAMetricRest.LRA_TCK_METRIC_RESOURCE_PATH)
-public class LRAMetricRest {
-    public static final String LRA_TCK_METRIC_RESOURCE_PATH = "lra-tck-metric";
-    public static final String METRIC_PATH = "metric";
-
-    public static final String METRIC_TYPE_PARAM = "metricType";
-    public static final String LRA_ID_PARAM = "lraId";
-    public static final String PARTICIPANT_NAME_PARAM = "participantName";
-
-    @Inject
-    private LRAMetricService lraMetricService;
-
-    @Path(METRIC_PATH)
-    @GET
-    @Produces(MediaType.TEXT_PLAIN)
-    public int getMetric(@QueryParam(METRIC_TYPE_PARAM) LRAMetricType metricType, @QueryParam(LRA_ID_PARAM) URI lra,
-                         @QueryParam(PARTICIPANT_NAME_PARAM) String participantName) {
-        if (metricType == null) {
-            throw new NullPointerException("metricType");
-        }
-        if (lra == null) {
-            throw new NullPointerException("lraId");
-        }
-        if (participantName == null) {
-            throw new NullPointerException("participantName");
-        }
-        return lraMetricService.getMetric(metricType, lra, participantName);
-    }
-}


Test patch:
diff --git a/tck/src/main/java/org/eclipse/microprofile/lra/tck/TckParticipantTests.java b/tck/src/main/java/org/eclipse/microprofile/lra/tck/TckParticipantTests.java
index fc35733..1b62ee0 100644
--- a/tck/src/main/java/org/eclipse/microprofile/lra/tck/TckParticipantTests.java
+++ b/tck/src/main/java/org/eclipse/microprofile/lra/tck/TckParticipantTests.java
@@ -19,6 +19,25 @@
  *******************************************************************************/
 package org.eclipse.microprofile.lra.tck;
 
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.net.URI;
+import java.time.temporal.ChronoUnit;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+import java.util.logging.Logger;
+
+import javax.inject.Inject;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.Response;
+
+import org.eclipse.microprofile.lra.annotation.ws.rs.LRA;
+import org.eclipse.microprofile.lra.tck.participant.nonjaxrs.valid.LongBusinessMethodParticipant;
 import org.eclipse.microprofile.lra.tck.participant.nonjaxrs.valid.ValidLRACSParticipant;
 import org.eclipse.microprofile.lra.tck.participant.nonjaxrs.valid.ValidLRAParticipant;
 import org.eclipse.microprofile.lra.tck.service.LRAMetricService;
@@ -27,26 +46,18 @@ import org.eclipse.microprofile.lra.tck.service.LRATestService;
 import org.jboss.arquillian.container.test.api.Deployment;
 import org.jboss.arquillian.junit.Arquillian;
 import org.jboss.shrinkwrap.api.spec.WebArchive;
+import org.junit.Assert;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
-import javax.inject.Inject;
-import javax.ws.rs.WebApplicationException;
-import javax.ws.rs.client.WebTarget;
-import javax.ws.rs.core.Response;
-
-import java.net.URI;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-
 /**
  * TCK to verify that valid non-JAX-RS participant method signatures are respected
  */
 @RunWith(Arquillian.class)
 public class TckParticipantTests extends TckTestBase {
-    
+
     private static final String VALID_DEPLOYMENT = "valid-deploy";
+    private static final Logger LOGGER = Logger.getLogger(TckParticipantTests.class.getName());
 
     @Inject
     private LRAMetricService lraMetricService;
@@ -59,18 +70,18 @@ public class TckParticipantTests extends TckTestBase {
         return TckTestBase.deploy(VALID_DEPLOYMENT)
             .addPackage(ValidLRAParticipant.class.getPackage());
     }
-    
+
     /**
      * Test verifies that non-JAX-RS @Complete method is invoked according to the
      * LRA protocol and that if {@link WebApplicationException} is
-     * thrown inside of a non-JAX-RS participant method than {@link Response} it 
+     * thrown inside of a non-JAX-RS participant method than {@link Response} it
      * is carrying is extracted and acted upon according to LRA response handling
      */
     @Test
     public void validWebApplicationExceptionReturnedTest() {
         WebTarget resourcePath = tckSuiteTarget.path(ValidLRAParticipant.RESOURCE_PATH)
             .path(ValidLRAParticipant.ENLIST_WITH_COMPLETE);
-        
+
         Response response = resourcePath.request().get();
         URI lraId = URI.create(checkStatusReadAndCloseResponse(Response.Status.OK, response, resourcePath));
 
@@ -89,13 +100,13 @@ public class TckParticipantTests extends TckTestBase {
     }
 
     /**
-     * This test verifies chained call of non-JAX-RS participant methods. First 
+     * This test verifies chained call of non-JAX-RS participant methods. First
      * it starts and cancels a new LRA. @Compensate non-JAX-RS method then returns
-     * {@link org.eclipse.microprofile.lra.annotation.ParticipantStatus#Compensating} 
-     * (see {@link ValidLRAParticipant}) indicating that non-JAX-RS @Status method should 
-     * be invoked. The test then waits for recovery and then verifies that @Status method is 
-     * called. This method finishes compensation with return of the {@link Response} object 
-     * indicating failure and so the test then verifies that non-JAX-RS @Forget method has 
+     * {@link org.eclipse.microprofile.lra.annotation.ParticipantStatus#Compensating}
+     * (see {@link ValidLRAParticipant}) indicating that non-JAX-RS @Status method should
+     * be invoked. The test then waits for recovery and then verifies that @Status method is
+     * called. This method finishes compensation with return of the {@link Response} object
+     * indicating failure and so the test then verifies that non-JAX-RS @Forget method has
      * also been called.
      *
      * @throws InterruptedException When Test is interrupted during sleep.
@@ -104,11 +115,11 @@ public class TckParticipantTests extends TckTestBase {
     public void validSignaturesChainTest() throws InterruptedException {
         WebTarget resourcePath = tckSuiteTarget.path(ValidLRAParticipant.RESOURCE_PATH)
             .path(ValidLRAParticipant.ENLIST_WITH_COMPENSATE);
-        
+
         Response response = resourcePath.request().get();
 
         URI lraId = URI.create(checkStatusReadAndCloseResponse(Response.Status.INTERNAL_SERVER_ERROR, response, resourcePath));
-        
+
         assertEquals("Non JAX-RS @Compensate method should have been called",
             1, lraMetricService.getMetric(LRAMetricType.Compensated, lraId));
         assertEquals("@Complete method should not have been called as LRA compensated",
@@ -116,7 +127,7 @@ public class TckParticipantTests extends TckTestBase {
 
         lraTestService.waitForRecovery(lraId);
 
-        assertTrue("Non JAX-RS @Status method should have been called", 
+        assertTrue("Non JAX-RS @Status method should have been called",
             lraMetricService.getMetric(LRAMetricType.Status, lraId) >= 1);
         assertTrue("Non JAX-RS @Forget method should have been called",
             lraMetricService.getMetric(LRAMetricType.Forget, lraId) >= 1);
@@ -124,10 +135,8 @@ public class TckParticipantTests extends TckTestBase {
     }
 
     /**
-     * Test verifies {@link java.util.concurrent.CompletionStage} parametrized with 
+     * Test verifies {@link java.util.concurrent.CompletionStage} parametrized with
      * {@link Void} as valid non-JAX-RS participant method return type
-     *
-     * @throws InterruptedException when waiting for the finishing the completion is interrupted
      */
     @Test
     public void testNonJaxRsCompletionStageVoid() throws InterruptedException {
@@ -147,7 +156,7 @@ public class TckParticipantTests extends TckTestBase {
     }
 
     /**
-     * Test verifyies {@link java.util.concurrent.CompletionStage} parametrized by 
+     * Test verifyies {@link java.util.concurrent.CompletionStage} parametrized by
      * {@link Response} and {@link org.eclipse.microprofile.lra.annotation.ParticipantStatus} as valid
      * non-JAX-RS participant methods return types
      *
@@ -171,7 +180,43 @@ public class TckParticipantTests extends TckTestBase {
 
         assertTrue("Non JAX-RS @Status method with CompletionStage<ParticipantStatus> should have been called",
             lraMetricService.getMetric(LRAMetricType.Status, lraId) >= 1);
-        
+
+        lraTestService.waitForRecovery(lraId);
+    }
+
+    @Test
+    public void cancelLraDuringBusinessMethod() throws InterruptedException, ExecutionException, TimeoutException {
+        LRAClientOps lraOps = lraTestService.getLRAClient();
+        URI lraId = lraOps.startLRA(null, lraClientId(), 0L, ChronoUnit.MILLIS);
+        LOGGER.info(String.format("Started LRA with URI %s", lraId));
+        // Start business method asynchronously, i.e. return immediately.
+        Future<Response> lraFuture = tckSuiteTarget.path(LongBusinessMethodParticipant.ROOT_PATH)
+                .path(LongBusinessMethodParticipant.BUSINESS_METHOD)
+                .request()
+                .header(LRA.LRA_HTTP_CONTEXT_HEADER, lraId)
+                .async()
+                .put(Entity.text(""));
+
+        // Make sure that when we cancel the LRA, the participant is waiting in the business method.
+        Response syncMethodResponse = tckSuiteTarget.path(LongBusinessMethodParticipant.ROOT_PATH)
+                      .path(LongBusinessMethodParticipant.SYNC_METHOD)
+                      .request()
+                      .put(Entity.text(""));
+        Assert.assertEquals(200, syncMethodResponse.getStatus());
+        // -1 indicates that the LRAMetricType.Compensated key is not yet present in the metrics Map.
+        // This in turn means that @Compensate could not have been called yet.
+        Assert.assertEquals(-1, lraMetricService.getMetric(
+                LRAMetricType.Compensated, lraId, LongBusinessMethodParticipant.class.getName()));
+        LOGGER.info(String.format("Cancelled LRA with URI %s", lraId));
+        lraOps.cancelLRA(lraId);
+        // waiting for the LRA to be finished
         lraTestService.waitForRecovery(lraId);
+        // participant has to be compensated
+        Assert.assertTrue("@Compensate method should have been called at least once.",
+                lraMetricService.getMetric(LRAMetricType.Compensated, lraId, LongBusinessMethodParticipant.class.getName()) >= 1);
+
+        Response response = lraFuture.get(lraTimeout(), TimeUnit.MILLISECONDS);
+        Assert.assertEquals(LongBusinessMethodParticipant.class.getSimpleName() + "'s business method is expected " +
+                "to finish successfully despite the delay.", 200, response.getStatus());
     }
 }
diff --git a/tck/src/main/java/org/eclipse/microprofile/lra/tck/TckRecoveryTests.java b/tck/src/main/java/org/eclipse/microprofile/lra/tck/TckRecoveryTests.java
index 5822b5e..f0f43ff 100644
--- a/tck/src/main/java/org/eclipse/microprofile/lra/tck/TckRecoveryTests.java
+++ b/tck/src/main/java/org/eclipse/microprofile/lra/tck/TckRecoveryTests.java
@@ -20,12 +20,11 @@
 package org.eclipse.microprofile.lra.tck;
 
 import org.eclipse.microprofile.lra.tck.participant.api.RecoveryResource;
-import org.eclipse.microprofile.lra.tck.service.LRAMetricRest;
-import org.eclipse.microprofile.lra.tck.service.LRAMetricType;
 import org.eclipse.microprofile.lra.tck.service.LRATestService;
+import org.eclipse.microprofile.lra.tck.service.spi.LRACallbackException;
+import org.eclipse.microprofile.lra.tck.service.spi.LRARecoveryService;
 import org.jboss.arquillian.container.test.api.Deployer;
 import org.jboss.arquillian.container.test.api.Deployment;
-import org.jboss.arquillian.container.test.api.RunAsClient;
 import org.jboss.arquillian.junit.Arquillian;
 import org.jboss.arquillian.test.api.ArquillianResource;
 import org.jboss.shrinkwrap.api.spec.WebArchive;
@@ -39,30 +38,24 @@ import org.junit.runner.RunWith;
 
 import javax.ws.rs.client.Client;
 import javax.ws.rs.client.ClientBuilder;
-import javax.ws.rs.client.Entity;
 import javax.ws.rs.client.WebTarget;
 import javax.ws.rs.core.Response;
 import java.net.URI;
 import java.net.URISyntaxException;
 import java.net.URL;
-import java.util.logging.Level;
 import java.util.logging.Logger;
 
 /**
- * <p>
  * Tests for the recovery of failed LRA services. Test that LRA functions properly even in case of service failures.
- * </p>
- * <p>
- * This test is meant to be run in "run as client mode controlling the behaviour not via CDI injection but via HTTP calls.
- * The @{@link Deployment} is defined as <code>managed = false</code>
- * which means that Arquillian does not automatically deploy the deployment at the start of the test
- * and the test control this step on its own.
- * </p>
+ * 
+ * As this test is not running a managed Arquillian deployment, CDI is not working inside of this class. This is
+ * why the test execution is moved into {@link RecoveryResource} in two phases (see {@link RecoveryResource#PHASE_1} and
+ * {@link RecoveryResource#PHASE_2}) which also verify the results and pass the results in HTTP response.
+ * 
+ * Note that this test relies on Arquillian to supply the deployment URL via the {@link ArquillianResource} injection.
  */
 @RunWith(Arquillian.class)
-@RunAsClient
 public class TckRecoveryTests {
-    private static final Logger LOG = Logger.getLogger(TckRecoveryTests.class.getName());
     
     public static final String LRA_TCK_DEPLOYMENT_URL = "LRA-TCK-Deployment-URL";
 
@@ -75,7 +68,8 @@ public class TckRecoveryTests {
     @ArquillianResource
     private URL deploymentURL;
 
-    private LRATestService lraTestService;
+    private LRARecoveryService lraRecoveryService;
+    
     private Client deploymentClient;
     private WebTarget deploymentTarget;
 
@@ -88,20 +82,12 @@ public class TckRecoveryTests {
         
         deploymentClient = ClientBuilder.newClient();
         deploymentTarget = deploymentClient.target(deploymentURL.toURI());
-        lraTestService = new LRATestService();
-        lraTestService.start(deploymentURL);
+        lraRecoveryService = LRATestService.loadService(LRARecoveryService.class);
     }
     
     @After
     public void after() {
-        try {
-            deployer.undeploy(DEPLOYMENT_NAME);
-        } catch (Exception e) {
-            LOG.log(Level.WARNING, "Cannot undeploy the deployment " + DEPLOYMENT_NAME +
-                    " at the end of the test " + testName, e);
-        }
         deploymentClient.close();
-        lraTestService.stop();
     }
 
     @Deployment(name = DEPLOYMENT_NAME, managed = false)
@@ -125,15 +111,17 @@ public class TckRecoveryTests {
     public void testCancelWhenParticipantIsRestarted() {
         // deploy the test service
         deployer.deploy(DEPLOYMENT_NAME);
-
-        // starting and enlisting to LRA
-        Response response = deploymentTarget
-                .path(RecoveryResource.RECOVERY_RESOURCE_PATH)
-                .path(RecoveryResource.REQUIRED_PATH)
-                .request().put(Entity.text(""));
-
-        Assert.assertEquals(200, response.getStatus());
-        URI lra = URI.create(response.readEntity(String.class));
+        
+        // invoke phase 1 inside the container (start new LRA and enlist resource)
+        Response response1 = deploymentTarget
+            .path(RecoveryResource.RECOVERY_RESOURCE_PATH)
+            .path(RecoveryResource.PHASE_1)
+            .request()
+            .header(LRA_TCK_DEPLOYMENT_URL, deploymentURL.toExternalForm())
+            .get();
+        
+        Assert.assertEquals(200, response1.getStatus());
+        URI lra = URI.create(response1.readEntity(String.class));
 
         // kill the test service while LRA is still active
         deployer.undeploy(DEPLOYMENT_NAME);
@@ -141,13 +129,18 @@ public class TckRecoveryTests {
         // start the test service again
         deployer.deploy(DEPLOYMENT_NAME);
 
-        // Cancel the LRA and verify that the @Compensate method was called on the enlisted resource
-        lraTestService.getLRAClient().cancelLRA(lra);
-        lraTestService.waitForCallbacks(lra);
-
-        assertMetricCallbackCalled(LRAMetricType.Compensated, lra);
-        assertMetricCallbackCalled(LRAMetricType.Cancelled, lra);
-
+        // invoke phase 2 inside the container (cancel the LRA and verify that the
+        // @Compensate method was called on the enlisted resource)
+        Response response2 = deploymentTarget.path(RecoveryResource.RECOVERY_RESOURCE_PATH)
+            .path(RecoveryResource.PHASE_2)
+            .request()
+                .header(RecoveryResource.LRA_HEADER, lra)
+                .header(LRA_TCK_DEPLOYMENT_URL, deploymentURL.toExternalForm())
+                .get();
+        
+        Assert.assertEquals(response2.readEntity(String.class), 200, response2.getStatus());
+        
+        deployer.undeploy(DEPLOYMENT_NAME);
     }
 
     /**
@@ -170,14 +163,16 @@ public class TckRecoveryTests {
         // deploy the test service
         deployer.deploy(DEPLOYMENT_NAME);
 
-        // starting and enlisting to LRA
-        Response response = deploymentTarget
-                .path(RecoveryResource.RECOVERY_RESOURCE_PATH)
-                .path(RecoveryResource.REQUIRED_TIMEOUT_PATH)
-                .request().put(Entity.text(""));
+        // invoke phase 1 inside the container (start new LRA and enlist resource) which cancels after 500 millis
+        Response response1 = deploymentTarget.path(RecoveryResource.RECOVERY_RESOURCE_PATH)
+            .path(RecoveryResource.PHASE_1)
+            .queryParam("timeout", true)
+            .request()
+            .header(LRA_TCK_DEPLOYMENT_URL, deploymentURL.toExternalForm())
+            .get();
 
-        Assert.assertEquals(200, response.getStatus());
-        URI lra = URI.create(response.readEntity(String.class));
+        Assert.assertEquals(200, response1.getStatus());
+        URI lra = URI.create(response1.readEntity(String.class));
 
         // kill the test service while LRA is still active
         deployer.undeploy(DEPLOYMENT_NAME);
@@ -186,48 +181,39 @@ public class TckRecoveryTests {
         // Then wait for the short delay to actually perform the cancellation while the service is still down.
         // Compensate should be attempted to be called while the participant service is down
         try {
-            Thread.sleep(adjustTimeoutByDefaultFactor(RecoveryResource.LRA_TIMEOUT));
+            Thread.sleep(RecoveryResource.LRA_TIMEOUT);
         } catch (InterruptedException e) {
-            LOG.log(Level.SEVERE, "Sleep LRA timeout interrupted", e);
-            Assert.fail("Sleeping LRA timeout " + RecoveryResource.LRA_TIMEOUT + " was interrupted: " + e.getMessage());
+            Assert.fail(e.getMessage());
         }
+        
         // wait for the Compensate call to be delivered
-        lraTestService.waitForCallbacks(lra);
+        try {
+            lraRecoveryService.waitForCallbacks(lra);
+        } catch (LRACallbackException e) {
+            Assert.fail(e.getMessage());
+        }
 
         // start the test service again
         deployer.deploy(DEPLOYMENT_NAME);
         
         // trigger recovery causing the Compensate call to be replayed
-        lraTestService.waitForRecovery(lra);
-
-        // execute checks that verify that callbacks have been called
-        lraTestService.waitForCallbacks(lra);
-
-        assertMetricCallbackCalled(LRAMetricType.Compensated, lra);
-        assertMetricCallbackCalled(LRAMetricType.Cancelled, lra);
-    }
+        deploymentTarget.path(RecoveryResource.RECOVERY_RESOURCE_PATH)
+            .path(RecoveryResource.TRIGGER_RECOVERY)
+            .request()
+                .header(RecoveryResource.LRA_HEADER, lra)
+                .header(LRA_TCK_DEPLOYMENT_URL, deploymentURL.toExternalForm())
+                .get();
+
+        // invoke phase 2 inside the container (execute checks that verify that callbacks have been called)
+        Response response2 = deploymentTarget.path(RecoveryResource.RECOVERY_RESOURCE_PATH)
+            .path(RecoveryResource.PHASE_2)
+            .request()
+                .header(RecoveryResource.LRA_HEADER, lra)
+                .header(LRA_TCK_DEPLOYMENT_URL, deploymentURL.toExternalForm())
+                .get();
+
+        Assert.assertEquals(response2.readEntity(String.class), 200, response2.getStatus());
 
-    private void assertMetricCallbackCalled(LRAMetricType metricType, URI lra) {
-        Response responseMetric = deploymentTarget
-                .path(LRAMetricRest.LRA_TCK_METRIC_RESOURCE_PATH)
-                .path(LRAMetricRest.METRIC_PATH)
-                .queryParam(LRAMetricRest.METRIC_TYPE_PARAM, metricType)
-                .queryParam(LRAMetricRest.LRA_ID_PARAM, lra)
-                .queryParam(LRAMetricRest.PARTICIPANT_NAME_PARAM, RecoveryResource.class.getName())
-                .request().get();
-        Assert.assertEquals("Expect the metric REST call to " + responseMetric.getLocation()
-                + " to succeed", 200, responseMetric.getStatus());
-        int metricNumber = responseMetric.readEntity(Integer.class);
-        Assert.assertTrue("Expecting the metric " + metricType + " callback was called",
-                metricNumber >= 1);
-    }
-
-    /**
-     * A helper method which is capable to adjust timeout value
-     * by factor obtained from system property {@code LraTckConfigBean#LRA_TCK_TIMEOUT_FACTOR_PROPETY_NAME}.
-     */
-    private long adjustTimeoutByDefaultFactor(long timeout) {
-        String timeoutFactor = System.getProperty(LraTckConfigBean.LRA_TCK_TIMEOUT_FACTOR_PROPETY_NAME, "1.0");
-        return (long) Math.ceil(timeout * Double.parseDouble(timeoutFactor));
+        deployer.undeploy(DEPLOYMENT_NAME);
     }
 }
diff --git a/tck/src/main/java/org/eclipse/microprofile/lra/tck/TckTestBase.java b/tck/src/main/java/org/eclipse/microprofile/lra/tck/TckTestBase.java
index 78d3739..b3da654 100644
--- a/tck/src/main/java/org/eclipse/microprofile/lra/tck/TckTestBase.java
+++ b/tck/src/main/java/org/eclipse/microprofile/lra/tck/TckTestBase.java
@@ -42,10 +42,6 @@ import java.util.logging.Logger;
 
 import static org.junit.Assert.assertEquals;
 
-/**
- * Base testsuite class for in-container tests.
- * It provides {@link Before} and @{@link After} junit hooks to clean the environment.
- */
 public class TckTestBase {
     private static final Logger LOGGER = Logger.getLogger(TckTestBase.class.getName());
 
@@ -77,22 +73,22 @@ public class TckTestBase {
                 LRARecoveryService.class.getPackage())
             .addAsManifestResource(EmptyAsset.INSTANCE, "beans.xml");
     }
+    
+    @After
+    public void after() {
+        lraTestService.stop();
+    }
 
     @Before
     public void before() {
         LOGGER.info("Running test: " + testName.getMethodName());
-
+        
         lraTestService.start(deploymentURL);
         lraMetricService.clear();
         this.lraClient = lraTestService.getLRAClient();
         this.tckSuiteTarget = lraTestService.getTCKSuiteTarget();
     }
 
-    @After
-    public void after() {
-        lraTestService.stop();
-    }
-
     void checkStatusAndCloseResponse(Response.Status expectedStatus, Response response, WebTarget resourcePath) {
         try {
             assertEquals("Not expected status at call '" + resourcePath.getUri() + "'",
@@ -120,9 +116,13 @@ public class TckTestBase {
     }
 
     /**
-     * Returning default timeout configured for the TCK tests.
+     * Adjusting the default timeout by the specified timeout factor
+     * which can be defined by user.
      */
     long lraTimeout() {
-        return config.getDefaultTimeout();
+        if(LraTckConfigBean.LRA_TIMEOUT_MILLIS < 0){
+            throw new IllegalArgumentException("value of timeout can't be negative");
+        }
+        return (long) Math.ceil(LraTckConfigBean.LRA_TIMEOUT_MILLIS * config.timeoutFactor());
     }
 }
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 6dbda37..f49cdda 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
@@ -22,8 +22,8 @@ package org.eclipse.microprofile.lra.tck;
 import static org.eclipse.microprofile.lra.annotation.ws.rs.LRA.LRA_HTTP_CONTEXT_HEADER;
 import static org.eclipse.microprofile.lra.tck.participant.api.AfterLRAListener.AFTER_LRA_LISTENER_WORK;
 import static org.eclipse.microprofile.lra.tck.participant.api.LraResource.ACCEPT_WORK;
-import static org.eclipse.microprofile.lra.tck.participant.api.LraResource.LRA_RESOURCE_PATH;
 import static org.eclipse.microprofile.lra.tck.participant.api.LraResource.CANCEL_PATH;
+import static org.eclipse.microprofile.lra.tck.participant.api.LraResource.LRA_RESOURCE_PATH;
 import static org.eclipse.microprofile.lra.tck.participant.api.LraResource.TIME_LIMIT;
 import static org.eclipse.microprofile.lra.tck.participant.api.LraResource.TIME_LIMIT_HALF_SEC;
 import static org.eclipse.microprofile.lra.tck.participant.api.LraResource.TRANSACTIONAL_WORK_PATH;
@@ -64,6 +64,7 @@ import org.eclipse.microprofile.lra.tck.service.LRATestService;
 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.Test;
 import org.junit.runner.RunWith;
 
@@ -85,6 +86,11 @@ public class TckTests extends TckTestBase {
         return TckTestBase.deploy(TckTests.class.getSimpleName().toLowerCase());
     }
 
+    @Before
+    public void before() {
+        super.before();
+    }
+
     /**
      * <p>
      * Starting LRA and cancelling it.
@@ -219,8 +225,6 @@ public class TckTests extends TckTestBase {
     /**
      * TCK test to verify that methods annotated with {@link AfterLRA}
      * are notified correctly when an LRA terminates
-     *
-     * @throws InterruptedException when waiting for the finishing the callbacks is interrupted
      */
     @Test
     public void testAfterLRAParticipant() throws WebApplicationException, InterruptedException {
@@ -318,7 +322,8 @@ public class TckTests extends TckTestBase {
                 .request()
                 .get();
 
-        URI lraId = URI.create(checkStatusReadAndCloseResponse(Response.Status.OK, response, resourcePath));
+        URI lraId = URI.create(response.readEntity(String.class));
+        response.close();
 
         // Note that the timeout firing will cause the implementation to compensate
         // the LRA so it may no longer exist
diff --git a/tck/src/main/java/org/eclipse/microprofile/lra/tck/service/LRATestService.java b/tck/src/main/java/org/eclipse/microprofile/lra/tck/service/LRATestService.java
index fb28f97..9e5b6ea 100644
--- a/tck/src/main/java/org/eclipse/microprofile/lra/tck/service/LRATestService.java
+++ b/tck/src/main/java/org/eclipse/microprofile/lra/tck/service/LRATestService.java
@@ -20,11 +20,13 @@
 package org.eclipse.microprofile.lra.tck.service;
 
 import org.eclipse.microprofile.lra.tck.LRAClientOps;
+import org.eclipse.microprofile.lra.tck.LraTckConfigBean;
 import org.eclipse.microprofile.lra.tck.service.spi.LRACallbackException;
 import org.eclipse.microprofile.lra.tck.service.spi.LRARecoveryService;
 import org.junit.Assert;
 
 import javax.enterprise.context.ApplicationScoped;
+import javax.inject.Inject;
 import javax.ws.rs.client.Client;
 import javax.ws.rs.client.ClientBuilder;
 import javax.ws.rs.client.WebTarget;
@@ -32,12 +34,12 @@ import java.net.URI;
 import java.net.URL;
 import java.util.Iterator;
 import java.util.ServiceLoader;
-import java.util.logging.Level;
-import java.util.logging.Logger;
 
 @ApplicationScoped
 public class LRATestService {
-    private static final Logger LOG = Logger.getLogger(LRATestService.class.getName());
+
+    @Inject
+    LraTckConfigBean config;
 
     private LRAClientOps lraClient;
 
@@ -71,7 +73,6 @@ public class LRATestService {
         try {
             lraRecoveryService.waitForCallbacks(lraId);
         } catch (LRACallbackException e) {
-            LOG.log(Level.SEVERE, "Fail to 'waitForCallbacks' for LRA " + lraId, e);
             Assert.fail(e.getMessage());
         }
     }
@@ -80,7 +81,6 @@ public class LRATestService {
         try {
             lraRecoveryService.waitForRecovery(lraId);
         } catch (LRACallbackException e) {
-            LOG.log(Level.SEVERE, "Fail to 'waitForRecovery' for LRA " + lraId, e);
             Assert.fail(e.getMessage());
         }
     }
@@ -89,7 +89,6 @@ public class LRATestService {
         try {
             lraRecoveryService.waitForEndPhaseReplay(lraId);
         } catch (LRACallbackException e) {
-            LOG.log(Level.SEVERE, "Fail to 'waitForEndPhaseReplay' for LRA " + lraId, e);
             Assert.fail(e.getMessage());
         }
     }