Merge pull request #1231 from jim-krueger/1127-Clarify-JAVASE-support

fast-track: Clarify the JavaSE support in Jakarta Rest Specification
diff --git a/jaxrs-api/src/main/java/jakarta/ws/rs/core/MediaType.java b/jaxrs-api/src/main/java/jakarta/ws/rs/core/MediaType.java
index 6dba6da..fc906fb 100644
--- a/jaxrs-api/src/main/java/jakarta/ws/rs/core/MediaType.java
+++ b/jaxrs-api/src/main/java/jakarta/ws/rs/core/MediaType.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2019 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010  Oracle and/or its affiliates. All rights reserved.
  *
  * This program and the accompanying materials are made available under the
  * terms of the Eclipse Public License v. 2.0, which is available at
@@ -164,6 +164,14 @@
      * A {@link MediaType} constant representing {@value #APPLICATION_JSON_PATCH_JSON} media type.
      */
     public static final MediaType APPLICATION_JSON_PATCH_JSON_TYPE = new MediaType("application", "json-patch+json");
+    /**
+    * {@link String} representation of {@value #APPLICATION_MERGE_PATCH_JSON} media type..
+    */
+    public static final String APPLICATION_MERGE_PATCH_JSON = "application/merge-patch+json";
+    /**
+    * A {@link MediaType} constant representing {@value #APPLICATION_MERGE_PATCH_JSON} media type.
+    */
+    public static final MediaType APPLICATION_MERGE_PATCH_JSON_TYPE = new MediaType("application", "merge-patch+json");
 
     /**
      * Creates a new instance of {@code MediaType} by parsing the supplied string.
diff --git a/jaxrs-api/src/main/java/jakarta/ws/rs/core/UriInfo.java b/jaxrs-api/src/main/java/jakarta/ws/rs/core/UriInfo.java
index 26a0a9f..2fad294 100644
--- a/jaxrs-api/src/main/java/jakarta/ws/rs/core/UriInfo.java
+++ b/jaxrs-api/src/main/java/jakarta/ws/rs/core/UriInfo.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2019 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2024 Oracle and/or its affiliates. All rights reserved.
  *
  * This program and the accompanying materials are made available under the
  * terms of the Eclipse Public License v. 2.0, which is available at
@@ -18,6 +18,8 @@
 
 import java.net.URI;
 import java.util.List;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.ApplicationPath;
 
 /**
  * An injectable interface that provides access to application and request URI information. Relative URIs are relative
@@ -231,6 +233,71 @@
     public List<String> getMatchedURIs();
 
     /**
+     * <p>
+     * Get a URI template that includes all {@link Path Paths} (including {@link ApplicationPath})
+     * matched by the current request's URI.
+     * </p>
+     * <p>
+     * Each {@link Path} value used to match a resource class, a sub-resource method or a sub-resource locator is concatenated
+     * into a single {@code String} value. The template does not include query parameters but does include matrix parameters
+     * if present in the request URI. The concatenation is ordered in the request URI matching order, with the
+     * {@link ApplicationPath} value first and current resource URI last. E.g. given the following resource classes:
+     * </p>
+     *
+     * <pre>
+     * &#064;Path("foo")
+     * public class FooResource {
+     *  &#064;GET
+     *  &#064;Path("{foo:[f-z][a-z]*}")
+     *  public String getFoo() {...}
+     *
+     *  &#064;Path("{bar:[b-e][a-z]*}")
+     *  public BarResource getBarResource() {...}
+     * }
+     *
+     * public class BarResource {
+     *  &#064;GET
+     *  &#064;Path("{id}{id:[0-9]}")
+     *  public String getBar() {...}
+     * }
+     * </pre>
+     *
+     * <p>
+     * The values returned by this method based on request uri and where the method is called from are:
+     * </p>
+     *
+     * <table border="1">
+     * <caption>Matched URIs from requests</caption>
+     * <tr>
+     * <th>Request</th>
+     * <th>Called from</th>
+     * <th>Value(s)</th>
+     * </tr>
+     * <tr>
+     * <td>GET /foo</td>
+     * <td>FooResource.getFoo</td>
+     * <td>/foo/{foo:[f-z][a-z]*}</td>
+     * </tr>
+     * <tr>
+     * <td>GET /foo/bar</td>
+     * <td>FooResource.getBarResource</td>
+     * <td>/foo/{bar:[b-e][a-z]*}</td>
+     * </tr>
+     * <tr>
+     * <td>GET /foo/bar/id0</td>
+     * <td>BarResource.getBar</td>
+     * <td>/foo/{bar:[b-e][a-z]*}/{id}{id:[0-9]}</td>
+     * </tr>
+     * </table>
+     *
+     * In case the method is invoked prior to the request matching (e.g. from a pre-matching filter), the method returns an
+     * empty string.
+     *
+     * @return A concatenated string of {@link Path} templates.
+     */
+    public String getMatchedResourceTemplate();
+
+    /**
      * Get a read-only list of URIs for matched resources.
      *
      * Each entry is a relative URI that matched a resource class, a sub-resource method or a sub-resource locator. Entries
diff --git a/jaxrs-tck/src/main/java/ee/jakarta/tck/ws/rs/ee/resource/webappexception/defaultmapper/DefaultExceptionMapperIT.java b/jaxrs-tck/src/main/java/ee/jakarta/tck/ws/rs/ee/resource/webappexception/defaultmapper/DefaultExceptionMapperIT.java
new file mode 100644
index 0000000..ccf2f9e
--- /dev/null
+++ b/jaxrs-tck/src/main/java/ee/jakarta/tck/ws/rs/ee/resource/webappexception/defaultmapper/DefaultExceptionMapperIT.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2024 Contributors to the Eclipse Foundation
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package ee.jakarta.tck.ws.rs.ee.resource.webappexception.defaultmapper;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.jboss.arquillian.container.test.api.Deployment;
+import org.jboss.arquillian.junit5.ArquillianExtension;
+import org.jboss.shrinkwrap.api.ShrinkWrap;
+import org.jboss.shrinkwrap.api.asset.StringAsset;
+import org.jboss.shrinkwrap.api.spec.WebArchive;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.TestInfo;
+import org.junit.jupiter.api.extension.ExtendWith;
+
+import ee.jakarta.tck.ws.rs.common.JAXRSCommonClient;
+import ee.jakarta.tck.ws.rs.lib.util.TestUtil;
+
+/*
+ * @class.setup_props: webServerHost;
+ *                     webServerPort;
+ *                     ts_home;
+ */
+@ExtendWith(ArquillianExtension.class)
+public class DefaultExceptionMapperIT extends JAXRSCommonClient {
+
+  public DefaultExceptionMapperIT() {
+    setContextRoot("/jaxrs_resource_webappexception_defaultmapper_web/resource");
+  }
+
+  @Deployment(testable = false)
+  public static WebArchive createDeployment() throws IOException {
+
+    InputStream inStream = DefaultExceptionMapperIT.class.getClassLoader().getResourceAsStream("ee/jakarta/tck/ws/rs/ee/resource/webappexception/defaultmapper/web.xml.template");
+    // Replace the servlet_adaptor in web.xml.template with the System variable set as servlet adaptor
+    String webXml = editWebXmlString(inStream);
+
+    WebArchive archive = ShrinkWrap.create(WebArchive.class, "jaxrs_resource_webappexception_defaultmapper_web.war");
+    archive.addClasses(
+        TSAppConfig.class, 
+        Resource.class, 
+        OverriddenDefaultExceptionMapper.class
+    );
+    archive.setWebXML(new StringAsset(webXml));
+    
+    return archive;
+  }
+
+  @BeforeEach
+  void logStartTest(TestInfo testInfo) {
+    super.setup();
+    TestUtil.logMsg("STARTING TEST : "+testInfo.getDisplayName());
+  }
+
+  @AfterEach
+  void logFinishTest(TestInfo testInfo) {
+    TestUtil.logMsg("FINISHED TEST : "+testInfo.getDisplayName());
+  }
+
+  /*
+   * @testName: overrideDefaultExceptionMapperTest
+   * 
+   * @test_Strategy: The default ExceptionMapper must be able to be overridden.
+   */
+  @Test
+  public void overrideDefaultExceptionMapperTest() throws Fault {
+    setProperty(REQUEST, buildRequest(GET, "throwable"));
+    setProperty(STATUS_CODE, "512");
+    invoke();
+  }
+}
\ No newline at end of file
diff --git a/jaxrs-tck/src/main/java/ee/jakarta/tck/ws/rs/ee/resource/webappexception/defaultmapper/OverriddenDefaultExceptionMapper.java b/jaxrs-tck/src/main/java/ee/jakarta/tck/ws/rs/ee/resource/webappexception/defaultmapper/OverriddenDefaultExceptionMapper.java
new file mode 100644
index 0000000..83c8c0a
--- /dev/null
+++ b/jaxrs-tck/src/main/java/ee/jakarta/tck/ws/rs/ee/resource/webappexception/defaultmapper/OverriddenDefaultExceptionMapper.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2024 Contributors to the Eclipse Foundation
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package ee.jakarta.tck.ws.rs.ee.resource.webappexception.defaultmapper;
+
+import jakarta.ws.rs.core.Response;
+import jakarta.ws.rs.ext.ExceptionMapper;
+import jakarta.ws.rs.ext.Provider;
+
+@Provider
+public class OverriddenDefaultExceptionMapper implements ExceptionMapper<Throwable> {
+
+    /*
+     * 4.4. Exception Mapping Providers states:
+     * "A JAX-RS implementation MUST include a default exception mapping provider
+     * that implements ExceptionMapper<Throwable> and which SHOULD set the
+     * response status to 500."
+     * 
+     * This class should override the default ExceptionMapper and set the
+     * response status to 512 to verify that the default ExceptionMapper
+     * was overriden.
+     */
+  @Override
+  public Response toResponse(Throwable throwable) {
+    return Response.status(512).build();
+  }
+    
+}
diff --git a/jaxrs-tck/src/main/java/ee/jakarta/tck/ws/rs/ee/resource/webappexception/defaultmapper/Resource.java b/jaxrs-tck/src/main/java/ee/jakarta/tck/ws/rs/ee/resource/webappexception/defaultmapper/Resource.java
new file mode 100644
index 0000000..a304804
--- /dev/null
+++ b/jaxrs-tck/src/main/java/ee/jakarta/tck/ws/rs/ee/resource/webappexception/defaultmapper/Resource.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2024 Contributors to the Eclipse Foundation
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package ee.jakarta.tck.ws.rs.ee.resource.webappexception.defaultmapper;
+
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.core.Response;
+
+@Path("resource")
+public class Resource {
+
+  @GET
+  @Path("/throwable")
+  public Response throwable() throws Throwable {
+    throw new Throwable();
+  }
+
+}
\ No newline at end of file
diff --git a/jaxrs-tck/src/main/java/ee/jakarta/tck/ws/rs/ee/resource/webappexception/defaultmapper/TSAppConfig.java b/jaxrs-tck/src/main/java/ee/jakarta/tck/ws/rs/ee/resource/webappexception/defaultmapper/TSAppConfig.java
new file mode 100644
index 0000000..bcf5174
--- /dev/null
+++ b/jaxrs-tck/src/main/java/ee/jakarta/tck/ws/rs/ee/resource/webappexception/defaultmapper/TSAppConfig.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2024 Contributors to the Eclipse Foundation
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package ee.jakarta.tck.ws.rs.ee.resource.webappexception.defaultmapper;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import jakarta.ws.rs.core.Application;
+
+public class TSAppConfig extends Application {
+  public java.util.Set<java.lang.Class<?>> getClasses() {
+    Set<Class<?>> resources = new HashSet<Class<?>>();
+    resources.add(Resource.class);
+    resources.add(OverriddenDefaultExceptionMapper.class);
+    return resources;
+  }
+}
\ No newline at end of file
diff --git a/jaxrs-tck/src/main/java/ee/jakarta/tck/ws/rs/jaxrs40/ee/rs/core/uriinfo/TSAppConfig.java b/jaxrs-tck/src/main/java/ee/jakarta/tck/ws/rs/jaxrs40/ee/rs/core/uriinfo/TSAppConfig.java
new file mode 100644
index 0000000..afcfdda
--- /dev/null
+++ b/jaxrs-tck/src/main/java/ee/jakarta/tck/ws/rs/jaxrs40/ee/rs/core/uriinfo/TSAppConfig.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2024 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package ee.jakarta.tck.ws.rs.jaxrs40.ee.rs.core.uriinfo;
+
+import jakarta.ws.rs.ApplicationPath;
+import jakarta.ws.rs.core.Application;
+
+import java.util.HashSet;
+import java.util.Set;
+
+@ApplicationPath("/app")
+public class TSAppConfig extends Application {
+
+  public Set<Class<?>> getClasses() {
+    Set<Class<?>> resources = new HashSet<Class<?>>();
+    resources.add(UriInfoTestResource.class);
+    return resources;
+  }
+}
diff --git a/jaxrs-tck/src/main/java/ee/jakarta/tck/ws/rs/jaxrs40/ee/rs/core/uriinfo/UriInfo40ClientIT.java b/jaxrs-tck/src/main/java/ee/jakarta/tck/ws/rs/jaxrs40/ee/rs/core/uriinfo/UriInfo40ClientIT.java
new file mode 100644
index 0000000..f6c20ad
--- /dev/null
+++ b/jaxrs-tck/src/main/java/ee/jakarta/tck/ws/rs/jaxrs40/ee/rs/core/uriinfo/UriInfo40ClientIT.java
@@ -0,0 +1,125 @@
+/*
+ * Copyright (c) 2024 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package ee.jakarta.tck.ws.rs.jaxrs40.ee.rs.core.uriinfo;
+
+import ee.jakarta.tck.ws.rs.common.JAXRSCommonClient;
+import ee.jakarta.tck.ws.rs.lib.util.TestUtil;
+import jakarta.ws.rs.core.UriInfo;
+import org.jboss.arquillian.container.test.api.Deployment;
+import org.jboss.arquillian.junit5.ArquillianExtension;
+import org.jboss.shrinkwrap.api.ShrinkWrap;
+import org.jboss.shrinkwrap.api.spec.WebArchive;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.TestInfo;
+import org.junit.jupiter.api.extension.ExtendWith;
+
+import java.io.IOException;
+
+/*
+ * @class.setup_props: webServerHost;
+ *                     webServerPort;
+ */
+@ExtendWith(ArquillianExtension.class)
+public class UriInfo40ClientIT extends JAXRSCommonClient {
+  protected static final String ROOT = "jaxrs40_ee_core_uriinfo_web";
+
+  protected static final String RESOURCE = "app/resource";
+
+  public UriInfo40ClientIT() {
+    setup();
+    setContextRoot("/" + ROOT + "/" + RESOURCE);
+  }
+
+
+  @BeforeEach
+  void logStartTest(TestInfo testInfo) {
+    TestUtil.logMsg("STARTING TEST : " + testInfo.getDisplayName());
+  }
+
+  @AfterEach
+  void logFinishTest(TestInfo testInfo) {
+    TestUtil.logMsg("FINISHED TEST : " + testInfo.getDisplayName());
+  }
+
+  @Deployment(testable = false)
+  public static WebArchive createDeployment() throws IOException{
+    WebArchive archive = ShrinkWrap.create(WebArchive.class, "jaxrs40_ee_core_uriinfo_web.war");
+    archive.addClasses(TSAppConfig.class, UriInfoTestResource.class);
+    return archive;
+  }
+
+  /* Run test */
+
+  /**
+   * @testName: getMatchedResourceTemplateOneTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:97;
+   *
+   * @test_Strategy: Check the template containing {@link UriInfoTestResource#ONE_POST}
+   */
+  @Test
+  public void getMatchedResourceTemplateOneTest() throws Fault {
+    setProperty(Property.REQUEST, buildRequest(Request.POST, "one/azazaz00"));
+    setProperty(Property.SEARCH_STRING, "/app/resource/one/" + UriInfoTestResource.ONE_POST);
+    invoke();
+  }
+
+  /**
+   * @testName: getMatchedResourceTemplateTwoGetTest
+   *
+   * @assertion_ids: JAXRS:JAVADOC:97;
+   *
+   * @test_Strategy: Check the template containing {@link UriInfoTestResource#TWO_GET}
+   */
+  @Test
+  public void getMatchedResourceTemplateTwoGetTest() throws Fault {
+    setProperty(Property.REQUEST, buildRequest(Request.GET, "two/P/abc/MyNumber"));
+    setProperty(Property.SEARCH_STRING, "/app/resource/two/" + UriInfoTestResource.TWO_GET);
+    invoke();
+  }
+
+  /**
+   * @testName: getMatchedResourceTemplateTwoPostTest
+   *
+   * @assertion_ids: JAXRS:JAVADOC:97;
+   *
+   * @test_Strategy: Check the template containing {@link UriInfoTestResource#TWO_POST}
+   */
+  @Test
+  public void getMatchedResourceTemplateTwoPostTest() throws Fault {
+    setProperty(Property.REQUEST, buildRequest(Request.POST, "two/P/abc/MyNumber"));
+    setProperty(Property.SEARCH_STRING, "/app/resource/two/" + UriInfoTestResource.TWO_POST);
+    invoke();
+  }
+
+  /**
+   * @testName: getMatchedResourceTemplateSubTest
+   *
+   * @assertion_ids: JAXRS:JAVADOC:97;
+   *
+   * @test_Strategy: Check the template including subresource containing {@link UriInfoTestResource#THREE_SUB}
+   */
+  @Test
+  public void getMatchedResourceTemplateSubTest() throws Fault {
+    setProperty(Property.REQUEST, buildRequest(Request.PUT, "three/a/z"));
+    setProperty(Property.SEARCH_STRING,
+            "/app/resource/three/" + UriInfoTestResource.THREE_SUB + "/" + UriInfoTestResource.THREE_SUB);
+    invoke();
+  }
+}
diff --git a/jaxrs-tck/src/main/java/ee/jakarta/tck/ws/rs/jaxrs40/ee/rs/core/uriinfo/UriInfoTestResource.java b/jaxrs-tck/src/main/java/ee/jakarta/tck/ws/rs/jaxrs40/ee/rs/core/uriinfo/UriInfoTestResource.java
new file mode 100644
index 0000000..f648482
--- /dev/null
+++ b/jaxrs-tck/src/main/java/ee/jakarta/tck/ws/rs/jaxrs40/ee/rs/core/uriinfo/UriInfoTestResource.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2024 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package ee.jakarta.tck.ws.rs.jaxrs40.ee.rs.core.uriinfo;
+
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.POST;
+import jakarta.ws.rs.PUT;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.core.Context;
+import jakarta.ws.rs.core.Response;
+import jakarta.ws.rs.core.UriInfo;
+
+@Path("/resource")
+public class UriInfoTestResource {
+    public static final String ONE_POST = "{name:[a-zA-Z][a-zA-Z_0-9]*}";
+    public static final String TWO_GET = "{Prefix}{p:/?}{id: ((\\d+)?)}/abc{p2:/?}{number: (([A-Za-z0-9]*)?)}";
+    public static final String TWO_POST = "{Prefix}{p:/?}{id: ((\\d+)?)}/abc/{yeah}";
+    public static final String THREE_SUB = "{x:[a-z]}";
+
+    public static class SubGet {
+        @PUT
+        @Path(THREE_SUB)
+        public String get(@Context UriInfo uriInfo) {
+            return uriInfo.getMatchedResourceTemplate();
+        }
+    }
+
+    @POST
+    @Path("one/" + ONE_POST)
+    public Response post(@Context UriInfo info) {
+        return Response.ok(info.getMatchedResourceTemplate()).build();
+    }
+
+    @GET
+    @Path("two/" + TWO_GET)
+    public Response get(@Context UriInfo info) {
+        return Response.ok(info.getMatchedResourceTemplate()).build();
+    }
+
+    @POST
+    @Path("two/" + TWO_POST)
+    public Response postTwo(@Context UriInfo info) {
+        return Response.ok(info.getMatchedResourceTemplate()).build();
+    }
+
+    @Path("three/" + THREE_SUB)
+    public SubGet doAnything4() {
+        return new SubGet();
+    }
+}
diff --git a/jaxrs-tck/src/main/resources/ee/jakarta/tck/ws/rs/ee/resource/webappexception/defaultmapper/web.xml.template b/jaxrs-tck/src/main/resources/ee/jakarta/tck/ws/rs/ee/resource/webappexception/defaultmapper/web.xml.template
new file mode 100644
index 0000000..21dc004
--- /dev/null
+++ b/jaxrs-tck/src/main/resources/ee/jakarta/tck/ws/rs/ee/resource/webappexception/defaultmapper/web.xml.template
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+    Copyright (c) 2024 Oracle and/or its affiliates. All rights reserved.
+    This program and the accompanying materials are made available under the
+    terms of the Eclipse Public License v. 2.0, which is available at
+    http://www.eclipse.org/legal/epl-2.0.
+    This Source Code may also be made available under the following Secondary
+    Licenses when the conditions for such availability set forth in the
+    Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+    version 2 with the GNU Classpath Exception, which is available at
+    https://www.gnu.org/software/classpath/license.html.
+    SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+-->
+
+<web-app version="5.0" xmlns="https://jakarta.ee/xml/ns/jakartaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/web-app_5_0.xsd">
+    <servlet>
+        <servlet-name>CTS_JAXRS_WEBAPPEXCEPTION_MAPPER</servlet-name>
+        <servlet-class>servlet_adaptor</servlet-class>
+        <init-param>
+            <param-name>jakarta.ws.rs.Application</param-name>
+            <param-value>ee.jakarta.tck.ws.rs.ee.resource.webappexception.defaultmapper.TSAppConfig</param-value>
+        </init-param>
+        <load-on-startup>1</load-on-startup>
+    </servlet>
+    <servlet-mapping>
+        <servlet-name>CTS_JAXRS_WEBAPPEXCEPTION_MAPPER</servlet-name>
+        <url-pattern>/*</url-pattern>
+    </servlet-mapping>
+    <session-config>
+        <session-timeout>30</session-timeout>
+    </session-config>
+</web-app>
\ No newline at end of file