Repository: eclipse/microprofile-lra
Pull request #108 (2019-03-06 07:20:47)

issue105 LRAid should be URI instead of URL
issue #105

Signed-off-by: xstefank <xstefank122@gmail.com>


Patch:
diff --git a/api/src/main/java/org/eclipse/microprofile/lra/client/GenericLRAException.java b/api/src/main/java/org/eclipse/microprofile/lra/client/GenericLRAException.java
index 59e9883..91eca6f 100644
--- a/api/src/main/java/org/eclipse/microprofile/lra/client/GenericLRAException.java
+++ b/api/src/main/java/org/eclipse/microprofile/lra/client/GenericLRAException.java
@@ -21,23 +21,23 @@
 package org.eclipse.microprofile.lra.client;
 
 import javax.ws.rs.WebApplicationException;
-import java.net.URL;
+import java.net.URI;
 
 public class GenericLRAException extends WebApplicationException {
     private static final long serialVersionUID = 1L;
 
-    private URL lraId;
+    private URI lraId;
     private int statusCode;
 
     public int getStatusCode() {
         return statusCode;
     }
 
-    public URL getLraId() {
+    public URI getLraId() {
         return lraId;
     }
 
-    public GenericLRAException(URL lraId, int statusCode, String message,
+    public GenericLRAException(URI lraId, int statusCode, String message,
                                Throwable cause) {
         super(String.format("%s: %s", lraId, message), cause);
 
diff --git a/api/src/main/java/org/eclipse/microprofile/lra/client/LRAClient.java b/api/src/main/java/org/eclipse/microprofile/lra/client/LRAClient.java
index e0f6109..2152ea1 100644
--- a/api/src/main/java/org/eclipse/microprofile/lra/client/LRAClient.java
+++ b/api/src/main/java/org/eclipse/microprofile/lra/client/LRAClient.java
@@ -25,7 +25,6 @@ import org.eclipse.microprofile.lra.annotation.Compensate;
 
 import javax.ws.rs.NotFoundException;
 import java.net.URI;
-import java.net.URL;
 import java.time.temporal.ChronoUnit;
 
 public interface LRAClient {
@@ -36,9 +35,9 @@ public interface LRAClient {
     String LRA_HTTP_HEADER = "Long-Running-Action";
 
     /**
-     * the name of the HTTP header field that contains a recovery URL corresponding
+     * the name of the HTTP header field that contains a recovery URI corresponding
      * to a participant
-     * enlistment in an LRA {@link LRAClient#joinLRA(URL, Class, URI, String)}
+     * enlistment in an LRA {@link LRAClient#joinLRA(URI, Class, URI, String)}
      */
     String LRA_HTTP_RECOVERY_HEADER = "Long-Running-Action-Recovery";
 
@@ -106,12 +105,12 @@ public interface LRAClient {
      *
      * @return the identifier of the new LRA
      */
-    URL startLRA(URL parentLRA, String clientID, Long timeout, ChronoUnit unit)
+    URI startLRA(URI parentLRA, String clientID, Long timeout, ChronoUnit unit)
             throws GenericLRAException;
 
     /**
      * Start a top level LRA (ie similar to
-     * {@link LRAClient#startLRA(URL, String, Long, ChronoUnit)}
+     * {@link LRAClient#startLRA(URI, String, Long, ChronoUnit)}
      *
      * @param clientID The client may provide a (preferably) unique identity which
      *                will be reported back when the LRA is queried.
@@ -126,7 +125,7 @@ public interface LRAClient {
      *
      * @return the identifier of the new LRA
      */
-    URL startLRA(String clientID, Long timeout, ChronoUnit unit)
+    URI startLRA(String clientID, Long timeout, ChronoUnit unit)
             throws GenericLRAException;
 
     /**
@@ -147,7 +146,7 @@ public interface LRAClient {
      *         If the final status is not returned the
      *         client can only discover the final state using proprietary APIs
      */
-    String cancelLRA(URL lraId) throws GenericLRAException;
+    String cancelLRA(URI lraId) throws GenericLRAException;
 
     /**
      * Attempt to close an LRA
@@ -167,7 +166,7 @@ public interface LRAClient {
      *         If the final status is not returned the
      *         client can only discover the final state using proprietary APIs
      */
-    String closeLRA(URL lraId) throws GenericLRAException;
+    String closeLRA(URI lraId) throws GenericLRAException;
 
     /**
      * Join an LRA passing in a class that will act as the participant.
@@ -180,7 +179,7 @@ public interface LRAClient {
      *                       pass to the participant when the LRA is closed or
      *                       cancelled
      *
-     * @return a recovery URL for this enlistment
+     * @return a recovery URI for this enlistment
      *
      * @throws NotFoundException if the LRA no longer exists
      *
@@ -188,20 +187,20 @@ public interface LRAClient {
      * {@link GenericLRAException#getCause()} and/or
      * {@link GenericLRAException#getStatusCode()} may provide a more specific reason.
      */
-    URL joinLRA(URL lraId, Class<?> resourceClass, URI baseUri, String compensatorData)
+    URI joinLRA(URI lraId, Class<?> resourceClass, URI baseUri, String compensatorData)
             throws GenericLRAException;
 
     /**
      * Change the endpoints that a participant can be contacted on.
      *
-     * @param recoveryUrl the recovery URL returned from a participant join request
+     * @param recoveryUri the recovery URI returned from a participant join request
      * @param resourceClass An annotated class for the participant methods:
      *      * {@link Compensate}, etc.
      * @param baseUri Base uri for the participant endpoints
      * @param compensatorData opaque data that returned to the participant when the
      *                       LRA is closed or cancelled
      *
-     * @return an updated recovery URL for this participant
+     * @return an updated recovery URI for this participant
      *
      * @throws NotFoundException if the LRA no longer exists
      *
@@ -209,14 +208,14 @@ public interface LRAClient {
      * {@link GenericLRAException#getCause()} and/or
      * {@link GenericLRAException#getStatusCode()} may provide a more specific reason.
      */
-    URL updateCompensator(URL recoveryUrl, Class<?> resourceClass, URI baseUri, String compensatorData)
+    URI updateCompensator(URI recoveryUri, Class<?> resourceClass, URI baseUri, String compensatorData)
             throws GenericLRAException;
 
     /**
      * A Compensator can resign from the LRA at any time prior to the completion
      * of an activity
      *
-     * @param recoveryUrl the recovery URL returned from a participant join request
+     * @param recoveryUri the recovery URI returned from a participant join request
      *
      * @throws NotFoundException if the LRA no longer exists
      *
@@ -224,7 +223,7 @@ public interface LRAClient {
      * {@link GenericLRAException#getCause()} and/or
      * {@link GenericLRAException#getStatusCode()} may provide a more specific reason.
      */
-    void leaveLRA(URL recoveryUrl) throws GenericLRAException;
+    void leaveLRA(URI recoveryUri) throws GenericLRAException;
 
     /**
      * LRAs can be created with timeouts after which they are cancelled. Use this
@@ -236,7 +235,7 @@ public interface LRAClient {
      * @param limit the new timeout period
      * @param unit the time unit for limit
      */
-    void renewTimeLimit(URL lraId, long limit, ChronoUnit unit);
+    void renewTimeLimit(URI lraId, long limit, ChronoUnit unit);
 
     /**
      * checks whether there is an LRA associated with the calling thread
@@ -247,7 +246,7 @@ public interface LRAClient {
      *
      * @return the current LRA (can be null)
      */
-    URL getCurrent();
+    URI getCurrent();
 
     /**
      * Lookup the status of an LRA
@@ -265,5 +264,5 @@ public interface LRAClient {
      * {@link GenericLRAException#getStatusCode()}
      * may provide a more specific reason.
      */
-    LRAStatus getStatus(URL lraId) throws GenericLRAException;
+    LRAStatus getStatus(URI lraId) throws GenericLRAException;
 }
diff --git a/api/src/main/java/org/eclipse/microprofile/lra/client/UnknowableException.java b/api/src/main/java/org/eclipse/microprofile/lra/client/UnknowableException.java
index 600adcf..6673135 100644
--- a/api/src/main/java/org/eclipse/microprofile/lra/client/UnknowableException.java
+++ b/api/src/main/java/org/eclipse/microprofile/lra/client/UnknowableException.java
@@ -19,13 +19,13 @@
  *******************************************************************************/
 package org.eclipse.microprofile.lra.client;
 
-import java.net.URL;
+import java.net.URI;
 
 /**
  * An exception type to indicate that a requested operation can never be completed.
  */
 public class UnknowableException extends GenericLRAException {
-    public UnknowableException(URL lraId, int statusCode, String message, Throwable cause) {
+    public UnknowableException(URI lraId, int statusCode, String message, Throwable cause) {
         super(lraId, statusCode, message, cause);
     }
 }
diff --git a/api/src/main/java/org/eclipse/microprofile/lra/participant/JoinLRAException.java b/api/src/main/java/org/eclipse/microprofile/lra/participant/JoinLRAException.java
index 24dc591..a59161d 100644
--- a/api/src/main/java/org/eclipse/microprofile/lra/participant/JoinLRAException.java
+++ b/api/src/main/java/org/eclipse/microprofile/lra/participant/JoinLRAException.java
@@ -20,13 +20,13 @@
 
 package org.eclipse.microprofile.lra.participant;
 
-import java.net.URL;
+import java.net.URI;
 
 /**
  * An exception used to report failures during enlistment of a participant in an LRA
  */
 public class JoinLRAException extends Exception {
-    private URL lraId;
+    private URI lraId;
     private int statusCode;
 
     /**
@@ -39,11 +39,11 @@ public class JoinLRAException extends Exception {
     /**
      * @return the LRA that join request related to
      */
-    public URL getLraId() {
+    public URI getLraId() {
         return lraId;
     }
 
-    public JoinLRAException(URL lraId, int statusCode, String message, Throwable cause) {
+    public JoinLRAException(URI lraId, int statusCode, String message, Throwable cause) {
         super(String.format("%s: %s", lraId, message), cause);
 
         this.lraId = lraId;
diff --git a/api/src/main/java/org/eclipse/microprofile/lra/participant/LRAManagement.java b/api/src/main/java/org/eclipse/microprofile/lra/participant/LRAManagement.java
index cf6bc68..f7b03b8 100644
--- a/api/src/main/java/org/eclipse/microprofile/lra/participant/LRAManagement.java
+++ b/api/src/main/java/org/eclipse/microprofile/lra/participant/LRAManagement.java
@@ -21,7 +21,7 @@
 package org.eclipse.microprofile.lra.participant;
 
 import javax.enterprise.context.ApplicationScoped;
-import java.net.URL;
+import java.net.URI;
 import java.time.temporal.ChronoUnit;
 
 @ApplicationScoped
@@ -37,14 +37,14 @@ public interface LRAManagement {
      *             to fulfil the protocol guarantees.
      * @param unit the unit that the timeLimit parameter is expressed in
      *
-     * @return a recovery URL for this enlistment
+     * @return a recovery URI for this enlistment
      *
      * @throws JoinLRAException if the request to the coordinator failed.
      * {@link JoinLRAException#getCause()} and/or
      * {@link JoinLRAException#getStatusCode()} may provide a more specific reason
      */
-    URL joinLRA(LRAParticipant participant, URL lraId, Long timeLimit,
-                   ChronoUnit unit)
+    URI joinLRA(LRAParticipant participant, URI lraId, Long timeLimit,
+                ChronoUnit unit)
             throws JoinLRAException;
 
     /**
@@ -57,12 +57,12 @@ public interface LRAManagement {
      *                   notified when the target LRA ends
      * @param lraId the LRA that the join request pertains to
      *
-     * @return a recovery URL for this enlistment
+     * @return a recovery URI for this enlistment
      *
      * @throws JoinLRAException if the request to the coordinator failed.
      * {@link JoinLRAException#getCause()} and/or
      * {@link JoinLRAException#getStatusCode()} may provide a more specific reason
      */
-    URL joinLRA(LRAParticipant participant, URL lraId) throws JoinLRAException;
+    URI joinLRA(LRAParticipant participant, URI lraId) throws JoinLRAException;
 
 }
diff --git a/api/src/main/java/org/eclipse/microprofile/lra/participant/LRAParticipant.java b/api/src/main/java/org/eclipse/microprofile/lra/participant/LRAParticipant.java
index 7142144..1126593 100644
--- a/api/src/main/java/org/eclipse/microprofile/lra/participant/LRAParticipant.java
+++ b/api/src/main/java/org/eclipse/microprofile/lra/participant/LRAParticipant.java
@@ -22,13 +22,13 @@ package org.eclipse.microprofile.lra.participant;
 
 import javax.ws.rs.NotFoundException;
 import java.io.Serializable;
-import java.net.URL;
+import java.net.URI;
 import java.util.concurrent.Future;
 
 /**
  * The API for notifying participants that a LRA is completing or cancelling.
  * A participant joins with an LRA via a call to
- * {@link LRAManagement#joinLRA(LRAParticipant, URL)}
+ * {@link LRAManagement#joinLRA(LRAParticipant, URI)}
  */
 public interface LRAParticipant extends Serializable {
     /**
@@ -44,7 +44,7 @@ public interface LRAParticipant extends Serializable {
      * @throws TerminationException the participant was unable to complete and will
      *         never be able to do so
      */
-    Future<Void> completeWork(URL lraId)
+    Future<Void> completeWork(URI lraId)
             throws NotFoundException, TerminationException;
 
     /**
@@ -60,7 +60,7 @@ public interface LRAParticipant extends Serializable {
      * @throws TerminationException the participant was unable to complete and
      *         will never be able to do so
      */
-    Future<Void> compensateWork(URL lraId)
+    Future<Void> compensateWork(URI lraId)
             throws NotFoundException, TerminationException;
 }
 
diff --git a/spec/src/main/asciidoc/microprofile-lra-spec.adoc b/spec/src/main/asciidoc/microprofile-lra-spec.adoc
index 66c988b..d05f0da 100644
--- a/spec/src/main/asciidoc/microprofile-lra-spec.adoc
+++ b/spec/src/main/asciidoc/microprofile-lra-spec.adoc
@@ -327,7 +327,7 @@ also contains methods annotated with `@Compensate` and `@Complete` then the bean
 (aka participant or compensator) will be enlisted with the LRA. Enlisting with
 an LRA means that the bean will be notified when the current LRA is
 subsequently cancelled or closed. In addition the implementation should generate a
-URL for this participant that can be used with the <<lra-client-api,Client API>>
+URI for this participant that can be used with the <<lra-client-api,Client API>>
 for recovery purposes and should make it available to the participant via a JAX-RS
 header param with name defined by the Java constant `LRA_HTTP_RECOVERY_HEADER` as defined
 <<source-LRAClient,in the Client API>>
@@ -810,7 +810,7 @@ public class UnannotatedParticpant implements LRAParticipant {
     public void doInTransaction() throws JoinLRAException
     {
         // start a new LRA with an unlimited timeout
-        URL lraId = lraClient.startLRA(
+        URI lraId = lraClient.startLRA(
                         "Unannotated client", 0L, ChronoUnit.MILLIS);
 
         // Join the LRA as a participant.
@@ -826,7 +826,7 @@ public class UnannotatedParticpant implements LRAParticipant {
 
     // the callback that will be invoked if the LRA is closed
     @Override
-    public Future<Void> completeWork(URL lraId)
+    public Future<Void> completeWork(URI lraId)
         throws NotFoundException, TerminationException
     {
         return null;
@@ -834,7 +834,7 @@ public class UnannotatedParticpant implements LRAParticipant {
 
     // the callback that will be invoked if the LRA is cancelled
     @Override
-    public Future<Void> compensateWork(URL lraId)
+    public Future<Void> compensateWork(URI lraId)
         throws NotFoundException, TerminationException
     {
         return null;
@@ -875,7 +875,7 @@ the option of adding a flight as part of the overall trip:
 @PUT
 @Path("/trip")
 @LRA(LRA.Type.REQUIRED) // ensures an LRA is active when the method executes
-public void bookTrip(@HeaderParam(LRA_HTTP_HEADER) URL lraId) {
+public void bookTrip(@HeaderParam(LRA_HTTP_HEADER) URI lraId) {
     // include a flight in the trip by sending a JAX-RS PUT
     // request to the flight booking service
     ...
@@ -896,7 +896,7 @@ void bookFlight(...) {
 
 @Compensate
 @PUT
-void cancelFlight(@HeaderParam(LRA_HTTP_HEADER) URL lraId) {...}
+void cancelFlight(@HeaderParam(LRA_HTTP_HEADER) URI lraId) {...}
 
 ----
 
@@ -922,7 +922,7 @@ LRA before sending the flight booking request:
     @PUT
     @Path("/trip")
     @LRA(LRA.Type.REQUIRED)
-    public void bookTrip(@HeaderParam(LRA_HTTP_HEADER) URL lraId) {
+    public void bookTrip(@HeaderParam(LRA_HTTP_HEADER) URI lraId) {
         // start a nested LRA with lraId as the parent
         flightLraId = lraClient.startLRA(lraId, ...)
 
diff --git a/tck/src/main/java/org/eclipse/microprofile/lra/tck/participant/activity/Activity.java b/tck/src/main/java/org/eclipse/microprofile/lra/tck/participant/activity/Activity.java
index 69bcaa6..230b2a2 100644
--- a/tck/src/main/java/org/eclipse/microprofile/lra/tck/participant/activity/Activity.java
+++ b/tck/src/main/java/org/eclipse/microprofile/lra/tck/participant/activity/Activity.java
@@ -32,7 +32,7 @@ public class Activity implements Serializable {
     private static final long serialVersionUID = 1L;
 
     private String lraId;
-    private String recoveryUrl;
+    private String recoveryUri;
     private String statusUrl;
     private ParticipantStatus status;
     private String userData;
@@ -53,12 +53,12 @@ public class Activity implements Serializable {
         return this;
     }
 
-    public String getRcvUrl() {
-        return recoveryUrl;
+    public String getRcvUri() {
+        return recoveryUri;
     }
 
-    public Activity setRecoveryUrl(String recoveryUrl) {
-        this.recoveryUrl = recoveryUrl;
+    public Activity setRecoveryUri(String recoveryUri) {
+        this.recoveryUri = recoveryUri;
         return this;
     }
 
@@ -84,7 +84,7 @@ public class Activity implements Serializable {
     public String toString() {
         return "Activity{" +
                 "lraId='" + getLraId() + '\'' +
-                ", recoveryUrl='" + getRcvUrl() + '\'' +
+                ", recoveryUri='" + getRcvUri() + '\'' +
                 ", statusUrl='" + getStatusUrl() + '\'' +
                 ", status=" + getStatus() +
                 ", userData='" + getUserData() + '\'' +
diff --git a/tck/src/main/java/org/eclipse/microprofile/lra/tck/participant/api/LraController.java b/tck/src/main/java/org/eclipse/microprofile/lra/tck/participant/api/LraController.java
index e0984c4..6f3d128 100644
--- a/tck/src/main/java/org/eclipse/microprofile/lra/tck/participant/api/LraController.java
+++ b/tck/src/main/java/org/eclipse/microprofile/lra/tck/participant/api/LraController.java
@@ -54,9 +54,8 @@ import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
 import javax.ws.rs.core.UriInfo;
 import java.io.UnsupportedEncodingException;
-import java.net.MalformedURLException;
 import java.net.URI;
-import java.net.URL;
+import java.net.URISyntaxException;
 import java.net.URLDecoder;
 import java.time.temporal.ChronoUnit;
 import java.util.List;
@@ -126,27 +125,26 @@ public class LraController {
 
     /**
      * Test that participants can leave an LRA using the {@link LRAClient} programmatic API
-     * @param lraUrl the id of the LRA
-     * @param recoveryUrl header param defines recovery url
-     * @return the url of the LRA if it was successfully removed
+     * @param lraUri the id of the LRA
+     * @param recoveryUri header param defines recovery URI
+     * @return the URI of the LRA if it was successfully removed
      * @throws NotFoundException if the activity was not found
-     * @throws MalformedURLException if the LRA is malformed
      */
     @PUT
-    @Path("/leave/{LraUrl}")
+    @Path("/leave/{LraUri}")
     @Produces(MediaType.APPLICATION_JSON)
-    public Response leaveWorkViaAPI(@PathParam("LraUrl")String lraUrl,
-                                    @HeaderParam(LRA_HTTP_RECOVERY_HEADER) String recoveryUrl)
-        throws NotFoundException, MalformedURLException {
+    public Response leaveWorkViaAPI(@PathParam("LraUri") String lraUri,
+                                    @HeaderParam(LRA_HTTP_RECOVERY_HEADER) String recoveryUri)
+        throws NotFoundException {
 
-        if (lraUrl != null && recoveryUrl != null) {
-            lraClient.leaveLRA(new URL(recoveryUrl));
+        if (lraUri != null && recoveryUri != null) {
+            lraClient.leaveLRA(URI.create(recoveryUri));
 
-            activityStore.getActivityAndAssertExistence(lraUrl, context);
+            activityStore.getActivityAndAssertExistence(lraUri, context);
 
-            activityStore.remove(lraUrl);
+            activityStore.remove(lraUri);
 
-            return Response.ok(lraUrl).build();
+            return Response.ok(lraUri).build();
         }
 
         return Response.ok("non transactional").build();
@@ -286,7 +284,7 @@ public class LraController {
         assertNotHeaderPresent(lraId);
 
         // manually start an LRA via the injection LRAClient api
-        URL lra = lraClient.startLRA(null,"subActivity", 0L, ChronoUnit.SECONDS);
+        URI lra = lraClient.startLRA(null,"subActivity", 0L, ChronoUnit.SECONDS);
 
         lraId = lra.toString();
 
@@ -322,14 +320,14 @@ public class LraController {
         return Response.ok(lraId).header(LRA_HTTP_RECOVERY_HEADER, recoveryId).build();
     }
 
-    private String restPutInvocation(URL lraURL, String path, String bodyText) {
+    private String restPutInvocation(URI lraURI, String path, String bodyText) {
         String id = null;
         Response response = ClientBuilder.newClient()
                 .target(context.getBaseUri())
                 .path(LRA_CONTROLLER_PATH)
                 .path(path)
                 .request()
-                .header(LRAClient.LRA_HTTP_HEADER, lraURL)
+                .header(LRAClient.LRA_HTTP_HEADER, lraURI)
                 .put(Entity.text(bodyText));
 
         if (response.hasEntity()) {
@@ -338,7 +336,7 @@ public class LraController {
 
         try {
             if (response.getStatus() != Response.Status.OK.getStatusCode()) {
-                throw new WebApplicationException("Error on REST PUT for LRA '" + lraURL
+                throw new WebApplicationException("Error on REST PUT for LRA '" + lraURI
                         + "' at path '" + path + "' and body '" + bodyText + "'", response);
             }
         } finally {
@@ -381,18 +379,18 @@ public class LraController {
 
         storeActivity(nestedLRAId, recoveryId);
 
-        URL lraURL;
+        URI lraURI;
 
         try {
-            lraURL = new URL(URLDecoder.decode(nestedLRAId, "UTF-8"));
-        } catch (MalformedURLException | UnsupportedEncodingException e) {
+            lraURI = URI.create(URLDecoder.decode(nestedLRAId, "UTF-8"));
+        } catch (UnsupportedEncodingException e) {
             throw new InvalidLRAIdException(nestedLRAId, e.getMessage(), e);
         }
 
         // invoke resources that enlist nested LRAs
         String[] lras = new String[nestedCnt + 1];
         lras[0] = nestedLRAId;
-        IntStream.range(1, lras.length).forEach(i -> lras[i] = restPutInvocation(lraURL,"nestedActivity", ""));
+        IntStream.range(1, lras.length).forEach(i -> lras[i] = restPutInvocation(lraURI,"nestedActivity", ""));
 
         return Response.ok(String.join(",", lras)).build();
     }
@@ -401,7 +399,7 @@ public class LraController {
         LOGGER.fine(String.format("Storing information about LRA id '%s' and recoveryId '%s'", lraId, recoveryId));
 
         Activity activity = new Activity(lraId)
-            .setRecoveryUrl(recoveryId)
+            .setRecoveryUri(recoveryId)
             .setStatus(null);
 
         return activityStore.add(activity);
@@ -464,7 +462,7 @@ public class LraController {
              * attribute update the timeLimit to 300 sleep for 200 return from the method so the LRA will
              * have been running for 200 ms so it should not be cancelled
              */
-            lraClient.renewTimeLimit(lraToURL(lraId, "Invalid LRA id"), 300, ChronoUnit.MILLIS);
+            lraClient.renewTimeLimit(lraToURI(lraId, "Invalid LRA id"), 300, ChronoUnit.MILLIS);
             // sleep for 200000 micro seconds (should be longer than specified in the timeLimit annotation attribute)
             Thread.sleep(200);
         } catch (InterruptedException e) {
@@ -548,11 +546,11 @@ public class LraController {
         return ParticipantStatus.Compensated.name();
     }
 
-    private static URL lraToURL(String lraId, String errorMessage) {
+    private static URI lraToURI(String lraId, String errorMessage) {
         try {
-            return new URL(lraId);
-        } catch (MalformedURLException e) {
-            LOGGER.log(Level.WARNING, "Can't construct URL from LRA id '" + lraId + "'", e);
+            return new URI(lraId);
+        } catch (URISyntaxException e) {
+            LOGGER.log(Level.WARNING, "Can't construct URI from LRA id '" + lraId + "'", e);
             throw new GenericLRAException(null, Response.Status.BAD_REQUEST.getStatusCode(),
                     errorMessage + ": LRA id '" + lraId + "'", e);
         }
diff --git a/tck/src/main/java/org/eclipse/microprofile/lra/tck/spi/ManagementSPI.java b/tck/src/main/java/org/eclipse/microprofile/lra/tck/spi/ManagementSPI.java
index 02d426b..6f60896 100644
--- a/tck/src/main/java/org/eclipse/microprofile/lra/tck/spi/ManagementSPI.java
+++ b/tck/src/main/java/org/eclipse/microprofile/lra/tck/spi/ManagementSPI.java
@@ -23,7 +23,7 @@ import org.eclipse.microprofile.lra.annotation.LRAStatus;
 import org.eclipse.microprofile.lra.tck.LRAInfo;
 
 import javax.ws.rs.NotFoundException;
-import java.net.URL;
+import java.net.URI;
 import java.util.List;
 
 public interface ManagementSPI {
@@ -38,7 +38,7 @@ public interface ManagementSPI {
      * not indicate that the LRA has already closed or cancelled depending upon
      * how long the implementation chooses to maintain such information).
      */
-    LRAInfo getStatus(URL lraId) throws NotFoundException;
+    LRAInfo getStatus(URI lraId) throws NotFoundException;
 
     /**
      * Lookup LRAs that are in a particular state.


Test patch:
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 534f7eb..71ed32d 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
@@ -31,6 +31,7 @@ import static org.junit.Assert.fail;
 import java.io.UnsupportedEncodingException;
 import java.net.MalformedURLException;
 import java.net.URI;
+import java.net.URISyntaxException;
 import java.net.URL;
 import java.net.URLEncoder;
 import java.time.temporal.ChronoUnit;
@@ -139,9 +140,9 @@ public class TckTests {
                         LOGGER.warning(String.format(
                                 "<after test> %s: test did not close %s%n", testName.getMethodName(), lra.getLraId()));
                         notProperlyClosedLRAs.add(lra);
-                        lraClient.closeLRA(new URL(lra.getLraId()));
+                        lraClient.closeLRA(URI.create(lra.getLraId()));
                     }
-                } catch (WebApplicationException | MalformedURLException e) {
+                } catch (WebApplicationException e) {
                     LOGGER.warning(String.format("<after test> %s: exception %s closing %s%n",
                             testName.getMethodName(), e.getMessage(), lra.getLraId()));
                 }
@@ -173,7 +174,7 @@ public class TckTests {
     // TODO: what's difference to closeLRA?
     @Test
     public void startLRA() throws WebApplicationException {
-        URL lra = lraClient.startLRA(null, lraClientId(), lraTimeout(), ChronoUnit.MILLIS);
+        URI lra = lraClient.startLRA(null, lraClientId(), lraTimeout(), ChronoUnit.MILLIS);
 
         lraClient.closeLRA(lra);
     }
@@ -186,7 +187,7 @@ public class TckTests {
      */
     @Test
     public void cancelLRA() throws WebApplicationException {
-        URL lra = lraClient.startLRA(null,lraClientId(), lraTimeout(), ChronoUnit.MILLIS);
+        URI lra = lraClient.startLRA(null,lraClientId(), lraTimeout(), ChronoUnit.MILLIS);
 
         lraClient.cancelLRA(lra);
 
@@ -205,7 +206,7 @@ public class TckTests {
      */
     @Test
     public void closeLRA() throws WebApplicationException {
-        URL lra = lraClient.startLRA(null, lraClientId(), lraTimeout(), ChronoUnit.MILLIS);
+        URI lra = lraClient.startLRA(null, lraClientId(), lraTimeout(), ChronoUnit.MILLIS);
 
         lraClient.closeLRA(lra);
 
@@ -221,7 +222,7 @@ public class TckTests {
      */
     @Test
     public void getActiveLRAs() throws WebApplicationException {
-        URL lra = lraClient.startLRA(null, lraClientId(), lraTimeout(), ChronoUnit.MILLIS);
+        URI lra = lraClient.startLRA(null, lraClientId(), lraTimeout(), ChronoUnit.MILLIS);
 
         List<LRAInfo> allActiveLRAs = lraManagement.getLRAs(LRAStatus.Active);
         boolean isLraIdInList = containsLraId(allActiveLRAs, lra);
@@ -237,7 +238,7 @@ public class TckTests {
      */
     @Test
     public void getAllLRAs() throws WebApplicationException {
-        URL lra = lraClient.startLRA(null, lraClientId(), lraTimeout(), ChronoUnit.MILLIS);
+        URI lra = lraClient.startLRA(null, lraClientId(), lraTimeout(), ChronoUnit.MILLIS);
 
         List<LRAInfo> allClientLRAs = lraManagement.getLRAs(null);
         boolean isLraIdInList = containsLraId(allClientLRAs, lra);
@@ -259,7 +260,7 @@ public class TckTests {
      */
     @Test
     public void isActiveLRA() throws WebApplicationException {
-        URL lra = lraClient.startLRA(null, lraClientId(), lraTimeout(), ChronoUnit.MILLIS);
+        URI lra = lraClient.startLRA(null, lraClientId(), lraTimeout(), ChronoUnit.MILLIS);
 
         assertEquals("LRA '" + lra + "' is not denoted as active even it was started",
                 LRAStatus.Active, lraClient.getStatus(lra));
@@ -274,7 +275,7 @@ public class TckTests {
     @Test
     @Ignore
     public void isCompensatedLRA() throws WebApplicationException {
-        URL lra = lraClient.startLRA(null, lraClientId(), lraTimeout(), ChronoUnit.MILLIS);
+        URI lra = lraClient.startLRA(null, lraClientId(), lraTimeout(), ChronoUnit.MILLIS);
 
         lraClient.cancelLRA(lra);
 
@@ -289,7 +290,7 @@ public class TckTests {
     @Test
     @Ignore
     public void isCompletedLRA() throws WebApplicationException {
-        URL lra = lraClient.startLRA(null, lraClientId(), lraTimeout(), ChronoUnit.MILLIS);
+        URI lra = lraClient.startLRA(null, lraClientId(), lraTimeout(), ChronoUnit.MILLIS);
 
         lraClient.closeLRA(lra);
 
@@ -321,7 +322,7 @@ public class TckTests {
 
     @Test
     public void nestedActivity() throws WebApplicationException {
-        URL lra = lraClient.startLRA(null, lraClientId(), lraTimeout(), ChronoUnit.MILLIS);
+        URI lra = lraClient.startLRA(null, lraClientId(), lraTimeout(), ChronoUnit.MILLIS);
         WebTarget resourcePath = tckSuiteTarget
                 .path(LRA_CONTROLLER_PATH).path("nestedActivity");
 
@@ -339,7 +340,7 @@ public class TckTests {
     
             assertNotNull("Expecting to get parent LRA id as response from " + resourcePath.getUri(), parentId);
             assertEquals("The nested activity should return the parent LRA id. The call to " + resourcePath.getUri(),
-                    parentId, lra.toExternalForm());
+                    parentId, lra.toString());
     
             String nestedLraId = response.readEntity(String.class);
     
@@ -379,7 +380,7 @@ public class TckTests {
     public void joinLRAViaHeader() throws WebApplicationException {
         int beforeCompletedCount = getCompletedCount();
 
-        URL lra = lraClient.startLRA(null, lraClientId(), lraTimeout(), ChronoUnit.MILLIS);
+        URI lra = lraClient.startLRA(null, lraClientId(), lraTimeout(), ChronoUnit.MILLIS);
 
         WebTarget resourcePath = tckSuiteTarget.path(LRA_CONTROLLER_PATH).path(TRANSACTIONAL_WORK_PATH);
         Response response = resourcePath
@@ -411,7 +412,7 @@ public class TckTests {
     public void join() throws WebApplicationException {
         List<LRAInfo> lras = lraManagement.getLRAs(LRAStatus.Active);
         int count = lras.size();
-        URL lra = lraClient.startLRA(null, lraClientId(), lraTimeout(), ChronoUnit.MILLIS);
+        URI lra = lraClient.startLRA(null, lraClientId(), lraTimeout(), ChronoUnit.MILLIS);
         WebTarget resourcePath = tckSuiteTarget.path(LRA_CONTROLLER_PATH).path(TRANSACTIONAL_WORK_PATH);
         Response response = resourcePath
                 .request().header(LRAClient.LRA_HTTP_HEADER, lra).put(Entity.text(""));
@@ -426,7 +427,7 @@ public class TckTests {
     @Test
     public void leaveLRA() throws WebApplicationException {
         int beforeCompletedCount = getCompletedCount();
-        URL lra = lraClient.startLRA(null, lraClientId(), lraTimeout(), ChronoUnit.MILLIS);
+        URI lra = lraClient.startLRA(null, lraClientId(), lraTimeout(), ChronoUnit.MILLIS);
         WebTarget resourcePath = tckSuiteTarget.path(LRA_CONTROLLER_PATH).path(TRANSACTIONAL_WORK_PATH);
         Response response = resourcePath.request().header(LRAClient.LRA_HTTP_HEADER, lra).put(Entity.text(""));
 
@@ -455,7 +456,7 @@ public class TckTests {
     @Test
     public void leaveLRAViaAPI() throws WebApplicationException {
         int beforeCompletedCount = getCompletedCount();
-        URL lra = lraClient.startLRA(null, lraClientId(), lraTimeout(), ChronoUnit.MILLIS);
+        URI lra = lraClient.startLRA(null, lraClientId(), lraTimeout(), ChronoUnit.MILLIS);
 
         WebTarget resourcePath = tckSuiteTarget.path(LRA_CONTROLLER_PATH).path(TRANSACTIONAL_WORK_PATH);
 
@@ -466,7 +467,7 @@ public class TckTests {
         resourcePath = tckSuiteTarget.path(LRA_CONTROLLER_PATH).path(TRANSACTIONAL_WORK_PATH);
         response = resourcePath.request().header(LRAClient.LRA_HTTP_HEADER, lra).put(Entity.text(""));
 
-        String recoveryUrl = response.getHeaderString(LRAClient.LRA_HTTP_RECOVERY_HEADER);        
+        String recoveryUri = response.getHeaderString(LRAClient.LRA_HTTP_RECOVERY_HEADER);        
         
         checkStatusAndClose(Response.Status.OK, response, resourcePath);
 
@@ -476,7 +477,7 @@ public class TckTests {
             response = resourcePath.path(URLEncoder.encode(lra.toString(), "UTF-8"))
                     .request()
                     .header(LRAClient.LRA_HTTP_HEADER, lra)
-                    .header(LRAClient.LRA_HTTP_RECOVERY_HEADER, recoveryUrl)
+                    .header(LRAClient.LRA_HTTP_RECOVERY_HEADER, recoveryUri)
                     .put(Entity.text(""));
         } catch (UnsupportedEncodingException e) {
             throw new WebApplicationException(
@@ -496,7 +497,7 @@ public class TckTests {
     }
 
     @Test
-    public void dependentLRA() throws WebApplicationException, MalformedURLException {
+    public void dependentLRA() throws WebApplicationException {
         // call a method annotated with NOT_SUPPORTED but one which programatically starts an LRA and returns it via a header
         WebTarget resourcePath = tckSuiteTarget.path(LRA_CONTROLLER_PATH).path("startViaApi");
         Response response = resourcePath.request().put(Entity.text(""));
@@ -514,7 +515,7 @@ public class TckTests {
         assertEquals("The dependent LRA has to belong to the same LRA id. The test call went to " + resourcePath.getUri(),
                 lraId, lraHeader.toString());
 
-        lraClient.closeLRA(new URL(lraHeader.toString()));
+        lraClient.closeLRA(URI.create(lraHeader.toString()));
     }
 
     @Test
@@ -590,7 +591,7 @@ public class TckTests {
     // TODO the spec does not specifiy recovery semantics
     private void joinAndEnd(boolean waitForRecovery, boolean close, String path, String path2) throws WebApplicationException {
         int beforeActiveLRACount = lraManagement.getLRAs(LRAStatus.Active).size();
-        URL lra = lraClient.startLRA(null, lraClientId(), lraTimeout(), ChronoUnit.MILLIS);
+        URI lra = lraClient.startLRA(null, lraClientId(), lraTimeout(), ChronoUnit.MILLIS);
         WebTarget resourcePath = tckSuiteTarget.path(path).path(path2);
 
         Response response = resourcePath
@@ -629,7 +630,7 @@ public class TckTests {
 
         int beforeCompletedCount = getCompletedCount();
         int beforeCompensatedCount = getCompensatedCount();
-        URL lra = lraClient.startLRA(null, lraClientId(), lraTimeout(), ChronoUnit.MILLIS);
+        URI lra = lraClient.startLRA(null, lraClientId(), lraTimeout(), ChronoUnit.MILLIS);
 
         Response response = resourcePath.request().header(LRAClient.LRA_HTTP_HEADER, lra)
                 .put(Entity.text(""));
@@ -637,7 +638,7 @@ public class TckTests {
         String lraId = checkStatusReadAndClose(Response.Status.OK, response, resourcePath);
 
         assertEquals("While calling non-LRA method the controller returns not expected LRA id",
-                lraId, lra.toExternalForm());
+                lraId, lra.toString());
 
         lraClient.cancelLRA(lra);
 
@@ -730,7 +731,7 @@ public class TckTests {
             how = CompletionType.complete;
         }
 
-        URL lra = lraClient.startLRA(null, lraClientId(), lraTimeout(), ChronoUnit.MILLIS);
+        URI lra = lraClient.startLRA(null, lraClientId(), lraTimeout(), ChronoUnit.MILLIS);
         String lraId = lra.toString();
 
         Response response = resourcePath
@@ -744,13 +745,13 @@ public class TckTests {
         assert lraStr != null;
         String[] lraArray = lraStr.split(",");
         final List<LRAInfo> lras = lraManagement.getLRAs(LRAStatus.Active);
-        URL[] urls = new URL[lraArray.length];
+        URI[] uris = new URI[lraArray.length];
 
-        IntStream.range(0, urls.length).forEach(i -> {
+        IntStream.range(0, uris.length).forEach(i -> {
             try {
-                urls[i] = new URL(lraArray[i]);
-            } catch (MalformedURLException e) {
-                fail(String.format("%s (multiLevelNestedActivity): returned an invalid URL: %s",
+                uris[i] = new URI(lraArray[i]);
+            } catch (URISyntaxException e) {
+                fail(String.format("%s (multiLevelNestedActivity): returned an invalid URI: %s",
                         resourcePath.getUri().toString(), e.getMessage()));
             }
         });
@@ -800,7 +801,7 @@ public class TckTests {
              * - C2 is completed and then compensated
              * - C3, ... are completed
              */
-            lraClient.cancelLRA(urls[1]); // compensate the first nested LRA
+            lraClient.cancelLRA(uris[1]); // compensate the first nested LRA
             lraClient.closeLRA(lra); // should not complete any nested LRAs (since they have already completed via the interceptor)
         }
 
@@ -855,8 +856,8 @@ public class TckTests {
         }
     }
 
-    private boolean containsLraId(List<LRAInfo> lras, URL lraIdURL) {
-        String lraId = lraIdURL.toExternalForm();
+    private boolean containsLraId(List<LRAInfo> lras, URI lraIdURI) {
+        String lraId = lraIdURI.toString();
         return containsLraId(lras, lraId);
     }