You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cxf.apache.org by co...@apache.org on 2019/12/10 10:54:52 UTC

[cxf] 02/02: CXF-8153 - @Path with REGEX in path parameter and checkMethodsForInvalidURITemplates(userType, methods);

This is an automated email from the ASF dual-hosted git repository.

coheigea pushed a commit to branch 3.3.x-fixes
in repository https://gitbox.apache.org/repos/asf/cxf.git

commit 35e2fa7bed48961f6db8ff5f7b09b778b4228b5e
Author: Colm O hEigeartaigh <co...@apache.org>
AuthorDate: Mon Dec 9 18:17:19 2019 +0000

    CXF-8153 - @Path with REGEX in path parameter and checkMethodsForInvalidURITemplates(userType, methods);
    
    (cherry picked from commit bfd834bcda6c23b243ac760445612b7401e9419e)
---
 .../apache/cxf/microprofile/client/Validator.java  |  50 +++----
 .../cxf/microprofile/client/ValidatorTest.java     |  19 ++-
 .../org/apache/cxf/systest/jaxrs/BookStore.java    |  28 ++--
 .../cxf/systest/jaxrs/JAXRSPathRegexTest.java      | 149 +++++++++++++++++++++
 .../microprofile/rest/client/regex/Book.java       |  66 +++++++++
 .../microprofile/rest/client/regex/BookStore.java  |  29 ++++
 .../rest/client/regex/BookStoreClient.java         |  38 ++++++
 .../rest/client/regex/JaxrsPathRegexTest.java      | 126 +++++++++++++++++
 8 files changed, 463 insertions(+), 42 deletions(-)

diff --git a/rt/rs/microprofile-client/src/main/java/org/apache/cxf/microprofile/client/Validator.java b/rt/rs/microprofile-client/src/main/java/org/apache/cxf/microprofile/client/Validator.java
index 1ae4807..dfa7ce6 100644
--- a/rt/rs/microprofile-client/src/main/java/org/apache/cxf/microprofile/client/Validator.java
+++ b/rt/rs/microprofile-client/src/main/java/org/apache/cxf/microprofile/client/Validator.java
@@ -24,7 +24,6 @@ import java.lang.reflect.Modifier;
 import java.lang.reflect.Parameter;
 import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
@@ -54,7 +53,7 @@ final class Validator {
     private Validator() {
     }
 
-    
+
     public static void checkValid(Class<?> userType) throws RestClientDefinitionException {
         if (!userType.isInterface()) {
             throwException("VALIDATION_NOT_AN_INTERFACE", userType);
@@ -86,11 +85,11 @@ final class Validator {
 
     }
 
-    private static void checkMethodsForInvalidURITemplates(Class<?> userType, Method[] methods) 
+    private static void checkMethodsForInvalidURITemplates(Class<?> userType, Method[] methods)
         throws RestClientDefinitionException {
 
         Path classPathAnno = userType.getAnnotation(Path.class);
-        
+
         final Set<String> classLevelVariables = new HashSet<>();
         URITemplate classTemplate = null;
         if (classPathAnno != null) {
@@ -99,10 +98,10 @@ final class Validator {
         }
         URITemplate template;
         for (Method method : methods) {
-            
+
             Path methodPathAnno = method.getAnnotation(Path.class);
             if (methodPathAnno != null) {
-                template = classPathAnno == null ? new URITemplate(methodPathAnno.value()) 
+                template = classPathAnno == null ? new URITemplate(methodPathAnno.value())
                     : new URITemplate(classPathAnno.value() + "/" + methodPathAnno.value());
             } else {
                 template = classTemplate;
@@ -110,31 +109,24 @@ final class Validator {
             if (template == null) {
                 continue;
             }
+
+            List<String> foundParams = new ArrayList<>();
+            for (Parameter p : method.getParameters()) {
+                PathParam pathParam = p.getAnnotation(PathParam.class);
+                if (pathParam != null) {
+                    foundParams.add(pathParam.value());
+                }
+            }
+
             Set<String> allVariables = new HashSet<>(template.getVariables());
             if (!allVariables.isEmpty()) {
-                Map<String, String> paramMap = new HashMap<>();
-                for (Parameter p : method.getParameters()) {
-                    PathParam pathParam = p.getAnnotation(PathParam.class);
-                    if (pathParam != null) {
-                        paramMap.put(pathParam.value(), "x");
+                for (String variable : template.getVariables()) {
+                    if (!foundParams.contains(variable)) {
+                        throwException("VALIDATION_UNRESOLVED_PATH_PARAMS", userType, method);
                     }
                 }
-                try {
-                    template.substitute(paramMap, Collections.<String>emptySet(), false);
-                } catch (IllegalArgumentException ex) {
-                    throwException("VALIDATION_UNRESOLVED_PATH_PARAMS", userType, method);
-                }
-            } else {
-                List<String> foundParams = new ArrayList<>();
-                for (Parameter p : method.getParameters()) {
-                    PathParam pathParam = p.getAnnotation(PathParam.class);
-                    if (pathParam != null) {
-                        foundParams.add(pathParam.value());
-                    }
-                }
-                if (!foundParams.isEmpty()) {
-                    throwException("VALIDATION_EXTRA_PATH_PARAMS", userType, method);
-                }
+            } else if (!foundParams.isEmpty()) {
+                throwException("VALIDATION_EXTRA_PATH_PARAMS", userType, method);
             }
         }
     }
@@ -184,7 +176,7 @@ final class Validator {
                             methods = Arrays.stream(computeClass.getDeclaredMethods())
                                                                 .filter(m -> {
                                                                     int i = m.getModifiers();
-                                                                    return Modifier.isPublic(i) 
+                                                                    return Modifier.isPublic(i)
                                                                         && Modifier.isStatic(i);
                                                                 })
                                                                 .toArray(Method[]::new);
@@ -194,7 +186,7 @@ final class Validator {
                             }
                             throwException("CLIENT_HEADER_COMPUTE_CLASS_NOT_FOUND", userType.getName(), ex);
                         }
-                       
+
                     }
                     boolean foundMatchingMethod = false;
                     for (Method method : methods) {
diff --git a/rt/rs/microprofile-client/src/test/java/org/apache/cxf/microprofile/client/ValidatorTest.java b/rt/rs/microprofile-client/src/test/java/org/apache/cxf/microprofile/client/ValidatorTest.java
index f79437e..5b36f81 100644
--- a/rt/rs/microprofile-client/src/test/java/org/apache/cxf/microprofile/client/ValidatorTest.java
+++ b/rt/rs/microprofile-client/src/test/java/org/apache/cxf/microprofile/client/ValidatorTest.java
@@ -123,7 +123,7 @@ public class ValidatorTest {
     }
 
     public interface ClientHeaderParamInaccessibleComputeMethod {
-        @ClientHeaderParam(name = "SomeHeader", 
+        @ClientHeaderParam(name = "SomeHeader",
             value = "{org.apache.cxf.microprofile.client.mock.HeaderGenerator.generateHeaderPrivate}")
         @GET
         Response get();
@@ -152,6 +152,14 @@ public class ValidatorTest {
         }
     }
 
+    public interface PathRegexTestClient {
+
+        // Only books with id consisting of 3 or 4 digits of the numbers between 5 and 9 are accepted
+        @POST
+        @Path("/echoxmlbookregex/{id : [5-9]{3,4}}")
+        void testRegex(@PathParam("id") String id);
+    }
+
     private static RestClientBuilder newBuilder() {
         RestClientBuilder builder = RestClientBuilder.newBuilder();
         try {
@@ -197,7 +205,7 @@ public class ValidatorTest {
 
     @Test
     public void testClientHeaderParamNoComputeMethod() {
-        test(ClientHeaderParamNoComputeMethod.class, ClientHeaderParamNoComputeMethod.class.getName(), 
+        test(ClientHeaderParamNoComputeMethod.class, ClientHeaderParamNoComputeMethod.class.getName(),
              "value attribute specifies a method", "that does not exist");
     }
 
@@ -222,6 +230,11 @@ public class ValidatorTest {
              " contains an incorrect signature");
     }
 
+    @Test
+    public void testPathRegularExpression() {
+        assertNotNull(newBuilder().build(PathRegexTestClient.class));
+    }
+
     private void test(Class<?> clientInterface, String...expectedMessageTexts) {
         try {
             newBuilder().build(clientInterface);
@@ -230,7 +243,7 @@ public class ValidatorTest {
             String msgText = ex.getMessage();
             assertNotNull("No message text in RestClientDefinitionException", msgText);
             for (String expectedMessageText : expectedMessageTexts) {
-                assertTrue("Exception text does not contain expected message: " + expectedMessageText, 
+                assertTrue("Exception text does not contain expected message: " + expectedMessageText,
                            msgText.contains(expectedMessageText));
             }
         }
diff --git a/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/BookStore.java b/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/BookStore.java
index d2001ef..ca53ff7 100644
--- a/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/BookStore.java
+++ b/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/BookStore.java
@@ -188,10 +188,10 @@ public class BookStore {
         } else if ("".equalsIgnoreCase(lStr)) {
             lStr = "0";
         }
-        
+
         return new Book("cxf", Long.parseLong(lStr));
     }
-    
+
     @GET
     @Path("/")
     public Book getBookRoot() {
@@ -352,6 +352,14 @@ public class BookStore {
         return book;
     }
 
+    // Only books with id consisting of 3 or 4 digits of the numbers between 5 and 9 are accepted
+    @POST
+    @Path("/echoxmlbookregex/{id : [5-9]{3,4}}")
+    @Produces("application/xml")
+    public Book echoXmlBookregex(Book book, @PathParam("id") String id) {
+        return book;
+    }
+
     @POST
     @Path("/emptyform")
     @Produces("text/plain")
@@ -395,7 +403,7 @@ public class BookStore {
     public BookStoreSub getBeanParamBookSub() {
         return new BookStoreSub(this);
     }
-    
+
     @Path("/querysub")
     public BookStoreQuerySub getQuerySub() {
         return new BookStoreQuerySub();
@@ -1987,7 +1995,7 @@ public class BookStore {
         public long getId4() {
             return id4;
         }
-        
+
         @QueryParam("id4")
         public void setId4(long id4) {
             this.id4 = id4;
@@ -2012,7 +2020,7 @@ public class BookStore {
         public void setId2(long id2) {
             this.id2 = id2;
         }
-        
+
         public long getId2() {
             return id2;
         }
@@ -2021,7 +2029,7 @@ public class BookStore {
         public void setId3(long id3) {
             this.id3 = id3;
         }
-        
+
         public long getId3() {
             return id3;
         }
@@ -2234,22 +2242,22 @@ public class BookStore {
             return bookStore.getBeanParamBook(bean);
         }
     }
-    
+
     public static class BookStoreQuerySub {
         @GET
         @Path("/listofstrings")
         @Produces("text/xml")
         public Book getBookFromListStrings(@QueryParam("value") List<String> value) {
             final StringBuilder builder = new StringBuilder();
-            
+
             for (String v : value) {
                 if (builder.length() > 0) {
                     builder.append(' ');
                 }
-                
+
                 builder.append(v);
             }
-            
+
             return new Book(builder.toString(), 0L);
         }
     }
diff --git a/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSPathRegexTest.java b/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSPathRegexTest.java
new file mode 100644
index 0000000..bbba1a7
--- /dev/null
+++ b/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSPathRegexTest.java
@@ -0,0 +1,149 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.cxf.systest.jaxrs;
+
+import javax.ws.rs.NotFoundException;
+import javax.ws.rs.client.Client;
+import javax.ws.rs.client.ClientBuilder;
+import javax.ws.rs.client.Entity;
+
+import org.apache.cxf.jaxrs.client.WebClient;
+import org.apache.cxf.jaxrs.model.AbstractResourceInfo;
+import org.apache.cxf.testutil.common.AbstractBusClientServerTestBase;
+
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+/**
+ * Testing: @Path("/echoxmlbookregex/{id : [5-9]{3,4}}")
+ */
+public class JAXRSPathRegexTest extends AbstractBusClientServerTestBase {
+    public static final String PORT = BookServer.PORT;
+    public static final String PORT2 = allocatePort(JAXRSPathRegexTest.class);
+
+    @BeforeClass
+    public static void startServers() throws Exception {
+        AbstractResourceInfo.clearAllMaps();
+        assertTrue("server did not launch correctly",
+                   launchServer(BookServer.class, true));
+        createStaticBus();
+    }
+
+    @Test
+    public void testWeblientPathRegularExpression() throws Exception {
+        String endpointAddress = "http://localhost:" + PORT + "/bookstore/echoxmlbookregex";
+        WebClient client = WebClient.create(endpointAddress);
+        long id = 5678;
+        Book book = new Book();
+        book.setId(id);
+
+        // Successful
+        Book echoedBook = client.type("application/xml").accept("application/xml")
+            .path("/" + id).post(book, Book.class);
+        assertEquals(id, echoedBook.getId());
+
+        // Too long
+        try {
+            client.reset().type("application/xml").accept("application/xml")
+                .path("/" + 56789).post(book, Book.class);
+            fail("Failure expected on a failing regex");
+        } catch (NotFoundException ex) {
+            // expected
+        }
+
+        // Too short
+        try {
+            client.reset().type("application/xml").accept("application/xml")
+                .path("/" + 56).post(book, Book.class);
+            fail("Failure expected on a failing regex");
+        } catch (NotFoundException ex) {
+            // expected
+        }
+
+        // Wrong digits
+        try {
+            client.reset().type("application/xml").accept("application/xml")
+                .path("/" + 1234).post(book, Book.class);
+            fail("Failure expected on a failing regex");
+        } catch (NotFoundException ex) {
+            // expected
+        }
+
+        // Finally try another successful call
+        assertNotNull(client.reset().type("application/xml").accept("application/xml")
+                      .path("/" + 8667).post(book, Book.class));
+    }
+
+    @Test
+    public void testJaxrs20PathRegularExpression() throws Exception {
+        String endpointAddress = "http://localhost:" + PORT + "/bookstore/echoxmlbookregex";
+        long id = 5678;
+        Book book = new Book();
+        book.setId(id);
+
+        // Successful
+        Client client = ClientBuilder.newClient();
+        Book echoedBook = client.target(endpointAddress).path("/" + id)
+            .request("application/xml")
+            .post(Entity.entity(book, "application/xml"), Book.class);
+        assertEquals(id, echoedBook.getId());
+
+        // Too long
+        try {
+            client.target(endpointAddress).path("/" + 56789)
+                .request("application/xml")
+                .post(Entity.entity(book, "application/xml"), Book.class);
+            fail("Failure expected on a failing regex");
+        } catch (NotFoundException ex) {
+            // expected
+        }
+
+        // Too short
+        try {
+            client.target(endpointAddress).path("/" + 56)
+                .request("application/xml")
+                .post(Entity.entity(book, "application/xml"), Book.class);
+            fail("Failure expected on a failing regex");
+        } catch (NotFoundException ex) {
+            // expected
+        }
+
+        // Wrong digits
+        try {
+            client.target(endpointAddress).path("/" + 1234)
+                .request("application/xml")
+                .post(Entity.entity(book, "application/xml"), Book.class);
+            fail("Failure expected on a failing regex");
+        } catch (NotFoundException ex) {
+            // expected
+        }
+
+        // Finally try another successful call
+        client = ClientBuilder.newClient();
+        assertNotNull(client.target(endpointAddress).path("/" + 8667)
+                      .request("application/xml")
+                      .post(Entity.entity(book, "application/xml"), Book.class));
+    }
+}
diff --git a/systests/microprofile/client/jaxrs/src/test/java/org/apache/cxf/systest/microprofile/rest/client/regex/Book.java b/systests/microprofile/client/jaxrs/src/test/java/org/apache/cxf/systest/microprofile/rest/client/regex/Book.java
new file mode 100644
index 0000000..bc52ae1
--- /dev/null
+++ b/systests/microprofile/client/jaxrs/src/test/java/org/apache/cxf/systest/microprofile/rest/client/regex/Book.java
@@ -0,0 +1,66 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.cxf.systest.microprofile.rest.client.regex;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.PUT;
+import javax.xml.bind.annotation.XmlRootElement;
+
+@XmlRootElement(name = "Book")
+public class Book {
+    private String name;
+    private long id;
+
+    public Book() {
+
+    }
+
+    public Book(String name, long id) {
+        this.name = name;
+        this.id = id;
+    }
+
+    public void setName(String n) {
+        name = n;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setId(long i) {
+        id = i;
+    }
+    public long getId() {
+        return id;
+    }
+
+    @PUT
+    public void cloneState(Book book) {
+        id = book.getId();
+        name = book.getName();
+    }
+
+    @GET
+    public Book retrieveState() {
+        return this;
+    }
+
+}
diff --git a/systests/microprofile/client/jaxrs/src/test/java/org/apache/cxf/systest/microprofile/rest/client/regex/BookStore.java b/systests/microprofile/client/jaxrs/src/test/java/org/apache/cxf/systest/microprofile/rest/client/regex/BookStore.java
new file mode 100644
index 0000000..a7b9556
--- /dev/null
+++ b/systests/microprofile/client/jaxrs/src/test/java/org/apache/cxf/systest/microprofile/rest/client/regex/BookStore.java
@@ -0,0 +1,29 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.cxf.systest.microprofile.rest.client.regex;
+
+public class BookStore implements BookStoreClient {
+
+    // Only books with id consisting of 3 or 4 digits of the numbers between 5 and 9 are accepted
+    public Book echoXmlBookregex(Book book, String id) {
+        return book;
+    }
+
+}
\ No newline at end of file
diff --git a/systests/microprofile/client/jaxrs/src/test/java/org/apache/cxf/systest/microprofile/rest/client/regex/BookStoreClient.java b/systests/microprofile/client/jaxrs/src/test/java/org/apache/cxf/systest/microprofile/rest/client/regex/BookStoreClient.java
new file mode 100644
index 0000000..d8257a8
--- /dev/null
+++ b/systests/microprofile/client/jaxrs/src/test/java/org/apache/cxf/systest/microprofile/rest/client/regex/BookStoreClient.java
@@ -0,0 +1,38 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.cxf.systest.microprofile.rest.client.regex;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+
+@Path("/bookstore")
+public interface BookStoreClient {
+
+    // Only books with id consisting of 3 or 4 digits of the numbers between 5 and 9 are accepted
+    @POST
+    @Path("/echoxmlbookregex/{id : [5-9]{3,4}}")
+    @Consumes("application/xml")
+    @Produces("application/xml")
+    Book echoXmlBookregex(Book book, @PathParam("id") String id);
+
+}
\ No newline at end of file
diff --git a/systests/microprofile/client/jaxrs/src/test/java/org/apache/cxf/systest/microprofile/rest/client/regex/JaxrsPathRegexTest.java b/systests/microprofile/client/jaxrs/src/test/java/org/apache/cxf/systest/microprofile/rest/client/regex/JaxrsPathRegexTest.java
new file mode 100644
index 0000000..660d93a
--- /dev/null
+++ b/systests/microprofile/client/jaxrs/src/test/java/org/apache/cxf/systest/microprofile/rest/client/regex/JaxrsPathRegexTest.java
@@ -0,0 +1,126 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.cxf.systest.microprofile.rest.client.regex;
+
+import java.net.URI;
+
+import org.apache.cxf.jaxrs.JAXRSServerFactoryBean;
+import org.apache.cxf.jaxrs.client.WebClient;
+import org.apache.cxf.jaxrs.lifecycle.SingletonResourceProvider;
+import org.apache.cxf.jaxrs.model.AbstractResourceInfo;
+import org.apache.cxf.testutil.common.AbstractBusClientServerTestBase;
+import org.apache.cxf.testutil.common.AbstractBusTestServerBase;
+import org.eclipse.microprofile.rest.client.RestClientBuilder;
+
+import org.junit.BeforeClass;
+import org.junit.Ignore;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+/**
+ * Testing: @Path("/echoxmlbookregex/{id : [5-9]{3,4}}")
+ */
+public class JaxrsPathRegexTest extends AbstractBusClientServerTestBase {
+    public static final String PORT = allocatePort(JaxrsPathRegexTest.class);
+
+    WebClient client;
+    @Ignore
+    public static class Server extends AbstractBusTestServerBase {
+        protected void run() {
+            final JAXRSServerFactoryBean sf = new JAXRSServerFactoryBean();
+            sf.setResourceClasses(BookStore.class);
+            sf.setResourceProvider(BookStore.class,
+                new SingletonResourceProvider(new BookStore()));
+            sf.setAddress("http://localhost:" + PORT + "/");
+            sf.setPublishedEndpointUrl("/");
+            sf.create();
+        }
+
+        public static void main(String[] args) {
+            try {
+                Server s = new Server();
+                s.start();
+            } catch (Exception ex) {
+                ex.printStackTrace();
+                System.exit(-1);
+            } finally {
+                System.out.println("done!");
+            }
+        }
+    }
+
+    @BeforeClass
+    public static void startServers() throws Exception {
+
+        AbstractResourceInfo.clearAllMaps();
+        //keep out of process due to stack traces testing failures
+        assertTrue("server did not launch correctly", launchServer(Server.class, true));
+        createStaticBus();
+        System.out.println("Listening on port " + PORT);
+    }
+
+    @Test
+    public void testPathRegularExpression() throws Exception {
+
+        String endpointAddress = "http://localhost:" + PORT + "/";
+        long id = 5678;
+        Book book = new Book();
+        book.setId(id);
+
+        // Successful
+        BookStoreClient bookStoreClient = RestClientBuilder.newBuilder()
+            .baseUri(URI.create(endpointAddress))
+            .build(BookStoreClient.class);
+
+        Book echoedBook = bookStoreClient.echoXmlBookregex(book, String.valueOf(id));
+        assertEquals(id, echoedBook.getId());
+
+        // Too long
+        try {
+            bookStoreClient.echoXmlBookregex(book, "56789");
+            fail("Failure expected on a failing regex");
+        } catch (IllegalArgumentException ex) {
+            // expected
+        }
+
+        // Too short
+        try {
+            bookStoreClient.echoXmlBookregex(book, "56");
+            fail("Failure expected on a failing regex");
+        } catch (IllegalArgumentException ex) {
+            // expected
+        }
+
+        // Wrong digits
+        try {
+            bookStoreClient.echoXmlBookregex(book, "1234");
+            fail("Failure expected on a failing regex");
+        } catch (IllegalArgumentException ex) {
+            // expected
+        }
+
+        // Finally try another successful call
+        echoedBook = bookStoreClient.echoXmlBookregex(book, "8667");
+        assertEquals(id, echoedBook.getId());
+    }
+
+}