TCK Migration: Move pending jaxrs/ee/rs/core,client,ext tests from jakartaee-tck   (#1029)

* Initial change to lift tests from jaxrs/ee/rs/client,core,ext folders in jakartaee-tck

- Removed the build.xml files
- Moved web.xml.template to corresponding resources folder

* fix compilation errors

- rename packages
- add missing classes/jar dependencies
- assertFault change to assertTrue
- deployment code, test run log

* JAXRSClient to JAXRSClientIT for test files

* enable and fix tests

- add @Test annotation
- change assertTrue arguments to append as string
- add classes or packages for archive deployable
- JAXRSProvidersClientIT not to inherit core.application.JAXRSClientIT , duplicate test methods

* fix securitycontext tests, disable failing tests

* correct bad values for system variables
diff --git a/jaxrs-tck/pom.xml b/jaxrs-tck/pom.xml
index 16e7867..5119ba6 100644
--- a/jaxrs-tck/pom.xml
+++ b/jaxrs-tck/pom.xml
@@ -153,7 +153,11 @@
             <version>2.0.1</version>
         </dependency>
 
-
+        <dependency>
+            <groupId>jakarta.validation</groupId>
+            <artifactId>jakarta.validation-api</artifactId>
+            <version>3.0.0</version>
+        </dependency>
 
     </dependencies>
 </project>
\ No newline at end of file
diff --git a/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/api/client/clientrequestcontext/ContextProvider.java b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/api/client/clientrequestcontext/ContextProvider.java
new file mode 100644
index 0000000..742c11d
--- /dev/null
+++ b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/api/client/clientrequestcontext/ContextProvider.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2012, 2020 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 jakarta.ws.rs.tck.api.client.clientrequestcontext;
+
+import java.io.IOException;
+
+import jakarta.ws.rs.tck.common.JAXRSCommonClient.Fault;
+
+import jakarta.ws.rs.client.ClientRequestContext;
+import jakarta.ws.rs.client.ClientRequestFilter;
+import jakarta.ws.rs.ext.Provider;
+
+@Provider
+public class ContextProvider implements ClientRequestFilter {
+
+  protected void checkFilterContext(ClientRequestContext context) throws Fault {
+    throw new Fault("this TCK method is not implemented yet");
+  }
+
+  @Override
+  public void filter(ClientRequestContext context) throws IOException {
+    try {
+      checkFilterContext(context);
+    } catch (Fault e) {
+      throw new IOException(e);
+    }
+  }
+
+}
diff --git a/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/api/client/clientrequestcontext/GetPropertyNamesIsImmutableProvider.java b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/api/client/clientrequestcontext/GetPropertyNamesIsImmutableProvider.java
new file mode 100644
index 0000000..153725a
--- /dev/null
+++ b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/api/client/clientrequestcontext/GetPropertyNamesIsImmutableProvider.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2012, 2020 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 jakarta.ws.rs.tck.api.client.clientrequestcontext;
+
+import java.util.Collection;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import jakarta.ws.rs.tck.common.JAXRSCommonClient.Fault;
+
+import jakarta.ws.rs.client.ClientRequestContext;
+import jakarta.ws.rs.core.Response;
+import jakarta.ws.rs.ext.Provider;
+
+@Provider
+/**
+ * Counter should remain the same as any change would suggest that the
+ * getPropertyNames collection is not immutable
+ */
+public class GetPropertyNamesIsImmutableProvider extends ContextProvider {
+  private AtomicInteger counter;
+
+  public static final String NEWNAME = "AnyNewNameAddedToPropertyNames";
+
+  public GetPropertyNamesIsImmutableProvider(AtomicInteger counter) {
+    super();
+    this.counter = counter;
+  }
+
+  @Override
+  protected void checkFilterContext(ClientRequestContext context) throws Fault {
+    Collection<String> properties = context.getPropertyNames();
+    try {
+      properties.add(NEWNAME);
+    } catch (Exception e) {
+      // any possible exception here is ok as collection should be
+      // immutable
+    }
+    properties = context.getPropertyNames();
+    if (properties.contains(NEWNAME))
+      counter.set(counter.get() + 100);
+    context.abortWith(Response.ok(counter.get()).build());
+  }
+}
diff --git a/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/api/client/clientrequestcontext/GetPropertyNamesProvider.java b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/api/client/clientrequestcontext/GetPropertyNamesProvider.java
new file mode 100644
index 0000000..0ea80fc
--- /dev/null
+++ b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/api/client/clientrequestcontext/GetPropertyNamesProvider.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2012, 2020 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 jakarta.ws.rs.tck.api.client.clientrequestcontext;
+
+import java.util.Collection;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import jakarta.ws.rs.tck.common.JAXRSCommonClient.Fault;
+import jakarta.ws.rs.tck.common.util.JaxrsUtil;
+
+import jakarta.ws.rs.client.ClientRequestContext;
+import jakarta.ws.rs.core.Response;
+
+public class GetPropertyNamesProvider extends ContextProvider {
+  private AtomicInteger counter;
+
+  public GetPropertyNamesProvider(AtomicInteger counter) {
+    super();
+    this.counter = counter;
+  }
+
+  @Override
+  protected void checkFilterContext(ClientRequestContext context) throws Fault {
+    if (counter.incrementAndGet() == 2) {
+      Collection<String> properties = context.getPropertyNames();
+      String entity = properties == null ? "NULL"
+          : JaxrsUtil.iterableToString(";", properties);
+      Response r = Response.ok(entity).build();
+      context.abortWith(r);
+    } else {
+      context.setProperty("PROPERTY1", "value1");
+      context.setProperty("PROPERTY2", "value2");
+    }
+  }
+
+  protected static <T> String collectionToString(Collection<T> collection) {
+    StringBuilder sb = new StringBuilder();
+    for (T t : collection)
+      sb.append(t).append(";");
+    return sb.toString();
+  }
+}
diff --git a/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/api/client/clientrequestcontext/GetSetPropertyProvider.java b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/api/client/clientrequestcontext/GetSetPropertyProvider.java
new file mode 100644
index 0000000..56ae44a
--- /dev/null
+++ b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/api/client/clientrequestcontext/GetSetPropertyProvider.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2012, 2020 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 jakarta.ws.rs.tck.api.client.clientrequestcontext;
+
+import java.util.concurrent.atomic.AtomicInteger;
+
+import jakarta.ws.rs.tck.common.JAXRSCommonClient.Fault;
+
+import jakarta.ws.rs.client.ClientRequestContext;
+import jakarta.ws.rs.core.Response;
+
+public class GetSetPropertyProvider extends ContextProvider {
+  private AtomicInteger counter;
+
+  public GetSetPropertyProvider(AtomicInteger counter) {
+    super();
+    this.counter = counter;
+  }
+
+  @Override
+  protected void checkFilterContext(ClientRequestContext context) throws Fault {
+    Object property = context.getProperty("PROPERTY");
+    String entity = property == null ? "NULL" : property.toString();
+    if (counter.incrementAndGet() == 2) {
+      Response r = Response.ok(entity).build();
+      context.abortWith(r);
+    } else
+      context.setProperty("PROPERTY", "value");
+  }
+
+}
diff --git a/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/api/client/clientrequestcontext/JAXRSClient.java b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/api/client/clientrequestcontext/JAXRSClient.java
new file mode 100644
index 0000000..3686107
--- /dev/null
+++ b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/api/client/clientrequestcontext/JAXRSClient.java
@@ -0,0 +1,1485 @@
+/*
+ * Copyright (c) 2012, 2020 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 jakarta.ws.rs.tck.api.client.clientrequestcontext;
+
+import java.io.ByteArrayInputStream;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import jakarta.ws.rs.tck.lib.util.TestUtil;
+import jakarta.ws.rs.tck.common.JAXRSCommonClient;
+import jakarta.ws.rs.tck.common.provider.StringBean;
+import jakarta.ws.rs.tck.common.provider.StringBeanEntityProvider;
+import jakarta.ws.rs.tck.common.provider.StringBeanRuntimeDelegate;
+import jakarta.ws.rs.tck.common.provider.StringBeanWithAnnotation;
+import jakarta.ws.rs.tck.common.util.JaxrsUtil;
+
+import jakarta.ws.rs.client.Client;
+import jakarta.ws.rs.client.ClientBuilder;
+import jakarta.ws.rs.client.ClientRequestContext;
+import jakarta.ws.rs.client.Entity;
+import jakarta.ws.rs.client.Invocation;
+import jakarta.ws.rs.client.WebTarget;
+import jakarta.ws.rs.core.Configuration;
+import jakarta.ws.rs.core.Cookie;
+import jakarta.ws.rs.core.GenericEntity;
+import jakarta.ws.rs.core.MediaType;
+import jakarta.ws.rs.core.MultivaluedMap;
+import jakarta.ws.rs.core.Response;
+import jakarta.ws.rs.core.Response.Status;
+import jakarta.ws.rs.core.Variant;
+import jakarta.ws.rs.ext.RuntimeDelegate;
+
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+/*
+ * @class.setup_props: webServerHost;
+ *                     webServerPort;
+ *                     ts_home;
+ */
+public class JAXRSClient extends JAXRSCommonClient {
+
+  private static final long serialVersionUID = 8883841555516513076L;
+
+  /**
+   * Entry point for different-VM execution. It should delegate to method
+   * run(String[], PrintWriter, PrintWriter), and this method should not contain
+   * any test configuration.
+   */
+  // public static void main(String[] args) {
+  //   new JAXRSClient().run(args);
+  // }
+
+  /* Run test */
+
+  /*
+   * @testName: abortWithTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:427; JAXRS:JAVADOC:455; JAXRS:JAVADOC:456;
+   * JAXRS:SPEC:85;
+   * 
+   * @test_Strategy: Abort the filter chain with a response. This method breaks
+   * the filter chain processing and returns the provided response back to the
+   * client. The provided response goes through the chain of applicable response
+   * filters.
+   * 
+   * ClientRequestFilter.filter ClientRequestFilter.abortWith
+   */
+  public void abortWithTest() throws Fault {
+    ContextProvider provider = new ContextProvider() {
+      @Override
+      protected void checkFilterContext(ClientRequestContext context)
+          throws Fault {
+        Response r = Response.status(Status.CREATED).build();
+        context.abortWith(r);
+      }
+    };
+    Invocation i = buildInvocation(provider);
+    Response r = invoke(i);
+    assertStatus(r, Status.CREATED);
+  }
+
+  /*
+   * @testName: getAcceptableLanguagesTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:428; JAXRS:JAVADOC:455; JAXRS:JAVADOC:456;
+   * JAXRS:SPEC:85; JAXRS:JAVADOC:427;
+   * 
+   * @test_Strategy: Get a list of languages that are acceptable for the
+   * response. Returns: a read-only list of acceptable languages sorted
+   * according to their q-value, with highest preference first.
+   * 
+   * ClientRequestFilter.filter ClientRequestFilter.abortWith
+   */
+  public void getAcceptableLanguagesTest() throws Fault {
+    ContextProvider provider = new ContextProvider() {
+      @Override
+      protected void checkFilterContext(ClientRequestContext context)
+          throws Fault {
+        List<Locale> locales = context.getAcceptableLanguages();
+        String languages = JaxrsUtil.iterableToString(";", locales);
+        Response r = Response.ok(languages).build();
+        context.abortWith(r);
+      }
+    };
+    Invocation.Builder builder = buildBuilder(provider);
+    Invocation invocation;
+    invocation = builder.acceptLanguage(Locale.CANADA_FRENCH)
+        .acceptLanguage(Locale.PRC).buildGet();
+    Response response = invoke(invocation);
+    String entity = response.readEntity(String.class);
+    assertContains(entity, Locale.CANADA_FRENCH.toString());
+    assertContains(entity, Locale.PRC.toString());
+  }
+
+  /*
+   * @testName: getAcceptableLanguagesByWeightsTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:428; JAXRS:JAVADOC:455; JAXRS:JAVADOC:456;
+   * JAXRS:SPEC:85; JAXRS:JAVADOC:427;
+   * 
+   * @test_Strategy: a read-only list of requested response media types sorted
+   * according to their q-value, with highest preference first.
+   * 
+   * ClientRequestFilter.filter ClientRequestFilter.abortWith
+   */
+  public void getAcceptableLanguagesByWeightsTest() throws Fault {
+    ContextProvider provider = new ContextProvider() {
+      @Override
+      protected void checkFilterContext(ClientRequestContext context)
+          throws Fault {
+        List<Locale> locales = context.getAcceptableLanguages();
+        String languages = JaxrsUtil.iterableToString(";", locales);
+        Response r = Response.ok(languages).build();
+        context.abortWith(r);
+      }
+    };
+    Invocation.Builder builder = buildBuilder(provider);
+    Invocation invocation;
+    invocation = builder.acceptLanguage("da, en-gb;q=0.6, en-us;q=0.7")
+        .buildGet();
+    Response response = invoke(invocation);
+    String entity = response.readEntity(String.class).toLowerCase();
+    assertContains(entity, "da");
+    assertContains(entity, "gb");
+    assertContains(entity, "us");
+    int indexDa = entity.indexOf("da");
+    int indexUs = entity.indexOf("us");
+    int indexGb = entity.indexOf("gb");
+
+    assertTrue(indexDa < indexUs && indexUs < indexGb,
+        "List of acceptable languages"+ entity+ "is not sorted by q values");
+  }
+
+  /*
+   * @testName: getAcceptableLanguagesIsImmutableTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:428; JAXRS:JAVADOC:455; JAXRS:JAVADOC:456;
+   * JAXRS:SPEC:85; JAXRS:JAVADOC:427;
+   * 
+   * @test_Strategy: a read-only list of requested response media types sorted
+   * according to their q-value, with highest preference first.
+   * 
+   * ClientRequestFilter.abortWith
+   */
+  public void getAcceptableLanguagesIsImmutableTest() throws Fault {
+    ContextProvider provider = new ContextProvider() {
+      @Override
+      protected void checkFilterContext(ClientRequestContext context)
+          throws Fault {
+        List<Locale> locales = context.getAcceptableLanguages();
+        try {
+          locales.add(Locale.JAPAN);
+        } catch (Exception e) {
+          // either exception is thrown, or add does nothing
+        }
+        locales = context.getAcceptableLanguages();
+        boolean b = locales.contains(Locale.JAPAN);
+        assertTrue(!b, "getAcceptableLanguages is not read-only");
+        Response r = Response.ok().build();
+        context.abortWith(r);
+      }
+    };
+    WebTarget target = buildTarget(provider);
+    Invocation.Builder builder = target.request();
+    Invocation invocation;
+    invocation = builder
+        .header("Accept-Language", "da, en-gb;q=0.6, en-us;q=0.7").buildGet();
+    Response response = invoke(invocation);
+    assertStatus(response, Status.OK);
+  }
+
+  /*
+   * @testName: getAcceptableMediaTypesTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:429; JAXRS:JAVADOC:455; JAXRS:JAVADOC:456;
+   * JAXRS:SPEC:85; JAXRS:JAVADOC:427;
+   * 
+   * @test_Strategy: Get a list of media types that are acceptable for the
+   * response. Returns a read-only list of requested response media types sorted
+   * according to their q-value, with highest preference first.
+   * 
+   * ClientRequestFilter.abortWith
+   */
+  public void getAcceptableMediaTypesTest() throws Fault {
+    ContextProvider provider = new ContextProvider() {
+      @Override
+      protected void checkFilterContext(ClientRequestContext context)
+          throws Fault {
+        List<MediaType> types = context.getAcceptableMediaTypes();
+        String medias = JaxrsUtil.iterableToString(";", types);
+        Response r = Response.ok(medias).build();
+        context.abortWith(r);
+      }
+    };
+    String media = "text/*;q=0.3, text/html;q=0.7, text/html;level=1, text/html;level=2;q=0.4, */*;q=0.5";
+    Invocation.Builder builder = buildBuilder(provider);
+    Invocation invocation = builder.header("Accept", media).buildGet();
+    Response response = invoke(invocation);
+
+    String entity = response.readEntity(String.class);
+    assertContains(entity, "text/*");
+    assertContains(entity, "text/html");
+    assertContains(entity, "*/*");
+  }
+
+  /*
+   * @testName: getAcceptableMediaTypesIsSortedTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:429; JAXRS:JAVADOC:455; JAXRS:JAVADOC:456;
+   * JAXRS:SPEC:85; JAXRS:JAVADOC:427;
+   * 
+   * @test_Strategy: Get a list of media types that are acceptable for the
+   * response. Returns a read-only list of requested response media types sorted
+   * according to their q-value, with highest preference first.
+   * 
+   * ClientRequestFilter.abortWith
+   */
+  public void getAcceptableMediaTypesIsSortedTest() throws Fault {
+    ContextProvider provider = new ContextProvider() {
+      @Override
+      protected void checkFilterContext(ClientRequestContext context)
+          throws Fault {
+        List<MediaType> types = context.getAcceptableMediaTypes();
+        String medias = JaxrsUtil.iterableToString(";", types);
+        Response r = Response.ok(medias).build();
+        context.abortWith(r);
+      }
+    };
+    String media = "text/plain;q=0.3, text/html;q=0.7, text/xml;level=1, text/java;level=2;q=0.4, */*;q=0.5";
+    Invocation.Builder builder = buildBuilder(provider);
+    Invocation invocation = builder.header("Accept", media).buildGet();
+    Response response = invoke(invocation);
+
+    String entity = response.readEntity(String.class).toLowerCase();
+    int indexXml = entity.indexOf(MediaType.TEXT_XML);
+    int indexHtml = entity.indexOf(MediaType.TEXT_HTML);
+    int indexAny = entity.indexOf(MediaType.WILDCARD);
+    int indexJava = entity.indexOf("text/java");
+    int indexPlain = entity.indexOf(MediaType.TEXT_PLAIN);
+
+    assertTrue(indexXml < indexHtml && indexHtml < indexAny
+        && indexAny < indexJava && indexJava < indexPlain, "Media Types"+
+        entity+ "are not sorted");
+  }
+
+  /*
+   * @testName: getAcceptableMediaTypesIsImmutableTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:429; JAXRS:JAVADOC:455; JAXRS:JAVADOC:456;
+   * JAXRS:SPEC:85; JAXRS:JAVADOC:427;
+   * 
+   * @test_Strategy: Get a list of media types that are acceptable for the
+   * response. Returns a read-only list of requested response media types sorted
+   * according to their q-value, with highest preference first.
+   * 
+   * ClientRequestFilter.abortWith
+   */
+  public void getAcceptableMediaTypesIsImmutableTest() throws Fault {
+    ContextProvider provider = new ContextProvider() {
+      @Override
+      protected void checkFilterContext(ClientRequestContext context)
+          throws Fault {
+        List<MediaType> types = context.getAcceptableMediaTypes();
+        try {
+          types.add(MediaType.APPLICATION_JSON_TYPE);
+        } catch (Exception e) {
+          // either exception is thrown or add does nothing
+        }
+        types = context.getAcceptableMediaTypes();
+        boolean b = types.contains(MediaType.APPLICATION_JSON_TYPE);
+        assertTrue(!b, "getAcceptableMediaTypes is not read only");
+        Response r = Response.ok().build();
+        context.abortWith(r);
+      }
+    };
+    String media = "text/*;q=0.3, text/html;q=0.7, text/html;level=1, text/html;level=2;q=0.4, */*;q=0.5";
+    Invocation.Builder builder = buildBuilder(provider);
+    Invocation invocation = builder.header("Accept", media).buildGet();
+    Response response = invoke(invocation);
+    assertStatus(response, Status.OK);
+  }
+
+  /*
+   * @testName: getClientTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:430; JAXRS:JAVADOC:455; JAXRS:JAVADOC:456;
+   * JAXRS:SPEC:85; JAXRS:JAVADOC:427;
+   * 
+   * @test_Strategy: Get the client instance associated with the request.
+   * 
+   * ClientRequestFilter.abortWith
+   */
+  public void getClientTest() throws Fault {
+    final Client client = ClientBuilder.newClient();
+
+    ContextProvider provider = new ContextProvider() {
+      @Override
+      protected void checkFilterContext(ClientRequestContext context)
+          throws Fault {
+        Client contextClient = context.getClient();
+        assertTrue(client == contextClient,
+            "the client instance is different from the context one");
+        Response r = Response.ok().build();
+        context.abortWith(r);
+      }
+    };
+    client.register(provider);
+    WebTarget target = client.target(getUrl());
+    Invocation invocation = target.request().buildGet();
+    Response response = invoke(invocation);
+    assertStatus(response, Status.OK);
+  }
+
+  /*
+   * @testName: getConfigurationTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:977; JAXRS:JAVADOC:455; JAXRS:JAVADOC:456;
+   * JAXRS:SPEC:85; JAXRS:JAVADOC:427;
+   * 
+   * @test_Strategy: Get the immutable configuration of the request.
+   * 
+   * ClientRequestFilter.abortWith
+   */
+  public void getConfigurationTest() throws Fault {
+    final Client client = ClientBuilder.newClient();
+    ContextProvider provider = new ContextProvider() {
+      @Override
+      protected void checkFilterContext(ClientRequestContext context)
+          throws Fault {
+        Client contextClient = context.getClient();
+        assertEquals(contextClient, client,
+            "the client instance is different from the context one");
+        Configuration contextConfig = context.getConfiguration();
+        assertNotNull(contextConfig,
+            "context.getConfiguration() returned null");
+        Response r = Response.ok().build();
+        context.abortWith(r);
+      }
+    };
+    client.register(provider);
+    WebTarget target = client.target(getUrl());
+    Invocation invocation = target.request().buildGet();
+    Response response = invoke(invocation);
+    assertStatus(response, Status.OK);
+  }
+
+  /*
+   * @testName: getCookiesTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:432; JAXRS:JAVADOC:455; JAXRS:JAVADOC:456;
+   * JAXRS:SPEC:85; JAXRS:JAVADOC:427;
+   * 
+   * @test_Strategy: Get any cookies that accompanied the request. Returns a
+   * read-only map of cookie name (String) to Cookie.
+   * 
+   * ClientRequestFilter.abortWith
+   */
+  public void getCookiesTest() throws Fault {
+    Cookie cts = new Cookie("cts", "cts");
+    Cookie tck = new Cookie("tck", "tck");
+    Cookie jee = new Cookie("jee", "jee");
+
+    ContextProvider provider = new ContextProvider() {
+      @Override
+      protected void checkFilterContext(ClientRequestContext context)
+          throws Fault {
+        String cookies = JaxrsUtil.iterableToString(";",
+            context.getCookies().values());
+        Response r = Response.ok(cookies).build();
+        context.abortWith(r);
+      }
+    };
+    Invocation invocation = buildBuilder(provider).cookie(cts).cookie(tck)
+        .cookie(jee).buildGet();
+    Response response = invoke(invocation);
+
+    String entity = response.readEntity(String.class);
+    assertContains(entity, "cts");
+    assertContains(entity, "tck");
+    assertContains(entity, "jee");
+  }
+
+  /*
+   * @testName: getCookiesIsImmutableTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:432; JAXRS:JAVADOC:455; JAXRS:JAVADOC:456;
+   * JAXRS:SPEC:85; JAXRS:JAVADOC:427;
+   * 
+   * @test_Strategy: Get any cookies that accompanied the request. Returns a
+   * read-only map of cookie name (String) to Cookie.
+   * 
+   * ClientRequestFilter.abortWith
+   */
+  public void getCookiesIsImmutableTest() throws Fault {
+    final Cookie cts = new Cookie("cts", "cts");
+
+    ContextProvider provider = new ContextProvider() {
+      @Override
+      protected void checkFilterContext(ClientRequestContext context)
+          throws Fault {
+        Map<String, Cookie> cookies = context.getCookies();
+        try {
+          cookies.put("test", cts);
+        } catch (Exception e) {
+          // either exception is thrown or put does nothing
+        }
+        cookies = context.getCookies();
+        Cookie cookie = cookies.get("test");
+        assertTrue(cookie == null, "getCookies is not read-only");
+        Response r = Response.ok().build();
+        context.abortWith(r);
+      }
+    };
+    Invocation invocation = buildBuilder(provider).cookie(cts).buildGet();
+    Response response = invoke(invocation);
+    assertStatus(response, Status.OK);
+  }
+
+  /*
+   * @testName: getDateNullTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:433; JAXRS:JAVADOC:455; JAXRS:JAVADOC:456;
+   * JAXRS:SPEC:85; JAXRS:JAVADOC:427;
+   * 
+   * @test_Strategy: Get message date. Returns: the message date, otherwise null
+   * if not present.
+   *
+   * ClientRequestFilter.abortWith
+   */
+  public void getDateNullTest() throws Fault {
+    ContextProvider provider = new ContextProvider() {
+      @Override
+      protected void checkFilterContext(ClientRequestContext context)
+          throws Fault {
+        Date date = context.getDate();
+        Response r = Response.ok(date == null ? "NULL" : date.toString())
+            .build();
+        context.abortWith(r);
+      }
+    };
+    Invocation invocation = buildInvocation(provider);
+    Response response = invoke(invocation);
+
+    String entity = response.readEntity(String.class);
+    assertContains(entity, "NULL");
+  }
+
+  /*
+   * @testName: getDateTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:433; JAXRS:JAVADOC:455; JAXRS:JAVADOC:456;
+   * JAXRS:SPEC:85; JAXRS:JAVADOC:427;
+   * 
+   * @test_Strategy: Get message date. Returns: the message date, otherwise null
+   * if not present.
+   *
+   * ClientRequestFilter.abortWith
+   */
+  public void getDateTest() throws Fault {
+    ContextProvider provider = new ContextProvider() {
+      @Override
+      protected void checkFilterContext(ClientRequestContext context)
+          throws Fault {
+        Date date = context.getDate();
+        Response r = Response.ok(date.toString()).build();
+        context.abortWith(r);
+      }
+    };
+    Invocation invocation = buildBuilder(provider)
+        .header("Date", "Tue, 15 Nov 1994 08:12:31 GMT").buildGet();
+    Response response = invoke(invocation);
+
+    String entity = response.readEntity(String.class);
+    assertContains(entity, "Nov");
+    assertContains(entity, "1994");
+    assertContains(entity, "31");
+  }
+
+  /*
+   * @testName: getEntityNullTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:434; JAXRS:JAVADOC:455; JAXRS:JAVADOC:456;
+   * JAXRS:SPEC:85; JAXRS:JAVADOC:427;
+   * 
+   * @test_Strategy: Get the message entity Java instance. Returns null if the
+   * message does not contain an entity.
+   * 
+   * ClientRequestFilter.abortWith
+   */
+  public void getEntityNullTest() throws Fault {
+    ContextProvider provider = new ContextProvider() {
+      @Override
+      protected void checkFilterContext(ClientRequestContext context)
+          throws Fault {
+        Object entity = context.getEntity();
+        Response r = Response.ok(entity == null ? "NULL" : entity.toString())
+            .build();
+        context.abortWith(r);
+      }
+    };
+    Invocation invocation = buildInvocation(provider);
+    Response response = invoke(invocation);
+
+    String entity = response.readEntity(String.class);
+    assertContains(entity, "NULL");
+  }
+
+  /*
+   * @testName: getEntityTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:434; JAXRS:JAVADOC:455; JAXRS:JAVADOC:456;
+   * JAXRS:SPEC:85;
+   * 
+   * @test_Strategy: Get the message entity Java instance. Returns null if the
+   * message does not contain an entity.
+   * 
+   * ClientRequestFilter.abortWith
+   */
+  public void getEntityTest() throws Fault {
+    ContextProvider provider = new ContextProvider() {
+      @Override
+      protected void checkFilterContext(ClientRequestContext context)
+          throws Fault {
+        Object entity = context.getEntity();
+        Response r = Response.ok(entity.toString()).build();
+        context.abortWith(r);
+      }
+    };
+    Entity<String> post = createEntity("test");
+    Invocation invocation = buildBuilder(provider).buildPost(post);
+    Response response = invoke(invocation);
+
+    String entity = response.readEntity(String.class);
+    assertContains(entity, "test");
+  }
+
+  /*
+   * @testName: getEntityAnnotationsTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:435; JAXRS:JAVADOC:455; JAXRS:JAVADOC:456;
+   * JAXRS:SPEC:85; JAXRS:JAVADOC:427;
+   * 
+   * @test_Strategy: Get the annotations attached to the entity. Note that the
+   * returned annotations array contains only those annotations explicitly
+   * attached to entity instance (such as the ones attached using
+   * Entity.Entity(Object, jakarta.ws.rs.core.MediaType,
+   * java.lang.annotation.Annotation[]) method).
+   * 
+   * ClientRequestFilter.abortWith
+   */
+  public void getEntityAnnotationsTest() throws Fault {
+    Annotation[] annotations = ContextProvider.class.getAnnotations();
+    ContextProvider provider = new ContextProvider() {
+      @Override
+      protected void checkFilterContext(ClientRequestContext context)
+          throws Fault {
+        Annotation[] annotations = context.getEntityAnnotations();
+        String first = annotations == null ? "NULL"
+            : annotations.length == 0 ? "0"
+                : annotations[0].annotationType().getName();
+        Response r = Response.ok(first).build();
+        context.abortWith(r);
+      }
+    };
+    Entity<String> post = Entity.entity("test", MediaType.WILDCARD_TYPE,
+        annotations);
+    Invocation invocation = buildBuilder(provider).buildPost(post);
+    Response response = invoke(invocation);
+
+    String entity = response.readEntity(String.class);
+    assertContains(entity, annotations[0].annotationType().getName());
+  }
+
+  /*
+   * @testName: getEntityAnnotationsIsNotTakenFromEntityClassTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:435; JAXRS:JAVADOC:455; JAXRS:JAVADOC:456;
+   * JAXRS:SPEC:85; JAXRS:JAVADOC:427;
+   * 
+   * @test_Strategy: Get the annotations attached to the entity. Note that the
+   * returned annotations array contains only those annotations explicitly
+   * attached to entity instance (such as the ones attached using
+   * Entity.Entity(Object, jakarta.ws.rs.core.MediaType,
+   * java.lang.annotation.Annotation[]) method). The entity instance annotations
+   * array does not include annotations declared on the entity implementation
+   * class or its ancestors.
+   * 
+   * ClientRequestFilter.abortWith
+   */
+  public void getEntityAnnotationsIsNotTakenFromEntityClassTest() throws Fault {
+    ContextProvider provider = new ContextProvider() {
+      @Override
+      protected void checkFilterContext(ClientRequestContext context)
+          throws Fault {
+        Annotation[] annotations = context.getEntityAnnotations();
+        String first = annotations == null ? "0"
+            : String.valueOf(annotations.length);
+        Response r = Response.ok(first).build();
+        context.abortWith(r);
+      }
+    };
+    Entity<StringBeanWithAnnotation> post = createEntity(
+        new StringBeanWithAnnotation("test"));
+    Invocation invocation = buildTarget(provider)
+        .register(StringBeanEntityProvider.class).request().buildPost(post);
+    Response response = invoke(invocation);
+
+    String entity = response.readEntity(String.class);
+    assertContains(entity, "0");
+  }
+
+  /*
+   * @testName: getEntityAnnotationsNullTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:435; JAXRS:JAVADOC:455; JAXRS:JAVADOC:456;
+   * JAXRS:SPEC:85; JAXRS:JAVADOC:427;
+   * 
+   * @test_Strategy: Get the annotations attached to the entity.
+   * 
+   * ClientRequestFilter.abortWith
+   */
+  public void getEntityAnnotationsNullTest() throws Fault {
+    ContextProvider provider = new ContextProvider() {
+      @Override
+      protected void checkFilterContext(ClientRequestContext context)
+          throws Fault {
+        Annotation[] annotations = context.getEntityAnnotations();
+        String len = annotations == null ? "0"
+            : String.valueOf(annotations.length);
+        Response r = Response.ok(len).build();
+        context.abortWith(r);
+      }
+    };
+    Entity<String> post = createEntity("test");
+    Invocation invocation = buildBuilder(provider).buildPost(post);
+    Response response = invoke(invocation);
+
+    String entity = response.readEntity(String.class);
+    assertContains(entity, "0");
+  }
+
+  /*
+   * @testName: getEntityClassTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:436; JAXRS:JAVADOC:455; JAXRS:JAVADOC:456;
+   * JAXRS:SPEC:85; JAXRS:JAVADOC:427;
+   * 
+   * @test_Strategy: Get the raw entity type information.
+   * 
+   * ClientRequestFilter.abortWith
+   */
+  public void getEntityClassTest() throws Fault {
+    ContextProvider provider = new ContextProvider() {
+      @Override
+      protected void checkFilterContext(ClientRequestContext context)
+          throws Fault {
+        Class<?> clazz = context.getEntityClass();
+        Response r = Response.ok(clazz.getName()).build();
+        context.abortWith(r);
+      }
+    };
+    Entity<ByteArrayInputStream> post = createEntity(
+        new ByteArrayInputStream("test".getBytes()));
+    Invocation invocation = buildBuilder(provider).buildPost(post);
+    Response response = invoke(invocation);
+
+    String entity = response.readEntity(String.class);
+    assertContains(entity, ByteArrayInputStream.class.getName());
+  }
+
+  /*
+   * @testName: getEntityClassListStringTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:436; JAXRS:JAVADOC:455; JAXRS:JAVADOC:456;
+   * JAXRS:SPEC:85; JAXRS:JAVADOC:427;
+   * 
+   * @test_Strategy: Get the raw entity type information.
+   * 
+   * ClientRequestFilter.abortWith
+   */
+  public void getEntityClassListStringTest() throws Fault {
+    ContextProvider provider = new ContextProvider() {
+      @Override
+      protected void checkFilterContext(ClientRequestContext context)
+          throws Fault {
+        Class<?> clazz = context.getEntityClass();
+        Response r = Response.ok(clazz.getName()).build();
+        context.abortWith(r);
+      }
+    };
+    List<String> list = new ArrayList<String>();
+    Entity<List<String>> post = createEntity(list);
+    Invocation invocation = buildBuilder(provider).buildPost(post);
+    Response response = invoke(invocation);
+
+    String entity = response.readEntity(String.class);
+    assertContains(entity, ArrayList.class.getName());
+  }
+
+  /*
+   * @testName: getEntityTypeListStringTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:438; JAXRS:JAVADOC:455; JAXRS:JAVADOC:456;
+   * JAXRS:SPEC:85; JAXRS:JAVADOC:427;
+   * 
+   * @test_Strategy: Get the generic entity type information.
+   * 
+   * ClientRequestFilter.abortWith
+   */
+  public void getEntityTypeListStringTest() throws Fault {
+    ContextProvider provider = new ContextProvider() {
+      @Override
+      protected void checkFilterContext(ClientRequestContext context)
+          throws Fault {
+        Type type = context.getEntityType();
+        String entity = type.toString();
+        Response r = Response.ok(entity).build();
+        context.abortWith(r);
+      }
+    };
+    List<String> list = new ArrayList<String>();
+    GenericEntity<List<String>> generic = new GenericEntity<List<String>>(
+        list) {
+    };
+    Entity<GenericEntity<List<String>>> post = createEntity(generic);
+    Invocation invocation = buildBuilder(provider).buildPost(post);
+    Response response = invoke(invocation);
+
+    String entity = response.readEntity(String.class);
+    assertContains(entity, String.class.getName());
+  }
+
+  /*
+   * @testName: getHeadersTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:439; JAXRS:JAVADOC:455; JAXRS:JAVADOC:456;
+   * JAXRS:SPEC:85; JAXRS:JAVADOC:427;
+   * 
+   * @test_Strategy: Get the mutable request headers multivalued map.
+   * 
+   * ClientRequestFilter.abortWith
+   */
+  public void getHeadersTest() throws Fault {
+    ContextProvider provider = new ContextProvider() {
+      @Override
+      protected void checkFilterContext(ClientRequestContext context)
+          throws Fault {
+        MultivaluedMap<String, Object> headers = context.getHeaders();
+        String entity = JaxrsUtil.iterableToString(";", headers.keySet());
+        Response r = Response.ok(entity).build();
+        context.abortWith(r);
+      }
+    };
+    Invocation invocation = buildBuilder(provider)
+        .header("Accept", MediaType.TEXT_HTML).header("tck", "cts")
+        .header("Date", "Tue, 15 Nov 1994 08:12:31 GMT").buildGet();
+    Response response = invoke(invocation);
+
+    String entity = response.readEntity(String.class);
+    assertContains(entity, "Accept");
+    assertContains(entity, "Date");
+    assertContains(entity, "tck");
+  }
+
+  /*
+   * @testName: getHeadersIsMutableTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:440; JAXRS:JAVADOC:455; JAXRS:JAVADOC:456;
+   * JAXRS:SPEC:85; JAXRS:JAVADOC:427;
+   * 
+   * @test_Strategy: Get the mutable request headers multivalued map.
+   * 
+   * ClientRequestFilter.abortWith
+   */
+  public void getHeadersIsMutableTest() throws Fault {
+    ContextProvider provider = new ContextProvider() {
+      @Override
+      protected void checkFilterContext(ClientRequestContext context)
+          throws Fault {
+        MultivaluedMap<String, Object> headers = context.getHeaders();
+        headers.add("Accept", MediaType.APPLICATION_JSON);
+
+        headers = context.getHeaders();
+        String entity = JaxrsUtil.iterableToString(";", headers.keySet());
+        Response r = Response.ok(entity).build();
+        context.abortWith(r);
+      }
+    };
+    Invocation invocation = buildBuilder(provider).buildGet();
+    Response response = invoke(invocation);
+
+    String entity = response.readEntity(String.class);
+    assertContains(entity, "Accept");
+  }
+
+  /*
+   * @testName: getHeaderStringTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:440; JAXRS:JAVADOC:455; JAXRS:JAVADOC:456;
+   * JAXRS:SPEC:85; JAXRS:JAVADOC:427;
+   * 
+   * @test_Strategy: Get a message header as a single string value.
+   * 
+   * ClientRequestFilter.abortWith
+   */
+  public void getHeaderStringTest() throws Fault {
+    final String TCK = "cts";
+    final String DATE = "Tue, 15 Nov 1994 08:12:31 GMT";
+    ContextProvider provider = new ContextProvider() {
+      @Override
+      protected void checkFilterContext(ClientRequestContext context)
+          throws Fault {
+        String value;
+        value = context.getHeaderString("tck");
+        assertContainsIgnoreCase(value, TCK, "The expected value", TCK,
+            "was not found, found", value, "instead");
+        value = context.getHeaderString("accept");
+        assertContainsIgnoreCase(value, MediaType.TEXT_HTML,
+            "The expected value", MediaType.TEXT_HTML, "was not found, found",
+            value, "instead");
+        value = context.getHeaderString("date");
+        assertContainsIgnoreCase(value, DATE, "The expected value", DATE,
+            "was not found, found", value, "instead");
+        Response r = Response.ok().build();
+        context.abortWith(r);
+      }
+    };
+    Invocation invocation = buildBuilder(provider)
+        .header("Accept", MediaType.TEXT_HTML)
+        .header("tck", new StringBuffer().append(TCK)) // toString()
+        .header("Date", DATE).buildGet();
+    Response response = invoke(invocation);
+    assertStatus(response, Status.OK);
+  }
+
+  /*
+   * @testName: getHeaderStringUsingHeaderDelegateTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:440; JAXRS:JAVADOC:455; JAXRS:JAVADOC:456;
+   * JAXRS:SPEC:85; JAXRS:JAVADOC:427;
+   * 
+   * @test_Strategy: Get a message header as a single string value. Each single
+   * header value is converted to String using a RuntimeDelegate.HeaderDelegate.
+   * 
+   * ClientRequestFilter.abortWith
+   */
+  public void getHeaderStringUsingHeaderDelegateTest() throws Fault {
+    final String name = "BEAN";
+    final StringBean bean = new StringBean(name);
+    ContextProvider provider = new ContextProvider() {
+      @Override
+      protected void checkFilterContext(ClientRequestContext context)
+          throws Fault {
+        String value = context.getHeaderString(name);
+        Response r = Response.ok(value).build();
+        context.abortWith(r);
+      }
+    };
+    RuntimeDelegate original = RuntimeDelegate.getInstance();
+    RuntimeDelegate.setInstance(new StringBeanRuntimeDelegate(original));
+    try {
+      Invocation invocation = buildBuilder(provider).header(name, bean)
+          .buildGet();
+      Response response = invoke(invocation);
+      String body = response.readEntity(String.class);
+      assertContains(name.toLowerCase(), body.toLowerCase());
+    } finally {
+      RuntimeDelegate.setInstance(original);
+      StringBeanRuntimeDelegate.assertNotStringBeanRuntimeDelegate();
+    }
+  }
+
+  /*
+   * @testName: getLanguageIsNullTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:441; JAXRS:JAVADOC:455; JAXRS:JAVADOC:456;
+   * JAXRS:SPEC:85; JAXRS:JAVADOC:427;
+   * 
+   * @test_Strategy: Get the language of the entity. Returns: the language of
+   * the entity or null if not specified
+   * 
+   * ClientRequestFilter.abortWith
+   */
+  public void getLanguageIsNullTest() throws Fault {
+    ContextProvider provider = new ContextProvider() {
+      @Override
+      protected void checkFilterContext(ClientRequestContext context)
+          throws Fault {
+        Locale lang = context.getLanguage();
+        String entity = lang == null ? "NULL" : lang.toString();
+        Response r = Response.ok(entity).build();
+        context.abortWith(r);
+      }
+    };
+    Entity<String> entity = createEntity("TEST");
+    Invocation invocation = buildBuilder(provider).buildPost(entity);
+    Response response = invoke(invocation);
+
+    String body = response.readEntity(String.class);
+    assertContains(body, "NULL");
+  }
+
+  /*
+   * @testName: getLanguageTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:441; JAXRS:JAVADOC:455; JAXRS:JAVADOC:456;
+   * JAXRS:SPEC:85; JAXRS:JAVADOC:427;
+   * 
+   * @test_Strategy: Get the language of the entity. Returns: the language of
+   * the entity or null if not specified
+   * 
+   * ClientRequestFilter.abortWith
+   */
+  public void getLanguageTest() throws Fault {
+    ContextProvider provider = new ContextProvider() {
+      @Override
+      protected void checkFilterContext(ClientRequestContext context)
+          throws Fault {
+        Locale lang = context.getLanguage();
+        String entity = lang == null ? "NULL" : lang.toString();
+        Response r = Response.ok(entity).build();
+        context.abortWith(r);
+      }
+    };
+    Locale locale = Locale.TRADITIONAL_CHINESE;
+    Variant variant = new Variant(MediaType.TEXT_XML_TYPE, locale, null);
+    Entity<String> entity = Entity.entity("TEST", variant);
+    Invocation invocation = buildBuilder(provider).buildPost(entity);
+    Response response = invoke(invocation);
+
+    String body = response.readEntity(String.class).toLowerCase().replace('-',
+        '_');
+    assertContains(body, locale.toString().toLowerCase());
+  }
+
+  /*
+   * @testName: getMediaTypeIsNullTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:442; JAXRS:JAVADOC:455; JAXRS:JAVADOC:456;
+   * JAXRS:SPEC:85; JAXRS:JAVADOC:427;
+   * 
+   * @test_Strategy: Get the media type of the entity. Returns: the media type
+   * or null if not specified (e.g. there's no request entity).
+   * 
+   * ClientRequestFilter.abortWith
+   */
+  public void getMediaTypeIsNullTest() throws Fault {
+    ContextProvider provider = new ContextProvider() {
+      @Override
+      protected void checkFilterContext(ClientRequestContext context)
+          throws Fault {
+        MediaType media = context.getMediaType();
+        String entity = media == null ? "NULL" : media.toString();
+        Response r = Response.ok(entity).build();
+        context.abortWith(r);
+      }
+    };
+    Invocation invocation = buildBuilder(provider).buildGet();
+    Response response = invoke(invocation);
+
+    String body = response.readEntity(String.class);
+    assertContains(body, "NULL");
+  }
+
+  /*
+   * @testName: getMediaTypeTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:442; JAXRS:JAVADOC:455; JAXRS:JAVADOC:456;
+   * JAXRS:SPEC:85; JAXRS:JAVADOC:427;
+   * 
+   * @test_Strategy: Get the media type of the entity. Returns: the media type
+   * or null if not specified (e.g. there's no request entity).
+   * 
+   * ClientRequestFilter.abortWith
+   */
+  public void getMediaTypeTest() throws Fault {
+    ContextProvider provider = new ContextProvider() {
+      @Override
+      protected void checkFilterContext(ClientRequestContext context)
+          throws Fault {
+        MediaType media = context.getMediaType();
+        String entity = media == null ? "NULL" : media.toString();
+        Response r = Response.ok(entity).build();
+        context.abortWith(r);
+      }
+    };
+    Entity<String> entity = Entity.entity("TEST",
+        MediaType.APPLICATION_FORM_URLENCODED);
+    Invocation invocation = buildBuilder(provider).buildPost(entity);
+    Response response = invoke(invocation);
+
+    String body = response.readEntity(String.class);
+    assertContains(body, MediaType.APPLICATION_FORM_URLENCODED);
+  }
+
+  /*
+   * @testName: getMethodTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:443; JAXRS:JAVADOC:455; JAXRS:JAVADOC:456;
+   * JAXRS:SPEC:85; JAXRS:JAVADOC:427;
+   * 
+   * @test_Strategy: Get the request method.
+   * 
+   * ClientRequestFilter.abortWith
+   */
+  public void getMethodTest() throws Fault {
+    ContextProvider provider = new ContextProvider() {
+      @Override
+      protected void checkFilterContext(ClientRequestContext context)
+          throws Fault {
+        String method = context.getMethod();
+        Response r = Response.ok(method).build();
+        context.abortWith(r);
+      }
+    };
+    Entity<String> entity = createEntity("TEST");
+    Invocation invocation;
+    Response response;
+
+    for (String method : new String[] { "OPTIONS", "DELETE", "GET", "TRACE" }) {
+      invocation = buildBuilder(provider).build(method);
+      response = invoke(invocation);
+      String body = response.readEntity(String.class).toUpperCase();
+      assertContains(body, method);
+    }
+
+    for (String method : new String[] { "PUT", "POST" }) {
+      invocation = buildBuilder(provider).build(method, entity);
+      response = invoke(invocation);
+      String body = response.readEntity(String.class).toUpperCase();
+      assertContains(body, method);
+    }
+  }
+
+  /*
+   * @testName: getPropertyIsNullTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:444; JAXRS:JAVADOC:455; JAXRS:JAVADOC:456;
+   * JAXRS:SPEC:85; JAXRS:JAVADOC:427;
+   * 
+   * @test_Strategy: Returns the property with the given name registered in the
+   * current request/response exchange context, or null if there is no property
+   * by that name.
+   * 
+   * ClientRequestFilter.abortWith
+   */
+  public void getPropertyIsNullTest() throws Fault {
+    ContextProvider provider = new ContextProvider() {
+      @Override
+      protected void checkFilterContext(ClientRequestContext context)
+          throws Fault {
+        Object property = context.getProperty("PROPERTY");
+        String entity = property == null ? "NULL" : property.toString();
+        Response r = Response.ok(entity).build();
+        context.abortWith(r);
+      }
+    };
+    Invocation invocation = buildBuilder(provider).buildGet();
+    Response response = invoke(invocation);
+
+    String body = response.readEntity(String.class);
+    assertContains(body, "NULL");
+  }
+
+  /*
+   * @testName: getSetPropertyTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:444; JAXRS:JAVADOC:453; JAXRS:JAVADOC:455;
+   * JAXRS:JAVADOC:456; JAXRS:SPEC:85; JAXRS:JAVADOC:427;
+   * 
+   * @test_Strategy: Returns the property with the given name registered in the
+   * current request/response exchange context, or null if there is no property
+   * by that name.
+   * 
+   * Binds an object to a given property name in the current request/response
+   * exchange context.
+   * 
+   * ClientRequestFilter.abortWith
+   */
+  public void getSetPropertyTest() throws Fault {
+    final AtomicInteger counter = new AtomicInteger(0);
+    ContextProvider provider = new GetSetPropertyProvider(counter);
+    ContextProvider provider2 = new GetSetPropertyProvider(counter) {
+    };
+
+    Invocation invocation = buildInvocation(provider, provider2);
+    Response response = invoke(invocation);
+
+    String body = response.readEntity(String.class);
+    assertContains(body, "value");
+  }
+
+  /*
+   * @testName: getPropertyNamesTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:978; JAXRS:JAVADOC:453; JAXRS:JAVADOC:455;
+   * JAXRS:JAVADOC:456; JAXRS:SPEC:85; JAXRS:JAVADOC:427;
+   * 
+   * @test_Strategy: Returns an immutable collection containing the property
+   * names available within the context of the current request/response exchange
+   * context.
+   * 
+   * Binds an object to a given property name in the current request/response
+   * exchange context.
+   * 
+   * ClientRequestFilter.abortWith
+   */
+  public void getPropertyNamesTest() throws Fault {
+    final AtomicInteger counter = new AtomicInteger(0);
+    ContextProvider provider = new GetPropertyNamesProvider(counter);
+    ContextProvider provider2 = new GetPropertyNamesProvider(counter) {
+    };
+
+    Invocation invocation = buildInvocation(provider, provider2);
+    Response response = invoke(invocation);
+
+    String body = response.readEntity(String.class);
+    assertContains(body, "PROPERTY1");
+    assertContains(body, "PROPERTY2");
+  }
+
+  /*
+   * @testName: getPropertyNamesIsImmutableTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:978; JAXRS:JAVADOC:453; JAXRS:JAVADOC:455;
+   * JAXRS:JAVADOC:456; JAXRS:SPEC:85; JAXRS:JAVADOC:427;
+   * 
+   * @test_Strategy: Returns an immutable collection containing the property
+   * names available within the context of the current request/response exchange
+   * context.
+   * 
+   * Binds an object to a given property name in the current request/response
+   * exchange context.
+   * 
+   * ClientRequestFilter.abortWith
+   */
+  public void getPropertyNamesIsImmutableTest() throws Fault {
+    final AtomicInteger counter = new AtomicInteger(0);
+    ContextProvider provider = new GetPropertyNamesIsImmutableProvider(counter);
+
+    Invocation invocation = buildInvocation(provider);
+    Response response = invoke(invocation);
+    String body = response.readEntity(String.class);
+    assertEqualsInt(0, counter.get(),
+        "getPropertyNames collection is not immutable");
+    assertEquals("0", body, "getPropertyNames collection is not immutable");
+    logMsg("getPropertyNames is immutable as expected");
+  }
+
+  /*
+   * @testName: getStringHeadersTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:446; JAXRS:JAVADOC:455; JAXRS:JAVADOC:456;
+   * JAXRS:SPEC:85; JAXRS:JAVADOC:427;
+   * 
+   * @test_Strategy: Get a string view of header values associated with the
+   * message.
+   * 
+   * ClientRequestFilter.abortWith
+   */
+  public void getStringHeadersTest() throws Fault {
+    final String TCK = "cts";
+    final String DATE = "Tue, 15 Nov 1994 08:12:31 GMT";
+    ContextProvider provider = new ContextProvider() {
+      @Override
+      protected void checkFilterContext(ClientRequestContext context)
+          throws Fault {
+        MultivaluedMap<String, String> map;
+        map = context.getStringHeaders();
+        StringBuilder value = new StringBuilder();
+        value.append(map.getFirst("Accept")).append(" ");
+        value.append(map.getFirst("tck")).append(" ");
+        value.append(map.getFirst("Date"));
+        Response r = Response.ok(value.toString()).build();
+        context.abortWith(r);
+      }
+    };
+    Invocation invocation = buildBuilder(provider)
+        .header("Accept", MediaType.TEXT_HTML).header("tck", TCK)
+        .header("Date", DATE).buildGet();
+    Response response = invoke(invocation);
+    String body = response.readEntity(String.class);
+    assertContains(body, MediaType.TEXT_HTML);
+    assertContains(body, TCK);
+    assertContains(body, DATE);
+  }
+
+  /*
+   * @testName: getStringHeadersReflectsTheUnderlayingMapTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:446; JAXRS:JAVADOC:455; JAXRS:JAVADOC:456;
+   * JAXRS:SPEC:85; JAXRS:JAVADOC:427;
+   * 
+   * @test_Strategy: Get a string view of header values associated with the
+   * message. Changes in the underlying headers map are reflected in this view.
+   * 
+   * ClientRequestFilter.abortWith
+   */
+  public void getStringHeadersReflectsTheUnderlayingMapTest() throws Fault {
+    final String TCK = "cts";
+    ContextProvider provider = new ContextProvider() {
+      @Override
+      protected void checkFilterContext(ClientRequestContext context)
+          throws Fault {
+        context.getHeaders().add(TCK, TCK);
+        MultivaluedMap<String, String> map;
+        map = context.getStringHeaders();
+        String value = map.getFirst(TCK);
+        Response r = Response.ok(value).build();
+        context.abortWith(r);
+      }
+    };
+    Invocation invocation = buildBuilder(provider).buildGet();
+    Response response = invoke(invocation);
+    String body = response.readEntity(String.class);
+    assertContains(body, TCK);
+  }
+
+  /*
+   * @testName: getStringHeadersUsingHeaderDelegateTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:446; JAXRS:JAVADOC:455; JAXRS:JAVADOC:456;
+   * JAXRS:SPEC:85; JAXRS:JAVADOC:427;
+   * 
+   * @test_Strategy: Get a string view of header values associated with the
+   * message. The method converts the non-string header values to strings using
+   * a RuntimeDelegate.HeaderDelegate
+   * 
+   * ClientRequestFilter.abortWith
+   */
+  public void getStringHeadersUsingHeaderDelegateTest() throws Fault {
+    final String TCK = "cts";
+    final StringBean bean = new StringBean(TCK);
+    ContextProvider provider = new ContextProvider() {
+      @Override
+      protected void checkFilterContext(ClientRequestContext context)
+          throws Fault {
+        MultivaluedMap<String, String> map;
+        map = context.getStringHeaders();
+        StringBuilder value = new StringBuilder();
+        value.append(map.getFirst(TCK));
+        Response r = Response.ok(value.toString()).build();
+        context.abortWith(r);
+      }
+    };
+    RuntimeDelegate delegate = RuntimeDelegate.getInstance();
+    RuntimeDelegate.setInstance(new StringBeanRuntimeDelegate(delegate));
+    try {
+      Invocation invocation = buildBuilder(provider).header(TCK, bean)
+          .buildGet();
+      Response response = invoke(invocation);
+      String body = response.readEntity(String.class);
+      assertContains(body, TCK);
+    } finally {
+      RuntimeDelegate.setInstance(delegate);
+      StringBeanRuntimeDelegate.assertNotStringBeanRuntimeDelegate();
+    }
+  }
+
+  /*
+   * @testName: getUriTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:447; JAXRS:JAVADOC:455; JAXRS:JAVADOC:456;
+   * JAXRS:SPEC:85; JAXRS:JAVADOC:427;
+   * 
+   * @test_Strategy: Get the request URI.
+   * 
+   * ClientRequestFilter.abortWith
+   */
+  public void getUriTest() throws Fault {
+    ContextProvider provider = new ContextProvider() {
+      @Override
+      protected void checkFilterContext(ClientRequestContext context)
+          throws Fault {
+        URI uri = context.getUri();
+        String entity = uri.toASCIIString();
+        Response r = Response.ok(entity).build();
+        context.abortWith(r);
+      }
+    };
+
+    Invocation invocation = buildInvocation(provider);
+    Response response = invoke(invocation);
+
+    String body = response.readEntity(String.class);
+    assertContains(body, getUrl());
+  }
+
+  /*
+   * @testName: hasEntityTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:448; JAXRS:JAVADOC:455; JAXRS:JAVADOC:456;
+   * JAXRS:SPEC:85; JAXRS:JAVADOC:427;
+   * 
+   * @test_Strategy: Check if there is an entity available in the request. The
+   * method returns true if the entity is present, returns false otherwise.
+   * 
+   * ClientRequestFilter.abortWith
+   */
+  public void hasEntityTest() throws Fault {
+    ContextProvider provider = new ContextProvider() {
+      @Override
+      protected void checkFilterContext(ClientRequestContext context)
+          throws Fault {
+        boolean has = context.hasEntity();
+        String entity = String.valueOf(has);
+        Response r = Response.ok(entity).build();
+        context.abortWith(r);
+      }
+    };
+
+    Invocation invocation = buildInvocation(provider);
+    Response response = invoke(invocation);
+    String body = response.readEntity(String.class);
+    assertContains(body, "false");
+
+    Entity<String> entity = createEntity("TEST");
+    WebTarget target = buildTarget(provider);
+    invocation = target.request().buildPost(entity);
+    response = invoke(invocation);
+    body = response.readEntity(String.class);
+    assertContains(body, "true");
+  }
+
+  /*
+   * @testName: removePropertyTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:449; JAXRS:JAVADOC:455; JAXRS:JAVADOC:456;
+   * JAXRS:SPEC:85; JAXRS:JAVADOC:427;
+   * 
+   * @test_Strategy:Removes a property with the given name from the current
+   * request/response exchange context. After removal, subsequent calls to
+   * getProperty(java.lang.String) to retrieve the property value will return
+   * null.
+   *
+   * ClientRequestFilter.abortWith
+   */
+  public void removePropertyTest() throws Fault {
+    final AtomicInteger counter = new AtomicInteger(0);
+    ContextProvider provider = new RemovePropertyProvider(counter);
+    ContextProvider provider2 = new RemovePropertyProvider(counter) {
+    };
+    ContextProvider provider3 = new RemovePropertyProvider(counter) {
+    };
+
+    Invocation invocation = buildInvocation(provider, provider2, provider3);
+    Response response = invoke(invocation);
+
+    String body = response.readEntity(String.class);
+    assertContains(body, "NULL");
+  }
+
+  /*
+   * @testName: setEntityTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:450; JAXRS:JAVADOC:434; JAXRS:JAVADOC:435;
+   * JAXRS:JAVADOC:438; JAXRS:JAVADOC:455; JAXRS:JAVADOC:456; JAXRS:SPEC:85;
+   * 
+   * @test_Strategy: Set a new response message entity. It is the callers
+   * responsibility to wrap the actual entity with
+   * jakarta.ws.rs.core.GenericEntity if preservation of its generic type is
+   * required.
+   * 
+   * ClientRequestFilter.abortWith
+   */
+  public void setEntityTest() throws Fault {
+    final AtomicInteger counter = new AtomicInteger(0);
+
+    ContextProvider provider = new SetEntityProvider(counter);
+    ContextProvider provider2 = new SetEntityProvider(counter) {
+    };
+
+    Entity<ByteArrayInputStream> entity = createEntity(
+        new ByteArrayInputStream("test".getBytes()));
+
+    WebTarget target = buildTarget(provider, provider2);
+    Invocation invocation = target.request().buildPost(entity);
+    Response response = invoke(invocation);
+
+    assertStatus(response, Status.OK);
+  }
+
+  // ///////////////////////////////////////////////////////////////////////
+  /**
+   * Call given provider CheckContextFilter method
+   */
+  protected static Response invoke(Invocation i) throws Fault {
+    Response r = null;
+    try {
+      r = i.invoke();
+    } catch (Exception e) {
+      Object cause = e.getCause();
+      if (cause instanceof Fault)
+        throw (Fault) cause;
+      else
+        throw new Fault(e);
+    }
+    return r;
+  }
+
+  protected static Invocation buildInvocation(ContextProvider... provider) {
+    WebTarget target = buildTarget(provider);
+    Invocation i = target.request().buildGet();
+    return i;
+  }
+
+  protected static WebTarget buildTarget(ContextProvider... providers) {
+    Client client = ClientBuilder.newClient();
+    for (ContextProvider provider : providers)
+      client.register(provider);
+    WebTarget target = client.target(getUrl());
+    return target;
+  }
+
+  protected static Invocation.Builder buildBuilder(
+      ContextProvider... provider) {
+    Invocation.Builder builder = buildTarget(provider).request();
+    return builder;
+  }
+
+  protected static void assertStatus(Response r, Status status) throws Fault {
+    assertTrue(r.getStatus() == status.getStatusCode(), "Expected"+
+        status.getStatusCode()+ "got"+ r.getStatus());
+    TestUtil.logMsg("Found expected status: " + status.getStatusCode());
+  }
+
+  protected static void assertContains(String string, String substring)
+      throws Fault {
+    assertTrue(string.contains(substring), string+ "does NOT contain"+
+        substring+ ", it is:"+ string);
+    TestUtil.logMsg("Found expected substring: " + substring);
+  }
+
+  /**
+   * @return any possible url
+   */
+  protected static String getUrl() {
+    return "http://localhost:8080/404URL/";
+  }
+
+  protected <T> Entity<T> createEntity(T entity) {
+    return Entity.entity(entity, MediaType.WILDCARD_TYPE);
+  }
+}
diff --git a/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/api/client/clientrequestcontext/RemovePropertyProvider.java b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/api/client/clientrequestcontext/RemovePropertyProvider.java
new file mode 100644
index 0000000..be186e3
--- /dev/null
+++ b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/api/client/clientrequestcontext/RemovePropertyProvider.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2012, 2020 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 jakarta.ws.rs.tck.api.client.clientrequestcontext;
+
+import java.util.concurrent.atomic.AtomicInteger;
+
+import jakarta.ws.rs.tck.common.JAXRSCommonClient.Fault;
+
+import jakarta.ws.rs.client.ClientRequestContext;
+import jakarta.ws.rs.core.Response;
+
+public class RemovePropertyProvider extends ContextProvider {
+  private AtomicInteger counter;
+
+  public RemovePropertyProvider(AtomicInteger counter) {
+    super();
+    this.counter = counter;
+  }
+
+  @Override
+  protected void checkFilterContext(ClientRequestContext context) throws Fault {
+    String propName = "PROPERTY";
+    switch (counter.incrementAndGet()) {
+    case 1:
+      Object property = context.getProperty(propName);
+      assertFault(property == null, "property already exist");
+      context.setProperty(propName, propName);
+      break;
+    case 2:
+      property = context.getProperty(propName);
+      assertFault(property != null, "property not exist");
+      context.removeProperty(propName);
+      break;
+    case 3:
+      property = context.getProperty(propName);
+      assertFault(property == null, "property already exist");
+      Response response = Response.ok("NULL").build();
+      context.abortWith(response);
+      break;
+    }
+  }
+
+  /**
+   * @param conditionTrue
+   * @param message
+   * @throws Fault
+   *           when conditionTrue is not met with message provided
+   */
+  protected static void //
+      assertFault(boolean conditionTrue, Object... message) throws Fault {
+    if (!conditionTrue) {
+      StringBuilder sb = new StringBuilder();
+      for (Object msg : message)
+        sb.append(msg).append(" ");
+      throw new Fault(sb.toString());
+    }
+  }
+
+}
diff --git a/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/api/client/clientrequestcontext/SetEntityProvider.java b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/api/client/clientrequestcontext/SetEntityProvider.java
new file mode 100644
index 0000000..376827e
--- /dev/null
+++ b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/api/client/clientrequestcontext/SetEntityProvider.java
@@ -0,0 +1,124 @@
+/*
+ * Copyright (c) 2012, 2020 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 jakarta.ws.rs.tck.api.client.clientrequestcontext;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import jakarta.ws.rs.tck.common.JAXRSCommonClient.Fault;
+import jakarta.ws.rs.tck.lib.util.TestUtil;
+
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.POST;
+import jakarta.ws.rs.client.ClientRequestContext;
+import jakarta.ws.rs.core.MediaType;
+import jakarta.ws.rs.core.Response;
+
+public class SetEntityProvider extends ContextProvider {
+  private AtomicInteger counter;
+
+  protected Annotation anno1 = new GET() {
+    @Override
+    public Class<? extends Annotation> annotationType() {
+      return null;
+    }
+  };
+
+  protected Annotation anno2 = new POST() {
+    @Override
+    public Class<? extends Annotation> annotationType() {
+      return null;
+    }
+  };
+
+  protected Annotation[] annos = new Annotation[] { anno1, anno2 };
+
+  protected MediaType type = MediaType.MULTIPART_FORM_DATA_TYPE;
+
+  protected String entityName = "ENTITY";
+
+  public SetEntityProvider(AtomicInteger counter) {
+    super();
+    this.counter = counter;
+  }
+
+  /**
+   * This method expects the request with entity != String.class has been sent
+   * Also, the mediaType is MediaType.WILDCARD_TYPE
+   */
+  @Override
+  protected void checkFilterContext(ClientRequestContext context) throws Fault {
+    Object entity;
+    MediaType mtype;
+    Annotation[] annotations;
+    Type clz;
+    switch (counter.incrementAndGet()) {
+    case 1:
+      TestUtil.logMsg("Counter is 1");
+      // get
+      entity = context.getEntity();
+      mtype = context.getMediaType();
+      annotations = context.getEntityAnnotations();
+      clz = context.getEntityType();
+      // check
+      assertFault(entity != null, "there is no entity, yet");
+      assertFault(!entity.toString().equals(entityName),
+          "the fake entity was already set");
+      assertFault(annotations == null || annotations.length == 0,
+          "there are already annotations!");
+      assertFault(!mtype.equals(type), "fake MediaType is already set");
+      assertFault(clz != String.class, "String entity is already set");
+      // set
+      context.setEntity(entityName, annos, type);
+      break;
+    case 2:
+      TestUtil.logMsg("Counter is 2");
+      // get
+      entity = context.getEntity();
+      mtype = context.getMediaType();
+      annotations = context.getEntityAnnotations();
+      clz = context.getEntityType();
+      // check
+      assertFault(entity != null, "there is no entity set");
+      assertFault(entity.toString().equals(entityName),
+          "there is no fake entity set, yet");
+      assertFault(annotations.length == 2,
+          "the fake annotations were not set, yet");
+      assertFault(mtype.equals(type), "fake MediaType was not set, yet");
+      assertFault(clz == String.class, "String entity not set, yet");
+      // set
+      context.setEntity(entityName, annos, type);
+      Response response = Response.ok().build();
+      context.abortWith(response);
+      break;
+    }
+  }
+
+  /**
+   * @param conditionTrue
+   * @param message
+   * @throws Fault
+   *           when conditionTrue is not met with message provided
+   */
+  protected static void //
+      assertFault(boolean conditionTrue, Object message) throws Fault {
+    if (!conditionTrue) {
+      throw new Fault(message.toString());
+    }
+  }
+}
diff --git a/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/api/rs/core/configurable/Assertable.java b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/api/rs/core/configurable/Assertable.java
new file mode 100644
index 0000000..66ca227
--- /dev/null
+++ b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/api/rs/core/configurable/Assertable.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2012, 2020 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 jakarta.ws.rs.tck.api.rs.core.configurable;
+
+import jakarta.ws.rs.tck.common.JAXRSCommonClient.Fault;
+
+import jakarta.ws.rs.client.Client;
+import jakarta.ws.rs.client.WebTarget;
+
+public abstract class Assertable {
+  final static String[] LOCATION = { "Client", "WebTarget",
+      "Invocation.Builder", "Invocation" };
+
+  private int locationIndex = 0;
+
+  public abstract void check1OnClient(Client client) throws Fault;
+
+  public abstract void check2OnTarget(WebTarget target) throws Fault;
+
+  public void incrementLocation() {
+    locationIndex = (locationIndex + 1 == LOCATION.length) ? 0
+        : locationIndex + 1;
+  }
+
+  public String getLocation() {
+    return new StringBuilder().append("on ").append(LOCATION[locationIndex])
+        .append(" configuration").toString();
+  }
+
+  public static String getLocation(int index) {
+    return LOCATION[index];
+  }
+
+  public int getLocationIndex() {
+    return locationIndex;
+  }
+
+}
diff --git a/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/api/rs/core/configurable/CallableProvider.java b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/api/rs/core/configurable/CallableProvider.java
new file mode 100644
index 0000000..d8d406e
--- /dev/null
+++ b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/api/rs/core/configurable/CallableProvider.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2012, 2020 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 jakarta.ws.rs.tck.api.rs.core.configurable;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+import java.util.concurrent.Callable;
+
+import jakarta.ws.rs.tck.common.util.JaxrsUtil;
+
+import jakarta.ws.rs.WebApplicationException;
+import jakarta.ws.rs.core.MediaType;
+import jakarta.ws.rs.core.MultivaluedMap;
+import jakarta.ws.rs.ext.MessageBodyReader;
+import jakarta.ws.rs.ext.MessageBodyWriter;
+import jakarta.ws.rs.ext.Provider;
+
+@Provider
+public class CallableProvider
+    implements MessageBodyWriter<Callable<?>>, MessageBodyReader<Callable<?>> {
+
+  @Override
+  public long getSize(Callable<?> arg0, Class<?> arg1, Type arg2,
+      Annotation[] arg3, MediaType arg4) {
+    return arg0.toString().length();
+  }
+
+  @Override
+  public boolean isWriteable(Class<?> arg0, Type arg1, Annotation[] arg2,
+      MediaType arg3) {
+    return Callable.class.isAssignableFrom(arg0);
+  }
+
+  @Override
+  public void writeTo(Callable<?> arg0, Class<?> arg1, Type arg2,
+      Annotation[] arg3, MediaType arg4, MultivaluedMap<String, Object> arg5,
+      OutputStream arg6) throws IOException, WebApplicationException {
+    arg6.write(arg0.toString().getBytes());
+  }
+
+  @Override
+  public boolean isReadable(Class<?> type, Type genericType,
+      Annotation[] annotations, MediaType mediaType) {
+    return isWriteable(type, genericType, annotations, mediaType);
+  }
+
+  @Override
+  public Callable<?> readFrom(Class<Callable<?>> type, Type genericType,
+      Annotation[] annotations, MediaType mediaType,
+      MultivaluedMap<String, String> httpHeaders,
+      final InputStream entityStream)
+      throws IOException, WebApplicationException {
+    String content = null;
+    try {
+      content = JaxrsUtil.readFromStream(entityStream);
+      entityStream.close();
+    } catch (Exception e) {
+      content = "Error while reading Callable from InputStream";
+    }
+    return createCallable(content);
+  }
+
+  public static Callable<String> createCallable(final String content) {
+    Callable<String> callable = new Callable<String>() {
+      @Override
+      public String call() throws Exception {
+        return toString();
+      }
+
+      @Override
+      public String toString() {
+        return content;
+      }
+    };
+    return callable;
+  }
+
+}
diff --git a/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/api/rs/core/configurable/ConfigurableObject.java b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/api/rs/core/configurable/ConfigurableObject.java
new file mode 100644
index 0000000..27e5b01
--- /dev/null
+++ b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/api/rs/core/configurable/ConfigurableObject.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2012, 2020 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 jakarta.ws.rs.tck.api.rs.core.configurable;
+
+import jakarta.ws.rs.core.Configurable;
+
+/**
+ * Wraps Client, WebTarget and Invocation objects that have configuration()
+ * method
+ */
+public interface ConfigurableObject {
+
+  void config(Configurable<?> config);
+
+}
diff --git a/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/api/rs/core/configurable/FeatureReturningFalse.java b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/api/rs/core/configurable/FeatureReturningFalse.java
new file mode 100644
index 0000000..650cf11
--- /dev/null
+++ b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/api/rs/core/configurable/FeatureReturningFalse.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2013, 2020 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 jakarta.ws.rs.tck.api.rs.core.configurable;
+
+import jakarta.ws.rs.core.Feature;
+import jakarta.ws.rs.core.FeatureContext;
+
+public class FeatureReturningFalse implements Feature {
+  @Override
+  public boolean configure(FeatureContext context) {
+    // false returning feature is not to be registered
+    return false;
+  }
+}
diff --git a/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/api/rs/core/configurable/JAXRSClient.java b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/api/rs/core/configurable/JAXRSClient.java
new file mode 100644
index 0000000..d0cda9e
--- /dev/null
+++ b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/api/rs/core/configurable/JAXRSClient.java
@@ -0,0 +1,241 @@
+/*
+ * Copyright (c) 2012, 2020 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 jakarta.ws.rs.tck.api.rs.core.configurable;
+
+import jakarta.ws.rs.tck.common.JAXRSCommonClient;
+
+import jakarta.ws.rs.client.Client;
+import jakarta.ws.rs.client.ClientBuilder;
+import jakarta.ws.rs.client.WebTarget;
+import jakarta.ws.rs.core.Configurable;
+import jakarta.ws.rs.core.Configuration;
+import jakarta.ws.rs.core.Feature;
+
+/*
+ * @class.setup_props: webServerHost;
+ *                     webServerPort;
+ *                     ts_home;
+ */
+public class JAXRSClient extends JAXRSCommonClient {
+
+  private static final long serialVersionUID = -6880902064949040518L;
+
+  private int registeredClassesCnt = -1;
+
+  private int registeredInstancesCnt = -1;
+
+  /**
+   * Entry point for different-VM execution. It should delegate to method
+   * run(String[], PrintWriter, PrintWriter), and this method should not contain
+   * any test configuration.
+   */
+  // public static void main(String[] args) {
+  //   new JAXRSClient().run(args);
+  // }
+
+  /* Run test */
+
+  /*
+   * @testName: registerFeatureClassReturningFalseTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:754;
+   * 
+   * @test_Strategy: Register a feature meta-provider to be instantiated and
+   * used in the scope of this configurable context.
+   * 
+   * Any subsequent registration attempts for a component type, for which a
+   * class or instance-based registration already exists in the system MUST be
+   * rejected by the JAX-RS implementation and a warning SHOULD be raised to
+   * inform the user about the rejected registration.
+   */
+  public void registerFeatureClassReturningFalseTest() throws Fault {
+    Assertable assertable = new SingleCheckAssertable() {
+      @Override
+      protected void check(Configurable<?> configurable) throws Fault {
+        assertSizeAndLog(configurable);
+      }
+
+      void assertSizeAndLog(Configurable<?> config) throws Fault {
+        int cnt = config.getConfiguration().getClasses().size();
+        assertEqualsInt(cnt, 1 + registeredClassesCnt,
+            "unexpected number of registered classes found:", cnt,
+            getLocation());
+        logMsg("Found", cnt, "features");
+      }
+
+    };
+    Class<?>[] classes = new Class<?>[] { FeatureReturningFalse.class,
+        FeatureReturningFalse.class };
+    checkConfig(assertable, classes);
+  }
+
+  /*
+   * @testName: registerFeatureClassReturningFalseWithPriorityTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:755;
+   * 
+   * @test_Strategy: Register a feature meta-provider to be instantiated and
+   * used in the scope of this configurable context.
+   * 
+   * Any subsequent registration attempts for a component type, for which a
+   * class or instance-based registration already exists in the system MUST be
+   * rejected by the JAX-RS implementation and a warning SHOULD be raised to
+   * inform the user about the rejected registration.
+   */
+  public void registerFeatureClassReturningFalseWithPriorityTest()
+      throws Fault {
+    Assertable assertable = new SingleCheckAssertable() {
+      @Override
+      protected void check(Configurable<?> configurable) throws Fault {
+        assertSizeAndLog(configurable);
+      }
+
+      void assertSizeAndLog(Configurable<?> config) throws Fault {
+        int cnt = config.getConfiguration().getClasses().size();
+        assertEqualsInt(cnt, 1 + registeredClassesCnt,
+            "unexpected number of registered classes found:", cnt,
+            getLocation());
+        logMsg("Found", cnt, "features");
+      }
+
+    };
+
+    Registrar registrar = new Registrar() {
+      int priority = 0;
+
+      @Override
+      public void register(Configurable<?> config, Object registerable) {
+        config.register((Class<?>) registerable, ++priority);
+      }
+    };
+
+    Class<?>[] classes = new Class<?>[] { FeatureReturningFalse.class,
+        FeatureReturningFalse.class };
+    checkConfig(registrar, assertable, classes);
+  }
+
+  /*
+   * @testName: registerFeatureInstanceReturningFalseTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:758;
+   * 
+   * @test_Strategy: Register a feature. In case the registered provider is a
+   * client-side Feature feature, this object instantiates the feature and
+   * invokes the Feature#configure(FeatureContext) method and lets the feature
+   * update it's internal configuration state.
+   */
+  public void registerFeatureInstanceReturningFalseTest() throws Fault {
+    final Feature feature = new FeatureReturningFalse();
+    Assertable assertable = new SingleCheckAssertable() {
+      @Override
+      protected void check(Configurable<?> configurable) throws Fault {
+        assertSizeAndLog(configurable);
+      }
+
+      void assertSizeAndLog(Configurable<?> config) throws Fault {
+        int cnt = config.getConfiguration().getInstances().size();
+        assertEqualsInt(cnt, 1 + registeredInstancesCnt,
+            "unexpected number of registered instances found:", cnt,
+            getLocation());
+        logMsg("Found", cnt, "features");
+      }
+
+    };
+    Object[] features = new Object[] { feature, feature };
+    checkConfig(assertable, features);
+  }
+
+  /*
+   * @testName: registerClassContractsTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:756;
+   * 
+   * @test_Strategy: Register a feature meta-provider to be instantiated and
+   * used in the scope of this configurable context.
+   * 
+   * Any subsequent registration attempts for a component type, for which a
+   * class or instance-based registration already exists in the system MUST be
+   * rejected by the JAX-RS implementation and a warning SHOULD be raised to
+   * inform the user about the rejected registration.
+   */
+  public void registerClassContractsTest() throws Fault {
+    Assertable assertable = new SingleCheckAssertable() {
+      @Override
+      protected void check(Configurable<?> configurable) throws Fault {
+        assertSizeAndLog(configurable);
+      }
+
+      void assertSizeAndLog(Configurable<?> config) throws Fault {
+        int cnt = config.getConfiguration().getClasses().size();
+        assertEqualsInt(cnt, 1 + registeredClassesCnt,
+            "unexpected number of registered classes found:", cnt,
+            getLocation());
+        logMsg("Found", cnt, "features");
+      }
+
+    };
+
+    Registrar registrar = new Registrar() {
+      int priority = 0;
+
+      @Override
+      public void register(Configurable<?> config, Object registerable) {
+        config.register((Class<?>) registerable, ++priority);
+      }
+    };
+
+    Class<?>[] classes = new Class<?>[] { FeatureReturningFalse.class,
+        FeatureReturningFalse.class };
+    checkConfig(registrar, assertable, classes);
+  }
+
+  // ///////////////////////////////////////////////////////////////////////
+  /**
+   * Check on every possible setting of configuration by a Feature or a
+   * singleton
+   * 
+   */
+  protected void checkConfig(Assertable assertable, Object[] registerables)
+      throws Fault {
+    checkConfig(new Registrar(), assertable, registerables);
+  }
+
+  protected void checkConfig(Registrar registrar, Assertable assertable,
+      Object[] registerables) throws Fault {
+    Client client = ClientBuilder.newClient();
+    Configuration config = client.getConfiguration();
+    registeredClassesCnt = config.getClasses().size();
+    registeredInstancesCnt = config.getInstances().size();
+    logMsg("Already registered", registeredClassesCnt, "classes");
+    logMsg("Already registered", registeredInstancesCnt, "instances");
+
+    register(registrar, client, registerables[0]);
+    assertable.check1OnClient(client);
+    assertable.incrementLocation();
+
+    WebTarget target = client.target("http://tck.cts:888");
+    register(registrar, target, registerables[1]);
+    assertable.check2OnTarget(target);
+    assertable.incrementLocation();
+  }
+
+  protected void register(Registrar registrar, Configurable<?> config,
+      Object registerable) {
+    registrar.register(config, registerable);
+  }
+
+}
diff --git a/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/api/rs/core/configurable/Registrar.java b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/api/rs/core/configurable/Registrar.java
new file mode 100644
index 0000000..efd796b
--- /dev/null
+++ b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/api/rs/core/configurable/Registrar.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2012, 2020 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 jakarta.ws.rs.tck.api.rs.core.configurable;
+
+import jakarta.ws.rs.core.Configurable;
+
+/**
+ * We need the possibility to override the way the registerable is registered
+ * The default behavior is for single argument register method
+ */
+public class Registrar {
+  public void register(Configurable<?> config, Object registerable) {
+    if (registerable instanceof Class) // register(Class)
+      config.register((Class<?>) registerable);
+    else if (registerable instanceof String) // setProperty()
+      config.property((String) registerable, registerable);
+    else
+      // register(Object)
+      config.register(registerable);
+  }
+}
diff --git a/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/api/rs/core/configurable/SingleCheckAssertable.java b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/api/rs/core/configurable/SingleCheckAssertable.java
new file mode 100644
index 0000000..3c4a76a
--- /dev/null
+++ b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/api/rs/core/configurable/SingleCheckAssertable.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2012, 2020 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 jakarta.ws.rs.tck.api.rs.core.configurable;
+
+import jakarta.ws.rs.tck.common.JAXRSCommonClient.Fault;
+
+import jakarta.ws.rs.client.Client;
+import jakarta.ws.rs.client.WebTarget;
+import jakarta.ws.rs.core.Configurable;
+
+public abstract class SingleCheckAssertable extends Assertable {
+
+  protected abstract void check(Configurable<?> configurable) throws Fault;
+
+  @Override
+  public void check1OnClient(Client client) throws Fault {
+    check(client);
+  }
+
+  @Override
+  public void check2OnTarget(WebTarget target) throws Fault {
+    check(target);
+  }
+
+}
diff --git a/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/api/rs/ext/interceptor/ContextOperation.java b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/api/rs/ext/interceptor/ContextOperation.java
new file mode 100644
index 0000000..d53401b
--- /dev/null
+++ b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/api/rs/ext/interceptor/ContextOperation.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2012, 2020 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 jakarta.ws.rs.tck.api.rs.ext.interceptor;
+
+import jakarta.annotation.Priority;
+import jakarta.ws.rs.ext.Provider;
+
+@Provider
+@Priority(100)
+/**
+ * These annotations are to get them set in InterceptorBodyOne#setAnnotations()
+ */
+public enum ContextOperation {
+  GETANNOTATIONS, GETGENERICTYPE, GETMEDIATYPE, GETPROPERTY, GETPROPERTYNAMES, GETPROPERTYNAMESISREADONLY, GETTYPE, REMOVEPROPERTY, SETANNOTATIONS, SETANNOTATIONSNULL, SETGENERICTYPE, SETMEDIATYPE, SETPROPERTY, SETPROPERTYNULL, SETTYPE, IOEXCEPTION, WEBAPPLICATIONEXCEPTION
+}
diff --git a/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/api/rs/ext/interceptor/InputStreamReaderProvider.java b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/api/rs/ext/interceptor/InputStreamReaderProvider.java
new file mode 100644
index 0000000..18ae459
--- /dev/null
+++ b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/api/rs/ext/interceptor/InputStreamReaderProvider.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2012, 2020 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 jakarta.ws.rs.tck.api.rs.ext.interceptor;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+
+import jakarta.ws.rs.tck.common.util.JaxrsUtil;
+
+import jakarta.ws.rs.WebApplicationException;
+import jakarta.ws.rs.core.MediaType;
+import jakarta.ws.rs.core.MultivaluedMap;
+import jakarta.ws.rs.ext.MessageBodyReader;
+import jakarta.ws.rs.ext.MessageBodyWriter;
+import jakarta.ws.rs.ext.Provider;
+
+@Provider
+public class InputStreamReaderProvider implements
+    MessageBodyReader<InputStreamReader>, MessageBodyWriter<InputStreamReader> {
+
+  @Override
+  public long getSize(InputStreamReader arg0, Class<?> arg1, Type arg2,
+      Annotation[] arg3, MediaType arg4) {
+    return InputStreamReader.class.getName().length();
+  }
+
+  @Override
+  public boolean isWriteable(Class<?> arg0, Type arg1, Annotation[] arg2,
+      MediaType arg3) {
+    return arg0 == InputStreamReader.class;
+  }
+
+  @Override
+  public void writeTo(InputStreamReader arg0, Class<?> arg1, Type arg2,
+      Annotation[] arg3, MediaType arg4, MultivaluedMap<String, Object> arg5,
+      OutputStream arg6) throws IOException, WebApplicationException {
+    String entity = JaxrsUtil.readFromReader(arg0);
+    arg0.close();
+    arg6.write(entity.getBytes());
+  }
+
+  @Override
+  public boolean isReadable(Class<?> arg0, Type arg1, Annotation[] arg2,
+      MediaType arg3) {
+    return isWriteable(arg0, arg1, arg2, arg3);
+  }
+
+  @Override
+  public InputStreamReader readFrom(Class<InputStreamReader> arg0, Type arg1,
+      Annotation[] arg2, MediaType arg3, MultivaluedMap<String, String> arg4,
+      InputStream arg5) throws IOException, WebApplicationException {
+    return new InputStreamReader(arg5);
+  }
+
+}
diff --git a/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/api/rs/ext/interceptor/InterceptorBodyOne.java b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/api/rs/ext/interceptor/InterceptorBodyOne.java
new file mode 100644
index 0000000..f7dbce8
--- /dev/null
+++ b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/api/rs/ext/interceptor/InterceptorBodyOne.java
@@ -0,0 +1,148 @@
+/*
+ * Copyright (c) 2012, 2020 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 jakarta.ws.rs.tck.api.rs.ext.interceptor;
+
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+import java.util.Collection;
+
+import jakarta.ws.rs.WebApplicationException;
+import jakarta.ws.rs.core.MediaType;
+import jakarta.ws.rs.core.Response;
+import jakarta.ws.rs.core.Response.Status;
+import jakarta.ws.rs.ext.InterceptorContext;
+
+public class InterceptorBodyOne<CONTEXT extends InterceptorContext>
+    extends TemplateInterceptorBody<CONTEXT> {
+
+  public void getAnnotations() {
+    Annotation[] annotations = context.getAnnotations();
+    setSeparatedEntity(";", annotations);
+  }
+
+  public void getGenericType() {
+    Type type = context.getGenericType();
+    String entity = null;
+    if (type instanceof Class)
+      entity = ((Class<?>) type).getName();
+    else
+      entity = type.toString();
+    setEntity(entity);
+  }
+
+  public void getMediaType() {
+    MediaType type = context.getMediaType();
+    setEntity(type);
+  }
+
+  public void getProperty() {
+    Object o = context.getProperty(PROPERTY);
+    setEntity(o == null ? NULL : ENTITY2);
+  }
+
+  public void getPropertyNames() {
+    for (int i = 0; i != 5; i++)
+      context.setProperty(PROPERTY + i, PROPERTY);
+  }
+
+  public void getPropertyNamesIsReadOnly() {
+    Collection<String> names = context.getPropertyNames();
+    int size = names.size();
+    for (int i = 0; i != 5; i++)
+      try {
+        names.add(PROPERTY + i);
+      } catch (Exception e) {
+        // exception is possible
+      }
+    names = context.getPropertyNames();
+    assertTrue(names.size() == size, "Unexpected property names", names);
+    setEntity(NULL);
+  }
+
+  public void getType() {
+    Class<?> type = context.getType();
+    setEntity(type.getName());
+  }
+
+  public void removeProperty() {
+    context.setProperty(PROPERTY, NULL);
+    assertTrue(NULL.equals(context.getProperty(PROPERTY)), PROPERTY,
+        "property not found");
+    context.removeProperty(PROPERTY);
+    Object o = context.getProperty(PROPERTY);
+    setEntity(o == null ? NULL : o.toString());
+  }
+
+  public void setAnnotations() {
+    Annotation[] annotations = ContextOperation.class.getAnnotations();
+    context.setAnnotations(annotations);
+    getAnnotations();
+  }
+
+  public void setAnnotationsNull() {
+    try {
+      context.setAnnotations(null);
+      setEntity(NULL);
+    } catch (NullPointerException e) {
+      setEntity(NPE);
+    }
+  }
+
+  public void setGenericType() {
+    byte[] array = new byte[0];
+    context.setGenericType(array.getClass());
+    getGenericType();
+  }
+
+  public void setMediaType() {
+    MediaType type = MediaType.APPLICATION_FORM_URLENCODED_TYPE;
+    context.setMediaType(type);
+    getMediaType();
+  }
+
+  public void setProperty() {
+    StringBuilder sb = new StringBuilder();
+    sb.append(ENTITY2);
+    context.setProperty(PROPERTY, NULL);
+    context.setProperty(PROPERTY, sb);
+  }
+
+  public void setPropertyNull() {
+    context.setProperty(ENTITY2, ENTITY2);
+    assertTrue(context.getProperty(ENTITY2) != null, "Property", ENTITY2,
+        "set but not found");
+    context.setProperty(ENTITY2, null);
+    String o = (String) context.getProperty(ENTITY2);
+    setEntity(o == null ? NULL : o);
+  }
+
+  public void setType() {
+    context.setType(InputStreamReader.class);
+    getType();
+  }
+
+  public void ioException() throws IOException {
+    throw new IOException(IOE);
+  }
+
+  public void webApplicationException() {
+    throw new WebApplicationException(
+        Response.status(Status.CONFLICT).entity(ENTITY2).build());
+  }
+}
diff --git a/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/api/rs/ext/interceptor/InterceptorBodyTwo.java b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/api/rs/ext/interceptor/InterceptorBodyTwo.java
new file mode 100644
index 0000000..bb6a6eb
--- /dev/null
+++ b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/api/rs/ext/interceptor/InterceptorBodyTwo.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2012, 2020 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 jakarta.ws.rs.tck.api.rs.ext.interceptor;
+
+import java.io.IOException;
+import java.util.Collection;
+
+import jakarta.ws.rs.tck.common.util.JaxrsUtil;
+
+import jakarta.ws.rs.ext.InterceptorContext;
+
+public class InterceptorBodyTwo<CONTEXT extends InterceptorContext>
+    extends TemplateInterceptorBody<CONTEXT> {
+
+  @Override
+  protected Object operationMethodNotFound(String operation)
+      throws IOException {
+    return proceed();
+  }
+
+  public void getPropertyNames() {
+    Collection<String> names = context.getPropertyNames();
+    setEntity(JaxrsUtil.iterableToString(";", names));
+  }
+
+  public void setProperty() {
+    Object property = context.getProperty(PROPERTY);
+    if (property instanceof StringBuilder)
+      setEntity(property.toString());
+    else
+      setEntity(NULL);
+  }
+}
diff --git a/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/api/rs/ext/interceptor/InterceptorCallbackMethods.java b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/api/rs/ext/interceptor/InterceptorCallbackMethods.java
new file mode 100644
index 0000000..78bf87e
--- /dev/null
+++ b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/api/rs/ext/interceptor/InterceptorCallbackMethods.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2012, 2018 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 jakarta.ws.rs.tck.api.rs.ext.interceptor;
+
+import java.io.IOException;
+
+/**
+ * Every InterceptorContext has different way to get header OPERATION, proceed,
+ * or write an entity to a response. Therefore, TemplateInterceptorBody is given
+ * the implementation of this interface so that it can abstractly call these
+ * methods no matter the given context.
+ * 
+ * It is passed as an argument to the only call-able method
+ * {@link TemplateInterceptorBody#executeMethod()}
+ */
+public interface InterceptorCallbackMethods {
+  void writeEntity(String entity);
+
+  Object proceed() throws IOException;
+
+  String getHeaderString();
+}
diff --git a/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/api/rs/ext/interceptor/TemplateInterceptorBody.java b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/api/rs/ext/interceptor/TemplateInterceptorBody.java
new file mode 100644
index 0000000..039a772
--- /dev/null
+++ b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/api/rs/ext/interceptor/TemplateInterceptorBody.java
@@ -0,0 +1,124 @@
+/*
+ * Copyright (c) 2012, 2020 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 jakarta.ws.rs.tck.api.rs.ext.interceptor;
+
+import java.io.IOException;
+import java.lang.reflect.Method;
+
+import jakarta.ws.rs.tck.common.util.JaxrsUtil;
+
+import jakarta.ws.rs.ext.InterceptorContext;
+
+/**
+ * Body for both reader and writer interceptor body The body is injected into
+ * Template<Reader/Writer>Interceptor
+ * 
+ * @param <CONTEXT>
+ *          The context the body methods will use.
+ */
+public abstract class TemplateInterceptorBody<CONTEXT extends InterceptorContext> {
+  public static final String OPERATION = "OPERATION";
+
+  public static final String ENTITY = "Entity";
+
+  public static final String ENTITY2 = "Other Entity";
+
+  public static final String PROPERTY = "Property";
+
+  public static final String NULL = "None";
+
+  public static final String NPE = "NullPointerException has been thrown as expected";
+
+  public static final String IOE = "IOException has been thrown as expected";
+
+  public static final String WAE = "WebApplicationException has been thrown as expected";
+
+  protected CONTEXT context;
+
+  protected InterceptorCallbackMethods callback;
+
+  public Object executeMethod(CONTEXT context,
+      InterceptorCallbackMethods callback) throws IOException {
+    this.context = context;
+    this.callback = callback;
+    String operation = getHeaderString();
+    Method[] methods = getClass().getMethods();
+    for (Method method : methods)
+      if (operation.equalsIgnoreCase(method.getName())) {
+        try {
+          Object ret = method.invoke(this);
+          if (ret == null)
+            return proceed();
+          else
+            return ret; // the method ensures the call of proceed();
+        } catch (Exception e) {
+          if (IOException.class.isInstance(e.getCause()))
+            throw (IOException) e.getCause();
+          else if (e.getCause() instanceof RuntimeException)
+            throw (RuntimeException) e.getCause();
+          else
+            throwIOEAndLog(operation, e);
+        }
+      }
+    return operationMethodNotFound(operation);
+  }
+
+  private static void throwIOEAndLog(String operation, Throwable e)
+      throws IOException {
+    System.out.println("Error while invoking method " + operation);
+    e.printStackTrace();
+    throw new IOException(e);
+  }
+
+  protected Object operationMethodNotFound(String operation)
+      throws IOException {
+    throw new IOException("Operation " + operation + " not implemented");
+  }
+
+  // ////////////////////////////////////////////////////////////////////
+  protected void assertTrue(boolean conditionTrue, Object... msg) {
+    if (conditionTrue)
+      return;
+    StringBuilder sb = new StringBuilder();
+    if (msg != null)
+      for (Object str : msg)
+        sb.append(str).append(" ");
+    throw new RuntimeException(new IOException(sb.toString()));
+  }
+
+  protected <T> void setEntity(T... entity) {
+    setSeparatedEntity(" ", entity);
+  }
+
+  protected <T> void setSeparatedEntity(String separator, T... entity) {
+    String complete = JaxrsUtil.iterableToString(separator, entity);
+    writeEntity(complete);
+  }
+
+  protected void writeEntity(String entity) {
+    callback.writeEntity(entity);
+  }
+
+  protected Object proceed() throws IOException {
+    return callback.proceed();
+  }
+
+  protected String getHeaderString() {
+    return callback.getHeaderString();
+  }
+
+}
diff --git a/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/api/rs/ext/interceptor/reader/ReaderClient.java b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/api/rs/ext/interceptor/reader/ReaderClient.java
new file mode 100644
index 0000000..06e5046
--- /dev/null
+++ b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/api/rs/ext/interceptor/reader/ReaderClient.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2012, 2020 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 jakarta.ws.rs.tck.api.rs.ext.interceptor.reader;
+
+import java.io.IOException;
+
+import jakarta.ws.rs.tck.api.rs.ext.interceptor.TemplateInterceptorBody;
+import jakarta.ws.rs.tck.common.client.JaxrsCommonClient;
+
+import jakarta.ws.rs.client.ClientRequestContext;
+import jakarta.ws.rs.client.ClientRequestFilter;
+import jakarta.ws.rs.core.Response;
+
+/**
+ * Client with given ContextOperation enum, so that an enum name is passed as a
+ * http header to an interceptor. Due to the ContextOperation, the proper method
+ * on an interceptor is called.
+ * 
+ * @param <CONTEXTOPERATION>
+ */
+public abstract class ReaderClient<CONTEXTOPERATION extends Enum<?>>
+    extends JaxrsCommonClient {
+
+  private static final long serialVersionUID = 7145627888730121260L;
+
+  /**
+   * Create response to be faked as returned from server
+   */
+  protected Response.ResponseBuilder createResponse(CONTEXTOPERATION op) {
+    Response.ResponseBuilder builder = Response.ok()
+        .header(TemplateInterceptorBody.OPERATION, op.name())
+        .entity(TemplateInterceptorBody.ENTITY);
+    return builder;
+  }
+
+  /**
+   * Create a request filter to be aborted with given fake response simulating
+   * the resource from a request
+   * 
+   * @param response
+   * @return
+   */
+  protected static ClientRequestFilter createRequestFilter(
+      final Response response) {
+    ClientRequestFilter outFilter = new ClientRequestFilter() {
+
+      @Override
+      public void filter(ClientRequestContext context) throws IOException {
+        Response r;
+        if (response == null)
+          r = Response.ok().build();
+        else
+          r = response;
+        context.abortWith(r);
+      }
+    };
+    return outFilter;
+  }
+
+  /**
+   * Invoke and convert IOException to Fault
+   */
+  protected void invoke() throws Fault {
+    try {
+      setProperty(Property.REQUEST, buildRequest(Request.GET, "404URL/"));
+      super.invoke();
+    } catch (Exception cause) {
+      if (cause instanceof IOException)
+        throw new Fault(cause.getMessage());
+      else
+        throw new Fault(cause);
+    }
+  }
+
+  /**
+   * Register providers to client configuration
+   * 
+   * @param response
+   *          ClientRequestFilter#abortWith response
+   */
+  protected void addProviders(Response response) throws Fault {
+    ClientRequestFilter requestFilter = createRequestFilter(response);
+    addProvider(requestFilter);
+  }
+}
diff --git a/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/api/rs/ext/interceptor/reader/TemplateReaderInterceptor.java b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/api/rs/ext/interceptor/reader/TemplateReaderInterceptor.java
new file mode 100644
index 0000000..a717918
--- /dev/null
+++ b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/api/rs/ext/interceptor/reader/TemplateReaderInterceptor.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2012, 2020 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 jakarta.ws.rs.tck.api.rs.ext.interceptor.reader;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+
+import jakarta.ws.rs.tck.api.rs.ext.interceptor.InterceptorCallbackMethods;
+import jakarta.ws.rs.tck.api.rs.ext.interceptor.TemplateInterceptorBody;
+
+import jakarta.ws.rs.WebApplicationException;
+import jakarta.ws.rs.core.MultivaluedMap;
+import jakarta.ws.rs.ext.ReaderInterceptor;
+import jakarta.ws.rs.ext.ReaderInterceptorContext;
+
+/**
+ * This class is a superclass for any interceptor @Provider. Any such provider
+ * is then given a body, inherited from TemplateInterceptorBody. The body
+ * actually contains methods with name equalIgnoreCase to ContextOperation items
+ * name, the name of the method executed is passed by http header OPERATION
+ * 
+ * @see TemplateInterceptorBody
+ * 
+ *      The injection of the body solves the issue with inheritance from two
+ *      super-classes.
+ */
+public abstract class TemplateReaderInterceptor
+    implements ReaderInterceptor, InterceptorCallbackMethods {
+
+  protected ReaderInterceptorContext readerCtx;
+
+  protected TemplateInterceptorBody<ReaderInterceptorContext> interceptorBody;
+
+  public TemplateReaderInterceptor(
+      TemplateInterceptorBody<ReaderInterceptorContext> interceptorBody) {
+    super();
+    this.interceptorBody = interceptorBody;
+  }
+
+  @Override
+  public Object aroundReadFrom(ReaderInterceptorContext ctx)
+      throws IOException, WebApplicationException {
+    this.readerCtx = ctx;
+    return interceptorBody.executeMethod(readerCtx, this);
+  }
+
+  @Override
+  public void writeEntity(String entity) {
+    readerCtx.setInputStream(new ByteArrayInputStream(entity.getBytes()));
+  }
+
+  @Override
+  public Object proceed() throws IOException {
+    return readerCtx.proceed();
+  }
+
+  @Override
+  public String getHeaderString() {
+    MultivaluedMap<String, String> headers = readerCtx.getHeaders();
+    return headers.getFirst(TemplateInterceptorBody.OPERATION);
+  }
+
+}
diff --git a/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/api/rs/ext/interceptor/reader/interceptorcontext/JAXRSClient.java b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/api/rs/ext/interceptor/reader/interceptorcontext/JAXRSClient.java
new file mode 100644
index 0000000..3e6eedd
--- /dev/null
+++ b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/api/rs/ext/interceptor/reader/interceptorcontext/JAXRSClient.java
@@ -0,0 +1,442 @@
+/*
+ * Copyright (c) 2012, 2020 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 jakarta.ws.rs.tck.api.rs.ext.interceptor.reader.interceptorcontext;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.lang.annotation.Annotation;
+
+import jakarta.ws.rs.tck.api.rs.ext.interceptor.ContextOperation;
+import jakarta.ws.rs.tck.api.rs.ext.interceptor.InputStreamReaderProvider;
+import jakarta.ws.rs.tck.api.rs.ext.interceptor.TemplateInterceptorBody;
+import jakarta.ws.rs.tck.api.rs.ext.interceptor.reader.ReaderClient;
+import jakarta.ws.rs.tck.common.util.JaxrsUtil;
+
+import jakarta.ws.rs.WebApplicationException;
+import jakarta.ws.rs.core.MediaType;
+import jakarta.ws.rs.core.Response;
+import jakarta.ws.rs.core.Response.ResponseBuilder;
+import jakarta.ws.rs.core.Response.Status;
+
+import static org.junit.jupiter.api.Assertions.assertTrue;
+/*
+ * @class.setup_props: webServerHost;
+ *                     webServerPort;
+ *                     ts_home;
+ */
+public class JAXRSClient extends ReaderClient<ContextOperation> {
+
+  private static final long serialVersionUID = -8828149277776372718L;
+
+  /* Run test */
+  /*
+   * @testName: getAnnotationsTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:903; JAXRS:JAVADOC:920; JAXRS:SPEC:85;
+   * 
+   * @test_Strategy: Get an array of the annotations formally declared on the
+   * artifact that initiated the intercepted entity provider invocation. The
+   * annotations are not on client reader.
+   * 
+   * ReaderInterceptor.aroundReadFrom If abortWith is invoked, execution is
+   * aborted
+   */
+  public void getAnnotationsTest() throws Fault {
+    Annotation[] annotations = ContextOperation.class.getAnnotations();
+    ResponseBuilder builder = createResponse(ContextOperation.GETANNOTATIONS);
+    Response fake = builder.entity(TemplateInterceptorBody.ENTITY, annotations)
+        .build();
+    addProviders(fake);
+    for (Annotation a : annotations)
+      setProperty(Property.UNEXPECTED_RESPONSE_MATCH,
+          a.annotationType().getName());
+    invoke();
+  }
+
+  /*
+   * @testName: getGenericTypeTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:904; JAXRS:JAVADOC:920; JAXRS:SPEC:85;
+   * 
+   * @test_Strategy: Get an array of the annotations formally declared on the
+   * artifact that initiated the intercepted entity provider invocation.
+   * 
+   * If abortWith is invoked, execution is aborted
+   */
+  public void getGenericTypeTest() throws Fault {
+    ResponseBuilder builder = createResponse(ContextOperation.GETGENERICTYPE);
+    Response fake = builder.build();
+
+    addProviders(fake);
+    setProperty(Property.SEARCH_STRING, String.class.getName());
+    invoke();
+  }
+
+  /*
+   * @testName: getMediaTypeTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:905; JAXRS:JAVADOC:920; JAXRS:SPEC:85;
+   * 
+   * @test_Strategy: Get media type of HTTP entity.
+   *
+   * ReaderInterceptor.aroundReadFrom If abortWith is invoked, execution is
+   * aborted
+   */
+  public void getMediaTypeTest() throws Fault {
+    ResponseBuilder builder = createResponse(ContextOperation.GETMEDIATYPE);
+    Response fake = builder.type(MediaType.APPLICATION_JSON_TYPE).build();
+
+    addProviders(fake);
+    setProperty(Property.SEARCH_STRING, MediaType.APPLICATION_JSON);
+    invoke();
+  }
+
+  /*
+   * @testName: getPropertyIsNullTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:906; JAXRS:JAVADOC:920; JAXRS:SPEC:85;
+   * 
+   * @test_Strategy: Returns null if there is no property by that name.
+   * 
+   * ReaderInterceptor.aroundReadFrom If abortWith is invoked, execution is
+   * aborted
+   */
+  public void getPropertyIsNullTest() throws Fault {
+    ResponseBuilder builder = createResponse(ContextOperation.GETPROPERTY);
+    Response fake = builder.build();
+
+    addProviders(fake);
+    setProperty(Property.SEARCH_STRING, TemplateInterceptorBody.NULL);
+    invoke();
+  }
+
+  /*
+   * @testName: getPropertyNamesTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:1007; JAXRS:JAVADOC:920; JAXRS:SPEC:85;
+   * 
+   * @test_Strategy: Returns immutable java.util.Collection collection
+   * containing the property names available within the context of the current
+   * request/response exchange context.
+   * 
+   * ReaderInterceptor.aroundReadFrom If abortWith is invoked, execution is
+   * aborted
+   */
+  public void getPropertyNamesTest() throws Fault {
+    ResponseBuilder builder = createResponse(ContextOperation.GETPROPERTYNAMES);
+    Response fake = builder.build();
+
+    addProviders(fake);
+    for (int i = 0; i != 5; i++)
+      setProperty(Property.UNORDERED_SEARCH_STRING,
+          TemplateInterceptorBody.PROPERTY + i);
+    invoke();
+  }
+
+  /*
+   * @testName: getPropertyNamesIsReadOnlyTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:1007; JAXRS:JAVADOC:920; JAXRS:SPEC:85;
+   * 
+   * @test_Strategy: Returns immutable java.util.Collection containing the
+   * property names available within the context of the current request/response
+   * exchange context.
+   * 
+   * ReaderInterceptor.aroundReadFrom If abortWith is invoked, execution is
+   * aborted
+   */
+  public void getPropertyNamesIsReadOnlyTest() throws Fault {
+    ResponseBuilder builder = createResponse(
+        ContextOperation.GETPROPERTYNAMESISREADONLY);
+    Response fake = builder.build();
+
+    addProviders(fake);
+    setProperty(Property.UNORDERED_SEARCH_STRING, TemplateInterceptorBody.NULL);
+    invoke();
+  }
+
+  /*
+   * @testName: getTypeTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:908; JAXRS:JAVADOC:920; JAXRS:SPEC:85;
+   * 
+   * @test_Strategy: Get Java type supported by corresponding message body
+   * provider.
+   * 
+   * ReaderInterceptor.aroundReadFrom If abortWith is invoked, execution is
+   * aborted
+   */
+  public void getTypeTest() throws Fault {
+    ResponseBuilder builder = createResponse(ContextOperation.GETTYPE);
+    Response fake = builder.build();
+
+    addProviders(fake);
+    setProperty(Property.SEARCH_STRING, String.class.getName());
+    invoke();
+  }
+
+  /*
+   * @testName: removePropertyTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:909; JAXRS:JAVADOC:920; JAXRS:SPEC:85;
+   * 
+   * @test_Strategy: Removes a property with the given name from the current
+   * request/response exchange context. After removal, subsequent calls to
+   * getProperty(java.lang.String) to retrieve the property value will return
+   * null.
+   * 
+   * ReaderInterceptor.aroundReadFrom If abortWith is invoked, execution is
+   * aborted
+   */
+  public void removePropertyTest() throws Fault {
+    ResponseBuilder builder = createResponse(ContextOperation.REMOVEPROPERTY);
+    Response fake = builder.build();
+
+    addProviders(fake);
+    setProperty(Property.SEARCH_STRING, TemplateInterceptorBody.NULL);
+    invoke();
+  }
+
+  /*
+   * @testName: setAnnotationsTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:910; JAXRS:JAVADOC:920; JAXRS:SPEC:85;
+   * 
+   * @test_Strategy: Update annotations on the formal declaration of the
+   * artifact that initiated the intercepted entity provider invocation.
+   * 
+   * ReaderInterceptor.aroundReadFrom If abortWith is invoked, execution is
+   * aborted
+   */
+  public void setAnnotationsTest() throws Fault {
+    Annotation[] annotations = ReaderInterceptorOne.class.getAnnotations();
+    ResponseBuilder builder = createResponse(ContextOperation.SETANNOTATIONS);
+    Response fake = builder.build();
+    addProviders(fake);
+    for (Annotation a : annotations)
+      setProperty(Property.UNORDERED_SEARCH_STRING,
+          a.annotationType().getName());
+    invoke();
+  }
+
+  /*
+   * @testName: setAnnotationsNullThrowsNPETest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:910; JAXRS:JAVADOC:920;
+   * 
+   * @test_Strategy: Throws NullPointerException - in case the input parameter
+   * is null.
+   * 
+   * ReaderInterceptor.aroundReadFrom If abortWith is invoked, execution is
+   * aborted
+   */
+  public void setAnnotationsNullThrowsNPETest() throws Fault {
+    ResponseBuilder builder = createResponse(
+        ContextOperation.SETANNOTATIONSNULL);
+    Response fake = builder.entity(TemplateInterceptorBody.ENTITY).build();
+    addProviders(fake);
+    setProperty(Property.SEARCH_STRING, TemplateInterceptorBody.NPE);
+    invoke();
+  }
+
+  /*
+   * @testName: setGenericTypeTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:911; JAXRS:JAVADOC:920; JAXRS:SPEC:85;
+   * 
+   * @test_Strategy: Update type of the object to be produced or written.
+   * 
+   * ReaderInterceptor.aroundReadFrom If abortWith is invoked, execution is
+   * aborted
+   */
+  public void setGenericTypeTest() throws Fault {
+    ResponseBuilder builder = createResponse(ContextOperation.SETGENERICTYPE);
+    Response fake = builder.build();
+
+    addProviders(fake);
+    setProperty(Property.SEARCH_STRING, "[B");
+    invoke();
+  }
+
+  /*
+   * @testName: setMediaTypeTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:912; JAXRS:JAVADOC:920; JAXRS:SPEC:85;
+   * 
+   * @test_Strategy: Update media type of HTTP entity.
+   * 
+   * ReaderInterceptor.aroundReadFrom If abortWith is invoked, execution is
+   * aborted
+   */
+  public void setMediaTypeTest() throws Fault {
+    ResponseBuilder builder = createResponse(ContextOperation.SETMEDIATYPE);
+    Response fake = builder.build();
+
+    addProviders(fake);
+    setProperty(Property.SEARCH_STRING, MediaType.APPLICATION_FORM_URLENCODED);
+    invoke();
+  }
+
+  /*
+   * @testName: setPropertyTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:913; JAXRS:JAVADOC:920; JAXRS:SPEC:85;
+   * 
+   * @test_Strategy: Binds an object to a given property name in the current
+   * request/response exchange context. If the name specified is already used
+   * for a property, this method will replace the value of the property with the
+   * new value.
+   * 
+   * ReaderInterceptor.aroundReadFrom If abortWith is invoked, execution is
+   * aborted
+   */
+  public void setPropertyTest() throws Fault {
+    ResponseBuilder builder = createResponse(ContextOperation.SETPROPERTY);
+    Response fake = builder.build();
+
+    addProviders(fake);
+    setProperty(Property.SEARCH_STRING, TemplateInterceptorBody.ENTITY2);
+    invoke();
+  }
+
+  /*
+   * @testName: setPropertyNullTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:913; JAXRS:JAVADOC:920; JAXRS:SPEC:85;
+   * 
+   * @test_Strategy: If a null value is passed, the effect is the same as
+   * calling the removeProperty(String) method.
+   * 
+   * ReaderInterceptor.aroundReadFrom If abortWith is invoked, execution is
+   * aborted
+   */
+  public void setPropertyNullTest() throws Fault {
+    ResponseBuilder builder = createResponse(ContextOperation.SETPROPERTYNULL);
+    Response fake = builder.build();
+
+    addProviders(fake);
+    setProperty(Property.SEARCH_STRING, TemplateInterceptorBody.NULL);
+    invoke();
+  }
+
+  /*
+   * @testName: setTypeTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:914; JAXRS:JAVADOC:920; JAXRS:SPEC:85;
+   * 
+   * @test_Strategy: Update Java type before calling message body provider.
+   * 
+   * ReaderInterceptor.aroundReadFrom If abortWith is invoked, execution is
+   * aborted
+   */
+  public void setTypeTest() throws Fault {
+    ResponseBuilder builder = createResponse(ContextOperation.SETTYPE);
+    ByteArrayInputStream bais = new ByteArrayInputStream(
+        TemplateInterceptorBody.ENTITY.getBytes());
+    Reader reader = new InputStreamReader(bais);
+    Response fake = builder.entity(reader).build();
+
+    addProviders(fake);
+    addProvider(InputStreamReaderProvider.class);
+    invoke();
+    InputStreamReader isr = getResponseBody(InputStreamReader.class);
+    try {
+      String entity = JaxrsUtil.readFromReader(isr);
+      assertTrue(entity.contains(InputStreamReader.class.getName()),
+          "Expected"+ InputStreamReader.class.getName()+ "not found");
+      logMsg("#setType set correct type", entity);
+    } catch (IOException e) {
+      throw new Fault(e);
+    }
+  }
+
+  /*
+   * @testName: ioExceptionTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:921; JAXRS:JAVADOC:920; JAXRS:SPEC:85;
+   * 
+   * @test_Strategy: Throws IOException - if an IO error arises.
+   * 
+   * ReaderInterceptor.aroundReadFrom If abortWith is invoked, execution is
+   * aborted
+   */
+  public void ioExceptionTest() throws Fault {
+    ResponseBuilder builder = createResponse(ContextOperation.IOEXCEPTION);
+    Response fake = builder.build();
+    addProviders(fake);
+    invoke();
+    try {
+      getResponseBody();
+    } catch (Exception e) {
+      assertNotNull(e.getMessage(), "Returned unexpected exception", e);
+      IOException io = assertCause(e, IOException.class,
+          "Unexpected exception has been found:", e);
+      assertContains(io.getMessage(), TemplateInterceptorBody.IOE,
+          "Found unexpected message from IOException", e.getMessage());
+      logMsg("found expected IOException", io);
+      return;
+    }
+    fault("Expected IOException not found");
+  }
+
+  /*
+   * @testName: webApplicationExceptionTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:922; JAXRS:JAVADOC:920; JAXRS:SPEC:85;
+   * 
+   * @test_Strategy: throws WebApplicationException thrown by wrapped method.
+   * 
+   * ReaderInterceptor.aroundReadFrom If abortWith is invoked, execution is
+   * aborted
+   */
+  public void webApplicationExceptionTest() throws Fault {
+    ResponseBuilder builder = createResponse(
+        ContextOperation.WEBAPPLICATIONEXCEPTION);
+    Response fake = builder.build();
+    addProviders(fake);
+    invoke();
+    try {
+      getResponseBody();
+    } catch (Exception e) {
+      WebApplicationException we = assertCause(e, WebApplicationException.class,
+          "Found unexpected exception", e);
+      assertNotNull(we.getResponse(),
+          "WebApplicationException.getResponse is null");
+      Response response = we.getResponse();
+      String entity = response.getEntity().toString();
+      assertEqualsInt(Status.CONFLICT.getStatusCode(), response.getStatus(),
+          "Unexcpected status returned from WebApplicationException.getResponse",
+          response.getStatus());
+      assertEquals(TemplateInterceptorBody.ENTITY2, entity,
+          "Found unexpected body content from WebApplicationException.getResponse",
+          entity);
+      logMsg("found expected WebApplicationException", we);
+      return;
+    }
+    fault("Expected WebApplicationException not found");
+  }
+
+  // /////////////////////////////////////////////////////////////////////
+  @Override
+  protected void addProviders(Response response) throws Fault {
+    super.addProviders(response);
+    addProvider(ReaderInterceptorTwo.class);
+    addProvider(new ReaderInterceptorOne());
+  }
+}
diff --git a/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/api/rs/ext/interceptor/reader/interceptorcontext/ReaderInterceptorOne.java b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/api/rs/ext/interceptor/reader/interceptorcontext/ReaderInterceptorOne.java
new file mode 100644
index 0000000..9d270b6
--- /dev/null
+++ b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/api/rs/ext/interceptor/reader/interceptorcontext/ReaderInterceptorOne.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2012, 2020 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 jakarta.ws.rs.tck.api.rs.ext.interceptor.reader.interceptorcontext;
+
+import jakarta.ws.rs.tck.api.rs.ext.interceptor.InterceptorBodyOne;
+import jakarta.ws.rs.tck.api.rs.ext.interceptor.reader.TemplateReaderInterceptor;
+
+import jakarta.annotation.Priority;
+import jakarta.ws.rs.ext.Provider;
+import jakarta.ws.rs.ext.ReaderInterceptorContext;
+
+@Provider
+@Priority(100)
+public class ReaderInterceptorOne extends TemplateReaderInterceptor {
+
+  public ReaderInterceptorOne() {
+    super(new InterceptorBodyOne<ReaderInterceptorContext>());
+  }
+
+}
diff --git a/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/api/rs/ext/interceptor/reader/interceptorcontext/ReaderInterceptorTwo.java b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/api/rs/ext/interceptor/reader/interceptorcontext/ReaderInterceptorTwo.java
new file mode 100644
index 0000000..bbd968a
--- /dev/null
+++ b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/api/rs/ext/interceptor/reader/interceptorcontext/ReaderInterceptorTwo.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2012, 2020 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 jakarta.ws.rs.tck.api.rs.ext.interceptor.reader.interceptorcontext;
+
+import jakarta.ws.rs.tck.api.rs.ext.interceptor.InterceptorBodyTwo;
+import jakarta.ws.rs.tck.api.rs.ext.interceptor.reader.TemplateReaderInterceptor;
+
+import jakarta.annotation.Priority;
+import jakarta.ws.rs.ext.Provider;
+import jakarta.ws.rs.ext.ReaderInterceptorContext;
+
+@Provider
+@Priority(200)
+public class ReaderInterceptorTwo extends TemplateReaderInterceptor {
+
+  public ReaderInterceptorTwo() {
+    super(new InterceptorBodyTwo<ReaderInterceptorContext>());
+  }
+}
diff --git a/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/api/rs/ext/interceptor/reader/readerinterceptorcontext/ContextOperation.java b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/api/rs/ext/interceptor/reader/readerinterceptorcontext/ContextOperation.java
new file mode 100644
index 0000000..6fb82e5
--- /dev/null
+++ b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/api/rs/ext/interceptor/reader/readerinterceptorcontext/ContextOperation.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2012, 2018 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 jakarta.ws.rs.tck.api.rs.ext.interceptor.reader.readerinterceptorcontext;
+
+public enum ContextOperation {
+  GETHEADERS, GETHEADERSISMUTABLE, GETINPUTSTREAM, PROCEEDTHROWSIOEXCEPTION, PROCEEDTHROWSWEBAPPEXCEPTION, SETINPUTSTREAM
+}
diff --git a/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/api/rs/ext/interceptor/reader/readerinterceptorcontext/ExceptionThrowingStringBean.java b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/api/rs/ext/interceptor/reader/readerinterceptorcontext/ExceptionThrowingStringBean.java
new file mode 100644
index 0000000..b5d799a
--- /dev/null
+++ b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/api/rs/ext/interceptor/reader/readerinterceptorcontext/ExceptionThrowingStringBean.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2012, 2020 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 jakarta.ws.rs.tck.api.rs.ext.interceptor.reader.readerinterceptorcontext;
+
+import java.io.IOException;
+
+import jakarta.ws.rs.tck.api.rs.ext.interceptor.TemplateInterceptorBody;
+import jakarta.ws.rs.tck.common.provider.StringBean;
+
+import jakarta.ws.rs.WebApplicationException;
+
+public class ExceptionThrowingStringBean extends StringBean {
+
+  public ExceptionThrowingStringBean(String header) {
+    super(header);
+    if (!header.equals(TemplateInterceptorBody.WAE))
+      throw new WebApplicationException(new IOException(header));
+  }
+
+  public ExceptionThrowingStringBean(String header, boolean b) {
+    super(header);
+  }
+}
diff --git a/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/api/rs/ext/interceptor/reader/readerinterceptorcontext/ExceptionThrowingStringBeanEntityProvider.java b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/api/rs/ext/interceptor/reader/readerinterceptorcontext/ExceptionThrowingStringBeanEntityProvider.java
new file mode 100644
index 0000000..5ee679c
--- /dev/null
+++ b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/api/rs/ext/interceptor/reader/readerinterceptorcontext/ExceptionThrowingStringBeanEntityProvider.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2013, 2020 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 jakarta.ws.rs.tck.api.rs.ext.interceptor.reader.readerinterceptorcontext;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+
+import jakarta.ws.rs.tck.common.util.JaxrsUtil;
+
+import jakarta.ws.rs.WebApplicationException;
+import jakarta.ws.rs.core.MediaType;
+import jakarta.ws.rs.core.MultivaluedMap;
+import jakarta.ws.rs.ext.MessageBodyReader;
+import jakarta.ws.rs.ext.MessageBodyWriter;
+import jakarta.ws.rs.ext.Provider;
+
+@Provider
+public class ExceptionThrowingStringBeanEntityProvider
+    implements MessageBodyReader<ExceptionThrowingStringBean>,
+    MessageBodyWriter<ExceptionThrowingStringBean> {
+
+  @Override
+  public boolean isWriteable(Class<?> type, Type genericType,
+      Annotation[] annotations, MediaType mediaType) {
+    return type == ExceptionThrowingStringBean.class;
+  }
+
+  @Override
+  public long getSize(ExceptionThrowingStringBean t, Class<?> type,
+      Type genericType, Annotation[] annotations, MediaType mediaType) {
+    return t.get().length();
+  }
+
+  @Override
+  public void writeTo(ExceptionThrowingStringBean t, Class<?> type,
+      Type genericType, Annotation[] annotations, MediaType mediaType,
+      MultivaluedMap<String, Object> httpHeaders, OutputStream entityStream)
+      throws IOException, WebApplicationException {
+    entityStream.write(t.get().getBytes());
+  }
+
+  @Override
+  public boolean isReadable(Class<?> type, Type genericType,
+      Annotation[] annotations, MediaType mediaType) {
+    return isWriteable(type, genericType, annotations, mediaType);
+  }
+
+  @Override
+  public ExceptionThrowingStringBean readFrom(
+      Class<ExceptionThrowingStringBean> type, Type genericType,
+      Annotation[] annotations, MediaType mediaType,
+      MultivaluedMap<String, String> httpHeaders, InputStream entityStream)
+      throws IOException, WebApplicationException {
+    String entity = JaxrsUtil.readFromStream(entityStream);
+    entityStream.close();
+    return new ExceptionThrowingStringBean(entity);
+  }
+
+}
diff --git a/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/api/rs/ext/interceptor/reader/readerinterceptorcontext/InterceptorOneBody.java b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/api/rs/ext/interceptor/reader/readerinterceptorcontext/InterceptorOneBody.java
new file mode 100644
index 0000000..8fc8f0d
--- /dev/null
+++ b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/api/rs/ext/interceptor/reader/readerinterceptorcontext/InterceptorOneBody.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2012, 2020 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 jakarta.ws.rs.tck.api.rs.ext.interceptor.reader.readerinterceptorcontext;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+import jakarta.ws.rs.tck.api.rs.ext.interceptor.TemplateInterceptorBody;
+import jakarta.ws.rs.tck.common.provider.StringBean;
+import jakarta.ws.rs.tck.common.util.JaxrsUtil;
+
+import jakarta.ws.rs.WebApplicationException;
+import jakarta.ws.rs.core.MultivaluedMap;
+import jakarta.ws.rs.ext.ReaderInterceptorContext;
+
+public class InterceptorOneBody
+    extends TemplateInterceptorBody<ReaderInterceptorContext> {
+
+  public void getHeaders() {
+    MultivaluedMap<String, String> headers = context.getHeaders();
+    setEntity(JaxrsUtil.iterableToString(";", headers.keySet()));
+  }
+
+  public void getHeadersIsMutable() {
+    MultivaluedMap<String, String> headers = context.getHeaders();
+    headers.add(PROPERTY, PROPERTY);
+  }
+
+  public void getInputStream() throws IOException {
+    InputStream stream = context.getInputStream();
+    String entity = JaxrsUtil.readFromStream(stream);
+    stream.close();
+    setEntity(entity);
+  }
+
+  public void proceedThrowsIOException() {
+    try {
+      context.proceed();
+      setEntity(NULL);
+    } catch (IOException ioe) {
+      setEntity(IOE);
+    }
+  }
+
+  public Object proceedThrowsWebAppException()
+      throws WebApplicationException, IOException {
+    Object proceedObject = new ExceptionThrowingStringBean(NULL, false);
+    try {
+      proceedObject = context.proceed();
+    } catch (WebApplicationException e) {
+      // Exception has been thrown, message body reader has read nothing
+      // hence we need to set expected value;
+      ((StringBean) proceedObject).set(WAE);
+    }
+    return proceedObject;
+  }
+
+  public void setInputStream() {
+    ByteArrayInputStream stream = new ByteArrayInputStream(NULL.getBytes());
+    context.setInputStream(stream);
+  }
+
+}
diff --git a/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/api/rs/ext/interceptor/reader/readerinterceptorcontext/InterceptorTwoBody.java b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/api/rs/ext/interceptor/reader/readerinterceptorcontext/InterceptorTwoBody.java
new file mode 100644
index 0000000..c15be8d
--- /dev/null
+++ b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/api/rs/ext/interceptor/reader/readerinterceptorcontext/InterceptorTwoBody.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2012, 2020 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 jakarta.ws.rs.tck.api.rs.ext.interceptor.reader.readerinterceptorcontext;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import jakarta.ws.rs.tck.api.rs.ext.interceptor.TemplateInterceptorBody;
+import jakarta.ws.rs.tck.common.util.JaxrsUtil;
+
+import jakarta.ws.rs.WebApplicationException;
+import jakarta.ws.rs.core.MultivaluedMap;
+import jakarta.ws.rs.ext.ReaderInterceptorContext;
+
+public class InterceptorTwoBody
+    extends TemplateInterceptorBody<ReaderInterceptorContext> {
+  @Override
+  protected Object operationMethodNotFound(String operation)
+      throws IOException {
+    return proceed();
+  }
+
+  public void getHeadersIsMutable() {
+    MultivaluedMap<String, String> headers = context.getHeaders();
+    String first = headers.getFirst(PROPERTY);
+    setEntity(first == null ? NULL : PROPERTY);
+  }
+
+  public void proceedThrowsIOException() throws IOException {
+    throw new IOException("Interceptor#proceed IOException tck test");
+  }
+
+  public Object proceedThrowsWebAppException()
+      throws WebApplicationException, IOException {
+    return context.proceed();
+  }
+
+  public void setInputStream() throws IOException {
+    InputStream stream = context.getInputStream();
+    String entity = JaxrsUtil.readFromStream(stream);
+    setEntity(NULL.equals(entity) ? ENTITY2 : NULL);
+  }
+}
diff --git a/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/api/rs/ext/interceptor/reader/readerinterceptorcontext/JAXRSClient.java b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/api/rs/ext/interceptor/reader/readerinterceptorcontext/JAXRSClient.java
new file mode 100644
index 0000000..45fa157
--- /dev/null
+++ b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/api/rs/ext/interceptor/reader/readerinterceptorcontext/JAXRSClient.java
@@ -0,0 +1,206 @@
+/*
+ * Copyright (c) 2012, 2020 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 jakarta.ws.rs.tck.api.rs.ext.interceptor.reader.readerinterceptorcontext;
+
+import jakarta.ws.rs.tck.api.rs.ext.interceptor.TemplateInterceptorBody;
+import jakarta.ws.rs.tck.api.rs.ext.interceptor.reader.ReaderClient;
+import jakarta.ws.rs.tck.common.client.TextCaser;
+import jakarta.ws.rs.tck.common.provider.StringBean;
+
+import jakarta.ws.rs.core.Response;
+import jakarta.ws.rs.core.Response.ResponseBuilder;
+
+/*
+ * @class.setup_props: webServerHost;
+ *                     webServerPort;
+ *                     ts_home;
+ */
+public class JAXRSClient extends ReaderClient<ContextOperation> {
+
+  private static final long serialVersionUID = -6962070973647934636L;
+
+  /* Run test */
+  /*
+   * @testName: getHeadersOperationSetTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:923; JAXRS:JAVADOC:920; JAXRS:SPEC:85;
+   * 
+   * @test_Strategy: Get mutable map of HTTP headers.
+   * 
+   * ReaderInterceptor.aroundReadFrom If abortWith is invoked, execution is
+   * aborted
+   */
+  public void getHeadersOperationSetTest() throws Fault {
+    ResponseBuilder builder = createResponse(ContextOperation.GETHEADERS);
+    Response fake = builder.build();
+
+    addProviders(fake);
+    setProperty(Property.SEARCH_STRING_IGNORE_CASE,
+        TemplateInterceptorBody.OPERATION);
+    invoke();
+  }
+
+  /*
+   * @testName: getHeadersHeadersSetTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:923; JAXRS:JAVADOC:920; JAXRS:SPEC:85;
+   * 
+   * @test_Strategy: Get mutable map of HTTP headers.
+   * 
+   * ReaderInterceptor.aroundReadFrom If abortWith is invoked, execution is
+   * aborted
+   */
+  public void getHeadersHeadersSetTest() throws Fault {
+    ResponseBuilder builder = createResponse(ContextOperation.GETHEADERS);
+    for (int i = 0; i != 5; i++) {
+      setProperty(Property.UNORDERED_SEARCH_STRING,
+          TemplateInterceptorBody.PROPERTY + i);
+      builder = builder.header(TemplateInterceptorBody.PROPERTY + i, "any");
+    }
+    Response fake = builder.build();
+
+    addProviders(fake);
+    setTextCaser(TextCaser.LOWER);
+    setProperty(Property.UNORDERED_SEARCH_STRING,
+        TemplateInterceptorBody.OPERATION);
+    invoke();
+  }
+
+  /* Run test */
+  /*
+   * @testName: getHeadersIsMutableTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:923; JAXRS:JAVADOC:920; JAXRS:SPEC:85;
+   * 
+   * @test_Strategy: Get mutable map of HTTP headers.
+   * 
+   * ReaderInterceptor.aroundReadFrom If abortWith is invoked, execution is
+   * aborted
+   */
+  public void getHeadersIsMutableTest() throws Fault {
+    ResponseBuilder builder = createResponse(
+        ContextOperation.GETHEADERSISMUTABLE);
+    Response fake = builder.build();
+
+    addProviders(fake);
+    setProperty(Property.SEARCH_STRING, TemplateInterceptorBody.PROPERTY);
+    invoke();
+  }
+
+  /*
+   * @testName: getInputStreamTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:924; JAXRS:JAVADOC:920; JAXRS:SPEC:85;
+   * 
+   * @test_Strategy: Get the input stream of the object to be read.
+   * 
+   * ReaderInterceptor.aroundReadFrom If abortWith is invoked, execution is
+   * aborted
+   */
+  public void getInputStreamTest() throws Fault {
+    String entity = "getInputStreamEntity";
+    ResponseBuilder builder = createResponse(ContextOperation.GETINPUTSTREAM);
+    Response fake = builder.entity(entity).build();
+
+    addProviders(fake);
+    setProperty(Property.SEARCH_STRING, entity);
+    invoke();
+  }
+
+  /*
+   * @testName: proceedThrowsIOExceptionTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:925; JAXRS:JAVADOC:926; JAXRS:JAVADOC:920;
+   * JAXRS:SPEC:85;
+   * 
+   * @test_Strategy: Throws: IOException - if an IO error arises
+   * 
+   * Proceed is tested in any of the interceptor tests.
+   * 
+   * ReaderInterceptor.aroundReadFrom If abortWith is invoked, execution is
+   * aborted
+   */
+  public void proceedThrowsIOExceptionTest() throws Fault {
+    ResponseBuilder builder = createResponse(
+        ContextOperation.PROCEEDTHROWSIOEXCEPTION);
+    Response fake = builder.build();
+
+    addProviders(fake);
+    setProperty(Property.SEARCH_STRING, TemplateInterceptorBody.IOE);
+    invoke();
+  }
+
+  /*
+   * @testName: proceedThrowsWebApplicationExceptionTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:925; JAXRS:JAVADOC:1008; JAXRS:JAVADOC:920;
+   * JAXRS:SPEC:85;
+   * 
+   * @test_Strategy: Throws: WebApplicationException - thrown by the wrapped
+   * {@code MessageBodyReader.readFrom} method.
+   * 
+   * Proceed is tested in any of the intercepter tests.
+   * 
+   * ReaderInterceptor.aroundReadFrom If abortWith is invoked, execution is
+   * aborted
+   */
+  public void proceedThrowsWebApplicationExceptionTest() throws Fault {
+    ResponseBuilder builder = createResponse(
+        ContextOperation.PROCEEDTHROWSWEBAPPEXCEPTION);
+    Response fake = builder.build();
+    addProviders(fake);
+    addProvider(ExceptionThrowingStringBeanEntityProvider.class);
+    invoke();
+    // Exception thrown, caught in InterceptorBodyOne
+    StringBean bean = getResponseBody(ExceptionThrowingStringBean.class);
+    //
+    assertContains(bean.get(), TemplateInterceptorBody.WAE,
+        "WebApplicationException has not been thrown and the message is",
+        bean.get());
+    logMsg("WebApplicationException has been thrown as expected", bean.get());
+  }
+
+  /*
+   * @testName: setInputStreamTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:927; JAXRS:JAVADOC:920; JAXRS:SPEC:85;
+   * 
+   * @test_Strategy: Update the input stream of the object to be read.
+   * 
+   * ReaderInterceptor.aroundReadFrom If abortWith is invoked, execution is
+   * aborted
+   */
+  public void setInputStreamTest() throws Fault {
+    ResponseBuilder builder = createResponse(ContextOperation.SETINPUTSTREAM);
+    Response fake = builder.build();
+
+    addProviders(fake);
+    setProperty(Property.SEARCH_STRING, TemplateInterceptorBody.ENTITY2);
+    invoke();
+  }
+
+  // ///////////////////////////////////////////////////////////////////////
+  /**
+   * Do not forget to register providers
+   */
+  @Override
+  protected void addProviders(Response response) throws Fault {
+    super.addProviders(response);
+    addProvider(ReaderInterceptorTwo.class);
+    addProvider(ReaderInterceptorOne.class);
+  }
+}
diff --git a/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/api/rs/ext/interceptor/reader/readerinterceptorcontext/ReaderInterceptorOne.java b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/api/rs/ext/interceptor/reader/readerinterceptorcontext/ReaderInterceptorOne.java
new file mode 100644
index 0000000..79badd9
--- /dev/null
+++ b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/api/rs/ext/interceptor/reader/readerinterceptorcontext/ReaderInterceptorOne.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2012, 2020 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 jakarta.ws.rs.tck.api.rs.ext.interceptor.reader.readerinterceptorcontext;
+
+import jakarta.ws.rs.tck.api.rs.ext.interceptor.reader.TemplateReaderInterceptor;
+
+import jakarta.annotation.Priority;
+import jakarta.ws.rs.ext.Provider;
+
+@Provider
+@Priority(100)
+public class ReaderInterceptorOne extends TemplateReaderInterceptor {
+
+  public ReaderInterceptorOne() {
+    super(new InterceptorOneBody());
+  }
+
+}
diff --git a/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/api/rs/ext/interceptor/reader/readerinterceptorcontext/ReaderInterceptorTwo.java b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/api/rs/ext/interceptor/reader/readerinterceptorcontext/ReaderInterceptorTwo.java
new file mode 100644
index 0000000..82c7104
--- /dev/null
+++ b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/api/rs/ext/interceptor/reader/readerinterceptorcontext/ReaderInterceptorTwo.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2012, 2020 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 jakarta.ws.rs.tck.api.rs.ext.interceptor.reader.readerinterceptorcontext;
+
+import jakarta.ws.rs.tck.api.rs.ext.interceptor.reader.TemplateReaderInterceptor;
+
+import jakarta.annotation.Priority;
+import jakarta.ws.rs.ext.Provider;
+
+@Provider
+@Priority(200)
+public class ReaderInterceptorTwo extends TemplateReaderInterceptor {
+
+  public ReaderInterceptorTwo() {
+    super(new InterceptorTwoBody());
+  }
+
+}
diff --git a/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/common/JAXRSCommonClient.java b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/common/JAXRSCommonClient.java
index f69dd67..e41d223 100644
--- a/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/common/JAXRSCommonClient.java
+++ b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/common/JAXRSCommonClient.java
@@ -677,8 +677,6 @@
    * @param message
    *          a space separated message[i].toString() compilation for
    *          i=<0,message.length)
-   * @ 
-   *           when conditionTrue is not met with message provided
    */
   //public static void //
   //    assertTrue(boolean condition, Object... message)   {
@@ -694,13 +692,11 @@
    * @param message
    *          a space separated message[i].toString() compilation for
    *          i=<0,message.length)
-   * @ 
-   *           when condition is not false with message provided
    */
-  /*public static void //
-      assertFalse(boolean condition, Object... message)   {
-    assertTrue(!condition, message);
-  }*/
+  // public static void //
+  //     assertFalse(boolean condition, Object... message)   {
+  //   assertTrue(!condition, message);
+  // }
 
   /**
    * Asserts that two objects are equal. When instances of Comparable, such as
diff --git a/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/common/provider/StringBeanWithAnnotation.java b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/common/provider/StringBeanWithAnnotation.java
new file mode 100644
index 0000000..8ba1d44
--- /dev/null
+++ b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/common/provider/StringBeanWithAnnotation.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2012, 2020 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 jakarta.ws.rs.tck.common.provider;
+
+import jakarta.ws.rs.Consumes;
+import jakarta.ws.rs.Produces;
+import jakarta.ws.rs.core.MediaType;
+
+@Consumes(MediaType.TEXT_PLAIN)
+@Produces(MediaType.TEXT_PLAIN)
+/**
+ * It does not make sense to put any of these annotations. But for test e.g.
+ * getEntityAnnotationsIsNotTakenFromEntityClassTest we need to check that
+ * context.getAnnotations won't have these annotations.
+ */
+public class StringBeanWithAnnotation extends StringBean {
+
+  public StringBeanWithAnnotation(String header) {
+    super(header);
+  }
+}
diff --git a/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/client/clientrequestcontext/ContextProvider.java b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/client/clientrequestcontext/ContextProvider.java
new file mode 100644
index 0000000..cc8dfc7
--- /dev/null
+++ b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/client/clientrequestcontext/ContextProvider.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2012, 2020 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 jakarta.ws.rs.tck.ee.rs.client.clientrequestcontext;
+
+import java.io.IOException;
+
+import jakarta.ws.rs.tck.common.JAXRSCommonClient.Fault;
+
+import jakarta.ws.rs.client.ClientRequestContext;
+import jakarta.ws.rs.client.ClientRequestFilter;
+import jakarta.ws.rs.ext.Provider;
+
+@Provider
+public class ContextProvider implements ClientRequestFilter {
+
+  protected void checkFilterContext(ClientRequestContext context) throws Fault {
+    throw new Fault("this TCK method is not implemented yet");
+  }
+
+  @Override
+  public void filter(ClientRequestContext context) throws IOException {
+    try {
+      checkFilterContext(context);
+    } catch (Fault e) {
+      throw new IOException(e);
+    }
+  }
+
+}
diff --git a/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/client/clientrequestcontext/JAXRSClientIT.java b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/client/clientrequestcontext/JAXRSClientIT.java
new file mode 100644
index 0000000..de6c77f
--- /dev/null
+++ b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/client/clientrequestcontext/JAXRSClientIT.java
@@ -0,0 +1,217 @@
+/*
+ * Copyright (c) 2012, 2020 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 jakarta.ws.rs.tck.ee.rs.client.clientrequestcontext;
+
+import java.io.ByteArrayInputStream;
+import java.io.OutputStream;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.io.InputStream;
+import java.io.IOException;
+
+import jakarta.ws.rs.tck.lib.util.TestUtil;
+import jakarta.ws.rs.tck.api.client.clientrequestcontext.ContextProvider;
+import jakarta.ws.rs.tck.common.client.JaxrsCommonClient;
+import jakarta.ws.rs.tck.common.impl.ReplacingOutputStream;
+
+import jakarta.ws.rs.client.ClientRequestContext;
+import jakarta.ws.rs.core.MultivaluedMap;
+
+import org.jboss.arquillian.junit5.ArquillianExtension;
+import org.jboss.arquillian.container.test.api.Deployment;
+import org.jboss.shrinkwrap.api.ShrinkWrap;
+import org.jboss.shrinkwrap.api.asset.StringAsset;
+import org.jboss.shrinkwrap.api.spec.WebArchive;
+import org.jboss.shrinkwrap.api.exporter.ZipExporter;
+
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assertions.fail;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.junit.jupiter.api.TestInfo;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.AfterEach;
+
+/*
+ * @class.setup_props: webServerHost;
+ *                     webServerPort;
+ */
+@ExtendWith(ArquillianExtension.class)
+public class JAXRSClientIT extends JaxrsCommonClient {
+
+  private static final long serialVersionUID = -3234850442044177095L;
+
+  public JAXRSClientIT() {
+    setup();
+    setContextRoot("/jaxrs_ee_rs_client_clientrequestcontext_web/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{
+
+    InputStream inStream = JAXRSClientIT.class.getClassLoader().getResourceAsStream("jakarta/ws/rs/tck/ee/rs/client/clientrequestcontext/web.xml.template");
+    String webXml = editWebXmlString(inStream);
+
+    WebArchive archive = ShrinkWrap.create(WebArchive.class, "jaxrs_ee_rs_client_clientrequestcontext_web.war");
+    archive.addClasses(TSAppConfig.class, Resource.class, ContextProvider.class);
+    archive.setWebXML(new StringAsset(webXml));
+    return archive;
+
+  }
+
+
+  /* Run test */
+  /*
+   * @testName: getEntityStreamTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:437; JAXRS:JAVADOC:451; JAXRS:JAVADOC:455;
+   * JAXRS:JAVADOC:456;
+   * 
+   * @test_Strategy: Get the entity output stream. Set a new entity output
+   * stream.
+   */
+  @Test
+  public void getEntityStreamTest() throws Fault {
+    final String entityStreamWorks = "ENTITY_STREAM_WORKS";
+    ContextProvider provider = new ContextProvider() {
+      @Override
+      protected void checkFilterContext(ClientRequestContext context)
+          throws Fault {
+        OutputStream stream = context.getEntityStream();
+        ReplacingOutputStream wrapper = new ReplacingOutputStream(stream, 'X',
+            'T');
+        context.setEntityStream(wrapper);
+      }
+    };
+    ByteArrayInputStream entity = new ByteArrayInputStream(
+        entityStreamWorks.replace('T', 'X').getBytes());
+    addProvider(provider);
+    setRequestContentEntity(entity);
+    setProperty(Property.REQUEST, buildRequest(Request.POST, "post"));
+    invoke();
+
+    String body = getResponseBody();
+    assertContains(body, entityStreamWorks);
+  }
+
+  /*
+   * @testName: getHeadersIsMutableTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:439; JAXRS:JAVADOC:455; JAXRS:JAVADOC:456;
+   * 
+   * @test_Strategy: Get the generic entity type information.
+   */
+  @Test
+  public void getHeadersIsMutableTest() throws Fault {
+    ContextProvider provider = new ContextProvider() {
+      @Override
+      protected void checkFilterContext(ClientRequestContext context)
+          throws Fault {
+        MultivaluedMap<String, Object> headers = context.getHeaders();
+        headers.add("Accept-Language", "en_gb");
+        headers.add("Date", "Tue, 15 Nov 1994 08:12:31 GMT");
+        headers.add("tck", "cts");
+      }
+    };
+    addProvider(provider);
+    setProperty(Property.REQUEST, buildRequest(Request.GET, "headers"));
+    invoke();
+
+    String body = getResponseBody().toLowerCase();
+    assertContains(body, "accept-language");
+    assertContains(body, "date");
+    assertContains(body, "tck");
+  }
+
+  /*
+   * @testName: setMethodTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:452; JAXRS:JAVADOC:455; JAXRS:JAVADOC:456;
+   * 
+   * @test_Strategy: Set the request method.
+   */
+  @Test
+  public void setMethodTest() throws Fault {
+    String entity = "ENTITY";
+    ContextProvider provider = new ContextProvider() {
+      @Override
+      protected void checkFilterContext(ClientRequestContext context)
+          throws Fault {
+        context.setMethod("PUT");
+      }
+    };
+    addProvider(provider);
+    setRequestContentEntity(entity);
+    setProperty(Property.REQUEST, buildRequest(Request.POST, "put"));
+    invoke();
+
+    String body = getResponseBody();
+    assertContains(body, entity);
+  }
+
+  /*
+   * @testName: setUriTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:454; JAXRS:JAVADOC:447; JAXRS:JAVADOC:455;
+   * JAXRS:JAVADOC:456;
+   * 
+   * @test_Strategy: Set a new request URI. Get the request URI.
+   */
+  @Test
+  public void setUriTest() throws Fault {
+    String entity = "ENTITY";
+    ContextProvider provider = new ContextProvider() {
+      @Override
+      protected void checkFilterContext(ClientRequestContext context)
+          throws Fault {
+        URI uri = context.getUri();
+        try {
+          uri = new URI(uri.toASCIIString().replace("qwerty", "post"));
+        } catch (URISyntaxException e) {
+          throw new Fault(e);
+        }
+        context.setUri(uri);
+      }
+    };
+    addProvider(provider);
+    setRequestContentEntity(entity);
+    setProperty(Property.REQUEST, buildRequest(Request.POST, "qwerty"));
+    invoke();
+
+    String body = getResponseBody();
+    assertContains(body, entity);
+  }
+
+  // ////////////////////////////////////////////////////////////////////
+  protected static void assertContains(String string, String substring)
+      throws Fault {
+    assertTrue(string.contains(substring), string+ "does NOT contain"+
+        substring);
+    TestUtil.logMsg("Found expected substring: " + substring);
+  }
+
+}
diff --git a/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/client/clientrequestcontext/Resource.java b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/client/clientrequestcontext/Resource.java
new file mode 100644
index 0000000..7b7c857
--- /dev/null
+++ b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/client/clientrequestcontext/Resource.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2012, 2020 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 jakarta.ws.rs.tck.ee.rs.client.clientrequestcontext;
+
+import java.util.Collection;
+
+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.HttpHeaders;
+
+@Path("resource")
+public class Resource {
+
+  @POST
+  @Path("post")
+  public String post(String value) {
+    return value;
+  }
+
+  @PUT
+  @Path("put")
+  public String put(String value) {
+    return value;
+  }
+
+  @GET
+  @Path("headers")
+  public String headers(@Context HttpHeaders headers) {
+    String hdrs = collectionToString(headers.getRequestHeaders().keySet());
+    return hdrs;
+  }
+
+  protected static <T> String collectionToString(Collection<T> collection) {
+    StringBuilder sb = new StringBuilder();
+    for (T t : collection)
+      sb.append(t).append(";");
+    return sb.toString();
+  }
+
+}
diff --git a/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/client/clientrequestcontext/TSAppConfig.java b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/client/clientrequestcontext/TSAppConfig.java
new file mode 100644
index 0000000..9a302e6
--- /dev/null
+++ b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/client/clientrequestcontext/TSAppConfig.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2012, 2020 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 jakarta.ws.rs.tck.ee.rs.client.clientrequestcontext;
+
+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);
+    return resources;
+  }
+}
diff --git a/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/client/invocationbuilder/JAXRSClientIT.java b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/client/invocationbuilder/JAXRSClientIT.java
new file mode 100644
index 0000000..fe355dd
--- /dev/null
+++ b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/client/invocationbuilder/JAXRSClientIT.java
@@ -0,0 +1,389 @@
+/*
+ * Copyright (c) 2012, 2020 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 jakarta.ws.rs.tck.ee.rs.client.invocationbuilder;
+
+import java.util.Locale;
+import java.io.InputStream;
+import java.io.IOException;
+
+import jakarta.ws.rs.tck.common.client.JaxrsCommonClient;
+import jakarta.ws.rs.tck.common.client.JdkLoggingFilter;
+import jakarta.ws.rs.tck.lib.util.TestUtil;
+
+import jakarta.ws.rs.client.AsyncInvoker;
+import jakarta.ws.rs.client.Client;
+import jakarta.ws.rs.client.ClientBuilder;
+import jakarta.ws.rs.client.Entity;
+import jakarta.ws.rs.client.Invocation;
+import jakarta.ws.rs.client.WebTarget;
+import jakarta.ws.rs.core.CacheControl;
+import jakarta.ws.rs.core.Cookie;
+import jakarta.ws.rs.core.MediaType;
+import jakarta.ws.rs.core.MultivaluedHashMap;
+import jakarta.ws.rs.core.MultivaluedMap;
+
+import org.jboss.arquillian.junit5.ArquillianExtension;
+import org.jboss.arquillian.container.test.api.Deployment;
+import org.jboss.shrinkwrap.api.ShrinkWrap;
+import org.jboss.shrinkwrap.api.asset.StringAsset;
+import org.jboss.shrinkwrap.api.spec.WebArchive;
+import org.jboss.shrinkwrap.api.exporter.ZipExporter;
+
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assertions.fail;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.junit.jupiter.api.TestInfo;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.AfterEach;
+
+/*
+ * @class.setup_props: webServerHost;
+ *                     webServerPort;
+ */
+@ExtendWith(ArquillianExtension.class)
+public class JAXRSClientIT extends JaxrsCommonClient {
+
+  private static final long serialVersionUID = -8097693127928445210L;
+
+  public JAXRSClientIT() {
+    setup();
+    setContextRoot("/jaxrs_ee_rs_client_invocationbuilder_web/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{
+
+    InputStream inStream = JAXRSClientIT.class.getClassLoader().getResourceAsStream("jakarta/ws/rs/tck/ee/rs/client/invocationbuilder/web.xml.template");
+    String webXml = editWebXmlString(inStream);
+
+    WebArchive archive = ShrinkWrap.create(WebArchive.class, "jaxrs_ee_rs_client_invocationbuilder_web.war");
+    archive.addClasses(TSAppConfig.class, Resource.class, jakarta.ws.rs.tck.common.util.JaxrsUtil.class);
+    archive.setWebXML(new StringAsset(webXml));
+    return archive;
+
+  }
+
+
+  static final String[] METHODS = { "delete", "get", "options" };
+
+  static final String[] ENTITY_METHODS = { "put", "post" };
+
+  /* Run test */
+  /*
+   * @testName: acceptLanguageByLocalesTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:524;
+   * 
+   * @test_Strategy: Add acceptable languages.
+   */
+  @Test
+  public void acceptLanguageByLocalesTest() throws Fault {
+    Invocation.Builder builder = createBuilderForMethod("languages");
+    builder = builder.acceptLanguage(Locale.GERMAN, Locale.ITALIAN,
+        Locale.FRENCH);
+    String response = builder.buildGet().invoke(String.class);
+    String error = "Expected locale was not found in the response:";
+    assertContainsIgnoreCase(response, Locale.GERMAN, error, response);
+    assertContainsIgnoreCase(response, Locale.ITALIAN, error, response);
+    assertContainsIgnoreCase(response, Locale.FRENCH, error, response);
+  }
+
+  /*
+   * @testName: acceptLanguageByStringsTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:525;
+   * 
+   * @test_Strategy: Add acceptable languages.
+   */
+  @Test
+  public void acceptLanguageByStringsTest() throws Fault {
+    Invocation.Builder builder = createBuilderForMethod("languages");
+    builder = builder.acceptLanguage(langToString(Locale.GERMAN),
+        langToString(Locale.ITALIAN), langToString(Locale.FRENCH));
+    String response = builder.buildGet().invoke(String.class);
+    String error = "Expected locale was not found in the response:";
+    assertContainsIgnoreCase(response, Locale.GERMAN, error, response);
+    assertContainsIgnoreCase(response, Locale.ITALIAN, error, response);
+    assertContainsIgnoreCase(response, Locale.FRENCH, error, response);
+  }
+
+  /*
+   * @testName: asyncTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:526;
+   * 
+   * @test_Strategy: Access the asynchronous uniform request invocation
+   * interface to asynchronously invoke the built request.
+   */
+  @Test
+  public void asyncTest() throws Fault {
+    Invocation.Builder builder = createBuilderForMethod("forbid");
+    AsyncInvoker async = builder.async();
+    assertTrue(async != null, "Builder.async() does not work properly");
+  }
+
+  /*
+   * @testName: buildTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:527;
+   * 
+   * @test_Strategy: Build a request invocation using an arbitrary request
+   * method name.
+   */
+  @Test
+  public void buildTest() throws Fault {
+    String error = "Unexpected response returned:";
+    for (String method : METHODS) {
+      Invocation.Builder builder = createBuilderForMethod(method);
+      String response = builder.build(method.toUpperCase())
+          .invoke(String.class);
+      assertContainsIgnoreCase(response, method, error, response);
+    }
+  }
+
+  /*
+   * @testName: buildWithEntityTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:528;
+   * 
+   * @test_Strategy: Build a request invocation using an arbitrary request
+   * method name and request entity
+   */
+  @Test
+  public void buildWithEntityTest() throws Fault {
+    String error = "Unexpected response returned:";
+    for (String method : ENTITY_METHODS) {
+      Invocation.Builder builder = createBuilderForMethod(method);
+      Entity<String> entity = createEntity(method);
+      String response = builder.build(method.toUpperCase(), entity)
+          .invoke(String.class);
+      assertContainsIgnoreCase(response, method, error, response);
+    }
+  }
+
+  /*
+   * @testName: buildDeleteTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:529;
+   * 
+   * @test_Strategy: Build a DELETE request invocation.
+   */
+  @Test
+  public void buildDeleteTest() throws Fault {
+    String error = "Unexpected response returned:";
+    Invocation.Builder builder = createBuilderForMethod("delete");
+    String response = builder.buildDelete().invoke(String.class);
+    assertContainsIgnoreCase(response, "delete", error, response);
+  }
+
+  /*
+   * @testName: buildGetTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:530;
+   * 
+   * @test_Strategy: Build a GET request invocation.
+   */
+  @Test
+  public void buildGetTest() throws Fault {
+    String error = "Unexpected response returned:";
+    Invocation.Builder builder = createBuilderForMethod("get");
+    String response = builder.buildGet().invoke(String.class);
+    assertContainsIgnoreCase(response, "get", error, response);
+  }
+
+  /*
+   * @testName: buildPostTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:531;
+   * 
+   * @test_Strategy: Build a POST request invocation.
+   */
+  @Test
+  public void buildPostTest() throws Fault {
+    String error = "Unexpected response returned:";
+    Invocation.Builder builder = createBuilderForMethod("post");
+    Entity<String> entity = createEntity("post");
+    String response = builder.buildPost(entity).invoke(String.class);
+    assertContainsIgnoreCase(response, "post", error, response);
+  }
+
+  /*
+   * @testName: buildPutTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:532;
+   * 
+   * @test_Strategy: Build a PUT request invocation.
+   */
+  @Test
+  public void buildPutTest() throws Fault {
+    String error = "Unexpected response returned:";
+    Invocation.Builder builder = createBuilderForMethod("put");
+    Entity<String> entity = createEntity("put");
+    String response = builder.buildPut(entity).invoke(String.class);
+    assertContainsIgnoreCase(response, "put", error, response);
+  }
+
+  /*
+   * @testName: cacheControlTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:533;
+   * 
+   * @test_Strategy: Set the cache control data of the message.
+   */
+  @Test
+  public void cacheControlTest() throws Fault {
+    String error = "Unexpected response returned:";
+    Invocation.Builder builder = createBuilderForMethod("headerstostring");
+    CacheControl control = new CacheControl();
+    control.setMaxAge(2);
+    String response = builder.cacheControl(control).buildGet()
+        .invoke(String.class).toLowerCase();
+    assertContainsIgnoreCase(response, "max-age", error, response);
+  }
+
+  /*
+   * @testName: cookieCookieTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:535;
+   * 
+   * @test_Strategy: Add a cookie to be set.
+   */
+  @Test
+  public void cookieCookieTest() throws Fault {
+    String error = "Unexpected response returned:";
+    Invocation.Builder builder = createBuilderForMethod("cookie");
+    Cookie cookie = new Cookie("tck", "cts");
+    String response = builder.cookie(cookie).buildGet().invoke(String.class);
+    assertContainsIgnoreCase(response, "cts", error, response);
+  }
+
+  /*
+   * @testName: cookieStringStringTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:536;
+   * 
+   * @test_Strategy: Add a cookie to be set.
+   */
+  @Test
+  public void cookieStringStringTest() throws Fault {
+    String error = "Unexpected response returned:";
+    Invocation.Builder builder = createBuilderForMethod("cookie");
+    String response = builder.cookie("tck", "cts").buildGet()
+        .invoke(String.class);
+    assertContainsIgnoreCase(response, "cts", error, response);
+  }
+
+  /*
+   * @testName: headerObjectTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:537;
+   * 
+   * @test_Strategy: Add an arbitrary header.
+   */
+  @Test
+  public void headerObjectTest() throws Fault {
+    String error = "Unexpected response returned:";
+    Invocation.Builder builder = createBuilderForMethod("headerstostring");
+    String response = builder.header("tck-header", "cts-header").buildGet()
+        .invoke(String.class);
+    assertContainsIgnoreCase(response, "tck-header", error, response);
+    assertContainsIgnoreCase(response, "cts-header", error, response);
+  }
+
+  /*
+   * @testName: headersMultivaluedMapTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:538;
+   * 
+   * @test_Strategy: Replaces all existing headers with the newly supplied
+   * headers.
+   */
+  @Test
+  public void headersMultivaluedMapTest() throws Fault {
+    String error = "Unexpected response returned:";
+    Invocation.Builder builder = createBuilderForMethod("headerstostring");
+    MultivaluedMap<String, Object> map = new MultivaluedHashMap<String, Object>();
+    map.add("tck-header", "cts-header");
+    String response = builder.header("unexpected-header", "unexpected-header")
+        .headers(map).buildGet().invoke(String.class);
+    assertTrue(!response.contains("unexpected-header"),
+        "unexpected-header found in the response");
+    assertContainsIgnoreCase(response, "tck-header", error, response);
+    assertContainsIgnoreCase(response, "cts-header", error, response);
+  }
+
+  /*
+   * @testName: headersMultivaluedMapIsNullReplacesAllTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:538;
+   * 
+   * @test_Strategy: headers - new headers to be set, if null all existing
+   * headers will be removed.
+   */
+  @Test
+  public void headersMultivaluedMapIsNullReplacesAllTest() throws Fault {
+    Invocation.Builder builder = createBuilderForMethod("headerstostring");
+    String response = builder.header("unexpected-header", "unexpected-header")
+        .headers((MultivaluedMap<String, Object>) null).buildGet()
+        .invoke(String.class);
+    assertTrue(!response.contains("unexpected-header"),
+        "unexpected-header found in the response");
+  }
+
+  // ////////////////////////////////////////////////////////////////////
+
+  protected String getUrl(String method) {
+    StringBuilder url = new StringBuilder();
+    url.append("http://").append(_hostname).append(":").append(_port);
+    url.append(getContextRoot()).append("/").append(method);
+    return url.toString();
+  }
+
+  /**
+   * Create Invocation.Builder for given resource method and start time
+   */
+  protected Invocation.Builder createBuilderForMethod(String methodName) {
+    Client client = ClientBuilder.newClient();
+    client.register(new JdkLoggingFilter(false));
+    WebTarget target = client.target(getUrl(methodName));
+    Invocation.Builder builder = target.request();
+    return builder;
+  }
+
+  protected <T> Entity<T> createEntity(T entity) {
+    return Entity.entity(entity, MediaType.WILDCARD_TYPE);
+  }
+
+  /**
+   * @return simulates toLanguageTag() for java prior version 7
+   */
+  protected String langToString(Locale language) {
+    return language.toString().replace("_", "-");
+  }
+
+}
diff --git a/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/client/invocationbuilder/Resource.java b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/client/invocationbuilder/Resource.java
new file mode 100644
index 0000000..f04e8de
--- /dev/null
+++ b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/client/invocationbuilder/Resource.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2012, 2020 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 jakarta.ws.rs.tck.ee.rs.client.invocationbuilder;
+
+import java.util.List;
+import java.util.Map.Entry;
+
+import jakarta.ws.rs.tck.common.util.JaxrsUtil;
+
+import jakarta.ws.rs.CookieParam;
+import jakarta.ws.rs.DELETE;
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.HEAD;
+import jakarta.ws.rs.OPTIONS;
+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.HttpHeaders;
+import jakarta.ws.rs.core.MultivaluedMap;
+
+@Path("resource")
+public class Resource {
+
+  @GET
+  @Path("languages")
+  public String languages(@Context HttpHeaders headers) {
+    return JaxrsUtil.iterableToString(" ", headers.getAcceptableLanguages());
+  }
+
+  @GET
+  @Path("headerstostring")
+  public String headersToString(@Context HttpHeaders headers) {
+    MultivaluedMap<String, String> map = headers.getRequestHeaders();
+    StringBuilder sb = new StringBuilder();
+    for (Entry<String, List<String>> header : map.entrySet())
+      sb.append(header.getKey()).append(":")
+          .append(JaxrsUtil.iterableToString(" ", header.getValue()))
+          .append(";");
+    return sb.toString();
+  }
+
+  @GET
+  @Path("cookie")
+  public String cookie(@CookieParam("tck") String cookie) {
+    return cookie;
+  }
+
+  @GET
+  @Path("allow")
+  public String allow() {
+    return "allow";
+  }
+
+  @DELETE
+  @Path("forbid")
+  public String forbid() {
+    return "forbid";
+  }
+
+  @GET
+  @Path("get")
+  public String get() {
+    return "get";
+  }
+
+  @HEAD
+  @Path("head")
+  public String head() {
+    return "head";
+  }
+
+  @PUT
+  @Path("put")
+  public String put(String value) {
+    return value;
+  }
+
+  @POST
+  @Path("post")
+  public String post(String value) {
+    return value;
+  }
+
+  @DELETE
+  @Path("delete")
+  public String delete() {
+    return "delete";
+  }
+
+  @OPTIONS
+  @Path("options")
+  public String options() {
+    return "options";
+  }
+
+}
diff --git a/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/client/invocationbuilder/TSAppConfig.java b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/client/invocationbuilder/TSAppConfig.java
new file mode 100644
index 0000000..6cd7cd5
--- /dev/null
+++ b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/client/invocationbuilder/TSAppConfig.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2012, 2020 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 jakarta.ws.rs.tck.ee.rs.client.invocationbuilder;
+
+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);
+    return resources;
+  }
+}
diff --git a/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/client/syncinvoker/JAXRSClientIT.java b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/client/syncinvoker/JAXRSClientIT.java
new file mode 100644
index 0000000..89297cb
--- /dev/null
+++ b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/client/syncinvoker/JAXRSClientIT.java
@@ -0,0 +1,2171 @@
+/*
+ * Copyright (c) 2012, 2020 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 jakarta.ws.rs.tck.ee.rs.client.syncinvoker;
+
+import java.io.InputStream;
+import java.io.IOException;
+import jakarta.ws.rs.tck.lib.util.TestUtil;
+import jakarta.ws.rs.tck.common.client.JaxrsCommonClient;
+import jakarta.ws.rs.tck.common.client.JdkLoggingFilter;
+
+import jakarta.ws.rs.ProcessingException;
+import jakarta.ws.rs.WebApplicationException;
+import jakarta.ws.rs.client.Client;
+import jakarta.ws.rs.client.ClientBuilder;
+import jakarta.ws.rs.client.Entity;
+import jakarta.ws.rs.client.SyncInvoker;
+import jakarta.ws.rs.client.WebTarget;
+import jakarta.ws.rs.core.GenericType;
+import jakarta.ws.rs.core.MediaType;
+import jakarta.ws.rs.core.Response;
+import jakarta.ws.rs.core.Response.Status;
+
+import org.jboss.arquillian.junit5.ArquillianExtension;
+import org.jboss.arquillian.container.test.api.Deployment;
+import org.jboss.shrinkwrap.api.ShrinkWrap;
+import org.jboss.shrinkwrap.api.asset.StringAsset;
+import org.jboss.shrinkwrap.api.spec.WebArchive;
+import org.jboss.shrinkwrap.api.exporter.ZipExporter;
+
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assertions.fail;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.junit.jupiter.api.TestInfo;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.AfterEach;
+
+/*
+ * @class.setup_props: webServerHost;
+ *                     webServerPort;
+ */
+@ExtendWith(ArquillianExtension.class)
+public class JAXRSClientIT extends JaxrsCommonClient {
+
+  private static final long serialVersionUID = 4942772066511819511L;
+
+  protected long millis;
+
+  public JAXRSClientIT() {
+    setup();
+    setContextRoot("/jaxrs_ee_rs_client_syncinvoker_web/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{
+
+    InputStream inStream = JAXRSClientIT.class.getClassLoader().getResourceAsStream("jakarta/ws/rs/tck/ee/rs/client/syncinvoker/web.xml.template");
+    String webXml = editWebXmlString(inStream);
+
+    WebArchive archive = ShrinkWrap.create(WebArchive.class, "jaxrs_ee_rs_client_syncinvoker_web.war");
+    archive.addClasses(TSAppConfig.class, Resource.class, jakarta.ws.rs.tck.common.impl.TRACE.class);
+    archive.setWebXML(new StringAsset(webXml));
+    return archive;
+
+  }
+
+
+  static final String[] METHODS = { "DELETE", "GET", "OPTIONS" };
+
+  static final String[] ENTITY_METHODS = { "PUT", "POST" };
+
+  /* Run test */
+  // --------------------------------------------------------------------
+  // ---------------------- DELETE --------------------------------------
+  // --------------------------------------------------------------------
+  /*
+   * @testName: deleteTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:541;
+   * 
+   * @test_Strategy: Invoke HTTP DELETE method for the current request
+   * synchronously.
+   */
+  @Test
+  public Response deleteTest() throws Fault {
+    SyncInvoker sync = createSyncInvokerForMethod("delete");
+    Response response = sync.delete();
+    assertResponseOk(response);
+    return response;
+  }
+
+  /*
+   * @testName: deleteThrowsProcessingExceptionTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:541;
+   * 
+   * @test_Strategy: jakarta.ws.rs.client.SyncInvoker.delete throws
+   * ProcessingException in case the invocation failed.
+   */
+  @Test
+  public void deleteThrowsProcessingExceptionTest() throws Fault {
+    Runnable run = new Runnable() {
+      @Override
+      public void run() {
+        SyncInvoker sync = createSyncInvokerWrongUrl();
+        sync.delete();
+      }
+    };
+    assertProcessingException(run);
+  }
+
+  /*
+   * @testName: deleteWithStringClassTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:543;
+   * 
+   * @test_Strategy: Invoke HTTP DELETE method for the current request
+   * synchronously.
+   */
+  @Test
+  public String deleteWithStringClassTest() throws Fault {
+    SyncInvoker sync = createSyncInvokerForMethod("delete");
+    String response = sync.delete(String.class);
+    assertResponseString(response, "delete");
+    return response;
+  }
+
+  /*
+   * @testName: deleteWithResponseClassTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:543;
+   * 
+   * @test_Strategy: Invoke HTTP DELETE method for the current request
+   * synchronously.
+   */
+  @Test
+  public Response deleteWithResponseClassTest() throws Fault {
+    SyncInvoker sync = createSyncInvokerForMethod("delete");
+    Response response = sync.delete(Response.class);
+    assertResponseOk(response);
+    return response;
+  }
+
+  /*
+   * @testName: deleteWithStringClassThrowsProcessingExceptionTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:543;
+   * 
+   * @test_Strategy: jakarta.ws.rs.client.SyncInvoker.delete( Class ) throws
+   * ProcessingException in case the invocation failed.
+   */
+  @Test
+  public void deleteWithStringClassThrowsProcessingExceptionTest()
+      throws Fault {
+    Runnable run = new Runnable() {
+      @Override
+      public void run() {
+        SyncInvoker sync = createSyncInvokerWrongUrl();
+        sync.delete(String.class);
+      }
+    };
+    assertProcessingException(run);
+  }
+
+  /*
+   * @testName: deleteWithStringClassThrowsWebApplicationExceptionTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:543;
+   * 
+   * @test_Strategy: jakarta.ws.rs.client.SyncInvoker.delete( Class ) throws
+   * WebApplicationException - in case the response status code of the response
+   * returned by the server is not successful and the specified response type is
+   * not Response.
+   */
+  @Test
+  public void deleteWithStringClassThrowsWebApplicationExceptionTest()
+      throws Fault {
+    Runnable run = new Runnable() {
+      @Override
+      public void run() {
+        SyncInvoker sync = createSyncInvokerForMethod("deletenotok");
+        sync.delete(String.class);
+      }
+    };
+    assertWebApplicationException(run);
+  }
+
+  /*
+   * @testName: deleteWithResponseClassThrowsNoWebApplicationExceptionTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:543;
+   * 
+   * @test_Strategy: jakarta.ws.rs.client.SyncInvoker.delete( Class ) throws
+   * WebApplicationException - in case the response status code of the response
+   * returned by the server is not successful and the specified response type is
+   * not Response.
+   */
+  @Test
+  public void deleteWithResponseClassThrowsNoWebApplicationExceptionTest()
+      throws Fault {
+    SyncInvoker sync = createSyncInvokerForMethod("deletenotok");
+    Response response = sync.delete(Response.class);
+    assertStatusAndLog(response, Status.NOT_ACCEPTABLE);
+  }
+
+  /*
+   * @testName: deleteWithGenericTypeStringTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:546;
+   * 
+   * @test_Strategy: Invoke HTTP DELETE method for the current request
+   * synchronously.
+   */
+  @Test
+  public String deleteWithGenericTypeStringTest() throws Fault {
+    SyncInvoker sync = createSyncInvokerForMethod("delete");
+    GenericType<String> generic = createGeneric(String.class);
+    String response = sync.delete(generic);
+    assertResponseString(response, "delete");
+    return response;
+  }
+
+  /*
+   * @testName: deleteWithGenericTypeResponseTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:546;
+   * 
+   * @test_Strategy: Invoke HTTP DELETE method for the current request
+   * synchronously.
+   */
+  @Test
+  public Response deleteWithGenericTypeResponseTest() throws Fault {
+    SyncInvoker sync = createSyncInvokerForMethod("delete");
+    GenericType<Response> generic = createGeneric(Response.class);
+    Response response = sync.delete(generic);
+    assertResponseOk(response);
+    return response;
+  }
+
+  /*
+   * @testName: deleteWithGenericTypeStringThrowsProcessingExceptionTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:546;
+   * 
+   * @test_Strategy: jakarta.ws.rs.client.SyncInvoker.delete( Class ) throws
+   * ProcessingException in case the invocation failed.
+   */
+  @Test
+  public void deleteWithGenericTypeStringThrowsProcessingExceptionTest()
+      throws Fault {
+    Runnable run = new Runnable() {
+      @Override
+      public void run() {
+        SyncInvoker sync = createSyncInvokerWrongUrl();
+        GenericType<String> generic = createGeneric(String.class);
+        sync.delete(generic);
+      }
+    };
+    assertProcessingException(run);
+  }
+
+  /*
+   * @testName: deleteWithGenericTypeStringThrowsWebApplicationExceptionTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:546;
+   * 
+   * @test_Strategy: jakarta.ws.rs.client.SyncInvoker.delete( Class ) throws
+   * WebApplicationException - in case the response status code of the response
+   * returned by the server is not successful and the specified response type is
+   * not Response.
+   */
+  @Test
+  public void deleteWithGenericTypeStringThrowsWebApplicationExceptionTest()
+      throws Fault {
+    Runnable run = new Runnable() {
+      @Override
+      public void run() {
+        SyncInvoker sync = createSyncInvokerForMethod("deletenotok");
+        GenericType<String> generic = createGeneric(String.class);
+        sync.delete(generic);
+      }
+    };
+    assertWebApplicationException(run);
+  }
+
+  /*
+   * @testName: deleteWithGenericTypeResponseThrowsNoWebApplicationExceptionTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:546;
+   * 
+   * @test_Strategy: jakarta.ws.rs.client.SyncInvoker.delete( Class ) throws
+   * WebApplicationException - in case the response status code of the response
+   * returned by the server is not successful and the specified response type is
+   * not Response.
+   */
+  @Test
+  public void deleteWithGenericTypeResponseThrowsNoWebApplicationExceptionTest()
+      throws Fault {
+    SyncInvoker sync = createSyncInvokerForMethod("deletenotok");
+    GenericType<Response> generic = createGeneric(Response.class);
+    Response response = sync.delete(generic);
+    assertStatusAndLog(response, Status.NOT_ACCEPTABLE);
+  }
+
+  // ------------------------------------------------------------------
+  // ---------------------------GET------------------------------------
+  // ------------------------------------------------------------------
+  /*
+   * @testName: getTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:549;
+   * 
+   * @test_Strategy: Invoke HTTP GET method for the current request
+   * synchronously.
+   */
+  @Test
+  public Response getTest() throws Fault {
+    SyncInvoker sync = createSyncInvokerForMethod("get");
+    Response response = sync.get();
+    assertResponseOk(response);
+    return response;
+  }
+
+  /*
+   * @testName: getThrowsProcessingExceptionTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:549;
+   * 
+   * @test_Strategy: jakarta.ws.rs.client.SyncInvoker.get throws
+   * ProcessingException in case the invocation failed.
+   */
+  @Test
+  public void getThrowsProcessingExceptionTest() throws Fault {
+    Runnable run = new Runnable() {
+      @Override
+      public void run() {
+        SyncInvoker sync = createSyncInvokerWrongUrl();
+        sync.get();
+      }
+    };
+    assertProcessingException(run);
+  }
+
+  /*
+   * @testName: getWithStringClassTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:551;
+   * 
+   * @test_Strategy: Invoke HTTP GET method for the current request
+   * synchronously.
+   */
+  @Test
+  public String getWithStringClassTest() throws Fault {
+    SyncInvoker sync = createSyncInvokerForMethod("get");
+    String response = sync.get(String.class);
+    assertResponseString(response, "get");
+    return response;
+  }
+
+  /*
+   * @testName: getWithResponseClassTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:551;
+   * 
+   * @test_Strategy: Invoke HTTP GET method for the current request
+   * synchronously.
+   */
+  @Test
+  public Response getWithResponseClassTest() throws Fault {
+    SyncInvoker sync = createSyncInvokerForMethod("get");
+    Response response = sync.get(Response.class);
+    assertResponseOk(response);
+    return response;
+  }
+
+  /*
+   * @testName: getWithStringClassThrowsProcessingExceptionTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:551;
+   * 
+   * @test_Strategy: jakarta.ws.rs.client.SyncInvoker.get( Class ) throws
+   * ProcessingException in case the invocation failed.
+   */
+  @Test
+  public void getWithStringClassThrowsProcessingExceptionTest() throws Fault {
+    Runnable run = new Runnable() {
+      @Override
+      public void run() {
+        SyncInvoker sync = createSyncInvokerWrongUrl();
+        sync.get(String.class);
+      }
+    };
+    assertProcessingException(run);
+  }
+
+  /*
+   * @testName: getWithStringClassThrowsWebApplicationExceptionTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:551;
+   * 
+   * @test_Strategy: jakarta.ws.rs.client.SyncInvoker.get( Class ) throws
+   * WebApplicationException - in case the response status code of the response
+   * returned by the server is not successful and the specified response type is
+   * not Response.
+   */
+  @Test
+  public void getWithStringClassThrowsWebApplicationExceptionTest()
+      throws Fault {
+    Runnable run = new Runnable() {
+      @Override
+      public void run() {
+        SyncInvoker sync = createSyncInvokerForMethod("getnotok");
+        sync.get(String.class);
+      }
+    };
+    assertWebApplicationException(run);
+  }
+
+  /*
+   * @testName: getWithResponseClassThrowsNoWebApplicationExceptionTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:551;
+   * 
+   * @test_Strategy: jakarta.ws.rs.client.SyncInvoker.get( Class ) throws
+   * WebApplicationException - in case the response status code of the response
+   * returned by the server is not successful and the specified response type is
+   * not Response.
+   */
+  @Test
+  public void getWithResponseClassThrowsNoWebApplicationExceptionTest()
+      throws Fault {
+    SyncInvoker sync = createSyncInvokerForMethod("getnotok");
+    Response response = sync.get(Response.class);
+    assertStatusAndLog(response, Status.NOT_ACCEPTABLE);
+  }
+
+  /*
+   * @testName: getWithGenericTypeStringTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:554;
+   * 
+   * @test_Strategy: Invoke HTTP GET method for the current request
+   * synchronously.
+   */
+  @Test
+  public String getWithGenericTypeStringTest() throws Fault {
+    SyncInvoker sync = createSyncInvokerForMethod("get");
+    GenericType<String> generic = createGeneric(String.class);
+    String response = sync.get(generic);
+    assertResponseString(response, "get");
+    return response;
+  }
+
+  /*
+   * @testName: getWithGenericTypeResponseTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:554;
+   * 
+   * @test_Strategy: Invoke HTTP GET method for the current request
+   * synchronously.
+   */
+  @Test
+  public Response getWithGenericTypeResponseTest() throws Fault {
+    SyncInvoker sync = createSyncInvokerForMethod("get");
+    GenericType<Response> generic = createGeneric(Response.class);
+    Response response = sync.get(generic);
+    assertResponseOk(response);
+    return response;
+  }
+
+  /*
+   * @testName: getWithGenericTypeStringThrowsProcessingExceptionTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:554;
+   * 
+   * @test_Strategy: jakarta.ws.rs.client.SyncInvoker.get( GenericType ) throws
+   * ProcessingException in case the invocation failed.
+   */
+  @Test
+  public void getWithGenericTypeStringThrowsProcessingExceptionTest()
+      throws Fault {
+    Runnable run = new Runnable() {
+      @Override
+      public void run() {
+        SyncInvoker sync = createSyncInvokerWrongUrl();
+        GenericType<String> generic = createGeneric(String.class);
+        sync.get(generic);
+      }
+    };
+    assertProcessingException(run);
+  }
+
+  /*
+   * @testName: getWithGenericTypeStringThrowsWebApplicationExceptionTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:554;
+   * 
+   * @test_Strategy: jakarta.ws.rs.client.SyncInvoker.get( GenericType ) throws
+   * WebApplicationException - in case the response status code of the response
+   * returned by the server is not successful and the specified response type is
+   * not Response.
+   */
+  @Test
+  public void getWithGenericTypeStringThrowsWebApplicationExceptionTest()
+      throws Fault {
+    Runnable run = new Runnable() {
+      @Override
+      public void run() {
+        SyncInvoker sync = createSyncInvokerForMethod("getnotok");
+        GenericType<String> generic = createGeneric(String.class);
+        sync.get(generic);
+      }
+    };
+    assertWebApplicationException(run);
+  }
+
+  /*
+   * @testName: getWithGenericTypeResponseThrowsNoWebApplicationExceptionTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:554;
+   * 
+   * @test_Strategy: jakarta.ws.rs.client.SyncInvoker.get( GenericType ) throws
+   * WebApplicationException - in case the response status code of the response
+   * returned by the server is not successful and the specified response type is
+   * not Response.
+   */
+  @Test
+  public void getWithGenericTypeResponseThrowsNoWebApplicationExceptionTest()
+      throws Fault {
+    SyncInvoker sync = createSyncInvokerForMethod("getnotok");
+    GenericType<Response> generic = createGeneric(Response.class);
+    Response response = sync.get(generic);
+    assertStatusAndLog(response, Status.NOT_ACCEPTABLE);
+  }
+
+  // ------------------------------------------------------------------
+  // ---------------------------HEAD-----------------------------------
+  // ------------------------------------------------------------------
+
+  /*
+   * @testName: headTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:557;
+   * 
+   * @test_Strategy: Invoke HTTP HEAD method for the current request
+   * synchronously.
+   */
+  @Test
+  public Response headTest() throws Fault {
+    SyncInvoker sync = createSyncInvokerForMethod("head");
+    Response response = sync.head();
+    Status status = Status.fromStatusCode(response.getStatus());
+    assertTrue(status == Status.OK || status == Status.NO_CONTENT,
+        "Incorrect status for head received");
+    return response;
+  }
+
+  /*
+   * @testName: headThrowsProcessingExceptionTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:557;
+   * 
+   * @test_Strategy: jakarta.ws.rs.client.SyncInvoker.head throws
+   * ProcessingException in case the invocation failed.
+   */
+  @Test
+  public void headThrowsProcessingExceptionTest() throws Fault {
+    Runnable run = new Runnable() {
+      @Override
+      public void run() {
+        SyncInvoker sync = createSyncInvokerWrongUrl();
+        sync.head();
+      }
+    };
+    assertProcessingException(run);
+  }
+
+  // ------------------------------------------------------------------
+  // ---------------------------METHOD-----------------------------------
+  // ------------------------------------------------------------------
+
+  /*
+   * @testName: methodTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:559;
+   * 
+   * @test_Strategy: Invoke an arbitrary method for the current request
+   * synchronously.
+   */
+  @Test
+  public void methodTest() throws Fault {
+    Response response = null;
+    for (String method : METHODS) {
+      SyncInvoker sync = createSyncInvokerForMethod(method.toLowerCase());
+      response = sync.method(method);
+      assertResponseOk(response);
+    }
+  }
+
+  /*
+   * @testName: methodThrowsProcessingExceptionTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:559;
+   * 
+   * @test_Strategy: jakarta.ws.rs.client.SyncInvoker.method(String) throws
+   * ProcessingException in case the invocation failed.
+   */
+  @Test
+  public void methodThrowsProcessingExceptionTest() throws Fault {
+    for (final String method : METHODS) {
+      Runnable run = new Runnable() {
+        @Override
+        public void run() {
+          SyncInvoker sync = createSyncInvokerWrongUrl();
+          sync.method(method);
+        }
+      };
+      assertProcessingException(run);
+    }
+  }
+
+  /*
+   * @testName: methodWithStringClassTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:561;
+   * 
+   * @test_Strategy: Invoke an arbitrary method for the current request
+   * synchronously.
+   */
+  @Test
+  public void methodWithStringClassTest() throws Fault {
+    String response = null;
+    for (String method : METHODS) {
+      SyncInvoker sync = createSyncInvokerForMethod(method.toLowerCase());
+      response = sync.method(method, String.class);
+      assertResponseString(response, method.toLowerCase());
+    }
+  }
+
+  /*
+   * @testName: methodWithResponseClassTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:561;
+   * 
+   * @test_Strategy: Invoke an arbitrary method for the current request
+   * synchronously.
+   */
+  @Test
+  public void methodWithResponseClassTest() throws Fault {
+    Response response = null;
+    for (String method : METHODS) {
+      SyncInvoker sync = createSyncInvokerForMethod(method.toLowerCase());
+      response = sync.method(method, Response.class);
+      assertResponseOk(response);
+    }
+  }
+
+  /*
+   * @testName: methodWithStringClassThrowsProcessingExceptionTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:561;
+   * 
+   * @test_Strategy: jakarta.ws.rs.client.SyncInvoker.method(String) throws
+   * WebApplicationException - in case the response status code of the response
+   * returned by the server is not successful and the specified response type is
+   * not Response.
+   */
+  @Test
+  public void methodWithStringClassThrowsProcessingExceptionTest()
+      throws Fault {
+    for (final String method : METHODS) {
+      Runnable run = new Runnable() {
+        @Override
+        public void run() {
+          SyncInvoker sync = createSyncInvokerWrongUrl();
+          sync.method(method, String.class);
+        }
+      };
+      assertProcessingException(run);
+    }
+  }
+
+  /*
+   * @testName: methodWithStringClassThrowsWebApplicationExceptionTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:561;
+   * 
+   * @test_Strategy: jakarta.ws.rs.client.SyncInvoker.method(String) throws
+   * WebApplicationException - in case the response status code of the response
+   * returned by the server is not successful and the specified response type is
+   * not Response.
+   */
+  @Test
+  public void methodWithStringClassThrowsWebApplicationExceptionTest()
+      throws Fault {
+    for (final String method : METHODS) {
+      Runnable run = new Runnable() {
+        @Override
+        public void run() {
+          SyncInvoker sync = createSyncInvokerForMethod(
+              method.toLowerCase() + "notok");
+          sync.method(method, String.class);
+        }
+      };
+      assertWebApplicationException(run);
+    }
+  }
+
+  /*
+   * @testName: methodWithResponseClassThrowsNoWebApplicationExceptionTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:561;
+   * 
+   * @test_Strategy: jakarta.ws.rs.client.SyncInvoker.method(String) throws
+   * ProcessingException in case the invocation failed.
+   */
+  @Test
+  public void methodWithResponseClassThrowsNoWebApplicationExceptionTest()
+      throws Fault {
+    for (final String method : METHODS) {
+      SyncInvoker sync = createSyncInvokerForMethod(
+          method.toLowerCase() + "notok");
+      Response response = sync.method(method, Response.class);
+      assertStatusAndLog(response, Status.NOT_ACCEPTABLE);
+    }
+  }
+
+  /*
+   * @testName: methodWithGenericTypeStringTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:564;
+   * 
+   * @test_Strategy: Invoke an arbitrary method for the current request
+   * synchronously.
+   */
+  @Test
+  public void methodWithGenericTypeStringTest() throws Fault {
+    GenericType<String> generic = createGeneric(String.class);
+    String response = null;
+    for (String method : METHODS) {
+      SyncInvoker sync = createSyncInvokerForMethod(method.toLowerCase());
+      response = sync.method(method, generic);
+      assertResponseString(response, method.toLowerCase());
+    }
+  }
+
+  /*
+   * @testName: methodWithGenericTypeResponseTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:564;
+   * 
+   * @test_Strategy: Invoke an arbitrary method for the current request
+   * synchronously.
+   */
+  @Test
+  public void methodWithGenericTypeResponseTest() throws Fault {
+    GenericType<Response> generic = createGeneric(Response.class);
+    Response response = null;
+    for (String method : METHODS) {
+      SyncInvoker sync = createSyncInvokerForMethod(method.toLowerCase());
+      response = sync.method(method, generic);
+      assertResponseOk(response);
+    }
+  }
+
+  /*
+   * @testName: methodWithGenericTypeStringThrowsProcessingExceptionTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:564;
+   * 
+   * @test_Strategy: jakarta.ws.rs.client.SyncInvoker.method(String) throws
+   * ProcessingException in case the invocation failed.
+   */
+  @Test
+  public void methodWithGenericTypeStringThrowsProcessingExceptionTest()
+      throws Fault {
+    final GenericType<String> generic = createGeneric(String.class);
+    for (final String method : METHODS) {
+      Runnable run = new Runnable() {
+        @Override
+        public void run() {
+          SyncInvoker sync = createSyncInvokerWrongUrl();
+          sync.method(method, generic);
+        }
+      };
+      assertProcessingException(run);
+    }
+  }
+
+  /*
+   * @testName: methodWithGenericTypeStringThrowsWebApplicationExceptionTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:564;
+   * 
+   * @test_Strategy: jakarta.ws.rs.client.SyncInvoker.method(GenericType<String>)
+   * throws WebApplicationException - in case the response status code of the
+   * response returned by the server is not successful and the specified
+   * response type is not Response.
+   */
+  @Test
+  public void methodWithGenericTypeStringThrowsWebApplicationExceptionTest()
+      throws Fault {
+    final GenericType<String> generic = createGeneric(String.class);
+    for (final String method : METHODS) {
+      Runnable run = new Runnable() {
+        @Override
+        public void run() {
+          SyncInvoker sync = createSyncInvokerForMethod(
+              method.toLowerCase() + "notok");
+          sync.method(method, generic);
+        }
+      };
+      assertWebApplicationException(run);
+    }
+  }
+
+  /*
+   * @testName: methodWithGenericTypeResponseThrowsNoWebApplicationExceptionTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:564;
+   * 
+   * @test_Strategy:
+   * jakarta.ws.rs.client.SyncInvoker.method(GenericType<Response>) throws
+   * WebApplicationException - in case the response status code of the response
+   * returned by the server is not successful and the specified response type is
+   * not Response.
+   */
+  @Test
+  public void methodWithGenericTypeResponseThrowsNoWebApplicationExceptionTest()
+      throws Fault {
+    GenericType<Response> generic = createGeneric(Response.class);
+    Response response = null;
+    for (final String method : METHODS) {
+      SyncInvoker sync = createSyncInvokerForMethod(
+          method.toLowerCase() + "notok");
+      response = sync.method(method, generic);
+      assertStatusAndLog(response, Status.NOT_ACCEPTABLE);
+    }
+  }
+
+  /*
+   * @testName: methodWithEntityTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:567;
+   * 
+   * @test_Strategy: Invoke an arbitrary method for the current request
+   * synchronously.
+   */
+  @Test
+  public Response methodWithEntityTest() throws Fault {
+    Response response = null;
+    for (String method : ENTITY_METHODS) {
+      SyncInvoker sync = createSyncInvokerForMethod(method.toLowerCase());
+      Entity<String> entity = createEntity(method.toLowerCase());
+      response = sync.method(method, entity);
+      assertResponseOk(response);
+    }
+    return response;
+  }
+
+  /*
+   * @testName: methodWithEntityThrowsProcessingExceptionTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:567;
+   * 
+   * @test_Strategy: jakarta.ws.rs.client.SyncInvoker.method(String, Entity)
+   * throws ProcessingException in case the invocation failed.
+   */
+  @Test
+  public void methodWithEntityThrowsProcessingExceptionTest() throws Fault {
+    final Entity<String> entity = createEntity("entity");
+    for (final String method : ENTITY_METHODS) {
+      Runnable run = new Runnable() {
+        @Override
+        public void run() {
+          SyncInvoker sync = createSyncInvokerWrongUrl();
+          sync.method(method, entity);
+        }
+      };
+      assertProcessingException(run);
+    }
+  }
+
+  /*
+   * @testName: methodWithStringClassWithEntityTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:569;
+   * 
+   * @test_Strategy: Invoke an arbitrary method for the current request
+   * synchronously.
+   */
+  @Test
+  public String methodWithStringClassWithEntityTest() throws Fault {
+    String response = null;
+    for (String method : ENTITY_METHODS) {
+      SyncInvoker sync = createSyncInvokerForMethod(method.toLowerCase());
+      Entity<String> entity = createEntity(method.toLowerCase());
+      response = sync.method(method, entity, String.class);
+      assertResponseString(response, method.toLowerCase());
+    }
+    return response;
+  }
+
+  /*
+   * @testName: methodWithResponseClassWithEntityTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:569;
+   * 
+   * @test_Strategy: Invoke an arbitrary method for the current request
+   * synchronously.
+   */
+  @Test
+  public String methodWithResponseClassWithEntityTest() throws Fault {
+    String response = null;
+    for (String method : ENTITY_METHODS) {
+      SyncInvoker sync = createSyncInvokerForMethod(method.toLowerCase());
+      Entity<String> entity = createEntity(method.toLowerCase());
+      response = sync.method(method, entity, String.class);
+      assertResponseString(response, method.toLowerCase());
+    }
+    return response;
+  }
+
+  /*
+   * @testName: methodWithStringClassWithEntityThrowsProcessingExceptionTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:569;
+   * 
+   * @test_Strategy: jakarta.ws.rs.client.SyncInvoker.method(String, Entity,
+   * Class) throws ProcessingException in case the invocation failed.
+   */
+  @Test
+  public void methodWithStringClassWithEntityThrowsProcessingExceptionTest()
+      throws Fault {
+    for (final String method : ENTITY_METHODS) {
+      Runnable run = new Runnable() {
+        @Override
+        public void run() {
+          SyncInvoker sync = createSyncInvokerWrongUrl();
+          Entity<String> entity = createEntity(method.toLowerCase());
+          sync.method(method, entity, String.class);
+        }
+      };
+      assertProcessingException(run);
+    }
+  }
+
+  /*
+   * @testName: methodWithStringClassWithEntityThrowsWebApplicationExceptionTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:569;
+   * 
+   * @test_Strategy: jakarta.ws.rs.client.SyncInvoker.method(String, Entity,
+   * Class) throws WebApplicationException - in case the response status code of
+   * the response returned by the server is not successful and the specified
+   * response type is not Response.
+   */
+  @Test
+  public void methodWithStringClassWithEntityThrowsWebApplicationExceptionTest()
+      throws Fault {
+    for (final String method : ENTITY_METHODS) {
+      Runnable run = new Runnable() {
+        @Override
+        public void run() {
+          SyncInvoker sync = createSyncInvokerForMethod(
+              method.toLowerCase() + "notok");
+          Entity<String> entity = createEntity(method.toLowerCase());
+          sync.method(method, entity, String.class);
+        }
+      };
+      assertWebApplicationException(run);
+    }
+  }
+
+  /*
+   * @testName:
+   * methodWithResponseClassWithEntityThrowsNoWebApplicationExceptionTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:569;
+   * 
+   * @test_Strategy: jakarta.ws.rs.client.SyncInvoker.method(String, Entity,
+   * Class) throws WebApplicationException - in case the response status code of
+   * the response returned by the server is not successful and the specified
+   * response type is not Response.
+   */
+  @Test
+  public void methodWithResponseClassWithEntityThrowsNoWebApplicationExceptionTest()
+      throws Fault {
+    for (final String method : ENTITY_METHODS) {
+      SyncInvoker sync = createSyncInvokerForMethod(
+          method.toLowerCase() + "notok");
+      Entity<String> entity = createEntity(method.toLowerCase());
+      Response response = sync.method(method, entity, Response.class);
+      assertStatusAndLog(response, Status.NOT_ACCEPTABLE);
+    }
+  }
+
+  /*
+   * @testName: methodWithGenericTypeStringWithEntityTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:572;
+   * 
+   * @test_Strategy: Invoke an arbitrary method for the current request
+   * synchronously.
+   */
+  @Test
+  public void methodWithGenericTypeStringWithEntityTest() throws Fault {
+    String response = null;
+    for (String method : ENTITY_METHODS) {
+      GenericType<String> generic = createGeneric(String.class);
+      SyncInvoker sync = createSyncInvokerForMethod(method.toLowerCase());
+      Entity<String> entity = createEntity(method.toLowerCase());
+      response = sync.method(method, entity, generic);
+      assertResponseString(response, method.toLowerCase());
+    }
+  }
+
+  /*
+   * @testName: methodWithGenericTypeResponseWithEntityTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:572;
+   * 
+   * @test_Strategy: Invoke an arbitrary method for the current request
+   * synchronously.
+   */
+  @Test
+  public void methodWithGenericTypeResponseWithEntityTest() throws Fault {
+    Response response = null;
+    for (String method : ENTITY_METHODS) {
+      GenericType<Response> generic = createGeneric(Response.class);
+      SyncInvoker sync = createSyncInvokerForMethod(method.toLowerCase());
+      Entity<String> entity = createEntity(method.toLowerCase());
+      response = sync.method(method, entity, generic);
+      assertResponseOk(response);
+    }
+  }
+
+  /*
+   * @testName:
+   * methodWithGenericTypeStringWithEntityThrowsProcessingExceptionTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:572;
+   * 
+   * @test_Strategy: jakarta.ws.rs.client.SyncInvoker.method(String, Entity,
+   * GenericType) throws ProcessingException in case the invocation failed.
+   */
+  @Test
+  public void methodWithGenericTypeStringWithEntityThrowsProcessingExceptionTest()
+      throws Fault {
+    for (final String method : ENTITY_METHODS) {
+      Runnable run = new Runnable() {
+        @Override
+        public void run() {
+          GenericType<String> generic = createGeneric(String.class);
+          SyncInvoker sync = createSyncInvokerWrongUrl();
+          Entity<String> entity = createEntity(method);
+          sync.method(method, entity, generic);
+        }
+      };
+      assertProcessingException(run);
+    }
+  }
+
+  /*
+   * @testName:
+   * methodWithGenericTypeStringWithEntityThrowsWebApplicationExceptionTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:572;
+   * 
+   * @test_Strategy: jakarta.ws.rs.client.SyncInvoker.method(String, Entity,
+   * GenericType) throws WebApplicationException - in case the response status
+   * code of the response returned by the server is not successful and the
+   * specified response type is not Response.
+   */
+  @Test
+  public void methodWithGenericTypeStringWithEntityThrowsWebApplicationExceptionTest()
+      throws Fault {
+    for (final String method : ENTITY_METHODS) {
+      Runnable run = new Runnable() {
+        @Override
+        public void run() {
+          GenericType<String> generic = createGeneric(String.class);
+          SyncInvoker sync = createSyncInvokerForMethod(
+              method.toLowerCase() + "notok");
+          Entity<String> entity = createEntity(method);
+          sync.method(method, entity, generic);
+        }
+      };
+      assertWebApplicationException(run);
+    }
+  }
+
+  /*
+   * @testName:
+   * methodWithGenericTypeResponseWithEntityThrowsNoWebApplicationExceptionTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:572;
+   * 
+   * @test_Strategy: jakarta.ws.rs.client.SyncInvoker.method(String, Entity,
+   * GenericType) throws WebApplicationException - in case the response status
+   * code of the response returned by the server is not successful and the
+   * specified response type is not Response.
+   */
+  @Test
+  public void methodWithGenericTypeResponseWithEntityThrowsNoWebApplicationExceptionTest()
+      throws Fault {
+    for (final String method : ENTITY_METHODS) {
+      GenericType<Response> generic = createGeneric(Response.class);
+      SyncInvoker sync = createSyncInvokerForMethod(
+          method.toLowerCase() + "notok");
+      Entity<String> entity = createEntity(method);
+      Response response = sync.method(method, entity, generic);
+      assertStatusAndLog(response, Status.NOT_ACCEPTABLE);
+    }
+  }
+
+  // ------------------------------------------------------------------
+  // ---------------------------OPTIONS--------------------------------
+  // ------------------------------------------------------------------
+
+  /*
+   * @testName: optionsTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:575;
+   * 
+   * @test_Strategy: Invoke HTTP options method for the current request
+   * synchronously.
+   */
+  @Test
+  public Response optionsTest() throws Fault {
+    SyncInvoker sync = createSyncInvokerForMethod("options");
+    Response response = sync.options();
+    assertResponseOk(response);
+    return response;
+  }
+
+  /*
+   * @testName: optionsThrowsProcessingExceptionTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:575;
+   * 
+   * @test_Strategy: jakarta.ws.rs.client.SyncInvoker.options throws
+   * ProcessingException in case the invocation failed.
+   */
+  @Test
+  public void optionsThrowsProcessingExceptionTest() throws Fault {
+    Runnable run = new Runnable() {
+      @Override
+      public void run() {
+        SyncInvoker sync = createSyncInvokerWrongUrl();
+        sync.options();
+      }
+    };
+    assertProcessingException(run);
+  }
+
+  /*
+   * @testName: optionsWithStringClassTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:577;
+   * 
+   * @test_Strategy: Invoke HTTP options method for the current request
+   * synchronously.
+   */
+  @Test
+  public String optionsWithStringClassTest() throws Fault {
+    SyncInvoker sync = createSyncInvokerForMethod("options");
+    String response = sync.options(String.class);
+    assertResponseString(response, "options");
+    return response;
+  }
+
+  /*
+   * @testName: optionsWithResponseClassTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:577;
+   * 
+   * @test_Strategy: Invoke HTTP options method for the current request
+   * synchronously.
+   */
+  @Test
+  public Response optionsWithResponseClassTest() throws Fault {
+    SyncInvoker sync = createSyncInvokerForMethod("options");
+    Response response = sync.options(Response.class);
+    assertResponseOk(response);
+    return response;
+  }
+
+  /*
+   * @testName: optionsWithStringThrowsProcessingExceptionTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:577;
+   * 
+   * @test_Strategy: jakarta.ws.rs.client.SyncInvoker.options( Class ) throws
+   * ProcessingException in case the invocation failed.
+   */
+  @Test
+  public void optionsWithStringThrowsProcessingExceptionTest() throws Fault {
+    Runnable run = new Runnable() {
+      @Override
+      public void run() {
+        SyncInvoker sync = createSyncInvokerWrongUrl();
+        sync.options(String.class);
+      }
+    };
+    assertProcessingException(run);
+  }
+
+  /*
+   * @testName: optionsWithStringThrowsWebApplicationExceptionTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:577;
+   * 
+   * @test_Strategy: jakarta.ws.rs.client.SyncInvoker.options( Class ) throws
+   * WebApplicationException - in case the response status code of the response
+   * returned by the server is not successful and the specified response type is
+   * not Response.
+   */
+  @Test
+  public void optionsWithStringThrowsWebApplicationExceptionTest()
+      throws Fault {
+    Runnable run = new Runnable() {
+      @Override
+      public void run() {
+        SyncInvoker sync = createSyncInvokerForMethod("optionsnotok");
+        sync.options(String.class);
+      }
+    };
+    assertWebApplicationException(run);
+  }
+
+  /*
+   * @testName: optionsWithResponseThrowsNoWebApplicationExceptionTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:577;
+   * 
+   * @test_Strategy: jakarta.ws.rs.client.SyncInvoker.options( Class ) throws
+   * WebApplicationException - in case the response status code of the response
+   * returned by the server is not successful and the specified response type is
+   * not Response.
+   */
+  @Test
+  public void optionsWithResponseThrowsNoWebApplicationExceptionTest()
+      throws Fault {
+    SyncInvoker sync = createSyncInvokerForMethod("optionsnotok");
+    Response response = sync.options(Response.class);
+    assertStatusAndLog(response, Status.NOT_ACCEPTABLE);
+  }
+
+  /*
+   * @testName: optionsWithGenericTypeStringTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:580;
+   * 
+   * @test_Strategy: Invoke HTTP options method for the current request
+   * synchronously.
+   */
+  @Test
+  public String optionsWithGenericTypeStringTest() throws Fault {
+    SyncInvoker sync = createSyncInvokerForMethod("options");
+    GenericType<String> generic = createGeneric(String.class);
+    String response = sync.options(generic);
+    assertResponseString(response, "options");
+    return response;
+  }
+
+  /*
+   * @testName: optionsWithGenericTypeResponseTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:580;
+   * 
+   * @test_Strategy: Invoke HTTP options method for the current request
+   * synchronously.
+   */
+  @Test
+  public Response optionsWithGenericTypeResponseTest() throws Fault {
+    SyncInvoker sync = createSyncInvokerForMethod("options");
+    GenericType<Response> generic = createGeneric(Response.class);
+    Response response = sync.options(generic);
+    assertResponseOk(response);
+    return response;
+  }
+
+  /*
+   * @testName: optionsWithGenericTypeStringThrowsProcessingExceptionTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:580;
+   * 
+   * @test_Strategy: jakarta.ws.rs.client.SyncInvoker.options( GenericType )
+   * throws ProcessingException in case the invocation failed.
+   */
+  @Test
+  public void optionsWithGenericTypeStringThrowsProcessingExceptionTest()
+      throws Fault {
+    Runnable run = new Runnable() {
+      @Override
+      public void run() {
+        SyncInvoker sync = createSyncInvokerWrongUrl();
+        GenericType<String> generic = createGeneric(String.class);
+        sync.options(generic);
+      }
+    };
+    assertProcessingException(run);
+  }
+
+  /*
+   * @testName: optionsWithGenericTypeStringThrowsWebApplicationExceptionTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:580;
+   * 
+   * @test_Strategy: jakarta.ws.rs.client.SyncInvoker.options( GenericType )
+   * throws WebApplicationException - in case the response status code of the
+   * response returned by the server is not successful and the specified
+   * response type is not Response.
+   */
+  @Test
+  public void optionsWithGenericTypeStringThrowsWebApplicationExceptionTest()
+      throws Fault {
+    Runnable run = new Runnable() {
+      @Override
+      public void run() {
+        SyncInvoker sync = createSyncInvokerForMethod("optionsnotok");
+        GenericType<String> generic = createGeneric(String.class);
+        sync.options(generic);
+      }
+    };
+    assertWebApplicationException(run);
+  }
+
+  /*
+   * @testName:
+   * optionsWithGenericTypeResponseThrowsNoWebApplicationExceptionTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:580;
+   * 
+   * @test_Strategy: jakarta.ws.rs.client.SyncInvoker.options( GenericType )
+   * throws WebApplicationException - in case the response status code of the
+   * response returned by the server is not successful and the specified
+   * response type is not Response.
+   */
+  @Test
+  public void optionsWithGenericTypeResponseThrowsNoWebApplicationExceptionTest()
+      throws Fault {
+    SyncInvoker sync = createSyncInvokerForMethod("optionsnotok");
+    GenericType<Response> generic = createGeneric(Response.class);
+    Response response = sync.options(generic);
+    assertStatusAndLog(response, Status.NOT_ACCEPTABLE);
+  }
+
+  // ------------------------------------------------------------------
+  // ---------------------------POST-----------------------------------
+  // ------------------------------------------------------------------
+
+  /*
+   * @testName: postTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:583;
+   * 
+   * @test_Strategy: Invoke HTTP post method for the current request
+   * synchronously.
+   */
+  @Test
+  public Response postTest() throws Fault {
+    SyncInvoker sync = createSyncInvokerForMethod("post");
+    Entity<String> entity = createEntity("post");
+    Response response = sync.post(entity);
+    assertResponseOk(response);
+    return response;
+  }
+
+  /*
+   * @testName: postThrowsProcessingExceptionTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:583;
+   * 
+   * @test_Strategy: jakarta.ws.rs.client.SyncInvoker.post(Entity) throws
+   * ProcessingException in case the invocation failed.
+   */
+  @Test
+  public void postThrowsProcessingExceptionTest() throws Fault {
+    Runnable run = new Runnable() {
+      @Override
+      public void run() {
+        SyncInvoker sync = createSyncInvokerWrongUrl();
+        Entity<String> entity = createEntity("post");
+        sync.post(entity);
+      }
+    };
+    assertProcessingException(run);
+  }
+
+  /*
+   * @testName: postWithStringClassTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:585;
+   * 
+   * @test_Strategy: Invoke HTTP post method for the current request
+   * synchronously.
+   */
+  @Test
+  public String postWithStringClassTest() throws Fault {
+    Entity<String> entity = createEntity("post");
+    SyncInvoker sync = createSyncInvokerForMethod("post");
+    String response = sync.post(entity, String.class);
+    assertResponseString(response, "post");
+    return response;
+  }
+
+  /*
+   * @testName: postWithResponseClassTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:585;
+   * 
+   * @test_Strategy: Invoke HTTP post method for the current request
+   * synchronously.
+   */
+  @Test
+  public Response postWithResponseClassTest() throws Fault {
+    Entity<String> entity = createEntity("post");
+    SyncInvoker sync = createSyncInvokerForMethod("post");
+    Response response = sync.post(entity, Response.class);
+    assertResponseOk(response);
+    return response;
+  }
+
+  /*
+   * @testName: postWithStringClassThrowsProcessingExceptionTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:585;
+   * 
+   * @test_Strategy: jakarta.ws.rs.client.SyncInvoker.post( Entity, Class ) throws
+   * ProcessingException in case the invocation failed.
+   */
+  @Test
+  public void postWithStringClassThrowsProcessingExceptionTest() throws Fault {
+    Runnable run = new Runnable() {
+      @Override
+      public void run() {
+        SyncInvoker sync = createSyncInvokerWrongUrl();
+        Entity<String> entity = createEntity("post");
+        sync.post(entity, String.class);
+      }
+    };
+    assertProcessingException(run);
+  }
+
+  /*
+   * @testName: postWithStringClassThrowsWebApplicationExceptionTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:585;
+   * 
+   * @test_Strategy: jakarta.ws.rs.client.SyncInvoker.post( Entity, Class ) throws
+   * WebApplicationException - in case the response status code of the response
+   * returned by the server is not successful and the specified response type is
+   * not Response.
+   */
+  @Test
+  public void postWithStringClassThrowsWebApplicationExceptionTest()
+      throws Fault {
+    Runnable run = new Runnable() {
+      @Override
+      public void run() {
+        SyncInvoker sync = createSyncInvokerForMethod("postnotok");
+        Entity<String> entity = createEntity("post");
+        sync.post(entity, String.class);
+      }
+    };
+    assertWebApplicationException(run);
+  }
+
+  /*
+   * @testName: postWithResponseClassThrowsNoWebApplicationExceptionTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:585;
+   * 
+   * @test_Strategy: jakarta.ws.rs.client.SyncInvoker.post( Entity, Class ) throws
+   * WebApplicationException - in case the response status code of the response
+   * returned by the server is not successful and the specified response type is
+   * not Response.
+   */
+  @Test
+  public void postWithResponseClassThrowsNoWebApplicationExceptionTest()
+      throws Fault {
+    SyncInvoker sync = createSyncInvokerForMethod("postnotok");
+    Entity<String> entity = createEntity("post");
+    Response response = sync.post(entity, Response.class);
+    assertStatusAndLog(response, Status.NOT_ACCEPTABLE);
+  }
+
+  /*
+   * @testName: postWithGenericTypeStringTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:588;
+   * 
+   * @test_Strategy: Invoke HTTP post method for the current request
+   * synchronously.
+   */
+  @Test
+  public String postWithGenericTypeStringTest() throws Fault {
+    GenericType<String> generic = createGeneric(String.class);
+    Entity<String> entity = createEntity("post");
+    SyncInvoker sync = createSyncInvokerForMethod("post");
+    String response = sync.post(entity, generic);
+    assertResponseString(response, "post");
+    return response;
+  }
+
+  /*
+   * @testName: postWithGenericTypeResponseTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:588;
+   * 
+   * @test_Strategy: Invoke HTTP post method for the current request
+   * synchronously.
+   */
+  @Test
+  public Response postWithGenericTypeResponseTest() throws Fault {
+    GenericType<Response> generic = createGeneric(Response.class);
+    Entity<String> entity = createEntity("post");
+    SyncInvoker sync = createSyncInvokerForMethod("post");
+    Response response = sync.post(entity, generic);
+    assertResponseOk(response);
+    return response;
+  }
+
+  /*
+   * @testName: postWithGenericTypeStringThrowsProcessingExceptionTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:588;
+   * 
+   * @test_Strategy: jakarta.ws.rs.client.SyncInvoker.post( Entity, GenericType )
+   * throws ProcessingException in case the invocation failed.
+   */
+  @Test
+  public void postWithGenericTypeStringThrowsProcessingExceptionTest()
+      throws Fault {
+    Runnable run = new Runnable() {
+      @Override
+      public void run() {
+        SyncInvoker sync = createSyncInvokerWrongUrl();
+        Entity<String> entity = createEntity("post");
+        GenericType<String> generic = createGeneric(String.class);
+        sync.post(entity, generic);
+      }
+    };
+    assertProcessingException(run);
+  }
+
+  /*
+   * @testName: postWithGenericTypeStringThrowsWebApplicationExceptionTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:588;
+   * 
+   * @test_Strategy: jakarta.ws.rs.client.SyncInvoker.post( Entity, GenericType )
+   * throws WebApplicationException - in case the response status code of the
+   * response returned by the server is not successful and the specified
+   * response type is not Response.
+   */
+  @Test
+  public void postWithGenericTypeStringThrowsWebApplicationExceptionTest()
+      throws Fault {
+    Runnable run = new Runnable() {
+      @Override
+      public void run() {
+        SyncInvoker sync = createSyncInvokerForMethod("postnotok");
+        Entity<String> entity = createEntity("post");
+        GenericType<String> generic = createGeneric(String.class);
+        sync.post(entity, generic);
+      }
+    };
+    assertWebApplicationException(run);
+  }
+
+  /*
+   * @testName: postWithGenericTypeResponseThrowsNoWebApplicationExceptionTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:588;
+   * 
+   * @test_Strategy: jakarta.ws.rs.client.SyncInvoker.post( Entity, GenericType )
+   * throws WebApplicationException - in case the response status code of the
+   * response returned by the server is not successful and the specified
+   * response type is not Response.
+   */
+  @Test
+  public void postWithGenericTypeResponseThrowsNoWebApplicationExceptionTest()
+      throws Fault {
+    SyncInvoker sync = createSyncInvokerForMethod("postnotok");
+    Entity<String> entity = createEntity("post");
+    GenericType<Response> generic = createGeneric(Response.class);
+    Response response = sync.post(entity, generic);
+    assertStatusAndLog(response, Status.NOT_ACCEPTABLE);
+  }
+
+  // ------------------------------------------------------------------
+  // ---------------------------PUT -----------------------------------
+  // ------------------------------------------------------------------
+
+  /*
+   * @testName: putTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:591;
+   * 
+   * @test_Strategy: Invoke HTTP PUT method for the current request
+   * synchronously.
+   */
+  @Test
+  public Response putTest() throws Fault {
+    SyncInvoker sync = createSyncInvokerForMethod("put");
+    Entity<String> entity = createEntity("put");
+    Response response = sync.put(entity);
+    assertResponseOk(response);
+    return response;
+  }
+
+  /*
+   * @testName: putThrowsProcessingExceptionTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:591;
+   * 
+   * @test_Strategy: jakarta.ws.rs.client.SyncInvoker.put(Entity) throws
+   * ProcessingException in case the invocation failed.
+   */
+  @Test
+  public void putThrowsProcessingExceptionTest() throws Fault {
+    Runnable run = new Runnable() {
+      @Override
+      public void run() {
+        SyncInvoker sync = createSyncInvokerWrongUrl();
+        Entity<String> entity = createEntity("put");
+        sync.put(entity);
+      }
+    };
+    assertProcessingException(run);
+  }
+
+  /*
+   * @testName: putWithStringClassTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:593;
+   * 
+   * @test_Strategy: Invoke HTTP put method for the current request
+   * synchronously.
+   */
+  @Test
+  public String putWithStringClassTest() throws Fault {
+    Entity<String> entity = createEntity("put");
+    SyncInvoker sync = createSyncInvokerForMethod("put");
+    String response = sync.put(entity, String.class);
+    assertResponseString(response, "put");
+    return response;
+  }
+
+  /*
+   * @testName: putWithResponseClassTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:593;
+   * 
+   * @test_Strategy: Invoke HTTP put method for the current request
+   * synchronously.
+   */
+  @Test
+  public Response putWithResponseClassTest() throws Fault {
+    Entity<String> entity = createEntity("put");
+    SyncInvoker sync = createSyncInvokerForMethod("put");
+    Response response = sync.put(entity, Response.class);
+    assertResponseOk(response);
+    return response;
+  }
+
+  /*
+   * @testName: putWithStringClassThrowsProcessingExceptionTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:593;
+   * 
+   * @test_Strategy: jakarta.ws.rs.client.SyncInvoker.put( Entity, Class ) throws
+   * ProcessingException in case the invocation failed.
+   */
+  @Test
+  public void putWithStringClassThrowsProcessingExceptionTest() throws Fault {
+    Runnable run = new Runnable() {
+      @Override
+      public void run() {
+        SyncInvoker sync = createSyncInvokerWrongUrl();
+        Entity<String> entity = createEntity("put");
+        sync.put(entity, String.class);
+      }
+    };
+    assertProcessingException(run);
+  }
+
+  /*
+   * @testName: putWithStringClassThrowsWebApplicationExceptionTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:593;
+   * 
+   * @test_Strategy: jakarta.ws.rs.client.SyncInvoker.put( Entity, Class ) throws
+   * WebApplicationException - in case the response status code of the response
+   * returned by the server is not successful and the specified response type is
+   * not Response.
+   */
+  @Test
+  public void putWithStringClassThrowsWebApplicationExceptionTest()
+      throws Fault {
+    Runnable run = new Runnable() {
+      @Override
+      public void run() {
+        SyncInvoker sync = createSyncInvokerForMethod("putnotok");
+        Entity<String> entity = createEntity("put");
+        sync.put(entity, String.class);
+      }
+    };
+    assertWebApplicationException(run);
+  }
+
+  /*
+   * @testName: putWithResponseClassThrowsNoWebApplicationExceptionTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:593;
+   * 
+   * @test_Strategy: jakarta.ws.rs.client.SyncInvoker.put( Entity, Class ) throws
+   * WebApplicationException - in case the response status code of the response
+   * returned by the server is not successful and the specified response type is
+   * not Response.
+   */
+  @Test
+  public void putWithResponseClassThrowsNoWebApplicationExceptionTest()
+      throws Fault {
+    SyncInvoker sync = createSyncInvokerForMethod("putnotok");
+    Entity<String> entity = createEntity("put");
+    Response response = sync.put(entity, Response.class);
+    assertStatusAndLog(response, Status.NOT_ACCEPTABLE);
+  }
+
+  /*
+   * @testName: putWithGenericTypeStringTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:596;
+   * 
+   * @test_Strategy: Invoke HTTP put method for the current request
+   * synchronously.
+   */
+  @Test
+  public String putWithGenericTypeStringTest() throws Fault {
+    GenericType<String> generic = createGeneric(String.class);
+    Entity<String> entity = createEntity("put");
+    SyncInvoker sync = createSyncInvokerForMethod("put");
+    String response = sync.put(entity, generic);
+    assertResponseString(response, "put");
+    return response;
+  }
+
+  /*
+   * @testName: putWithGenericTypeResponseTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:596;
+   * 
+   * @test_Strategy: Invoke HTTP put method for the current request
+   * synchronously.
+   */
+  @Test
+  public Response putWithGenericTypeResponseTest() throws Fault {
+    GenericType<Response> generic = createGeneric(Response.class);
+    Entity<String> entity = createEntity("put");
+    SyncInvoker sync = createSyncInvokerForMethod("put");
+    Response response = sync.put(entity, generic);
+    assertResponseOk(response);
+    return response;
+  }
+
+  /*
+   * @testName: putWithGenericTypeStringThrowsProcessingExceptionTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:596;
+   * 
+   * @test_Strategy: jakarta.ws.rs.client.SyncInvoker.put( Entity, GenericType )
+   * throws ProcessingException in case the invocation failed.
+   */
+  @Test
+  public void putWithGenericTypeStringThrowsProcessingExceptionTest()
+      throws Fault {
+    Runnable run = new Runnable() {
+      @Override
+      public void run() {
+        SyncInvoker sync = createSyncInvokerWrongUrl();
+        Entity<String> entity = createEntity("put");
+        GenericType<String> generic = createGeneric(String.class);
+        sync.put(entity, generic);
+      }
+    };
+    assertProcessingException(run);
+  }
+
+  /*
+   * @testName: putWithGenericTypeStringThrowsWebApplicationExceptionTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:596;
+   * 
+   * @test_Strategy: jakarta.ws.rs.client.SyncInvoker.put( Entity, GenericType )
+   * throws WebApplicationException - in case the response status code of the
+   * response returned by the server is not successful and the specified
+   * response type is not Response.
+   */
+  @Test
+  public void putWithGenericTypeStringThrowsWebApplicationExceptionTest()
+      throws Fault {
+    Runnable run = new Runnable() {
+      @Override
+      public void run() {
+        SyncInvoker sync = createSyncInvokerForMethod("putnotok");
+        Entity<String> entity = createEntity("put");
+        GenericType<String> generic = createGeneric(String.class);
+        sync.put(entity, generic);
+      }
+    };
+    assertWebApplicationException(run);
+  }
+
+  /*
+   * @testName: putWithGenericTypeResponseThrowsNoWebApplicationExceptionTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:596;
+   * 
+   * @test_Strategy: throws WebApplicationException - in case the response
+   * status code of the response returned by the server is not successful and
+   * the specified response type is not Response.
+   */
+  @Test
+  public void putWithGenericTypeResponseThrowsNoWebApplicationExceptionTest()
+      throws Fault {
+    SyncInvoker sync = createSyncInvokerForMethod("putnotok");
+    Entity<String> entity = createEntity("put");
+    GenericType<Response> generic = createGeneric(Response.class);
+    Response response = sync.put(entity, generic);
+    assertStatusAndLog(response, Status.NOT_ACCEPTABLE);
+  }
+
+  // ------------------------------------------------------------------
+  // ---------------------------TRACE -----------------------------------
+  // ------------------------------------------------------------------
+
+  /*
+   * @testName: traceTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:599;
+   * 
+   * @test_Strategy: Invoke HTTP trace method for the current request
+   * synchronously.
+   */
+  @Test
+  public Response traceTest() throws Fault {
+    SyncInvoker sync = createSyncInvokerForMethod("trace");
+    Response response = sync.trace();
+    assertResponseOk(response);
+    return response;
+  }
+
+  /*
+   * @testName: traceThrowsProcessingExceptionTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:599;
+   * 
+   * @test_Strategy: jakarta.ws.rs.client.SyncInvoker.trace(Entity) throws
+   * ProcessingException in case the invocation failed.
+   */
+  @Test
+  public void traceThrowsProcessingExceptionTest() throws Fault {
+    Runnable run = new Runnable() {
+      @Override
+      public void run() {
+        SyncInvoker sync = createSyncInvokerWrongUrl();
+        sync.trace();
+      }
+    };
+    assertProcessingException(run);
+  }
+
+  /*
+   * @testName: traceWithStringClassTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:601;
+   * 
+   * @test_Strategy: Invoke HTTP trace method for the current request
+   * synchronously.
+   */
+  @Test
+  public String traceWithStringClassTest() throws Fault {
+    SyncInvoker sync = createSyncInvokerForMethod("trace");
+    String response = sync.trace(String.class);
+    assertResponseString(response, "trace");
+    return response;
+  }
+
+  /*
+   * @testName: traceWithResponseClassTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:601;
+   * 
+   * @test_Strategy: Invoke HTTP trace method for the current request
+   * synchronously.
+   */
+  @Test
+  public Response traceWithResponseClassTest() throws Fault {
+    SyncInvoker sync = createSyncInvokerForMethod("trace");
+    Response response = sync.trace(Response.class);
+    assertResponseOk(response);
+    return response;
+  }
+
+  /*
+   * @testName: traceWithStringClassThrowsProcessingExceptionTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:601;
+   * 
+   * @test_Strategy: jakarta.ws.rs.client.SyncInvoker.trace( Entity, Class )
+   * throws ProcessingException in case the invocation failed.
+   */
+  @Test
+  public void traceWithStringClassThrowsProcessingExceptionTest() throws Fault {
+    Runnable run = new Runnable() {
+      @Override
+      public void run() {
+        SyncInvoker sync = createSyncInvokerWrongUrl();
+        sync.trace(String.class);
+      }
+    };
+    assertProcessingException(run);
+  }
+
+  /*
+   * @testName: traceWithStringClassThrowsWebApplicationExceptionTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:601;
+   * 
+   * @test_Strategy: jakarta.ws.rs.client.SyncInvoker.trace( Entity, Class )
+   * throws WebApplicationException - in case the response status code of the
+   * response returned by the server is not successful and the specified
+   * response type is not Response.
+   */
+  @Test
+  public void traceWithStringClassThrowsWebApplicationExceptionTest()
+      throws Fault {
+    Runnable run = new Runnable() {
+      @Override
+      public void run() {
+        SyncInvoker sync = createSyncInvokerForMethod("tracenotok");
+        sync.trace(String.class);
+      }
+    };
+    assertWebApplicationException(run);
+  }
+
+  /*
+   * @testName: traceWithResponseClassThrowsNoWebApplicationExceptionTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:601;
+   * 
+   * @test_Strategy: jakarta.ws.rs.client.SyncInvoker.trace( Entity, Class )
+   * throws WebApplicationException - in case the response status code of the
+   * response returned by the server is not successful and the specified
+   * response type is not Response.
+   */
+  //@Test
+  public void traceWithResponseClassThrowsNoWebApplicationExceptionTest()
+      throws Fault {
+    SyncInvoker sync = createSyncInvokerForMethod("tracenotok");
+    Response response = sync.trace(Response.class);
+    assertStatusAndLog(response, Status.NOT_ACCEPTABLE);
+  }
+
+  /*
+   * @testName: traceWithGenericTypeStringTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:604;
+   * 
+   * @test_Strategy: Invoke HTTP trace method for the current request
+   * synchronously.
+   */
+  @Test
+  public String traceWithGenericTypeStringTest() throws Fault {
+    GenericType<String> generic = createGeneric(String.class);
+    SyncInvoker sync = createSyncInvokerForMethod("trace");
+    String response = sync.trace(generic);
+    assertResponseString(response, "trace");
+    return response;
+  }
+
+  /*
+   * @testName: traceWithGenericTypeResponseTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:604;
+   * 
+   * @test_Strategy: Invoke HTTP trace method for the current request
+   * synchronously.
+   */
+  @Test
+  public Response traceWithGenericTypeResponseTest() throws Fault {
+    GenericType<Response> generic = createGeneric(Response.class);
+    SyncInvoker sync = createSyncInvokerForMethod("trace");
+    Response response = sync.trace(generic);
+    assertResponseOk(response);
+    return response;
+  }
+
+  /*
+   * @testName: traceWithGenericTypeStringThrowsProcessingExceptionTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:604;
+   * 
+   * @test_Strategy: jakarta.ws.rs.client.SyncInvoker.trace( Entity, GenericType )
+   * throws ProcessingException in case the invocation failed.
+   */
+  @Test
+  public void traceWithGenericTypeStringThrowsProcessingExceptionTest()
+      throws Fault {
+    Runnable run = new Runnable() {
+      @Override
+      public void run() {
+        SyncInvoker sync = createSyncInvokerWrongUrl();
+        GenericType<String> generic = createGeneric(String.class);
+        sync.trace(generic);
+      }
+    };
+    assertProcessingException(run);
+  }
+
+  /*
+   * @testName: traceWithGenericTypeStringThrowsWebApplicationExceptionTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:604;
+   * 
+   * @test_Strategy: jakarta.ws.rs.client.SyncInvoker.trace( Entity, GenericType )
+   * throws WebApplicationException - in case the response status code of the
+   * response returned by the server is not successful and the specified
+   * response type is not Response.
+   */
+  @Test
+  public void traceWithGenericTypeStringThrowsWebApplicationExceptionTest()
+      throws Fault {
+    Runnable run = new Runnable() {
+      @Override
+      public void run() {
+        SyncInvoker sync = createSyncInvokerForMethod("tracenotok");
+        GenericType<String> generic = createGeneric(String.class);
+        sync.trace(generic);
+      }
+    };
+    assertWebApplicationException(run);
+  }
+
+  /*
+   * @testName: traceWithGenericTypeResponseThrowsNoWebApplicationExceptionTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:604;
+   * 
+   * @test_Strategy: jakarta.ws.rs.client.SyncInvoker.trace( Entity, GenericType )
+   * throws WebApplicationException - in case the response status code of the
+   * response returned by the server is not successful and the specified
+   * response type is not Response.
+   */
+  //@Test
+  public void traceWithGenericTypeResponseThrowsNoWebApplicationExceptionTest()
+      throws Fault {
+    SyncInvoker sync = createSyncInvokerForMethod("tracenotok");
+    GenericType<Response> generic = createGeneric(Response.class);
+    Response response = sync.trace(generic);
+    assertStatusAndLog(response, Status.NOT_ACCEPTABLE);
+  }
+
+  // ///////////////////////////////////////////////////////////////////////
+  // utility methods
+
+  protected String getUrl(String method) {
+    StringBuilder url = new StringBuilder();
+    url.append("http://").append(_hostname).append(":").append(_port);
+    url.append(getContextRoot()).append("/").append(method);
+    return url.toString();
+  }
+
+  /**
+   * Create SyncInvoker for given resource method and start time
+   */
+  protected SyncInvoker createSyncInvokerForMethod(String methodName) {
+    Client client = ClientBuilder.newClient();
+    client.register(new JdkLoggingFilter(false));
+    WebTarget target = client.target(getUrl(methodName));
+    SyncInvoker sync = target.request();
+    return sync;
+  }
+
+  protected SyncInvoker createSyncInvokerWrongUrl() {
+    _hostname = "tck.cts";
+    _port = 888;
+    return createSyncInvokerForMethod("wrongurl");
+  }
+
+  protected static void assertStatusAndLog(Response response, Status status)
+      throws Fault {
+    assertTrue(response.getStatus() == status.getStatusCode(),
+        "Returned unexpected status"+ response.getStatus());
+    String msg = new StringBuilder().append("Returned status ")
+        .append(status.getStatusCode()).append(" (").append(status.name())
+        .append(")").toString();
+    TestUtil.logMsg(msg);
+  }
+
+  protected static void assertResponseOk(Response response) throws Fault {
+    assertStatusAndLog(response, Status.OK);
+  }
+
+  protected static void assertResponseString(String response,
+      String expectedValue) throws Fault {
+    assertTrue(expectedValue.equals(response), "expected value"+ expectedValue+
+        "differes from acquired value"+ response);
+  }
+
+  protected static <T> Entity<T> createEntity(T entity) {
+    return Entity.entity(entity, MediaType.WILDCARD_TYPE);
+  }
+
+  protected static <T> GenericType<T> createGeneric(Class<T> clazz) {
+    return new GenericType<T>(clazz);
+  }
+
+  protected static void assertProcessingException(Runnable runnable)
+      throws Fault {
+    assertException(runnable, ProcessingException.class);
+  }
+
+  protected static//
+  void assertWebApplicationException(Runnable runnable) throws Fault {
+    assertException(runnable, WebApplicationException.class);
+  }
+
+  protected static <T extends Exception> void assertException(Runnable runnable,
+      Class<T> exception) throws Fault {
+    try {
+      runnable.run();
+    } catch (Exception e) {
+      if (exception != null && exception.isInstance(e)) {
+        return;
+      }
+      throw new Fault("unexpected exception", e);
+    }
+    fault("ProcessingException has not been thrown");
+  }
+
+}
diff --git a/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/client/syncinvoker/Resource.java b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/client/syncinvoker/Resource.java
new file mode 100644
index 0000000..c2e456a
--- /dev/null
+++ b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/client/syncinvoker/Resource.java
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 2012, 2020 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 jakarta.ws.rs.tck.ee.rs.client.syncinvoker;
+
+import jakarta.ws.rs.tck.common.impl.TRACE;
+
+import jakarta.ws.rs.DELETE;
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.HEAD;
+import jakarta.ws.rs.OPTIONS;
+import jakarta.ws.rs.POST;
+import jakarta.ws.rs.PUT;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.core.Response;
+import jakarta.ws.rs.core.Response.Status;
+
+@Path("resource")
+public class Resource {
+
+  @GET
+  @Path("get")
+  public String get() {
+    return "get";
+  }
+
+  @GET
+  @Path("getnotok")
+  public Response getNotOk() {
+    return Response.status(Status.NOT_ACCEPTABLE).build();
+  }
+
+  @HEAD
+  @Path("head")
+  public String head() {
+    return "head";
+  }
+
+  @HEAD
+  @Path("headnotok")
+  public Response headNotOk() {
+    return Response.status(Status.NOT_ACCEPTABLE).build();
+  }
+
+  @PUT
+  @Path("put")
+  public String put(String value) {
+    return value;
+  }
+
+  @PUT
+  @Path("putnotok")
+  public Response putNotOk(String value) {
+    return Response.status(Status.NOT_ACCEPTABLE).build();
+  }
+
+  @POST
+  @Path("post")
+  public String post(String value) {
+    return value;
+  }
+
+  @POST
+  @Path("postnotok")
+  public Response postNotOk(String value) {
+    return Response.status(Status.NOT_ACCEPTABLE).build();
+  }
+
+  @DELETE
+  @Path("delete")
+  public String delete() {
+    return "delete";
+  }
+
+  @DELETE
+  @Path("deletenotok")
+  public Response deleteNotOk() {
+    return Response.status(Status.NOT_ACCEPTABLE).build();
+  }
+
+  @OPTIONS
+  @Path("options")
+  public String options() {
+    return "options";
+  }
+
+  @OPTIONS
+  @Path("optionsnotok")
+  public Response optionsNotOk() {
+    return Response.status(Status.NOT_ACCEPTABLE).build();
+  }
+
+  @TRACE
+  @Path("trace")
+  public String trace() {
+    return "trace";
+  }
+
+  @TRACE
+  @Path("tracenotok")
+  public Response traceNotOk() {
+    return Response.status(Status.NOT_ACCEPTABLE).build();
+  }
+
+}
diff --git a/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/client/syncinvoker/TSAppConfig.java b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/client/syncinvoker/TSAppConfig.java
new file mode 100644
index 0000000..1b657bf
--- /dev/null
+++ b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/client/syncinvoker/TSAppConfig.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2012, 2020 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 jakarta.ws.rs.tck.ee.rs.client.syncinvoker;
+
+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);
+    return resources;
+  }
+}
diff --git a/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/core/application/ApplicationHolderSingleton.java b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/core/application/ApplicationHolderSingleton.java
new file mode 100644
index 0000000..2c1fd89
--- /dev/null
+++ b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/core/application/ApplicationHolderSingleton.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2013, 2020 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 jakarta.ws.rs.tck.ee.rs.core.application;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+
+import jakarta.ws.rs.WebApplicationException;
+import jakarta.ws.rs.core.Application;
+import jakarta.ws.rs.core.MediaType;
+import jakarta.ws.rs.core.MultivaluedMap;
+import jakarta.ws.rs.ext.MessageBodyReader;
+import jakarta.ws.rs.ext.Provider;
+
+@Provider
+/**
+ * ApplicationHolderSingleton is a Singleton that is a dummy provider, too, to
+ * conform requirement on Provider
+ */
+public class ApplicationHolderSingleton
+    implements MessageBodyReader<Application> {
+  private Application application;
+
+  public ApplicationHolderSingleton(Application application) {
+    super();
+    this.application = application;
+  }
+
+  public Application getApplication() {
+    return application;
+  }
+
+  @Override
+  public boolean isReadable(Class<?> type, Type genericType,
+      Annotation[] annotations, MediaType mediaType) {
+    return true;
+  }
+
+  @Override
+  public Application readFrom(Class<Application> type, Type genericType,
+      Annotation[] annotations, MediaType mediaType,
+      MultivaluedMap<String, String> httpHeaders, InputStream entityStream)
+      throws IOException, WebApplicationException {
+    return null;
+  }
+
+}
diff --git a/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/core/application/ApplicationServlet.java b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/core/application/ApplicationServlet.java
new file mode 100644
index 0000000..8e83069
--- /dev/null
+++ b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/core/application/ApplicationServlet.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2007, 2020 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 jakarta.ws.rs.tck.ee.rs.core.application;
+
+import java.util.Map;
+import java.util.Set;
+
+import jakarta.ws.rs.tck.common.util.JaxrsUtil;
+
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.core.Application;
+import jakarta.ws.rs.core.Context;
+import jakarta.ws.rs.core.Response;
+
+@Path("ApplicationTest")
+public class ApplicationServlet {
+
+  @GET
+  @Path("/GetSingletons")
+  public Response testGetSingletons(@Context Application application) {
+    // Derived from the default, thus return empty implementation
+    if (application.getSingletons() == null)
+      return Response.status(Response.Status.NOT_ACCEPTABLE).build();
+    // Passed
+    return Response.ok(String.valueOf(application.getSingletons().size()))
+        .build();
+  }
+
+  @GET
+  @Path("/GetClasses")
+  public Response testGetClasses(@Context Application application) {
+    // Context Issue
+    application = getDeproxiedApplication(application);
+    if (!application.getClasses().contains(ApplicationServlet.class))
+      return Response.status(Response.Status.NOT_ACCEPTABLE).build();
+    // Passed
+    return Response.ok(String.valueOf(application.getClasses().size())).build();
+  }
+
+  @Path("properties")
+  @GET
+  public Response getProperties(@Context Application application) {
+    Response response = null;
+    application = getDeproxiedApplication(application);
+    Map<String, Object> properties = application.getProperties();
+    if (properties == null || properties.size() == 0) {
+      response = Response.noContent().build();
+    } else {
+      Object val0 = properties.get(TSAppConfig.KEYS[0]);
+      Object val1 = properties.get(TSAppConfig.KEYS[1]);
+      if (TSAppConfig.VALUES[0].equals(val0)
+          && TSAppConfig.VALUES[1].equals(val1))
+        response = Response.ok(JaxrsUtil.mapToString(properties)).build();
+      else
+        response = Response.status(Response.Status.NOT_ACCEPTABLE).build();
+    }
+    return response;
+  }
+
+  // ////////////////////////////////////////////////////////////////////////
+
+  /**
+   * Deproxy
+   */
+  protected static Application getDeproxiedApplication(
+      Application application) {
+    Set<Object> singletons = application.getSingletons();
+    for (Object s : singletons)
+      if (s.getClass() == ApplicationHolderSingleton.class)
+        return ((ApplicationHolderSingleton) s).getApplication();
+    throw new IllegalStateException(
+        "ApplicationHolderSingleton has not been found in a list of singletons");
+  }
+
+}
diff --git a/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/core/application/JAXRSClientIT.java b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/core/application/JAXRSClientIT.java
new file mode 100644
index 0000000..6340618
--- /dev/null
+++ b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/core/application/JAXRSClientIT.java
@@ -0,0 +1,169 @@
+/*
+ * Copyright (c) 2007, 2020 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 jakarta.ws.rs.tck.ee.rs.core.application;
+
+import java.io.IOException;
+import java.util.Map;
+import java.io.InputStream;
+
+import jakarta.ws.rs.tck.common.webclient.http.HttpResponse;
+import jakarta.ws.rs.tck.common.JAXRSCommonClient;
+import jakarta.ws.rs.tck.common.util.JaxrsUtil;
+import jakarta.ws.rs.tck.lib.util.TestUtil;
+
+import jakarta.ws.rs.core.Application;
+import jakarta.ws.rs.core.Response.Status;
+
+import org.jboss.arquillian.junit5.ArquillianExtension;
+import org.jboss.arquillian.container.test.api.Deployment;
+import org.jboss.shrinkwrap.api.ShrinkWrap;
+import org.jboss.shrinkwrap.api.asset.StringAsset;
+import org.jboss.shrinkwrap.api.spec.WebArchive;
+import org.jboss.shrinkwrap.api.exporter.ZipExporter;
+
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assertions.fail;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.junit.jupiter.api.TestInfo;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.AfterEach;
+
+/*
+ * @class.setup_props: webServerHost;
+ *                     webServerPort;
+ */
+@ExtendWith(ArquillianExtension.class)
+public class JAXRSClientIT extends JAXRSCommonClient {
+  
+  public JAXRSClientIT() {
+    setup();
+    setContextRoot("/jaxrs_ee_core_application_web/ApplicationTest");
+  }
+
+  private static final long serialVersionUID = 1L;
+
+  protected int expectedSingletons = 1;
+
+  protected int expectedClasses = 1;
+
+  @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{
+
+    InputStream inStream = JAXRSClientIT.class.getClassLoader().getResourceAsStream("jakarta/ws/rs/tck/ee/rs/core/application/web.xml.template");
+    String webXml = editWebXmlString(inStream);
+
+    WebArchive archive = ShrinkWrap.create(WebArchive.class, "jaxrs_ee_core_application_web.war");
+    archive.addClasses(TSAppConfig.class, ApplicationServlet.class, ApplicationHolderSingleton.class, jakarta.ws.rs.tck.common.util.JaxrsUtil.class);
+    archive.setWebXML(new StringAsset(webXml));
+    return archive;
+
+  }
+
+
+  /*
+   * @testName: getSingletonsTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:23
+   * 
+   * @test_Strategy: Check that vi does not modify the getSingletons()
+   */
+  @Test
+  public void getSingletonsTest() throws Fault {
+    setProperty(REQUEST, buildRequest(GET, "GetSingletons"));
+    setProperty(STATUS_CODE, getStatusCode(Status.OK));
+    invoke();
+    assertTrue(getReturnedNumber() == expectedSingletons,
+        "Application.getSingletons() return incorrect value:"+
+        getReturnedNumber());
+  }
+
+  /*
+   * @testName: getClassesTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:22; JAXRS:SPEC:40;
+   * 
+   * @test_Strategy: Check the implementation injects TSAppConfig
+   */
+  @Test
+  public void getClassesTest() throws Fault {
+    setProperty(REQUEST, buildRequest(GET, "GetClasses"));
+    setProperty(STATUS_CODE, getStatusCode(Status.OK));
+    invoke();
+    assertTrue(getReturnedNumber() == expectedClasses,
+        "Application.getClasses() return incorrect value:"+
+        getReturnedNumber());
+  }
+
+  /*
+   * @testName: getPropertiesTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:1035; JAXRS:SPEC:40;
+   * 
+   * @test_Strategy: The returned properties are reflected in the application
+   * configuration passed to the server-side features or injected into
+   * server-side JAX-RS components.
+   */
+  @Test
+  public void getPropertiesTest() throws Fault {
+    setProperty(Property.REQUEST, buildRequest(GET, "properties"));
+    setProperty(Property.STATUS_CODE, getStatusCode(Status.OK));
+    setProperty(Property.SEARCH_STRING, TSAppConfig.KEYS[0]);
+    invoke();
+  }
+
+  /*
+   * @testName: defaultGetPropertiesIsEmptyTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:1035;
+   * 
+   * @test_Strategy: The default implementation returns an empty set.
+   */
+  @Test
+  public void defaultGetPropertiesIsEmptyTest() throws Fault {
+    Application application = new Application();
+    Map<String, Object> properties = application.getProperties();
+    assertNotNull(properties,
+        "Default implementation is not empty map, but null");
+    assertTrue(properties.isEmpty(), "Default implementation is not empty, but"+
+        JaxrsUtil.mapToString(properties));
+    logMsg("Default implementation gets empty map as expected");
+  }
+
+  // ///////////////////////////////////////////////////////////////////////
+
+  protected int getReturnedNumber() throws Fault {
+    HttpResponse response = _testCase.getResponse();
+    String body;
+    try {
+      body = response.getResponseBodyAsString();
+    } catch (IOException e) {
+      throw new Fault(e);
+    }
+    return Integer.parseInt(body);
+  }
+}
diff --git a/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/core/application/TSAppConfig.java b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/core/application/TSAppConfig.java
new file mode 100644
index 0000000..91ecf49
--- /dev/null
+++ b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/core/application/TSAppConfig.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2007, 2020 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 jakarta.ws.rs.tck.ee.rs.core.application;
+
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeMap;
+
+import jakarta.ws.rs.core.Application;
+
+public class TSAppConfig extends Application {
+  static final String[] KEYS = { "key1", "key2" };
+
+  static final String[] VALUES = { "value1", "value2" };
+
+  private Map<String, Object> properties = new TreeMap<String, Object>();
+
+  public TSAppConfig() {
+    properties.put(KEYS[0], VALUES[0]);
+    properties.put(KEYS[1], VALUES[1]);
+  }
+
+  @Override
+  public Set<Object> getSingletons() {
+    Set<Object> set = new HashSet<Object>();
+    set.add(new ApplicationHolderSingleton(this));
+    return set;
+  }
+
+  @Override
+  public java.util.Set<java.lang.Class<?>> getClasses() {
+    Set<Class<?>> resources = new HashSet<Class<?>>();
+    resources.add(ApplicationServlet.class);
+    return resources;
+  }
+
+  @Override
+  public Map<String, Object> getProperties() {
+    return properties;
+  }
+}
diff --git a/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/core/configurable/FirstFilter.java b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/core/configurable/FirstFilter.java
new file mode 100644
index 0000000..51acda4
--- /dev/null
+++ b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/core/configurable/FirstFilter.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2013, 2020 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 jakarta.ws.rs.tck.ee.rs.core.configurable;
+
+import java.io.IOException;
+
+import jakarta.annotation.Priority;
+import jakarta.ws.rs.client.ClientRequestContext;
+import jakarta.ws.rs.client.ClientRequestFilter;
+import jakarta.ws.rs.core.MediaType;
+import jakarta.ws.rs.ext.Provider;
+
+@Provider
+@Priority(100)
+public class FirstFilter implements ClientRequestFilter {
+
+  @Override
+  public void filter(ClientRequestContext requestContext) throws IOException {
+    requestContext.setEntity(getClass().getName(), null,
+        MediaType.WILDCARD_TYPE);
+  }
+
+}
diff --git a/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/core/configurable/JAXRSClientIT.java b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/core/configurable/JAXRSClientIT.java
new file mode 100644
index 0000000..7235422
--- /dev/null
+++ b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/core/configurable/JAXRSClientIT.java
@@ -0,0 +1,1280 @@
+/*
+ * Copyright (c) 2013, 2020 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 jakarta.ws.rs.tck.ee.rs.core.configurable;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.Callable;
+import java.io.InputStream;
+import java.io.IOException;
+
+import jakarta.ws.rs.tck.api.rs.core.configurable.Assertable;
+import jakarta.ws.rs.tck.api.rs.core.configurable.CallableProvider;
+import jakarta.ws.rs.tck.api.rs.core.configurable.Registrar;
+import jakarta.ws.rs.tck.api.rs.core.configurable.SingleCheckAssertable;
+import jakarta.ws.rs.tck.common.client.JaxrsCommonClient;
+import jakarta.ws.rs.tck.lib.util.TestUtil;
+
+import jakarta.ws.rs.client.Client;
+import jakarta.ws.rs.client.ClientBuilder;
+import jakarta.ws.rs.client.ClientRequestFilter;
+import jakarta.ws.rs.client.Entity;
+import jakarta.ws.rs.client.Invocation;
+import jakarta.ws.rs.client.WebTarget;
+import jakarta.ws.rs.core.Configurable;
+import jakarta.ws.rs.core.Configuration;
+import jakarta.ws.rs.core.MediaType;
+import jakarta.ws.rs.core.Response;
+import jakarta.ws.rs.ext.MessageBodyReader;
+import jakarta.ws.rs.ext.MessageBodyWriter;
+
+import org.jboss.arquillian.junit5.ArquillianExtension;
+import org.jboss.arquillian.container.test.api.Deployment;
+import org.jboss.shrinkwrap.api.ShrinkWrap;
+import org.jboss.shrinkwrap.api.asset.StringAsset;
+import org.jboss.shrinkwrap.api.spec.WebArchive;
+import org.jboss.shrinkwrap.api.exporter.ZipExporter;
+
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assertions.fail;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.junit.jupiter.api.TestInfo;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.AfterEach;
+
+/*
+ * @class.setup_props: webServerHost;
+ *                     webServerPort;
+ */
+@ExtendWith(ArquillianExtension.class)
+public class JAXRSClientIT extends JaxrsCommonClient {
+
+  private static final long serialVersionUID = -8051302528257391040L;
+
+  private static final int configurableCnt = 2;
+
+  private int registeredClassesCnt = -1;
+
+  private int registeredInstancesCnt = -1;
+
+  public JAXRSClientIT() {
+    setup();
+    setContextRoot("/jaxrs_ee_core_configurable_web/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{
+
+    InputStream inStream = JAXRSClientIT.class.getClassLoader().getResourceAsStream("jakarta/ws/rs/tck/ee/rs/core/configurable/web.xml.template");
+    String webXml = editWebXmlString(inStream);
+
+    WebArchive archive = ShrinkWrap.create(WebArchive.class, "jaxrs_ee_core_configurable_web.war");
+    archive.addClasses(TSAppConfig.class, Resource.class, Assertable.class, CallableProvider.class, Registrar.class, SingleCheckAssertable.class, jakarta.ws.rs.tck.api.rs.core.configurable.ConfigurableObject.class);
+    archive.setWebXML(new StringAsset(webXml));
+    return archive;
+
+  }
+
+
+  /* Run test */
+
+  /*
+   * @testName: registerClassWriterContractsTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:756;
+   * 
+   * @test_Strategy: This registration method provides the same functionality as
+   * register(Class) except the JAX-RS component class is only registered as a
+   * provider of the listed extension provider or meta-provider contracts.
+   */
+  @Test
+  public void registerClassWriterContractsTest() throws Fault {
+    final String content = "registerClassWriterContractsTest";
+
+    Class<?>[] classes = createProviderClasses();
+    // entity to send to a server
+    Entity<?> entity = getCallableEntity(content);
+
+    // register only once per client build
+    IncrementableRegistrar registrar = new IncrementableRegistrar(0, 1) {
+      @Override
+      public void register(Configurable<?> config, Object registerable) {
+        if (currentValue++ == finalValue)
+          config.register((Class<?>) registerable, MessageBodyWriter.class);
+      }
+    };
+
+    setResourceMethod("echo");
+    // build client configurableCnt times to register provider using a
+    // different
+    // configurable each time
+    for (int cnt = 0; cnt != configurableCnt; cnt++) {
+      // Check the provider is registered
+      logMsg("Check on Configurable", Assertable.getLocation(cnt));
+      Assertable assertable = getAssertableWithRegisteredProviderClassesOnConfigurable(
+          cnt, 1);
+
+      // set we want to register the provider on Configurable
+      // Assertable::LOCATION[cnt]
+      registrar.setCurrentValue(0).setFinalValue(cnt);
+      Invocation i = checkConfig(registrar, assertable, classes, entity);
+      Response response = i.invoke();
+      response.bufferEntity();
+      String responseString = response.readEntity(String.class);
+      assertEquals(content, responseString, "Expected", content,
+          "differs from given", response);
+      logMsg(
+          "sucessufully wrote Callable by provider registered on Configurable",
+          Assertable.getLocation(cnt));
+      // check message body reader contract
+      try {
+        Callable<?> callable = response.readEntity(Callable.class);
+        fault("MessageBodyReader contract has been unexpectedly registered",
+            callable);
+      } catch (Exception e) {
+        logMsg("MessageBodyReader contract has not been registered as expected",
+            e);
+      }
+    }
+  }
+
+  /*
+   * @testName: registerClassReaderContractsTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:756;
+   * 
+   * @test_Strategy: This registration method provides the same functionality as
+   * register(Class) except the JAX-RS component class is only registered as a
+   * provider of the listed extension provider or meta-provider contracts.
+   */
+  @Test
+  public void registerClassReaderContractsTest() throws Fault {
+    final String content = "registerClassReaderContractsTest";
+
+    Class<?>[] classes = createProviderClasses();
+    // entity to send to a server
+    Entity<?> entity = Entity.entity(content, MediaType.WILDCARD);
+
+    // register only once per client build
+    IncrementableRegistrar registrar = new IncrementableRegistrar(0, 1) {
+      @Override
+      public void register(Configurable<?> config, Object registerable) {
+        if (currentValue++ == finalValue)
+          config.register((Class<?>) registerable, MessageBodyReader.class);
+      }
+    };
+
+    setResourceMethod("echo");
+    // build client configurableCnt times to register provider using a
+    // different
+    // configurable each time
+    for (int cnt = 0; cnt != configurableCnt; cnt++) {
+      // Check the provider is registered
+      logMsg("Check on Configurable", Assertable.getLocation(cnt));
+      Assertable assertable = getAssertableWithRegisteredProviderClassesOnConfigurable(
+          cnt, 1);
+      // set we want to register the provider on Configurable
+      // Assertable::LOCATION[cnt]
+      registrar.setCurrentValue(0).setFinalValue(cnt);
+      Invocation i = checkConfig(registrar, assertable, classes, entity);
+      Response response = i.invoke();
+      Callable<?> callable = response.readEntity(Callable.class);
+      assertEquals(content, callable.toString(), "Expected", content,
+          "differs from given", response);
+      logMsg(
+          "sucessufully read Callable by provider registered on Configurable",
+          Assertable.getLocation(cnt));
+    }
+  }
+
+  /*
+   * @testName: registerClassEmptyContractsTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:756;
+   * 
+   * @test_Strategy: Implementations MUST ignore attempts to register a
+   * component class for an empty collection of contracts via this method and
+   * SHOULD raise a warning about such event.
+   */
+  @Test
+  public void registerClassEmptyContractsTest() throws Fault {
+    Class<?>[] classes = createProviderClasses();
+    // entity to send to a server
+    Entity<?> entity = Entity.entity("", MediaType.WILDCARD);
+
+    // register only once per client build
+    IncrementableRegistrar registrar = new IncrementableRegistrar(0, 1) {
+      @Override
+      public void register(Configurable<?> config, Object registerable) {
+        if (currentValue++ == finalValue)
+          config.register((Class<?>) registerable, new Class<?>[] {});
+      }
+    };
+
+    setResourceMethod("echo");
+    // build client configurableCnt times to register provider using a
+    // different
+    // configurable each time
+    Assertable assertable = getAssertableWithNoRegisteredProvider();
+    for (int cnt = 0; cnt != configurableCnt; cnt++) {
+      // Check the provider is registered
+      logMsg("Check on Configurable", Assertable.getLocation(cnt));
+      // set we want to register the provider on Configurable
+      // Assertable::LOCATION[cnt]
+      registrar.setCurrentValue(0).setFinalValue(cnt);
+      checkConfig(registrar, assertable, classes, entity);
+      logMsg("The provider of with contracts has ben ignored as expected");
+    }
+  }
+
+  /*
+   * @testName: registerClassNotAssignableContractsTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:756;
+   * 
+   * @test_Strategy: Contracts that are not assignable from the registered
+   * component class MUST be ignored
+   */
+  @Test
+  public void registerClassNotAssignableContractsTest() throws Fault {
+    Class<?>[] classes = createProviderClasses();
+    // entity to send to a server
+    Entity<?> entity = Entity.entity("", MediaType.WILDCARD);
+
+    // register only once per client build
+    IncrementableRegistrar registrar = new IncrementableRegistrar(0, 1) {
+      @Override
+      public void register(Configurable<?> config, Object registerable) {
+        if (currentValue++ == finalValue)
+          config.register((Class<?>) registerable, ClientRequestFilter.class);
+      }
+    };
+
+    setResourceMethod("echo");
+    // build client configurableCnt times to register provider using a
+    // different
+    // configurable each time
+    Assertable assertable = getAssertableWithNoRegisteredProvider();
+    for (int cnt = 0; cnt != configurableCnt; cnt++) {
+      // Check the provider is registered
+      logMsg("Check on Configurable", Assertable.getLocation(cnt));
+      // set we want to register the provider on Configurable
+      // Assertable::LOCATION[cnt]
+      registrar.setCurrentValue(0).setFinalValue(cnt);
+      checkConfig(registrar, assertable, classes, entity);
+      logMsg(
+          "The provider with unassignable contract has ben ignored as expected");
+    }
+  }
+
+  /*
+   * @testName: registerClassNullContractsTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:756;
+   * 
+   * @test_Strategy: Implementations MUST ignore attempts to register a
+   * component class for a null collection of contracts via this method and
+   * SHOULD raise a warning about such event.
+   */
+  @Test
+  public void registerClassNullContractsTest() throws Fault {
+    Class<?>[] classes = createProviderClasses();
+    // entity to send to a server
+    Entity<?> entity = Entity.entity("", MediaType.WILDCARD);
+
+    // register only once per client build
+    IncrementableRegistrar registrar = new IncrementableRegistrar(0, 1) {
+      @Override
+      public void register(Configurable<?> config, Object registerable) {
+        if (currentValue++ == finalValue)
+          config.register((Class<?>) registerable, (Class<?>[]) null);
+      }
+    };
+
+    setResourceMethod("echo");
+    // build client configurableCnt times to register provider using a
+    // different
+    // configurable each time
+    Assertable assertable = getAssertableWithNoRegisteredProvider();
+    for (int cnt = 0; cnt != configurableCnt; cnt++) {
+      // Check the provider is registered
+      logMsg("Check on Configurable", Assertable.getLocation(cnt));
+      // set we want to register the provider on Configurable
+      // Assertable::LOCATION[cnt]
+      registrar.setCurrentValue(0).setFinalValue(cnt);
+      checkConfig(registrar, assertable, classes, entity);
+      logMsg("The provider with null contract has ben ignored as expected");
+    }
+  }
+
+  /*
+   * @testName: registerClassBindingPriorityFirstIsSecondTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:755;
+   * 
+   * @test_Strategy: This registration method provides the same functionality as
+   * register(Class) except that any binding priority specified on the
+   * registered JAX-RS component class via
+   * 
+   * @Priority annotation is overridden with the supplied bindingPriority value.
+   */
+  @Test
+  public void registerClassBindingPriorityFirstIsSecondTest() throws Fault {
+    final String content = "registerClassBindingPriorityFirstIsSecondTest";
+    Class<?>[] classes = createProviderClasses();
+    // entity to send to a server
+    Entity<?> entity = Entity.entity(content, MediaType.WILDCARD);
+
+    // register only once per client build
+    IncrementableRegistrar registrar = new IncrementableRegistrar(0, 1) {
+      @Override
+      public void register(Configurable<?> config, Object registerable) {
+        if (currentValue++ == finalValue) {
+          config.register(FirstFilter.class, 400);
+          config.register(SecondFilter.class, 399);
+        }
+      }
+    };
+
+    setResourceMethod("echo");
+    // build client configurableCnt times to register provider using a
+    // different
+    // configurable each time
+    for (int cnt = 0; cnt != configurableCnt; cnt++) {
+      // Check the provider is registered
+      logMsg("Check on Configurable", Assertable.getLocation(cnt));
+      // set we want to register the provider on Configurable
+      // Assertable::LOCATION[cnt]
+      registrar.setCurrentValue(0).setFinalValue(cnt);
+      Assertable assertable = getAssertableWithRegisteredProviderClassesOnConfigurable(
+          cnt, 2);
+      Invocation i = checkConfig(registrar, assertable, classes, entity);
+      String response = i.invoke(String.class);
+      assertEquals(FirstFilter.class.getName(), response,
+          "Unexpected filter ordering, the last was", response);
+      logMsg(response, "has been executed as second, as expected");
+    }
+  }
+
+  /*
+   * @testName: registerClassBindingPriorityFirstIsFirstTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:755;
+   * 
+   * @test_Strategy: This registration method provides the same functionality as
+   * register(Class) except that any binding priority specified on the
+   * registered JAX-RS component class via
+   * 
+   * @Priority annotation is overridden with the supplied bindingPriority value.
+   */
+  @Test
+  public void registerClassBindingPriorityFirstIsFirstTest() throws Fault {
+    final String content = "registerClassBindingPriorityFirstIsFirstTest";
+    Class<?>[] classes = createProviderClasses();
+    // entity to send to a server
+    Entity<?> entity = Entity.entity(content, MediaType.WILDCARD);
+
+    // register only once per client build
+    IncrementableRegistrar registrar = new IncrementableRegistrar(0, 1) {
+      @Override
+      public void register(Configurable<?> config, Object registerable) {
+        if (currentValue++ == finalValue) {
+          config.register(FirstFilter.class, 300);
+          config.register(SecondFilter.class, 399);
+        }
+      }
+    };
+
+    setResourceMethod("echo");
+    // build client configurableCnt times to register provider using a
+    // different
+    // configurable each time
+    for (int cnt = 0; cnt != configurableCnt; cnt++) {
+      // Check the provider is registered
+      logMsg("Check on Configurable", Assertable.getLocation(cnt));
+      // set we want to register the provider on Configurable
+      // Assertable::LOCATION[cnt]
+      registrar.setCurrentValue(0).setFinalValue(cnt);
+      Assertable assertable = getAssertableWithRegisteredProviderClassesOnConfigurable(
+          cnt, 2);
+      Invocation i = checkConfig(registrar, assertable, classes, entity);
+      String response = i.invoke(String.class);
+      assertEquals(SecondFilter.class.getName(), response,
+          "Unexpected filter ordering, the last was", response);
+      logMsg(response, "has been executed as second, as expected");
+    }
+  }
+
+  /*
+   * @testName: registerObjectBindingPriorityTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:759;
+   * 
+   * @test_Strategy: Any binding priority specified on the registered JAX-RS
+   * component class via
+   * 
+   * @Priority annotation is overridden with the supplied bindingPriority value.
+   */
+  @Test
+  public void registerObjectBindingPriorityTest() throws Fault {
+    final String content = "registerObjectBindingPriorityTest";
+    Class<?>[] classes = createProviderClasses();
+    // entity to send to a server
+    Entity<?> entity = Entity.entity(content, MediaType.WILDCARD);
+
+    // register only once per client build
+    IncrementableRegistrar registrar = new IncrementableRegistrar(0, 1) {
+      @Override
+      public void register(Configurable<?> config, Object registerable) {
+        if (currentValue++ == finalValue) {
+          config.register(new FirstFilter(), 400);
+          config.register(new SecondFilter(), 399);
+        }
+      }
+    };
+
+    setResourceMethod("echo");
+    // build client configurableCnt times to register provider using a
+    // different
+    // configurable each time
+    for (int cnt = 0; cnt != configurableCnt; cnt++) {
+      // Check the provider is registered
+      logMsg("Check on Configurable", Assertable.getLocation(cnt));
+      // set we want to register the provider on Configurable
+      // Assertable::LOCATION[cnt]
+      registrar.setCurrentValue(0).setFinalValue(cnt);
+      Assertable assertable = getAssertableWithRegisteredProviderInstancesOnConfigurable(
+          cnt, 2);
+      Invocation i = checkConfig(registrar, assertable, classes, entity);
+      String response = i.invoke(String.class);
+      assertEquals(FirstFilter.class.getName(), response,
+          "Unexpected filter ordering, the last was", response);
+      logMsg(response, "has been executed as second, as expected");
+    }
+  }
+
+  /*
+   * @testName: registerObjectWriterContractsTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:760;
+   * 
+   * @test_Strategy: This registration method provides the same functionality as
+   * register(Object) except the JAX-RS component class is only registered as a
+   * provider of the listed extension provider or meta-provider contracts.
+   */
+  @Test
+  public void registerObjectWriterContractsTest() throws Fault {
+    final String content = "registerObjectWriterContractsTest";
+
+    Object[] instances = createProviderInstances();
+    // entity to send to a server
+    Entity<?> entity = getCallableEntity(content);
+
+    // register only once per client build
+    IncrementableRegistrar registrar = new IncrementableRegistrar(0, 1) {
+      @Override
+      public void register(Configurable<?> config, Object registerable) {
+        if (currentValue++ == finalValue)
+          config.register(registerable, MessageBodyWriter.class);
+      }
+    };
+
+    setResourceMethod("echo");
+    // build client configurableCnt times to register provider using a
+    // different
+    // configurable each time
+    for (int cnt = 0; cnt != configurableCnt; cnt++) {
+      // Check the provider is registered
+      logMsg("Check on Configurable", Assertable.getLocation(cnt));
+      Assertable assertable = getAssertableWithRegisteredProviderInstancesOnConfigurable(
+          cnt, 1);
+
+      // set we want to register the provider on Configurable
+      // Assertable::LOCATION[cnt]
+      registrar.setCurrentValue(0).setFinalValue(cnt);
+      Invocation i = checkConfig(registrar, assertable, instances, entity);
+      Response response = i.invoke();
+      response.bufferEntity();
+      String responseString = response.readEntity(String.class);
+      assertEquals(content, responseString, "Expected", content,
+          "differs from given", response);
+      logMsg(
+          "sucessufully wrote Callable by provider registered on Configurable",
+          Assertable.getLocation(cnt));
+      // check message body reader contract
+      try {
+        Callable<?> callable = response.readEntity(Callable.class);
+        fault("MessageBodyReader contract has been unexpectedly registered",
+            callable);
+      } catch (Exception e) {
+        logMsg("MessageBodyReader contract has not been registered as expected",
+            e);
+      }
+    }
+  }
+
+  /*
+   * @testName: registerObjectReaderContractsTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:760;
+   * 
+   * @test_Strategy: This registration method provides the same functionality as
+   * register(Object) except the JAX-RS component class is only registered as a
+   * provider of the listed extension provider or meta-provider contracts.
+   */
+  @Test
+  public void registerObjectReaderContractsTest() throws Fault {
+    final String content = "registerClassReaderContractsTest";
+
+    Object[] instances = createProviderInstances();
+    // entity to send to a server
+    Entity<?> entity = Entity.entity(content, MediaType.WILDCARD);
+
+    // register only once per client build
+    IncrementableRegistrar registrar = new IncrementableRegistrar(0, 1) {
+      @Override
+      public void register(Configurable<?> config, Object registerable) {
+        if (currentValue++ == finalValue)
+          config.register(registerable, MessageBodyReader.class);
+      }
+    };
+
+    setResourceMethod("echo");
+    // build client configurableCnt times to register provider using a
+    // different
+    // configurable each time
+    for (int cnt = 0; cnt != configurableCnt; cnt++) {
+      // Check the provider is registered
+      logMsg("Check on Configurable", Assertable.getLocation(cnt));
+      Assertable assertable = getAssertableWithRegisteredProviderInstancesOnConfigurable(
+          cnt, 1);
+      // set we want to register the provider on Configurable
+      // Assertable::LOCATION[cnt]
+      registrar.setCurrentValue(0).setFinalValue(cnt);
+      Invocation i = checkConfig(registrar, assertable, instances, entity);
+      Response response = i.invoke();
+      Callable<?> callable = response.readEntity(Callable.class);
+      assertEquals(content, callable.toString(), "Expected", content,
+          "differs from given", response);
+      logMsg(
+          "sucessufully read Callable by provider registered on Configurable",
+          Assertable.getLocation(cnt));
+    }
+  }
+
+  /*
+   * @testName: registerObjectEmptyContractsTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:760;
+   * 
+   * @test_Strategy: Implementations MUST ignore attempts to register a
+   * component class for an empty collection of contracts via this method and
+   * SHOULD raise a warning about such event.
+   */
+  @Test
+  public void registerObjectEmptyContractsTest() throws Fault {
+    Object[] instances = createProviderInstances();
+    // entity to send to a server
+    Entity<?> entity = Entity.entity("", MediaType.WILDCARD);
+
+    // register only once per client build
+    IncrementableRegistrar registrar = new IncrementableRegistrar(0, 1) {
+      @Override
+      public void register(Configurable<?> config, Object registerable) {
+        if (currentValue++ == finalValue)
+          config.register(registerable, new Class<?>[] {});
+      }
+    };
+
+    setResourceMethod("echo");
+    // build client configurableCnt times to register provider using a
+    // different
+    // configurable each time
+    Assertable assertable = getAssertableWithNoRegisteredProviderInstance();
+    for (int cnt = 0; cnt != configurableCnt; cnt++) {
+      // Check the provider is registered
+      logMsg("Check on Configurable", Assertable.getLocation(cnt));
+      // set we want to register the provider on Configurable
+      // Assertable::LOCATION[cnt]
+      registrar.setCurrentValue(0).setFinalValue(cnt);
+      checkConfig(registrar, assertable, instances, entity);
+      logMsg("The provider with empty contracts has ben ignored as expected");
+    }
+  }
+
+  /*
+   * @testName: registerObjectNotAssignableContractsTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:760;
+   * 
+   * @test_Strategy: Contracts that are not assignable from the registered
+   * component class MUST be ignored
+   */
+  @Test
+  public void registerObjectNotAssignableContractsTest() throws Fault {
+    Object[] instances = createProviderInstances();
+    // entity to send to a server
+    Entity<?> entity = Entity.entity("", MediaType.WILDCARD);
+
+    // register only once per client build
+    IncrementableRegistrar registrar = new IncrementableRegistrar(0, 1) {
+      @Override
+      public void register(Configurable<?> config, Object registerable) {
+        if (currentValue++ == finalValue)
+          config.register(registerable, ClientRequestFilter.class);
+      }
+    };
+
+    setResourceMethod("echo");
+    // build client configurableCnt times to register provider using a
+    // different
+    // configurable each time
+    Assertable assertable = getAssertableWithNoRegisteredProviderInstance();
+    for (int cnt = 0; cnt != configurableCnt; cnt++) {
+      // Check the provider is registered
+      logMsg("Check on Configurable", Assertable.getLocation(cnt));
+      // set we want to register the provider on Configurable
+      // Assertable::LOCATION[cnt]
+      registrar.setCurrentValue(0).setFinalValue(cnt);
+      checkConfig(registrar, assertable, instances, entity);
+      logMsg(
+          "The provider withO unassignable contract has ben ignored as expected");
+    }
+  }
+
+  /*
+   * @testName: registerObjectNullContractsTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:760;
+   * 
+   * @test_Strategy: Implementations MUST ignore attempts to register a
+   * component class for a null collection of contracts via this method and
+   * SHOULD raise a warning about such event.
+   */
+  @Test
+  public void registerObjectNullContractsTest() throws Fault {
+    Object[] instances = createProviderInstances();
+    // entity to send to a server
+    Entity<?> entity = Entity.entity("", MediaType.WILDCARD);
+
+    // register only once per client build
+    IncrementableRegistrar registrar = new IncrementableRegistrar(0, 1) {
+      @Override
+      public void register(Configurable<?> config, Object registerable) {
+        if (currentValue++ == finalValue)
+          config.register(registerable, (Class<?>[]) null);
+      }
+    };
+
+    setResourceMethod("echo");
+    // build client configurableCnt times to register provider using a
+    // different
+    // configurable each time
+    Assertable assertable = getAssertableWithNoRegisteredProvider();
+    for (int cnt = 0; cnt != configurableCnt; cnt++) {
+      // Check the provider is registered
+      logMsg("Check on Configurable", Assertable.getLocation(cnt));
+      // set we want to register the provider on Configurable
+      // Assertable::LOCATION[cnt]
+      registrar.setCurrentValue(0).setFinalValue(cnt);
+      checkConfig(registrar, assertable, instances, entity);
+      logMsg("The provider with null contract has ben ignored as expected");
+    }
+  }
+
+  /*
+   * @testName: registerClassWriterContractsInMapTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:989;
+   * 
+   * @test_Strategy: This registration method provides same functionality as
+   * register(Class, Class[]) except that any binding priority specified on the
+   * registered JAX-RS component class using @Priority annotation is overridden
+   * for each extension provider contract type separately with an integer
+   * binding priority value specified as a value in the supplied map.
+   */
+  @Test
+  public void registerClassWriterContractsInMapTest() throws Fault {
+    final String content = "registerClassWriterContractsInMapTest";
+
+    Class<?>[] classes = createProviderClasses();
+    // entity to send to a server
+    Entity<?> entity = getCallableEntity(content);
+
+    // register only once per client build
+    IncrementableRegistrar registrar = new IncrementableRegistrar(0, 1) {
+      @Override
+      public void register(Configurable<?> config, Object registerable) {
+        if (currentValue++ == finalValue) {
+          Map<Class<?>, Integer> contracts = new HashMap<Class<?>, Integer>();
+          contracts.put(MessageBodyWriter.class, 100);
+          config.register((Class<?>) registerable, contracts);
+        }
+      }
+    };
+
+    setResourceMethod("echo");
+    // build client configurableCnt times to register provider using a
+    // different
+    // configurable each time
+    for (int cnt = 0; cnt != configurableCnt; cnt++) {
+      // Check the provider is registered
+      logMsg("Check on Configurable", Assertable.getLocation(cnt));
+      Assertable assertable = getAssertableWithRegisteredProviderClassesOnConfigurable(
+          cnt, 1);
+
+      // set we want to register the provider on Configurable
+      // Assertable::LOCATION[cnt]
+      registrar.setCurrentValue(0).setFinalValue(cnt);
+      Invocation i = checkConfig(registrar, assertable, classes, entity);
+      Response response = i.invoke();
+      response.bufferEntity();
+      String responseString = response.readEntity(String.class);
+      assertEquals(content, responseString, "Expected", content,
+          "differs from given", response);
+      logMsg(
+          "sucessufully wrote Callable by provider registered on Configurable",
+          Assertable.getLocation(cnt));
+      // check message body reader contract
+      try {
+        Callable<?> callable = response.readEntity(Callable.class);
+        fault("MessageBodyReader contract has been unexpectedly registered",
+            callable);
+      } catch (Exception e) {
+        logMsg("MessageBodyReader contract has not been registered as expected",
+            e);
+      }
+    }
+  }
+
+  /*
+   * @testName: registerClassReaderContractsInMapTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:989;
+   * 
+   * @test_Strategy: This registration method provides same functionality as
+   * register(Class, Class[]) except that any binding priority specified on the
+   * registered JAX-RS component class using @Priority annotation is overridden
+   * for each extension provider contract type separately with an integer
+   * binding priority value specified as a value in the supplied map.
+   */
+  @Test
+  public void registerClassReaderContractsInMapTest() throws Fault {
+    final String content = "registerClassReaderContractsInMapTest";
+
+    Class<?>[] classes = createProviderClasses();
+    // entity to send to a server
+    Entity<?> entity = Entity.entity(content, MediaType.WILDCARD);
+
+    // register only once per client build
+    IncrementableRegistrar registrar = new IncrementableRegistrar(0, 1) {
+      @Override
+      public void register(Configurable<?> config, Object registerable) {
+        if (currentValue++ == finalValue) {
+          Map<Class<?>, Integer> contracts = new HashMap<Class<?>, Integer>();
+          contracts.put(MessageBodyReader.class, 100);
+          config.register((Class<?>) registerable, contracts);
+        }
+      }
+    };
+
+    setResourceMethod("echo");
+    // build client configurableCnt times to register provider using a
+    // different
+    // configurable each time
+    for (int cnt = 0; cnt != configurableCnt; cnt++) {
+      // Check the provider is registered
+      logMsg("Check on Configurable", Assertable.getLocation(cnt));
+      Assertable assertable = getAssertableWithRegisteredProviderClassesOnConfigurable(
+          cnt, 1);
+      // set we want to register the provider on Configurable
+      // Assertable::LOCATION[cnt]
+      registrar.setCurrentValue(0).setFinalValue(cnt);
+      Invocation i = checkConfig(registrar, assertable, classes, entity);
+      Response response = i.invoke();
+      Callable<?> callable = response.readEntity(Callable.class);
+      assertEquals(content, callable.toString(), "Expected", content,
+          "differs from given", response);
+      logMsg(
+          "sucessufully read Callable by provider registered on Configurable",
+          Assertable.getLocation(cnt));
+    }
+  }
+
+  /*
+   * @testName: registerClassBindingPriorityInMapTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:989;
+   * 
+   * @test_Strategy: This registration method provides same functionality as
+   * register(Class, Class[]) except that any binding priority specified on the
+   * registered JAX-RS component class using @Priority annotation is overridden
+   * for each extension provider contract type separately with an integer
+   * binding priority value specified as a value in the supplied map.
+   */
+  @Test
+  public void registerClassBindingPriorityInMapTest() throws Fault {
+    final String content = "registerClassBindingPriorityInMapTest";
+    Class<?>[] classes = createProviderClasses();
+    // entity to send to a server
+    Entity<?> entity = Entity.entity(content, MediaType.WILDCARD);
+
+    // register only once per client build
+    IncrementableRegistrar registrar = new IncrementableRegistrar(0, 1) {
+      @Override
+      public void register(Configurable<?> config, Object registerable) {
+        if (currentValue++ == finalValue) {
+          Map<Class<?>, Integer> contracts = new HashMap<Class<?>, Integer>();
+          contracts.put(ClientRequestFilter.class, 400);
+          config.register(FirstFilter.class, contracts);
+          contracts.clear();
+          contracts.put(ClientRequestFilter.class, 300);
+          config.register(SecondFilter.class, contracts);
+        }
+      }
+    };
+
+    setResourceMethod("echo");
+    // build client configurableCnt times to register provider using a
+    // different
+    // configurable each time
+    for (int cnt = 0; cnt != configurableCnt; cnt++) {
+      // Check the provider is registered
+      logMsg("Check on Configurable", Assertable.getLocation(cnt));
+      // set we want to register the provider on Configurable
+      // Assertable::LOCATION[cnt]
+      registrar.setCurrentValue(0).setFinalValue(cnt);
+      Assertable assertable = getAssertableWithRegisteredProviderClassesOnConfigurable(
+          cnt, 2);
+      Invocation i = checkConfig(registrar, assertable, classes, entity);
+      String response = i.invoke(String.class);
+      assertEquals(FirstFilter.class.getName(), response,
+          "Unexpected filter ordering, the last was", response);
+      logMsg(response, "has been executed as second, as expected");
+    }
+  }
+
+  /*
+   * @testName: registerClassNotAssignableContractsInMapTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:989;
+   * 
+   * @test_Strategy: Contracts that are not assignable from the registered
+   * component class MUST be ignored
+   */
+  @Test
+  public void registerClassNotAssignableContractsInMapTest() throws Fault {
+    Class<?>[] classes = createProviderClasses();
+    // entity to send to a server
+    Entity<?> entity = Entity.entity("", MediaType.WILDCARD);
+
+    // register only once per client build
+    IncrementableRegistrar registrar = new IncrementableRegistrar(0, 1) {
+      @Override
+      public void register(Configurable<?> config, Object registerable) {
+        if (currentValue++ == finalValue) {
+          Map<Class<?>, Integer> contracts = new HashMap<Class<?>, Integer>();
+          contracts.put(ClientRequestFilter.class, 400);
+          config.register((Class<?>) registerable, contracts);
+        }
+      }
+    };
+
+    setResourceMethod("echo");
+    // build client configurableCnt times to register provider using a
+    // different
+    // configurable each time
+    Assertable assertable = getAssertableWithNoRegisteredProviderInstance();
+    for (int cnt = 0; cnt != configurableCnt; cnt++) {
+      // Check the provider is registered
+      logMsg("Check on Configurable", Assertable.getLocation(cnt));
+      // set we want to register the provider on Configurable
+      // Assertable::LOCATION[cnt]
+      registrar.setCurrentValue(0).setFinalValue(cnt);
+      checkConfig(registrar, assertable, classes, entity);
+      logMsg(
+          "The provider with unassignable contract has ben ignored as expected");
+    }
+  }
+
+  /*
+   * @testName: registerObjectWriterContractsInMapTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:990;
+   * 
+   * @test_Strategy: This registration method provides same functionality as
+   * register(Object, Class[]) except that any binding priority specified on the
+   * registered JAX-RS component class using @Priority annotation is overridden
+   * for each extension provider contract type separately with an integer
+   * binding priority value specified as a value in the supplied map.
+   */
+  @Test
+  public void registerObjectWriterContractsInMapTest() throws Fault {
+    final String content = "registerObjectWriterContractsInMapTest";
+
+    Object[] instances = createProviderInstances();
+    // entity to send to a server
+    Entity<?> entity = getCallableEntity(content);
+
+    // register only once per client build
+    IncrementableRegistrar registrar = new IncrementableRegistrar(0, 1) {
+      @Override
+      public void register(Configurable<?> config, Object registerable) {
+        if (currentValue++ == finalValue) {
+          Map<Class<?>, Integer> contracts = new HashMap<Class<?>, Integer>();
+          contracts.put(MessageBodyWriter.class, 100);
+          config.register(registerable, contracts);
+        }
+      }
+    };
+
+    setResourceMethod("echo");
+    // build client configurableCnt times to register provider using a
+    // different
+    // configurable each time
+    for (int cnt = 0; cnt != configurableCnt; cnt++) {
+      // Check the provider is registered
+      logMsg("Check on Configurable", Assertable.getLocation(cnt));
+      Assertable assertable = getAssertableWithRegisteredProviderInstancesOnConfigurable(
+          cnt, 1);
+
+      // set we want to register the provider on Configurable
+      // Assertable::LOCATION[cnt]
+      registrar.setCurrentValue(0).setFinalValue(cnt);
+      Invocation i = checkConfig(registrar, assertable, instances, entity);
+      Response response = i.invoke();
+      response.bufferEntity();
+      String responseString = response.readEntity(String.class);
+      assertEquals(content, responseString, "Expected", content,
+          "differs from given", response);
+      logMsg(
+          "sucessufully wrote Callable by provider registered on Configurable",
+          Assertable.getLocation(cnt));
+      // check message body reader contract
+      try {
+        Callable<?> callable = response.readEntity(Callable.class);
+        fault("MessageBodyReader contract has been unexpectedly registered",
+            callable);
+      } catch (Exception e) {
+        logMsg("MessageBodyReader contract has not been registered as expected",
+            e);
+      }
+    }
+  }
+
+  /*
+   * @testName: registerObjectReaderContractsInMapTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:990;
+   * 
+   * @test_Strategy: This registration method provides same functionality as
+   * register(Object, Class[]) except that any binding priority specified on the
+   * registered JAX-RS component class using @Priority annotation is overridden
+   * for each extension provider contract type separately with an integer
+   * binding priority value specified as a value in the supplied map.
+   */
+  @Test
+  public void registerObjectReaderContractsInMapTest() throws Fault {
+    final String content = "registerObjectReaderContractsInMapTest";
+
+    Object[] instances = createProviderInstances();
+    // entity to send to a server
+    Entity<?> entity = Entity.entity(content, MediaType.WILDCARD);
+
+    // register only once per client build
+    IncrementableRegistrar registrar = new IncrementableRegistrar(0, 1) {
+      @Override
+      public void register(Configurable<?> config, Object registerable) {
+        if (currentValue++ == finalValue) {
+          Map<Class<?>, Integer> contracts = new HashMap<Class<?>, Integer>();
+          contracts.put(MessageBodyReader.class, 100);
+          config.register(registerable, contracts);
+        }
+      }
+    };
+
+    setResourceMethod("echo");
+    // build client configurableCnt times to register provider using a
+    // different
+    // configurable each time
+    for (int cnt = 0; cnt != configurableCnt; cnt++) {
+      // Check the provider is registered
+      logMsg("Check on Configurable", Assertable.getLocation(cnt));
+      Assertable assertable = getAssertableWithRegisteredProviderInstancesOnConfigurable(
+          cnt, 1);
+      // set we want to register the provider on Configurable
+      // Assertable::LOCATION[cnt]
+      registrar.setCurrentValue(0).setFinalValue(cnt);
+      Invocation i = checkConfig(registrar, assertable, instances, entity);
+      Response response = i.invoke();
+      Callable<?> callable = response.readEntity(Callable.class);
+      assertEquals(content, callable.toString(), "Expected", content,
+          "differs from given", response);
+      logMsg(
+          "sucessufully read Callable by provider registered on Configurable",
+          Assertable.getLocation(cnt));
+    }
+  }
+
+  /*
+   * @testName: registerObjectBindingPriorityInMapTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:990;
+   * 
+   * @test_Strategy: This registration method provides same functionality as
+   * register(Object, Class[]) except that any binding priority specified on the
+   * registered JAX-RS component class using @Priority annotation is overridden
+   * for each extension provider contract type separately with an integer
+   * binding priority value specified as a value in the supplied map.
+   */
+  @Test
+  public void registerObjectBindingPriorityInMapTest() throws Fault {
+    final String content = "registerObjectBindingPriorityInMapTest";
+    Class<?>[] classes = createProviderClasses();
+    // entity to send to a server
+    Entity<?> entity = Entity.entity(content, MediaType.WILDCARD);
+
+    // register only once per client build
+    IncrementableRegistrar registrar = new IncrementableRegistrar(0, 1) {
+      @Override
+      public void register(Configurable<?> config, Object registerable) {
+        if (currentValue++ == finalValue) {
+          Map<Class<?>, Integer> contracts = new HashMap<Class<?>, Integer>();
+          contracts.put(ClientRequestFilter.class, 400);
+          config.register(new FirstFilter(), contracts);
+          contracts.clear();
+          contracts.put(ClientRequestFilter.class, 300);
+          config.register(new SecondFilter(), contracts);
+        }
+      }
+    };
+
+    setResourceMethod("echo");
+    // build client configurableCnt times to register provider using a
+    // different
+    // configurable each time
+    for (int cnt = 0; cnt != configurableCnt; cnt++) {
+      // Check the provider is registered
+      logMsg("Check on Configurable", Assertable.getLocation(cnt));
+      // set we want to register the provider on Configurable
+      // Assertable::LOCATION[cnt]
+      registrar.setCurrentValue(0).setFinalValue(cnt);
+      Assertable assertable = getAssertableWithRegisteredProviderInstancesOnConfigurable(
+          cnt, 2);
+      Invocation i = checkConfig(registrar, assertable, classes, entity);
+      String response = i.invoke(String.class);
+      assertEquals(FirstFilter.class.getName(), response,
+          "Unexpected filter ordering, the last was", response);
+      logMsg(response, "has been executed as second, as expected");
+    }
+  }
+
+  /*
+   * @testName: registerObjectNotAssignableContractsInMapTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:990;
+   * 
+   * @test_Strategy: Contracts that are not assignable from the registered
+   * component class MUST be ignored
+   */
+  @Test
+  public void registerObjectNotAssignableContractsInMapTest() throws Fault {
+    Object[] instances = createProviderInstances();
+    // entity to send to a server
+    Entity<?> entity = Entity.entity("", MediaType.WILDCARD);
+
+    // register only once per client build
+    IncrementableRegistrar registrar = new IncrementableRegistrar(0, 1) {
+      @Override
+      public void register(Configurable<?> config, Object registerable) {
+        if (currentValue++ == finalValue) {
+          Map<Class<?>, Integer> contracts = new HashMap<Class<?>, Integer>();
+          contracts.put(ClientRequestFilter.class, 400);
+          config.register(registerable, contracts);
+        }
+      }
+    };
+
+    setResourceMethod("echo");
+    // build client configurableCnt times to register provider using a
+    // different
+    // configurable each time
+    Assertable assertable = getAssertableWithNoRegisteredProviderInstance();
+    for (int cnt = 0; cnt != configurableCnt; cnt++) {
+      // Check the provider is registered
+      logMsg("Check on Configurable", Assertable.getLocation(cnt));
+      // set we want to register the provider on Configurable
+      // Assertable::LOCATION[cnt]
+      registrar.setCurrentValue(0).setFinalValue(cnt);
+      checkConfig(registrar, assertable, instances, entity);
+      logMsg(
+          "The provider with unassignable contract has ben ignored as expected");
+    }
+  }
+
+  // ///////////////////////////////////////////////////////////////////////
+  private Assertable getAssertableWithRegisteredProviderClassesOnConfigurable(
+      final int configurableIndex, final int numberOfRegisteredClasses) {
+    Assertable assertable = new SingleCheckAssertable() {
+      @Override
+      protected void check(Configurable<?> configurable) throws Fault {
+        assertSizeAndLog(configurable);
+      }
+
+      void assertSizeAndLog(Configurable<?> config) throws Fault {
+        int size = config.getConfiguration().getClasses().size();
+        int shouldBe = getLocationIndex() >= configurableIndex
+            ? numberOfRegisteredClasses
+            : 0;
+        shouldBe += registeredClassesCnt;
+        assertEqualsInt(size, shouldBe,
+            "unexpected number of registered classes found:", size,
+            getLocation());
+        logMsg("Found", size, "provider(s) as expected");
+      }
+    };
+    return assertable;
+  }
+
+  private Assertable getAssertableWithRegisteredProviderInstancesOnConfigurable(
+      final int configurableIndex, final int numberOfRegisteredInstances) {
+    Assertable assertable = new SingleCheckAssertable() {
+      @Override
+      protected void check(Configurable<?> configurable) throws Fault {
+        assertSizeAndLog(configurable);
+      }
+
+      void assertSizeAndLog(Configurable<?> config) throws Fault {
+        int size = config.getConfiguration().getInstances().size();
+        int shouldBe = getLocationIndex() >= configurableIndex
+            ? numberOfRegisteredInstances
+            : 0;
+        shouldBe += registeredInstancesCnt;
+        assertEqualsInt(size, shouldBe,
+            "unexpected number of registered classes found:", size,
+            getLocation());
+        logMsg("Found", size, "provider(s) as expected");
+      }
+    };
+    return assertable;
+  }
+
+  private Assertable getAssertableWithNoRegisteredProvider() {
+    return getAssertableWithRegisteredProviderClassesOnConfigurable(0, 0);
+  }
+
+  private Assertable getAssertableWithNoRegisteredProviderInstance() {
+    return getAssertableWithRegisteredProviderInstancesOnConfigurable(0, 0);
+  }
+
+  /**
+   * Provider has to not be anonymous class, because we need @Provider
+   * annotation there
+   */
+  protected Object[] createProviderInstances() {
+    Object[] instances = new CallableProvider[] { new CallableProvider() {
+    }, new CallableProvider() {
+    } };
+    return instances;
+  }
+
+  protected static Class<?>[] createProviderClasses() {
+    Class<?>[] classes = new Class<?>[] { CallableProvider.class,
+        CallableProvider.class };
+    return classes;
+  }
+
+  protected Invocation checkConfig(Registrar registrar, Assertable assertable,
+      Object[] registerables, Entity<?> entity) throws Fault {
+    Client client = ClientBuilder.newClient();
+    Configuration config = client.getConfiguration();
+    registeredClassesCnt = config.getClasses().size();
+    registeredInstancesCnt = config.getInstances().size();
+    logMsg("Already registered", registeredClassesCnt, "classes");
+    logMsg("Already registered", registeredInstancesCnt, "instances");
+
+    register(registrar, client, registerables[0]);
+    assertable.check1OnClient(client);
+    assertable.incrementLocation();
+
+    WebTarget target = client.target(getAbsoluteUrl());
+    register(registrar, target, registerables[1]);
+    assertable.check2OnTarget(target);
+    assertable.incrementLocation();
+
+    Invocation.Builder builder = target.request();
+    Invocation invocation = builder.buildPost(entity);
+    return invocation;
+  }
+
+  protected void register(Registrar registrar, Configurable<?> config,
+      Object registerable) {
+    registrar.register(config, registerable);
+  }
+
+  protected class IncrementableRegistrar extends Registrar {
+    int currentValue;
+
+    int finalValue;
+
+    int getFinalValue() {
+      return finalValue;
+    }
+
+    IncrementableRegistrar setFinalValue(int finalValue) {
+      this.finalValue = finalValue;
+      return this;
+    }
+
+    IncrementableRegistrar(int initValue, int finalValue) {
+      currentValue = initValue;
+      this.finalValue = finalValue;
+    }
+
+    int getCurrentValue() {
+      return currentValue;
+    }
+
+    IncrementableRegistrar setCurrentValue(int set) {
+      currentValue = set;
+      return this;
+    }
+  }
+
+  private void setResourceMethod(String method) {
+    setContextRoot(getContextRoot() + "/" + method);
+  }
+
+  private static Entity<?> getCallableEntity(final String content) {
+    Entity<?> entity = Entity.entity(CallableProvider.createCallable(content),
+        MediaType.WILDCARD_TYPE);
+    return entity;
+  }
+
+}
diff --git a/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/core/configurable/Resource.java b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/core/configurable/Resource.java
new file mode 100644
index 0000000..b8f2c16
--- /dev/null
+++ b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/core/configurable/Resource.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2013, 2020 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 jakarta.ws.rs.tck.ee.rs.core.configurable;
+
+import jakarta.ws.rs.POST;
+import jakarta.ws.rs.Path;
+
+@Path("resource")
+public class Resource {
+  @POST
+  @Path("echo")
+  public String echo(String value) {
+    return value;
+  }
+}
diff --git a/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/core/configurable/SecondFilter.java b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/core/configurable/SecondFilter.java
new file mode 100644
index 0000000..52d78ab
--- /dev/null
+++ b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/core/configurable/SecondFilter.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2013, 2020 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 jakarta.ws.rs.tck.ee.rs.core.configurable;
+
+import java.io.IOException;
+
+import jakarta.annotation.Priority;
+import jakarta.ws.rs.client.ClientRequestContext;
+import jakarta.ws.rs.client.ClientRequestFilter;
+import jakarta.ws.rs.core.MediaType;
+import jakarta.ws.rs.ext.Provider;
+
+@Provider
+@Priority(200)
+public class SecondFilter implements ClientRequestFilter {
+
+  @Override
+  public void filter(ClientRequestContext requestContext) throws IOException {
+    requestContext.setEntity(getClass().getName(), null,
+        MediaType.WILDCARD_TYPE);
+  }
+
+}
diff --git a/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/core/configurable/TSAppConfig.java b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/core/configurable/TSAppConfig.java
new file mode 100644
index 0000000..c2f52f2
--- /dev/null
+++ b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/core/configurable/TSAppConfig.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2013, 2020 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 jakarta.ws.rs.tck.ee.rs.core.configurable;
+
+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);
+    return resources;
+  }
+}
diff --git a/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/core/configuration/JAXRSClientIT.java b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/core/configuration/JAXRSClientIT.java
new file mode 100644
index 0000000..459ab7f
--- /dev/null
+++ b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/core/configuration/JAXRSClientIT.java
@@ -0,0 +1,550 @@
+/*
+ * Copyright (c) 2013, 2020 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 jakarta.ws.rs.tck.ee.rs.core.configuration;
+
+import java.util.LinkedList;
+import java.util.List;
+import java.io.InputStream;
+import java.io.IOException;
+
+import jakarta.ws.rs.tck.api.rs.core.configurable.Assertable;
+import jakarta.ws.rs.tck.api.rs.core.configurable.Registrar;
+import jakarta.ws.rs.tck.common.client.JaxrsCommonClient;
+import jakarta.ws.rs.tck.lib.util.TestUtil;
+
+import jakarta.ws.rs.client.Client;
+import jakarta.ws.rs.client.ClientBuilder;
+import jakarta.ws.rs.client.Entity;
+import jakarta.ws.rs.client.Invocation;
+import jakarta.ws.rs.client.WebTarget;
+import jakarta.ws.rs.core.Configurable;
+import jakarta.ws.rs.core.Configuration;
+import jakarta.ws.rs.core.Feature;
+import jakarta.ws.rs.core.FeatureContext;
+import jakarta.ws.rs.core.MediaType;
+
+import org.jboss.arquillian.junit5.ArquillianExtension;
+import org.jboss.arquillian.container.test.api.Deployment;
+import org.jboss.shrinkwrap.api.ShrinkWrap;
+import org.jboss.shrinkwrap.api.asset.StringAsset;
+import org.jboss.shrinkwrap.api.spec.WebArchive;
+import org.jboss.shrinkwrap.api.exporter.ZipExporter;
+
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.fail;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.junit.jupiter.api.TestInfo;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.AfterEach;
+
+/*
+ * @class.setup_props: webServerHost;
+ *                     webServerPort;
+ */
+
+/**
+ * <p>
+ * These tests follow the intended JAXRS rule to enable Features in the order of
+ * them being registered. By this rule, it is possible to check the previous
+ * Feature has been / has not been enabled.
+ * </p>
+ * 
+ * <p>
+ * The isEnabled works only in runtime which has its own version of
+ * configuration, i.e. it does not work on Configurable.getConfiguration()
+ * </p>
+ */
+@ExtendWith(ArquillianExtension.class)
+public class JAXRSClientIT extends JaxrsCommonClient {
+
+  private static final long serialVersionUID = 7215781408688132392L;
+
+  public JAXRSClientIT() {
+    setup();
+    setContextRoot("/jaxrs_ee_core_configuration_web/resource/echo");
+  }
+
+  
+  @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{
+
+    InputStream inStream = JAXRSClientIT.class.getClassLoader().getResourceAsStream("jakarta/ws/rs/tck/ee/rs/core/configuration/web.xml.template");
+    String webXml = editWebXmlString(inStream);
+
+    WebArchive archive = ShrinkWrap.create(WebArchive.class, "jaxrs_ee_core_configuration_web.war");
+    archive.addClasses(jakarta.ws.rs.tck.ee.rs.core.configurable.Resource.class,
+      jakarta.ws.rs.tck.ee.rs.core.configurable.TSAppConfig.class,
+      jakarta.ws.rs.tck.api.rs.core.configurable.Assertable.class, 
+      jakarta.ws.rs.tck.api.rs.core.configurable.Registrar.class, 
+      jakarta.ws.rs.tck.api.rs.core.configurable.CallableProvider.class, 
+      jakarta.ws.rs.tck.api.rs.core.configurable.SingleCheckAssertable.class, 
+      jakarta.ws.rs.tck.api.rs.core.configurable.ConfigurableObject.class);
+    archive.setWebXML(new StringAsset(webXml));
+    return archive;
+
+  }
+
+
+  /* Run test */
+
+  /*
+   * @testName: isEnabledFeatureReturningFalseTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:999; JAXRS:JAVADOC:1003;
+   * 
+   * @test_Strategy: Check if a feature instance of featureClass class has been
+   * previously enabled in the runtime configuration context.
+   * 
+   * Returns true if the feature was successfully enabled, false otherwise
+   */
+  @Test
+  public void isEnabledFeatureReturningFalseTest() throws Fault {
+    final CheckingFeature feature1 = new FeatureReturningFalse1();
+    final CheckingFeature feature2 = new FeatureReturningFalse2();
+    final CheckingFeature feature3 = new FeatureReturningFalse3();
+    final CheckingFeature feature4 = new FeatureReturningFalse4();
+
+    feature1.addDisabledFeatures(feature2, feature3, feature4)
+        .setName("feature1");
+    feature2.addDisabledFeatures(feature1, feature3, feature4)
+        .setName("feature2");
+    feature3.addDisabledFeatures(feature1, feature2, feature4)
+        .setName("feature3");
+    feature4.addDisabledFeatures(feature1, feature2, feature3)
+        .setName("feature4");
+
+    Assertable assertable = new Assertable() {
+      @Override
+      public void check1OnClient(Client client) throws Fault {
+        assertIsDisabled(client, feature1);
+        assertIsDisabled(client, feature2);
+        assertIsDisabled(client, feature3);
+        assertIsDisabled(client, feature4);
+      }
+
+      @Override
+      public void check2OnTarget(WebTarget target) throws Fault {
+        assertIsDisabled(target, feature1);
+        assertIsDisabled(target, feature2);
+        assertIsDisabled(target, feature3);
+        assertIsDisabled(target, feature4);
+      }
+
+      void assertIsDisabled(Configurable<?> config, CheckingFeature feature)
+          throws Fault {
+        boolean isEnabled = config.getConfiguration().isEnabled(feature);
+        assertFalse(isEnabled, "Feature"+ feature.getName()+
+            "is unexpectedly enabled"+ getLocation());
+        logMsg("No feature enabled as expected", getLocation());
+      }
+    };
+    Object[] instances = { feature1, feature2, feature3, feature4 };
+    checkConfig(assertable, instances);
+    logMsg(
+        "The provider with unassignable contract has ben ignored as expected");
+  }
+
+  /*
+   * @testName: isEnabledFeatureReturningTrueTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:999; JAXRS:JAVADOC:1003;
+   * 
+   * @test_Strategy: Check if a feature instance of featureClass class has been
+   * previously enabled in the runtime configuration context.
+   * 
+   * Returns true if the feature was successfully enabled, false otherwise
+   */
+  @Test
+  public void isEnabledFeatureReturningTrueTest() throws Fault {
+    final CheckingFeature feature1 = new FeatureReturningTrue1();
+    final CheckingFeature feature2 = new FeatureReturningTrue2();
+    final CheckingFeature feature3 = new FeatureReturningTrue3();
+    final CheckingFeature feature4 = new FeatureReturningTrue4();
+
+    feature1.addDisabledFeatures(feature2, feature3, feature4)
+        .setName("feature1");
+    feature2.addDisabledFeatures(feature3, feature4)
+        .addEnabledFeatures(feature1).setName("feature2");
+    feature3.addDisabledFeatures(feature4)
+        .addEnabledFeatures(feature1, feature2).setName("feature3");
+    feature4.addEnabledFeatures(feature1, feature2, feature3)
+        .setName("feature4");
+
+    Assertable assertable = new Assertable() {
+      @Override
+      public void check1OnClient(Client client) throws Fault {
+        assertIsRegistered(client, feature1);
+        assertIsNotRegistered(client, feature2);
+        assertIsNotRegistered(client, feature3);
+        assertIsNotRegistered(client, feature4);
+      }
+
+      @Override
+      public void check2OnTarget(WebTarget target) throws Fault {
+        assertIsRegistered(target, feature1);
+        assertIsRegistered(target, feature2);
+        assertIsNotRegistered(target, feature3);
+        assertIsNotRegistered(target, feature4);
+      }
+
+      void assertIsRegistered(Configurable<?> config, CheckingFeature feature)
+          throws Fault {
+        Configuration configuration = config.getConfiguration();
+        assertTrue(configuration.isRegistered(feature), "Feature"+
+            feature.getName()+ "is NOT registered"+ getLocation());
+        logMsg("Feature", feature.getName(), "registered as expected",
+            getLocation());
+      }
+
+      void assertIsNotRegistered(Configurable<?> config,
+          CheckingFeature feature) throws Fault {
+        Configuration configuration = config.getConfiguration();
+        assertFalse(configuration.isRegistered(feature), "Feature"+
+            feature.getName()+ "is unexpectedly registered"+ getLocation());
+        logMsg("Feature", feature.getName(), "NOT registered as expected",
+            getLocation());
+      }
+
+    };
+    Object[] instances = { feature1, feature2, feature3, feature4 };
+    checkConfig(assertable, instances);
+    logMsg(
+        "The provider with unassignable contract has ben ignored as expected");
+  }
+
+  /*
+   * @testName: isEnabledClassReturningFalseTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:1000; JAXRS:JAVADOC:1003;
+   * 
+   * @test_Strategy: Check if a feature instance of featureClass class has been
+   * previously enabled in the runtime configuration context.
+   * 
+   * Returns true if the feature was successfully enabled, false otherwise
+   */
+  @SuppressWarnings("unchecked")
+  @Test
+  public void isEnabledClassReturningFalseTest() throws Fault {
+    final CheckingFeature feature1 = new FeatureReturningFalse1();
+    final CheckingFeature feature2 = new FeatureReturningFalse2();
+    final CheckingFeature feature3 = new FeatureReturningFalse3();
+    final CheckingFeature feature4 = new FeatureReturningFalse4();
+
+    feature1
+        .addDisabledClasses(FeatureReturningFalse2.class,
+            FeatureReturningFalse3.class, FeatureReturningFalse4.class)
+        .setName("feature1");
+    feature2
+        .addDisabledClasses(FeatureReturningFalse1.class,
+            FeatureReturningFalse3.class, FeatureReturningFalse4.class)
+        .setName("feature2");
+    feature3
+        .addDisabledClasses(FeatureReturningFalse1.class,
+            FeatureReturningFalse2.class, FeatureReturningFalse4.class)
+        .setName("feature3");
+    feature4
+        .addDisabledClasses(FeatureReturningFalse1.class,
+            FeatureReturningFalse2.class, FeatureReturningFalse3.class)
+        .setName("feature4");
+
+    Assertable assertable = new Assertable() {
+      @Override
+      public void check1OnClient(Client client) throws Fault {
+        assertIsDisabled(client, feature1);
+        assertIsDisabled(client, feature2);
+        assertIsDisabled(client, feature3);
+        assertIsDisabled(client, feature4);
+      }
+
+      @Override
+      public void check2OnTarget(WebTarget target) throws Fault {
+        assertIsDisabled(target, feature1);
+        assertIsDisabled(target, feature2);
+        assertIsDisabled(target, feature3);
+        assertIsDisabled(target, feature4);
+      }
+
+      void assertIsDisabled(Configurable<?> config, CheckingFeature feature)
+          throws Fault {
+        boolean isEnabled = config.getConfiguration().isEnabled(feature);
+        assertFalse(isEnabled, "Feature"+ feature.getName()+
+            "is unexpectedly enabled"+ getLocation());
+        logMsg("No feature enabled as expected", getLocation());
+      }
+    };
+    Object[] instances = { feature1, feature2, feature3, feature4 };
+    checkConfig(assertable, instances);
+    logMsg(
+        "The provider with unassignable contract has ben ignored as expected");
+  }
+
+  /*
+   * @testName: isEnabledFeatureClassReturningTrueTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:1000; JAXRS:JAVADOC:1003;
+   * 
+   * @test_Strategy: Check if a feature instance of featureClass class has been
+   * previously enabled in the runtime configuration context.
+   * 
+   * Returns true if the feature was successfully enabled, false otherwise
+   */
+  @SuppressWarnings("unchecked")
+  @Test
+  public void isEnabledFeatureClassReturningTrueTest() throws Fault {
+    final CheckingFeature feature1 = new FeatureReturningTrue1();
+    final CheckingFeature feature2 = new FeatureReturningTrue2();
+    final CheckingFeature feature3 = new FeatureReturningTrue3();
+    final CheckingFeature feature4 = new FeatureReturningTrue4();
+
+    feature1
+        .addDisabledClasses(FeatureReturningTrue2.class,
+            FeatureReturningTrue3.class, FeatureReturningTrue4.class)
+        .setName("feature1");
+    feature2
+        .addDisabledClasses(FeatureReturningTrue3.class,
+            FeatureReturningTrue4.class)
+        .addEnabledClasses(FeatureReturningTrue1.class).setName("feature2");
+    feature3.addDisabledClasses(FeatureReturningTrue4.class)
+        .addEnabledClasses(FeatureReturningTrue1.class,
+            FeatureReturningTrue2.class)
+        .setName("feature3");
+    feature4
+        .addEnabledClasses(FeatureReturningTrue1.class,
+            FeatureReturningTrue2.class, FeatureReturningTrue3.class)
+        .setName("feature4");
+
+    Assertable assertable = new Assertable() {
+      @Override
+      public void check1OnClient(Client client) throws Fault {
+        assertIsRegistered(client, feature1);
+        assertIsNotRegistered(client, feature2);
+        assertIsNotRegistered(client, feature3);
+        assertIsNotRegistered(client, feature4);
+      }
+
+      @Override
+      public void check2OnTarget(WebTarget target) throws Fault {
+        assertIsRegistered(target, feature1);
+        assertIsRegistered(target, feature2);
+        assertIsNotRegistered(target, feature3);
+        assertIsNotRegistered(target, feature4);
+      }
+
+      void assertIsRegistered(Configurable<?> config, CheckingFeature feature)
+          throws Fault {
+        Configuration configuration = config.getConfiguration();
+        assertTrue(configuration.isRegistered(feature), "Feature"+
+            feature.getName()+ "is NOT registered"+ getLocation());
+        logMsg("Feature", feature.getName(), "registered as expected",
+            getLocation());
+      }
+
+      void assertIsNotRegistered(Configurable<?> config,
+          CheckingFeature feature) throws Fault {
+        Configuration configuration = config.getConfiguration();
+        assertFalse(configuration.isRegistered(feature), "Feature"+
+            feature.getName()+ "is unexpectedly registered"+ getLocation());
+        logMsg("Feature", feature.getName(), "NOT registered as expected",
+            getLocation());
+      }
+
+    };
+    Object[] instances = { feature1, feature2, feature3, feature4 };
+    checkConfig(assertable, instances);
+    logMsg(
+        "The provider with unassignable contract has ben ignored as expected");
+  }
+
+  // ///////////////////////////////////////////////////////////////////////
+
+  /**
+   * Check on every possible setting of configuration by a Feature or a
+   * singleton
+   * 
+   */
+  protected void checkConfig(Assertable assertable, Object[] registerables)
+      throws Fault {
+    checkConfig(new Registrar(), assertable, registerables);
+  }
+
+  protected void checkConfig(Registrar registrar, Assertable assertable,
+      Object[] registerables) throws Fault {
+    Entity<String> entity = Entity.entity("echo", MediaType.WILDCARD_TYPE);
+
+    Client client = ClientBuilder.newClient();
+    logMsg("Registering on Client");
+    register(registrar, client, registerables[0]);
+
+    WebTarget target = client.target(getAbsoluteUrl());
+    logMsg("Registering on WebTarget");
+    register(registrar, target, registerables[1]);
+
+    Invocation.Builder builder = target.request();
+    Invocation invocation = builder.buildPost(entity);
+
+    String response = invocation.invoke(String.class);
+    assertEquals(entity.getEntity(), response, "Unexpected response received",
+        response);
+
+    assertable.check1OnClient(client);
+    assertable.incrementLocation();
+    assertable.check2OnTarget(target);
+  }
+
+  protected void register(Registrar registrar, Configurable<?> config,
+      Object registerable) {
+    registrar.register(config, registerable);
+  }
+
+  // //////////////////////////////////////////////////////////////////////
+  private abstract class NamedFeature implements Feature {
+    String name;
+
+    public String getName() {
+      return name;
+    }
+
+    public NamedFeature setName(String name) {
+      this.name = name;
+      return this;
+    }
+  }
+
+  class CheckingFeature extends NamedFeature {
+    List<NamedFeature> enabledFeatures = new LinkedList<NamedFeature>();
+
+    List<NamedFeature> disabledFeatures = new LinkedList<NamedFeature>();
+
+    List<Class<? extends NamedFeature>> enabledFeatureClasses = new LinkedList<Class<? extends NamedFeature>>();
+
+    List<Class<? extends NamedFeature>> disabledFeatureClasses = new LinkedList<Class<? extends NamedFeature>>();
+
+    @Override
+    public boolean configure(FeatureContext context) {
+      for (NamedFeature feature : enabledFeatures) {
+        if (!context.getConfiguration().isEnabled(feature))
+          throw new RuntimeException(
+              "Feature " + feature.getName() + " has NOT been enabled");
+        logMsg("Feature", feature.getName(), "has been enabled as expected");
+      }
+      for (NamedFeature feature : disabledFeatures) {
+        if (context.getConfiguration().isEnabled(feature))
+          throw new RuntimeException("Feature " + feature.getName()
+              + " has been unexpectedly enabled");
+        logMsg("Feature", feature.getName(),
+            "has NOT been enabled as expected");
+      }
+      for (Class<? extends NamedFeature> feature : enabledFeatureClasses) {
+        if (!context.getConfiguration().isEnabled(feature))
+          throw new RuntimeException(
+              "Feature " + feature.getName() + " has NOT been enabled");
+        logMsg("Feature", feature.getName(), "has been enabled as expected");
+      }
+      for (Class<? extends NamedFeature> feature : disabledFeatureClasses) {
+        if (context.getConfiguration().isEnabled(feature))
+          throw new RuntimeException("Feature " + feature.getName()
+              + " has been unexpectedly enabled");
+        logMsg("Feature", feature.getName(),
+            "has NOT been enabled as expected");
+      }
+      return true;
+    }
+
+    public CheckingFeature addEnabledFeatures(NamedFeature... features) {
+      if (features != null)
+        for (NamedFeature feature : features)
+          enabledFeatures.add(feature);
+      return this;
+    }
+
+    public CheckingFeature addDisabledFeatures(NamedFeature... features) {
+      if (features != null)
+        for (NamedFeature feature : features)
+          disabledFeatures.add(feature);
+      return this;
+    }
+
+    public CheckingFeature addEnabledClasses(
+        Class<? extends NamedFeature>... features) {
+      if (features != null)
+        for (Class<? extends NamedFeature> feature : features)
+          enabledFeatureClasses.add(feature);
+      return this;
+    }
+
+    public CheckingFeature addDisabledClasses(
+        Class<? extends NamedFeature>... features) {
+      if (features != null)
+        for (Class<? extends NamedFeature> feature : features)
+          disabledFeatureClasses.add(feature);
+      return this;
+    }
+  }
+
+  private class FeatureReturningFalse extends CheckingFeature {
+    @Override
+    public boolean configure(FeatureContext context) {
+      super.configure(context);
+      // false returning feature is not to be registered
+      return false;
+    }
+  }
+
+  private class FeatureReturningTrue extends CheckingFeature {
+    @Override
+    public boolean configure(FeatureContext context) {
+      return super.configure(context);
+    }
+  }
+
+  private class FeatureReturningFalse1 extends FeatureReturningFalse {
+  };
+
+  private class FeatureReturningFalse2 extends FeatureReturningFalse {
+  };
+
+  private class FeatureReturningFalse3 extends FeatureReturningFalse {
+  };
+
+  private class FeatureReturningFalse4 extends FeatureReturningFalse {
+  };
+
+  private class FeatureReturningTrue1 extends FeatureReturningTrue {
+  };
+
+  private class FeatureReturningTrue2 extends FeatureReturningTrue {
+  };
+
+  private class FeatureReturningTrue3 extends FeatureReturningTrue {
+  };
+
+  private class FeatureReturningTrue4 extends FeatureReturningTrue {
+  };
+
+}
diff --git a/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/core/headers/HttpHeadersTest.java b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/core/headers/HttpHeadersTest.java
new file mode 100644
index 0000000..f37116e
--- /dev/null
+++ b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/core/headers/HttpHeadersTest.java
@@ -0,0 +1,208 @@
+/*
+ * Copyright (c) 2007, 2020 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 jakarta.ws.rs.tck.ee.rs.core.headers;
+
+import java.util.Arrays;
+import java.util.Date;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+
+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.Cookie;
+import jakarta.ws.rs.core.HttpHeaders;
+import jakarta.ws.rs.core.MediaType;
+import jakarta.ws.rs.core.MultivaluedMap;
+
+@Path(value = "/HeadersTest")
+public class HttpHeadersTest {
+
+  @Context
+  HttpHeaders hs;
+
+  StringBuffer sb;
+
+  @GET
+  @Path("/headers")
+  public String headersGet() {
+    sb = new StringBuffer();
+    List<String> myHeaders = Arrays.asList("Accept", "Content-Type");
+
+    try {
+      MultivaluedMap<String, String> rqhdrs = hs.getRequestHeaders();
+      Set<String> keys = rqhdrs.keySet();
+      sb.append("getRequestHeaders= ");
+      for (String header : myHeaders) {
+        if (keys.contains(header)) {
+          sb.append(
+              "Found " + header + ": " + hs.getRequestHeader(header) + "; ");
+        }
+      }
+    } catch (Throwable ex) {
+      sb.append("Unexpected exception thrown in getRequestHeaders: "
+          + ex.getMessage());
+      ex.printStackTrace();
+    }
+    return sb.toString();
+  }
+
+  @GET
+  @Path("/acl")
+  public String aclGet() {
+    sb = new StringBuffer();
+    try {
+      sb.append("Accept-Language");
+
+      List<Locale> acl = hs.getAcceptableLanguages();
+      sb.append("getLanguage= ");
+      for (Locale tmp : acl) {
+        sb.append(langToString(tmp)).append("; ");
+      }
+    } catch (Throwable ex) {
+      sb.append("Unexpected exception thrown in getAcceptableLanguages: "
+          + ex.getMessage());
+      ex.printStackTrace();
+    }
+    return sb.toString();
+  }
+
+  @GET
+  @Path("/amt")
+  public String amtGet() {
+    sb = new StringBuffer();
+    try {
+      sb.append("getAcceptableMediaTypes");
+      List<MediaType> acmts = hs.getAcceptableMediaTypes();
+
+      for (MediaType mt : acmts) {
+        sb.append(mt.getType());
+        sb.append("/");
+        sb.append(mt.getSubtype());
+      }
+    } catch (Throwable ex) {
+      sb.append("Unexpected exception thrown: " + ex.getMessage());
+      ex.printStackTrace();
+    }
+    return sb.toString();
+  }
+
+  @GET
+  @Path("/mt")
+  public String mtGet() {
+    sb = new StringBuffer();
+
+    try {
+      sb.append("getMediaType");
+      MediaType mt = hs.getMediaType();
+      if (mt != null) {
+        sb.append(mt.getType());
+        sb.append("/");
+        sb.append(mt.getSubtype());
+        sb.append(" ");
+
+        java.util.Map<java.lang.String, java.lang.String> pmap = mt
+            .getParameters();
+
+        sb.append("MediaType size=" + pmap.size());
+
+        Iterator<Entry<String, String>> k = pmap.entrySet().iterator();
+        while (k.hasNext()) {
+          Entry<String, String> next = k.next();
+          String key = next.getKey();
+          sb.append("Key " + key + "; Value " + next.getValue());
+        }
+
+        sb.append(mt.toString());
+
+        sb.append("MediaType= " + mt.toString() + "; ");
+      } else {
+        sb.append("MediaType= null; ");
+      }
+    } catch (Throwable ex) {
+      sb.append("Unexpected exception thrown: " + ex.getMessage());
+      ex.printStackTrace();
+    }
+    return sb.toString();
+  }
+
+  @GET
+  @Path("/cookie")
+  public String cookieGet() {
+    sb = new StringBuffer();
+
+    try {
+      sb.append("getCookies= ");
+      Map<String, Cookie> cookies = hs.getCookies();
+      sb.append("Cookie Size=" + cookies.size());
+
+      for (Entry<String, Cookie> entry : cookies.entrySet()) {
+        sb.append("key=" + entry.getKey() + "; value=" + entry.getValue());
+        Cookie c = entry.getValue();
+        sb.append("Cookie Name=" + c.getName());
+        sb.append("Cookie Value=" + c.getValue());
+        sb.append("Cookie Path=" + c.getPath());
+        sb.append("Cookie Domain=" + c.getDomain());
+        sb.append("Cookie Version=" + c.getVersion());
+
+      }
+    } catch (Throwable ex) {
+      sb.append("Unexpected exception thrown: " + ex.getMessage());
+      ex.printStackTrace();
+    }
+    return sb.toString();
+  }
+
+  @PUT
+  public String headersPlainPut(String nil) {
+    sb = new StringBuffer();
+    sb.append("Content-Language");
+    sb.append(langToString(hs.getLanguage()));
+    return sb.toString();
+  }
+
+  @POST
+  @Path("date")
+  public String date(@Context HttpHeaders headers, String nil) {
+    Date date = headers.getDate();
+    long time = date.getTime();
+    return String.valueOf(time);
+  }
+
+  @POST
+  @Path("headerstring")
+  public String headerString(@Context HttpHeaders headers, String headerName) {
+    String header = headers.getHeaderString(headerName);
+    return header;
+  }
+
+  @GET
+  @Path("length")
+  public String headerLength(@Context HttpHeaders headers) {
+    return String.valueOf(headers.getLength());
+  }
+
+  private static String langToString(Locale locale) {
+    return locale.toString().replace("_", "-");
+  }
+}
diff --git a/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/core/headers/JAXRSClientIT.java b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/core/headers/JAXRSClientIT.java
new file mode 100644
index 0000000..1d50c1d
--- /dev/null
+++ b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/core/headers/JAXRSClientIT.java
@@ -0,0 +1,302 @@
+/*
+ * Copyright (c) 2007, 2020 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 jakarta.ws.rs.tck.ee.rs.core.headers;
+
+import java.io.IOException;
+import java.text.DateFormat;
+import java.util.TimeZone;
+import java.io.InputStream;
+
+import jakarta.ws.rs.tck.common.client.JaxrsCommonClient;
+import jakarta.ws.rs.tck.common.provider.StringBean;
+import jakarta.ws.rs.tck.common.util.JaxrsUtil;
+import jakarta.ws.rs.tck.lib.util.TestUtil;
+
+import jakarta.ws.rs.client.ClientRequestContext;
+import jakarta.ws.rs.client.ClientRequestFilter;
+import jakarta.ws.rs.client.Entity;
+import jakarta.ws.rs.core.MediaType;
+import jakarta.ws.rs.core.Variant;
+
+import org.jboss.arquillian.junit5.ArquillianExtension;
+import org.jboss.arquillian.container.test.api.Deployment;
+import org.jboss.shrinkwrap.api.ShrinkWrap;
+import org.jboss.shrinkwrap.api.asset.StringAsset;
+import org.jboss.shrinkwrap.api.spec.WebArchive;
+import org.jboss.shrinkwrap.api.exporter.ZipExporter;
+
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assertions.fail;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.junit.jupiter.api.TestInfo;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.AfterEach;
+
+/*
+ * @class.setup_props: webServerHost;
+ *                     webServerPort;
+ */
+@ExtendWith(ArquillianExtension.class)
+public class JAXRSClientIT extends JaxrsCommonClient {
+
+  private static final long serialVersionUID = -5727774504018187299L;
+
+  public JAXRSClientIT() {
+    setup();
+    setContextRoot("/jaxrs_ee_core_headers_web/HeadersTest");
+  }
+
+  
+  @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{
+
+    InputStream inStream = JAXRSClientIT.class.getClassLoader().getResourceAsStream("jakarta/ws/rs/tck/ee/rs/core/headers/web.xml.template");
+    String webXml = editWebXmlString(inStream);
+
+    WebArchive archive = ShrinkWrap.create(WebArchive.class, "jaxrs_ee_core_headers_web.war");
+    archive.addClasses(TSAppConfig.class, HttpHeadersTest.class);
+    archive.setWebXML(new StringAsset(webXml));
+    return archive;
+
+  }
+
+
+  /* Run test */
+  /*
+   * @testName: cookieTest
+   * 
+   * @assertion_ids: JAXRS:SPEC:3.6; JAXRS:JAVADOC:77;
+   * 
+   * @test_Strategy: Client invokes GET request on root resource at
+   * /HeadersTest/cookie with Cookie set; Verify that all Cookies properties are
+   * set by the request
+   */
+  @Test
+  public void cookieTest() throws Fault {
+    setProperty(Property.REQUEST_HEADERS,
+        "Cookie: $Version=1; name1=value1; $Domain=" + _hostname
+            + "; $Path=/jaxrs_ee_core_headers_web");
+    setProperty(Property.REQUEST, buildRequest(Request.GET, "cookie"));
+    setProperty(Property.SEARCH_STRING,
+        "getCookie|Cookie Name=name1|Cookie Value=value1"
+            + "|Cookie Path=/jaxrs_ee_core_headers_web" + "|Cookie Domain="
+            + "|Cookie Version=1");
+    invoke();
+  }
+
+  /*
+   * @testName: acceptLanguageTest
+   * 
+   * @assertion_ids: JAXRS:SPEC:3.6; JAXRS:JAVADOC:75;
+   * 
+   * @test_Strategy: Client invokes GET request on root resource at
+   * /HeadersTes/acl with Language Header set; Verify that HttpHeaders got the
+   * property set by the request
+   */
+  @Test
+  public void acceptLanguageTest() throws Fault {
+    setProperty(Property.REQUEST_HEADERS,
+        buildAccept(MediaType.TEXT_PLAIN_TYPE));
+    setProperty(Property.REQUEST_HEADERS, "Accept-Language:en-US");
+    setProperty(Property.REQUEST, buildRequest(Request.GET, "acl"));
+    setProperty(Property.SEARCH_STRING, "Accept-Language|en-US");
+    invoke();
+  }
+
+  /*
+   * @testName: contentLanguageTest
+   * 
+   * @assertion_ids: JAXRS:SPEC:3.6; JAXRS:JAVADOC:78;
+   * 
+   * @test_Strategy: Client invokes PUT request on root resource at /HeadersTest
+   * with Language Header set; Verify that HttpHeaders got the property set by
+   * the request
+   */
+  @Test
+  public void contentLanguageTest() throws Fault {
+    setProperty(Property.REQUEST_HEADERS,
+        buildAccept(MediaType.TEXT_PLAIN_TYPE));
+    Variant variant = new Variant(MediaType.WILDCARD_TYPE, "en-US", null);
+    Entity<String> entity = Entity.entity("anything", variant);
+    setRequestContentEntity(entity);
+    setProperty(Property.REQUEST, buildRequest(Request.PUT, ""));
+    setProperty(Property.SEARCH_STRING_IGNORE_CASE, "Content-Language|en-US");
+    invoke();
+  }
+
+  /*
+   * @testName: mediaTypeTest
+   * 
+   * @assertion_ids: JAXRS:SPEC:3.6; JAXRS:SPEC:33.8; JAXRS:JAVADOC:79;
+   * 
+   * @test_Strategy: Client invokes GET request on a sub resource at
+   * /HeadersTest/mt with Content-Type Header set; Verify that HttpHeaders got
+   * the property set by the request
+   */
+  @Test
+  public void mediaTypeTest() throws Fault {
+    setProperty(Property.REQUEST_HEADERS,
+        "Content-Type:application/xml;charset=utf8");
+    setProperty(Property.REQUEST, buildRequest(Request.GET, "mt"));
+    setProperty(Property.SEARCH_STRING, "getMediaType|application/xml"
+        + "|MediaType size=1|Key charset|Value utf8");
+    invoke();
+  }
+
+  /*
+   * @testName: mediaTypeAcceptableTest
+   * 
+   * @assertion_ids: JAXRS:SPEC:3.6; JAXRS:JAVADOC:76;
+   * 
+   * @test_Strategy: Client invokes GET request on a sub resource at
+   * /HeadersTest/amt with Accept MediaType Header set; Verify that HttpHeaders
+   * got the property set by the request
+   */
+  @Test
+  public void mediaTypeAcceptableTest() throws Fault {
+    setProperty(Property.REQUEST_HEADERS,
+        "Accept:text/*, text/html, text/html;level=1, */*");
+    setProperty(Property.REQUEST, buildRequest(Request.GET, "amt"));
+    setProperty(Property.UNORDERED_SEARCH_STRING,
+        "getAcceptableMediaTypes|text/*|text/html|text/html|*/*");
+    invoke();
+  }
+
+  /*
+   * @testName: requestHeadersTest
+   * 
+   * @assertion_ids: JAXRS:SPEC:3.6; JAXRS:SPEC:33.8; JAXRS:SPEC:40;
+   * JAXRS:JAVADOC:80; JAXRS:JAVADOC:81;
+   * 
+   * @test_Strategy: Client invokes GET request on a sub resource at
+   * /HeadersTest/sub2 with Accept MediaType and Content-Type Headers set;
+   * Verify that HttpHeaders got the property set by the request
+   */
+  @Test
+  public void requestHeadersTest() throws Fault {
+    setProperty(Property.REQUEST_HEADERS,
+        "Accept:text/*, text/html, text/html;level=1, */*");
+    setProperty(Property.REQUEST_HEADERS,
+        "Content-Type:application/xml;charset=utf8");
+    setProperty(Property.REQUEST, buildRequest(Request.GET, "headers"));
+    setProperty(Property.SEARCH_STRING, "getRequestHeaders=|Accept:|text/*");
+    setProperty(Property.SEARCH_STRING, "text/html|text/html|*/*");
+    setProperty(Property.SEARCH_STRING, "Content-Type:|application/xml");
+    setProperty(Property.SEARCH_STRING, "charset=utf8");
+    invoke();
+  }
+
+  /*
+   * @testName: getDateTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:779;
+   * 
+   * @test_Strategy: Get message date
+   */
+  @Test
+  public void getDateTest() throws Fault {
+    long currentTime = System.currentTimeMillis();
+    DateFormat format = JaxrsUtil.createDateFormat(TimeZone.getTimeZone("GMT"));
+    String gmt = format.format(currentTime);
+
+    setProperty(Property.REQUEST, buildRequest(Request.POST, "date"));
+    setProperty(Property.CONTENT, "getDate");
+    setProperty(Property.REQUEST_HEADERS, "Date:" + gmt);
+    invoke();
+    long responseTime = Long.parseLong(getResponseBody());
+    boolean check = Math.abs(currentTime - responseTime) < 1001L;
+    assertTrue(check, "HttpHeaders.getDate()="+ responseTime+
+        "differs from expected"+ currentTime+ "by more than 1000 ms.");
+    logMsg("#getDate() returned expected Date instance");
+  }
+
+  /*
+   * @testName: getHeaderStringTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:780;
+   * 
+   * @test_Strategy: Get a HTTP header as a single string value.
+   */
+  @Test
+  public void getHeaderStringTest() throws Fault {
+    String[] headers = { "askdjb", "ksadbva", "klwiaslkfn", "klwvasbk" };
+    for (String header : headers) {
+      setProperty(Property.REQUEST, buildRequest(Request.POST, "headerstring"));
+      setProperty(Property.CONTENT, header);
+      setProperty(Property.REQUEST_HEADERS, header + ":" + header + header);
+      setProperty(Property.SEARCH_STRING, header + header);
+      invoke();
+    }
+    logMsg("#getHeaderString() returned expected header values");
+  }
+
+  /*
+   * @testName: getHeaderStringUsesToStringTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:780;
+   * 
+   * @test_Strategy: Get a HTTP header as a single string value. Each single
+   * header value is converted to String using its toString method if a header
+   * delegate is not available.
+   */
+  @Test
+  public void getHeaderStringUsesToStringTest() throws Fault {
+    final StringBean bean = new StringBean("bean");
+    ClientRequestFilter filter = new ClientRequestFilter() {
+      @Override
+      public void filter(ClientRequestContext ctx) throws IOException {
+        ctx.getHeaders().add(bean.get(), bean);
+      }
+    };
+    setProperty(Property.REQUEST, buildRequest(Request.POST, "headerstring"));
+    setProperty(Property.CONTENT, bean.get());
+    addProvider(filter);
+    setProperty(Property.SEARCH_STRING, bean.toString());
+    invoke();
+    logMsg(
+        "#getHeaderString() returned expected header converted by toString() method");
+  }
+
+  /*
+   * @testName: getLengthTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:781;
+   * 
+   * @test_Strategy: Get Content-Length value
+   */
+  @Test
+  public void getLengthTest() throws Fault {
+    setProperty(Property.REQUEST, buildRequest(Request.GET, "length"));
+    invoke();
+    String body = getResponseBody();
+    assertTrue(body != null && body.length() > 0, "Nothing returned");
+    long length = Long.parseLong(body);
+    assertTrue(length != 0, "Nothing returned");
+    logMsg("#getLength() returned expected length", body);
+  }
+}
diff --git a/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/core/headers/TSAppConfig.java b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/core/headers/TSAppConfig.java
new file mode 100644
index 0000000..0c5538c
--- /dev/null
+++ b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/core/headers/TSAppConfig.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2007, 2020 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 jakarta.ws.rs.tck.ee.rs.core.headers;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import jakarta.ws.rs.core.Application;
+
+/**
+ *
+ * @author diannejiao
+ */
+public class TSAppConfig extends Application {
+
+  public java.util.Set<java.lang.Class<?>> getClasses() {
+    Set<Class<?>> resources = new HashSet<Class<?>>();
+    resources.add(HttpHeadersTest.class);
+    return resources;
+  }
+}
diff --git a/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/core/response/AnnotatedClass.java b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/core/response/AnnotatedClass.java
new file mode 100644
index 0000000..0da365b
--- /dev/null
+++ b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/core/response/AnnotatedClass.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2012, 2020 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 jakarta.ws.rs.tck.ee.rs.core.response;
+
+import jakarta.ws.rs.Consumes;
+import jakarta.ws.rs.ext.Provider;
+
+@Provider
+@Consumes
+/**
+ * This is the dummy class to get annotations from it
+ */
+public abstract class AnnotatedClass {
+
+}
diff --git a/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/core/response/CorruptedInputStream.java b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/core/response/CorruptedInputStream.java
new file mode 100644
index 0000000..91979eb
--- /dev/null
+++ b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/core/response/CorruptedInputStream.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2012, 2018 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 jakarta.ws.rs.tck.ee.rs.core.response;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.util.concurrent.atomic.AtomicInteger;
+
+public class CorruptedInputStream extends ByteArrayInputStream {
+
+  AtomicInteger atomic;
+
+  private boolean corrupted = false;
+
+  public static final int CLOSEVALUE = 999;
+
+  public static final String IOETEXT = "CorruptedInputStream tck test IOException";
+
+  public CorruptedInputStream(byte[] buf, AtomicInteger atomic) {
+    super(buf);
+    this.atomic = atomic;
+  }
+
+  @Override
+  public void close() throws IOException {
+    if (corrupted) {
+      atomic.set(CLOSEVALUE);
+      throw new IOException(IOETEXT);
+    }
+    super.close();
+  }
+
+  public boolean isCorrupted() {
+    return corrupted;
+  }
+
+  public void setCorrupted(boolean corrupted) {
+    this.corrupted = corrupted;
+  }
+
+}
diff --git a/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/core/response/DateReaderWriter.java b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/core/response/DateReaderWriter.java
new file mode 100644
index 0000000..0d83139
--- /dev/null
+++ b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/core/response/DateReaderWriter.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2012, 2020 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 jakarta.ws.rs.tck.ee.rs.core.response;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+import java.util.Date;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import jakarta.ws.rs.Consumes;
+import jakarta.ws.rs.WebApplicationException;
+import jakarta.ws.rs.core.MediaType;
+import jakarta.ws.rs.core.MultivaluedMap;
+import jakarta.ws.rs.ext.MessageBodyReader;
+import jakarta.ws.rs.ext.MessageBodyWriter;
+import jakarta.ws.rs.ext.Provider;
+
+@Provider
+public class DateReaderWriter
+    implements MessageBodyReader<Date>, MessageBodyWriter<Date> {
+
+  public static final int ANNOTATION_NONE = 0;
+
+  public static final int ANNOTATION_CONSUMES = 1 << 2;
+
+  public static final int ANNOTATION_PROVIDER = 1 << 3;
+
+  public static final int ANNOTATION_UNKNOWN = 1 << 7;
+
+  private AtomicInteger atom;
+
+  public DateReaderWriter(AtomicInteger atom) {
+    super();
+    this.atom = atom;
+  }
+
+  @Override
+  public long getSize(Date arg0, Class<?> arg1, Type arg2, Annotation[] arg3,
+      MediaType arg4) {
+    return String.valueOf(Long.MAX_VALUE).length();
+  }
+
+  @Override
+  public boolean isWriteable(Class<?> arg0, Type arg1, Annotation[] arg2,
+      MediaType arg3) {
+    return arg0 == Date.class;
+  }
+
+  @Override
+  public void writeTo(Date date, Class<?> arg1, Type arg2, Annotation[] arg3,
+      MediaType arg4, MultivaluedMap<String, Object> arg5, OutputStream stream)
+      throws IOException, WebApplicationException {
+    parseAnnotations(arg3);
+    stream.write(String.valueOf(date.getTime()).getBytes());
+  }
+
+  @Override
+  public boolean isReadable(Class<?> arg0, Type arg1, Annotation[] arg2,
+      MediaType arg3) {
+    return isWriteable(arg0, arg1, arg2, arg3);
+  }
+
+  @Override
+  public Date readFrom(Class<Date> arg0, Type arg1, Annotation[] arg2,
+      MediaType arg3, MultivaluedMap<String, String> arg4, InputStream arg5)
+      throws IOException, WebApplicationException {
+    parseAnnotations(arg2);
+
+    InputStreamReader reader = new InputStreamReader(arg5);
+    BufferedReader br = new BufferedReader(reader);
+    long date = Long.parseLong(br.readLine());
+    return new Date(date);
+  }
+
+  protected void parseAnnotations(Annotation[] annotations) {
+    int value = ANNOTATION_NONE;
+    if (annotations != null)
+      for (Annotation annotation : annotations)
+        if (annotation.annotationType() == Consumes.class)
+          value |= ANNOTATION_CONSUMES;
+        else if (annotation.annotationType() == Provider.class)
+          value |= ANNOTATION_PROVIDER;
+        else
+          value |= ANNOTATION_UNKNOWN;
+    atom.set(value);
+  }
+}
diff --git a/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/core/response/JAXRSClientIT.java b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/core/response/JAXRSClientIT.java
new file mode 100644
index 0000000..dd54287
--- /dev/null
+++ b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/core/response/JAXRSClientIT.java
@@ -0,0 +1,1825 @@
+/*
+ * Copyright (c) 2007, 2020 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 jakarta.ws.rs.tck.ee.rs.core.response;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Reader;
+import java.lang.annotation.Annotation;
+import java.net.URI;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import jakarta.ws.rs.tck.common.client.JaxrsCommonClient;
+import jakarta.ws.rs.tck.common.util.JaxrsUtil;
+import jakarta.ws.rs.tck.lib.util.TestUtil;
+
+import jakarta.ws.rs.ProcessingException;
+import jakarta.ws.rs.client.Client;
+import jakarta.ws.rs.client.ClientBuilder;
+import jakarta.ws.rs.client.ClientRequestContext;
+import jakarta.ws.rs.client.ClientResponseContext;
+import jakarta.ws.rs.client.ClientResponseFilter;
+import jakarta.ws.rs.client.WebTarget;
+import jakarta.ws.rs.core.EntityTag;
+import jakarta.ws.rs.core.GenericType;
+import jakarta.ws.rs.core.HttpHeaders;
+import jakarta.ws.rs.core.Link;
+import jakarta.ws.rs.core.Link.Builder;
+import jakarta.ws.rs.core.MediaType;
+import jakarta.ws.rs.core.MultivaluedMap;
+import jakarta.ws.rs.core.NewCookie;
+import jakarta.ws.rs.core.Response;
+import jakarta.ws.rs.core.Response.Status;
+import jakarta.ws.rs.core.Response.StatusType;
+
+import org.jboss.arquillian.junit5.ArquillianExtension;
+import org.jboss.arquillian.container.test.api.Deployment;
+import org.jboss.shrinkwrap.api.ShrinkWrap;
+import org.jboss.shrinkwrap.api.asset.StringAsset;
+import org.jboss.shrinkwrap.api.spec.WebArchive;
+import org.jboss.shrinkwrap.api.exporter.ZipExporter;
+
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.fail;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.junit.jupiter.api.TestInfo;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.AfterEach;
+
+/**
+ * Some tests are the same as the tests in api.rs.core package except how the
+ * Response is created. This is because implementation of inbound and outbound
+ * Response differ.
+ */
+@ExtendWith(ArquillianExtension.class)
+public class JAXRSClientIT extends JaxrsCommonClient {
+
+  private static final long serialVersionUID = 4182256439207983256L;
+
+  public JAXRSClientIT() {
+    setup();
+    setContextRoot("/jaxrs_ee_core_response_web/resource");
+    setPrintEntity(true);
+  }
+
+  
+  @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{
+
+    InputStream inStream = JAXRSClientIT.class.getClassLoader().getResourceAsStream("jakarta/ws/rs/tck/ee/rs/core/response/web.xml.template");
+    String webXml = editWebXmlString(inStream);
+
+    WebArchive archive = ShrinkWrap.create(WebArchive.class, "jaxrs_ee_core_response_web.war");
+    archive.addClasses(TSAppConfig.class, jakarta.ws.rs.tck.common.util.JaxrsUtil.class, ResponseTest.class, CorruptedInputStream.class, jakarta.ws.rs.tck.common.provider.StringBean.class, jakarta.ws.rs.tck.common.provider.StringBeanHeaderDelegate.class, jakarta.ws.rs.tck.common.provider.StringBeanEntityProvider.class, jakarta.ws.rs.tck.common.provider.StringBeanRuntimeDelegate.class, jakarta.ws.rs.tck.common.provider.PrintingErrorHandler.class);
+    archive.setWebXML(new StringAsset(webXml));
+    return archive;
+
+  }
+
+
+  /*
+   * @class.setup_props: webServerHost; webServerPort; ts_home;
+   */
+  /* Run test */
+
+  /*
+   * @testName: statusTest
+   * 
+   * @assertion_ids: JAXRS:SPEC:14.2; JAXRS:JAVADOC:131; JAXRS:JAVADOC:139;
+   * 
+   * @test_Strategy: Client send request to a resource, verify that correct
+   * status code returned
+   *
+   */
+  @Test
+  public void statusTest() throws Fault {
+    for (Response.Status status : Response.Status.values()) {
+      if (status == Status.RESET_CONTENT)
+        continue; // it takes some time
+      setProperty(Property.STATUS_CODE, getStatusCode(status));
+      invokeGet("status?status=" + getStatusCode(status));
+    }
+  }
+
+  /*
+   * @testName: bufferEntityBuffersDataTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:838;
+   * 
+   * @test_Strategy: Buffer the message entity. In case the message entity is
+   * backed by an unconsumed entity input stream, all the bytes of the original
+   * entity input stream are read and stored locally.
+   * 
+   * This operation is idempotent, i.e. it can be invoked multiple times with
+   * the same effect which also means that calling the bufferEntity() method on
+   * an already buffered (and thus closed) message instance is legal and has no
+   * further effect.
+   */
+  @Test
+  public void bufferEntityBuffersDataTest() throws Fault {
+    Response response = invokeGet("entity");
+    boolean buffer = response.bufferEntity();
+    assertTrue(buffer, "#bufferEntity() did not buffer opened stream");
+    buffer = response.bufferEntity();
+    assertTrue(buffer, "#bufferEntity() is not idempotent");
+
+    String read = response.readEntity(String.class);
+    assertTrue(read.equals(ResponseTest.ENTITY), "Read entity"+ read+
+        "instead of"+ ResponseTest.ENTITY);
+    read = response.readEntity(String.class);
+    assertTrue(read.equals(ResponseTest.ENTITY), "Read entity"+ read+
+        "instead of"+ ResponseTest.ENTITY);
+    logMsg("#bufferEntity did buffer opened stream as expected");
+  }
+
+  /*
+   * @testName: bufferEntityThrowsExceptionTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:838;
+   * 
+   * @test_Strategy: Throws: ProcessingException - if there was an error while
+   * buffering the entity input stream.
+   */
+  @Test
+  public void bufferEntityThrowsExceptionTest() throws Fault {
+    setCorruptedStream(); // the error is on buffering, which calls close()
+    Response response = invokeGet("corrupted");
+    catchCorruptedStreamExceptionOnBufferEntity(response);
+    logMsg("ProcessingException has been thrown as expected");
+  }
+
+  /*
+   * @testName: bufferEntityThrowsIllegalStateExceptionTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:838;
+   * 
+   * @test_Strategy: throws IllegalStateException - in case the response has
+   * been #close() closed.
+   */
+  @Test
+  public void bufferEntityThrowsIllegalStateExceptionTest() throws Fault {
+    Response response = invokeGet("entity");
+    response.close();
+    try {
+      response.bufferEntity();
+      fault("buffer entity did not throw IllegalStateException when closed");
+    } catch (IllegalStateException e) {
+      logMsg("#bufferEntity throws IllegalStateException as expected");
+    }
+  }
+
+  /*
+   * @testName: closeTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:841;
+   * 
+   * @test_Strategy: Close the message entity input stream (if available and
+   * open). This operation is idempotent, i.e. it can be invoked multiple times
+   * with the same effect which also means that calling the method on an already
+   * closed message instance is legal and has no further effect
+   */
+  @Test
+  public void closeTest() throws Fault {
+    // make new Client, the one from super class calls bufferEntity()
+    Client client = ClientBuilder.newClient();
+    WebTarget target = client
+        .target("http://" + _hostname + ":" + _port + getContextRoot())
+        .path("entity");
+    Response response = target.request(MediaType.TEXT_PLAIN_TYPE).buildGet()
+        .invoke();
+    response.close(); // calling the method on an already closed message
+    response.close(); // instance is legal
+
+    // Any attempts to manipulate (read, get, buffer) a message entity on a
+    // closed response will result in an IllegalStateException being thrown
+    try {
+      String entity = response.readEntity(String.class);
+      assertTrue(false, "IllegalStateException has not been thrown when"+
+          "#close() and #readEntity() but entity"+ entity+ "has been read");
+    } catch (IllegalStateException e) {
+      logMsg(
+          "#close() closed the stream, and consecutive reading threw IllegalStateException as expected");
+    }
+  }
+
+  /*
+   * @testName: closeThrowsExceptionWhenErrorTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:841;
+   * 
+   * @test_Strategy: throws ProcessingException - if there is an error closing
+   * the response.
+   */
+  @Test
+  public void closeThrowsExceptionWhenErrorTest() throws Fault {
+    setCorruptedStream();
+    Response response = invokeGet("corrupted");
+    try {
+      response.close(); // response.close should call stream.close()
+      assertTrue(false, "ProcessingException has not been thrown when"+
+          "CorruptedInputStream#close()");
+    } catch (ProcessingException e) {
+      // it is corrupted, #close throws IOException
+      assertNotNull(e.getCause(), "unknown exception thrown", e);
+      assertEquals(e.getCause().getMessage(), CorruptedInputStream.IOETEXT,
+          "unknown exception thrown", e);
+      logMsg("#close() threw ProcessingException as expected");
+    }
+  }
+
+  /*
+   * @testName: getAllowedMethodsTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:843;
+   * 
+   * @test_Strategy: Get the allowed HTTP methods from the Allow HTTP header.
+   */
+  @Test
+  public void getAllowedMethodsTest() throws Fault {
+    String allowed = Request.POST.name() + " " + Request.TRACE.name();
+    Response response = invokePost("allowedmethods", allowed);
+    Set<String> set = response.getAllowedMethods();
+    String methods = JaxrsUtil.iterableToString(";", set);
+    assertContainsIgnoreCase(methods, Request.POST.name(), Request.POST.name(),
+        "method has not been found");
+    assertContainsIgnoreCase(methods, Request.TRACE.name(),
+        Request.TRACE.name(), "method has not been found");
+    assertTrue(
+        methods.length() < Request.TRACE.name().length()
+            + Request.POST.name().length() + 3,
+        "Request contains some additional methods then expected"+ methods);
+    logMsg("#getAllowedMethods returned expected methods", methods);
+  }
+
+  /*
+   * @testName: getCookiesTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:844;
+   * 
+   * @test_Strategy: Get any new cookies set on the response message.
+   */
+  @Test
+  public void getCookiesTest() throws Fault {
+    Response response = invokeGet("cookies");
+    // getCookies test
+    Map<String, NewCookie> map = response.getCookies();
+    for (Entry<String, NewCookie> entry : map.entrySet()) {
+      String key = entry.getKey();
+      String value = entry.getValue().getValue();
+      if (key.equals("c1"))
+        assertEquals(value, "v1", value, "does not match expected v1");
+      else if (key.equals("c2"))
+        assertEquals(value, "v2", value, "does not match expected v2");
+      else
+        fault("Got unknown cookie", entry.getKey());
+    }
+
+    logMsg("#getCookies returned expected cookies");
+  }
+
+  /*
+   * @testName: getCookiesIsImmutableTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:844;
+   * 
+   * @test_Strategy: returns a read-only map of cookie name (String) to Cookie.
+   */
+  @Test
+  public void getCookiesIsImmutableTest() throws Fault {
+    NewCookie cookie3 = new NewCookie("c3", "v3");
+    Response response = invokeGet("cookies");
+    // getCookies test
+    Map<String, NewCookie> map;
+    try {
+      map = response.getCookies();
+      map.put("c3", cookie3);
+    } catch (Exception e) {
+      // can throw an exception or nothing or return a copy map
+    }
+    map = response.getCookies();
+    assertFalse(map.containsKey("c3"), "getCookies is not read-only returned"+
+        map.get("c3"));
+    logMsg("#getCookies is read-only as expected");
+  }
+
+  /*
+   * @testName: getDateTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:845;
+   * 
+   * @test_Strategy: Get message date.
+   */
+  @Test
+  public void getDateTest() throws Fault {
+    long date = getCurrentTimeMillis();
+    Response response = invokePost("date", String.valueOf(date));
+    long responseDate = response.getDate().getTime();
+    // assertEqualsLong(date, responseDate, "Original date", date,
+    // "and response#getDate()", responseDate, "differs");
+    // int TC, the Date settings is overriden by underlaying containers
+    // But getDate is to be tested, not setDate, hence
+    assertTrue(Math.abs(responseDate - date) < (10 * 60 * 1000),
+        "#getDate() returned time that differes by more than 10 minutes");
+    logMsg("#getDate matches the Date HTTP header");
+  }
+
+  /*
+   * @testName: getEntityThrowsIllegalStateExceptionTestWhenClosed
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:123;
+   * 
+   * @test_Strategy: if the entity was previously fully consumed as an
+   * InputStream input stream, or if the response has been #close() closed.
+   */
+  @Test
+  public void getEntityThrowsIllegalStateExceptionTestWhenClosed()
+      throws Fault {
+    Response response = invokeGet("entity");
+    response.close();
+    try {
+      Object entity = response.getEntity();
+      fault("No exception has been thrown, entity=", entity);
+    } catch (IllegalStateException e) {
+      logMsg("#getEntity throws IllegalStateException as expected", e);
+    }
+  }
+
+  /*
+   * @testName: getEntityThrowsIllegalStateExceptionWhenConsumedTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:123;
+   * 
+   * @test_Strategy: if the entity was previously fully consumed as an
+   * InputStream input stream, or if the response has been #close() closed.
+   */
+  @Test
+  public void getEntityThrowsIllegalStateExceptionWhenConsumedTest()
+      throws Fault {
+    Response response = invokeGet("entity");
+    response.readEntity(String.class);
+    try {
+      Object entity = response.getEntity();
+      fault("No exception has been thrown entity=", entity);
+    } catch (IllegalStateException e) {
+      logMsg("#getEntity throws IllegalStateException as expected", e);
+    }
+  }
+
+  /*
+   * @testName: getEntityTagTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:847;
+   * 
+   * @test_Strategy: Get the entity tag.
+   */
+  @Test
+  public void getEntityTagTest() throws Fault {
+    String tag = "ABCDEF0123456789";
+    setProperty(Property.STATUS_CODE, getStatusCode(Status.NOT_MODIFIED));
+    Response response = invokePost("entitytag", tag);
+    EntityTag responseTag = response.getEntityTag();
+    assertEquals(tag, responseTag.getValue(), "response#getEntityTag()",
+        responseTag.getValue(), "is unequal to expected EntityTag", tag);
+    logMsg("#getEntityTag is", responseTag, "as expected");
+  }
+
+  /*
+   * @testName: getEntityTagNotPresentTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:847;
+   * 
+   * @test_Strategy: Get null if not present.
+   */
+  @Test
+  public void getEntityTagNotPresentTest() throws Fault {
+    ResponseHeaderValue<EntityTag> value = new ResponseHeaderValue<>();
+    addProvider(new HeaderNotPresent<EntityTag>(value) {
+      @Override
+      protected void setHeader(ClientResponseContext responseContext,
+          ResponseHeaderValue<EntityTag> header) {
+        header.value = responseContext.getEntityTag();
+      }
+    });
+
+    Response response = invokePost("entitytag", null);
+    EntityTag responseTag = response.getEntityTag();
+    assertHeaderNull(responseTag, value, "getEntityTag");
+  }
+
+  /*
+   * @testName: getHeadersTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:848;
+   * 
+   * @test_Strategy: Get view of the response headers and their object values.
+   */
+  @Test
+  public void getHeadersTest() throws Fault {
+    Response response = invokePost("headers", "notnull");
+    logMsg("Found following objects:");
+    logMsg((Object[]) JaxrsCommonClient.getMetadata(response.getHeaders()));
+
+    MultivaluedMap<String, Object> headers = response.getHeaders();
+    String header = null;
+
+    header = headers.getFirst(HttpHeaders.CACHE_CONTROL).toString();
+    assertContainsIgnoreCase(header, "no-transform",
+        "Cache-Control:no-transform has not been found");
+
+    header = headers.getFirst(HttpHeaders.SET_COOKIE).toString();
+    assertContainsIgnoreCase(header, "cookie=eikooc",
+        "Set-Cookie:cookie=eikooc has not been found");
+
+    header = headers.getFirst(HttpHeaders.CONTENT_ENCODING).toString();
+    assertContainsIgnoreCase(header, "gzip",
+        "Content-Encoding:gzip has not been found");
+
+    header = headers.getFirst(HttpHeaders.EXPIRES).toString();
+    assertNotNull(header, "Expires has not been found");
+
+    header = headers.getFirst(HttpHeaders.CONTENT_LANGUAGE).toString();
+    assertContainsIgnoreCase(langToString(header),
+        langToString(Locale.CANADA_FRENCH), "Content-Language:",
+        langToString(Locale.CANADA_FRENCH), "has not been found");
+
+    Object noHeader = headers.getFirst("unknown");
+    assertNull(noHeader, "Unknown header has been found", header);
+  }
+
+  /*
+   * @testName: getHeadersUsingHeaderDelegateTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:848;
+   * 
+   * @test_Strategy: Get view of the response headers and their object values.
+   */
+  @Test
+  public void getHeadersUsingHeaderDelegateTest() throws Fault {
+    invokeGet("setstringbeanruntime");
+
+    Response response = invokePost("headerstring", "notnull");
+    String[] metadata = JaxrsCommonClient.getMetadata(response.getHeaders());
+    logMsg("Received:");
+    logMsg((Object[]) metadata);
+    String headers = JaxrsUtil.iterableToString(";", (Object[]) metadata);
+    for (int i = 1; i != 4; i++) {
+      String header = "s" + i + ":s" + i;
+      assertContainsIgnoreCase(headers, header, "Expected header", header,
+          "was not found in received headers", headers);
+    }
+    logMsg("Received expected headers", headers);
+
+    invokeGet("setoriginalruntime");
+  }
+
+  /*
+   * @testName: getHeadersIsMutableTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:848;
+   * 
+   * @test_Strategy: Get view of the response headers and their object values.
+   * Changes in the underlying header data are reflected in this view.
+   */
+  @Test
+  public void getHeadersIsMutableTest() throws Fault {
+    String header = "header";
+    Response response = invokePost("headers", null);
+    MultivaluedMap<String, Object> headers = response.getHeaders();
+    Object value = headers.getFirst(header);
+    assertNull(value, "Unexpected header", header, ":", value);
+    headers.add(header, header);
+    headers = response.getHeaders();
+    value = headers.getFirst(header);
+    assertContainsIgnoreCase(value, header, "Unexpected header value", header,
+        ":", value);
+    logMsg("getHeaders is mutable");
+  }
+
+  /*
+   * @testName: getHeaderStringTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:849;
+   * 
+   * @test_Strategy: Get a message header as a single string value.
+   */
+  @Test
+  public void getHeaderStringTest() throws Fault {
+    Response response = invokePost("headers", "headerstring");
+    logMsg("Found following objects:");
+    logMsg((Object[]) JaxrsCommonClient.getMetadata(response.getHeaders()));
+    assertContainsIgnoreCase(
+        response.getHeaderString(HttpHeaders.CACHE_CONTROL), "no-transform",
+        "Cache-Control:no-transform has not been found");
+    assertContainsIgnoreCase(response.getHeaderString(HttpHeaders.SET_COOKIE),
+        "cookie=eikooc", "Set-Cookie:cookie=eikooc has not been found");
+    assertContainsIgnoreCase(
+        response.getHeaderString(HttpHeaders.CONTENT_ENCODING), "gzip",
+        "Content-Encoding:gzip has not been found");
+    assertNotNull(response.getHeaderString(HttpHeaders.EXPIRES),
+        "Expires has not been found");
+    assertContainsIgnoreCase(
+        langToString(response.getHeaderString("Content-Language")),
+        langToString(Locale.CANADA_FRENCH), "Content-Language:",
+        langToString(Locale.CANADA_FRENCH), "has not been found");
+    assertNull(response.getHeaderString("unknown"),
+        "Unknown header has been found", response.getHeaderString("unknown"));
+  }
+
+  /*
+   * @testName: getHeaderStringUsingHeaderDelegateTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:849;
+   * 
+   * @test_Strategy: Get a message header as a single string value. Each single
+   * header value is converted to String using a RuntimeDelegate.HeaderDelegate
+   * or using its toString
+   */
+  @Test
+  public void getHeaderStringUsingHeaderDelegateTest() throws Fault {
+    invokeGet("setstringbeanruntime");
+
+    Response response = invokePost("headerstring", "delegate");
+    String header = response.getHeaderString("s3");
+    assertContainsIgnoreCase(header, "s3", "Header", "s3",
+        "has unexpected value", header);
+    logMsg("HeaderDelegate is used for header as expected");
+
+    invokeGet("setoriginalruntime");
+  }
+
+  /*
+   * @testName: getHeaderStringUsingToStringTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:849;
+   * 
+   * @test_Strategy: Get a message header as a single string value. Each single
+   * header value is converted to String using a RuntimeDelegate.HeaderDelegate
+   * or using its toString
+   */
+  @Test
+  public void getHeaderStringUsingToStringTest() throws Fault {
+    Response response = invokePost("headerstring", "toString");
+    String header = response.getHeaderString("s1");
+    assertContainsIgnoreCase(header, "s1", "Header s1 has unexpected value",
+        header);
+
+    header = response.getHeaderString("s2");
+    assertContainsIgnoreCase(header, "s2", "Header s2 has unexpected value",
+        header);
+
+    logMsg("toString method is used as expected");
+  }
+
+  /*
+   * @testName: getLanguageTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:850;
+   * 
+   * @test_Strategy: Get the language of the message entity.
+   */
+  @Test
+  public void getLanguageTest() throws Fault {
+    Response response = invokePost("language",
+        Locale.CANADA_FRENCH.getCountry());
+    Locale locale = response.getLanguage();
+    assertTrue(Locale.CANADA_FRENCH.equals(locale), "Locale"+
+        Locale.CANADA_FRENCH+ "does NOT match response#getLocale()"+ locale);
+    logMsg("#getLocale matches the Content-Language HTTP header");
+  }
+
+  /*
+   * @testName: getLanguageNotPresentTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:850;
+   * 
+   * @test_Strategy: Get null if not present.
+   */
+  @Test
+  public void getLanguageNotPresentTest() throws Fault {
+    ResponseHeaderValue<Locale> value = new ResponseHeaderValue<>();
+    addProvider(new HeaderNotPresent<Locale>(value) {
+      @Override
+      protected void setHeader(ClientResponseContext responseContext,
+          ResponseHeaderValue<Locale> header) {
+        header.value = responseContext.getLanguage();
+      }
+    });
+
+    Response response = invokePost("language", null);
+    Locale locale = response.getLanguage();
+    assertHeaderNull(locale, value, "getLanguage");
+  }
+
+  /*
+   * @testName: getLastModifiedTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:851;
+   * 
+   * @test_Strategy: Get the last modified date.
+   */
+  @Test
+  public void getLastModifiedTest() throws Fault {
+    long time = getCurrentTimeMillis();
+    Response response = invokePost("lastmodified", String.valueOf(time));
+    long responseDate = response.getLastModified().getTime();
+    assertEqualsLong(time, responseDate, "Last Modified date", time,
+        "does NOT match response#getLastModified()", responseDate);
+    logMsg("#getLastModified matches the Last-Modified HTTP header");
+  }
+
+  /*
+   * @testName: getLastModifiedNotPresentTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:851;
+   * 
+   * @test_Strategy: Get null if not present.
+   */
+  @Test
+  public void getLastModifiedNotPresentTest() throws Fault {
+    ResponseHeaderValue<Date> containerValue = new ResponseHeaderValue<>();
+    addProvider(new HeaderNotPresent<Date>(containerValue) {
+      @Override
+      protected void setHeader(ClientResponseContext responseContext,
+          ResponseHeaderValue<Date> header) {
+        header.value = responseContext.getLastModified();
+      }
+    });
+
+    Response response = invokePost("lastmodified", null);
+    Date responseDate = response.getLastModified();
+    assertHeaderNull(responseDate, containerValue, "getLastModified");
+  }
+
+  /*
+   * @testName: getLengthTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:852;
+   * 
+   * @test_Strategy: Get Content-Length value.
+   */
+  @Test
+  public void getLengthTest() throws Fault {
+    Response response = invokePost("length", "1234567890");
+    int len = response.getLength();
+    assertTrue(len > 9, "Expected Content-Length > 9"+
+        "does NOT match response#getLength()"+ len);
+    logMsg("#getLength matches expected Content-Length", len);
+  }
+
+  /*
+   * @testName: getLengthNotPresentTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:852;
+   * 
+   * @test_Strategy: In other cases returns -1.
+   */
+  @Test
+  public void getLengthNotPresentTest() throws Fault {
+    Response response = invokePost("length", null);
+    int len = response.getLength();
+    String headerLen = response.getHeaderString(HttpHeaders.CONTENT_LENGTH);
+    if (headerLen == null)
+      assertEqualsInt(len, -1, "Expected Content-Length = -1",
+          "does NOT match response#getLength()", len);
+    else
+      assertEqualsInt(len, Integer.parseInt(headerLen),
+          "Expected Content-Length =", headerLen,
+          "does NOT match response#getLength()=", len);
+    logMsg("#getLength matches expected Content-Length", len);
+  }
+
+  /*
+   * @testName: getLinkTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:853;
+   * 
+   * @test_Strategy: Get the link for the relation.
+   */
+  @Test
+  public void getLinkTest() throws Fault {
+    String rel = "getLinkTest";
+    Response response = invokePost("link", rel);
+    Link responseLink = response.getLink(rel);
+    assertNotNull(responseLink, "#getLink is null");
+    assertContains(rel, responseLink.getRel(),
+        "#getLink() returned unexpected Link", responseLink);
+    logMsg("#getLink matches expected Link");
+  }
+
+  /*
+   * @testName: getLinkNotPresentTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:853;
+   * 
+   * @test_Strategy: returns null if not present.
+   */
+  @Test
+  public void getLinkNotPresentTest() throws Fault {
+    ResponseHeaderValue<Link> containerValue = new ResponseHeaderValue<>();
+    addProvider(new HeaderNotPresent<Link>(containerValue) {
+      @Override
+      protected void setHeader(ClientResponseContext responseContext,
+          ResponseHeaderValue<Link> header) {
+        header.value = responseContext.getLink("getLinkTest");
+      }
+    });
+
+    Response response = invokePost("link", null);
+    Link responseLink = response.getLink("getLinkTest");
+    assertHeaderNull(responseLink, containerValue, "getLink");
+  }
+
+  /*
+   * @testName: getLinkBuilderForTheRelationTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:854;
+   * 
+   * @test_Strategy: Convenience method that returns a Link.Builder for the
+   * relation.
+   */
+  @Test
+  public void getLinkBuilderForTheRelationTest() throws Fault {
+    String rel = "anyrelation";
+    Response response = invokePost("linkbuilder", rel);
+    Link responseLink = response.getLink(rel);
+    assertNotNull(responseLink, "#getLinkBuilder('relation') returned null");
+    logMsg("#getLinkBuilder creates correct Link for given relation");
+  }
+
+  /*
+   * @testName: getLinkBuilderForTheNotPresentRelationTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:854;
+   * 
+   * @test_Strategy: returns null if not present.
+   */
+  @Test
+  public void getLinkBuilderForTheNotPresentRelationTest() throws Fault {
+    Response response = invokeGet("entity");
+    Builder builder = response.getLinkBuilder("anyrelation");
+    assertNull(builder,
+        "#getLinkBuilder('relation') returned unexpected builder", builder);
+    logMsg("#getLinkBuilder returned null as expected");
+  }
+
+  /*
+   * @testName: getLinksTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:855;
+   * 
+   * @test_Strategy: Get the links attached to the message as header.
+   */
+  @Test
+  public void getLinksTest() throws Fault {
+    Response response = invokeGet("links");
+    Set<Link> responseLinks = response.getLinks();
+    assertEqualsInt(responseLinks.size(), 2,
+        "#getLinks() returned set of unexpected size", responseLinks.size());
+    logMsg("#getLinks contains expected links");
+  }
+
+  /*
+   * @testName: getLinksIsNotNullTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:855;
+   * 
+   * @test_Strategy: Does not return null.
+   */
+  @Test
+  public void getLinksIsNotNullTest() throws Fault {
+    Response response = invokeGet("entity");
+    Set<Link> responseLinks = response.getLinks();
+    assertTrue(responseLinks != null, "#getLinks() returned null!");
+    assertTrue(responseLinks.size() == 0,
+        "#getLinks() returned non-empty map!");
+    logMsg("#getLinks contains no links as expected");
+  }
+
+  /*
+   * @testName: getLocationTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:856;
+   * 
+   * @test_Strategy: Get the location.
+   */
+  @Test
+  public void getLocationTest() throws Fault {
+    String path = "path";
+    URI serverUri = ResponseTest.createUri(path);
+    Response response = invokePost("location", path);
+    URI responseLocation = response.getLocation();
+    assertEquals(responseLocation, serverUri, "#getLocation()",
+        responseLocation, "differs from expected", serverUri);
+    logMsg("#getLocation contains expected location");
+  }
+
+  /*
+   * @testName: getLocationNotPresentTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:856;
+   * 
+   * @test_Strategy: Get null when no present.
+   */
+  @Test
+  public void getLocationNotPresentTest() throws Fault {
+    ResponseHeaderValue<URI> containerValue = new ResponseHeaderValue<>();
+    addProvider(new HeaderNotPresent<URI>(containerValue) {
+      @Override
+      protected void setHeader(ClientResponseContext responseContext,
+          ResponseHeaderValue<URI> header) {
+        header.value = responseContext.getLocation();
+      }
+    });
+
+    Response response = invokeGet("entity");
+    URI responseLocation = response.getLocation();
+    assertHeaderNull(responseLocation, containerValue, "getLocation");
+  }
+
+  /*
+   * @testName: getMediaTypeTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:857;
+   * 
+   * @test_Strategy: Get the media type of the message entity.
+   */
+  @Test
+  public void getMediaTypeTest() throws Fault {
+    MediaType mediaType = MediaType.APPLICATION_ATOM_XML_TYPE;
+    Response response = invokePost("mediatype", mediaType.toString());
+    MediaType responseMedia = response.getMediaType();
+    assertEquals(mediaType, responseMedia, "#getMediaType()", responseMedia,
+        "differs from expected", MediaType.APPLICATION_ATOM_XML);
+    logMsg("#getMediaType returned expected MediaType");
+  }
+
+  /*
+   * @testName: getStatusInfoTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:858;
+   * 
+   * @test_Strategy: Get the complete status information associated with the
+   * response.
+   */
+  @Test
+  public void getStatusInfoTest() throws Fault {
+    for (Status status : Status.values()) {
+      setProperty(Property.STATUS_CODE, getStatusCode(status));
+      Response response = invokePost("statusinfo", status.name());
+      StatusType info = response.getStatusInfo();
+      assertEqualsInt(info.getStatusCode(), status.getStatusCode(),
+          "#getStatusInfo returned unexpected value", info);
+    }
+    logMsg("#getStatusInfo returned expected StatusTypes");
+  }
+
+  /*
+   * @testName: getStringHeadersUsingToStringTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:859;
+   * 
+   * @test_Strategy: Get view of the response headers and their string values.
+   * Each single header value is converted to String using a
+   * RuntimeDelegate.HeaderDelegate or using its toString
+   */
+  @Test
+  public void getStringHeadersUsingToStringTest() throws Fault {
+    Response response = invokePost("headerstring", "stringheaders");
+    MultivaluedMap<String, String> headers = response.getStringHeaders();
+    String header = headers.getFirst("s1");
+    assertContainsIgnoreCase(header, "s1", "Header", "s1",
+        "has unexpected value", header);
+
+    header = headers.getFirst("s2");
+    assertContainsIgnoreCase(header, "s2", "Header", "s2",
+        "has unexpected value", header);
+
+    logMsg("#getStringHeaders contains expected values",
+        JaxrsUtil.iterableToString(",", headers.entrySet()));
+  }
+
+  /*
+   * @testName: getStringHeadersUsingHeaderDelegateTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:859;
+   * 
+   * @test_Strategy: Get view of the response headers and their string values.
+   * Each single header value is converted to String using a
+   * RuntimeDelegate.HeaderDelegate or using its toString
+   */
+  @Test
+  public void getStringHeadersUsingHeaderDelegateTest() throws Fault {
+    invokeGet("setstringbeanruntime");
+
+    Response response = invokePost("headerstring", "stringheaders");
+    MultivaluedMap<String, String> headers = response.getStringHeaders();
+    String header = headers.getFirst("s3");
+    assertContainsIgnoreCase("s3", header, "Header", "s3",
+        "has unexpected value", header);
+
+    logMsg("#getStringHeaders contains expected values",
+        JaxrsUtil.iterableToString(",", headers.entrySet()));
+
+    invokeGet("setoriginalruntime");
+  }
+
+  /*
+   * @testName: hasEntityWhenEntityTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:860;
+   * 
+   * @test_Strategy: Check if there is an entity available in the response.
+   */
+  @Test
+  public void hasEntityWhenEntityTest() throws Fault {
+    Response response = invokeGet("entity");
+    assertTrue(response.hasEntity(), "#hasEntity did not found the entity");
+    logMsg("#hasEntity found the entity as expected");
+  }
+
+  /*
+   * @testName: hasEntityWhenNoEntityTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:860;
+   * 
+   * @test_Strategy: Check if there is an entity available in the response.
+   */
+  @Test
+  public void hasEntityWhenNoEntityTest() throws Fault {
+    Response response = invokePost("headerstring", null);
+    assertFalse(response.hasEntity(), "#hasEntity did found the entity");
+    logMsg("#hasEntity has not found any entity as expected");
+  }
+
+  /*
+   * @testName: hasEntityThrowsIllegalStateExceptionTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:860;
+   * 
+   * @test_Strategy: throws java.lang.IllegalStateException - in case the
+   * response has been closed.
+   */
+  @Test
+  public void hasEntityThrowsIllegalStateExceptionTest() throws Fault {
+    Response response = invokeGet("entity");
+    response.close();
+    try {
+      response.hasEntity();
+      fault("No exception has been thrown");
+    } catch (IllegalStateException e) {
+      logMsg("IllegalStateException has been thrown as expected");
+    }
+
+  }
+
+  /*
+   * @testName: hasLinkWhenLinkTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:862;
+   * 
+   * @test_Strategy: Check if link for relation exists.
+   */
+  @Test
+  public void hasLinkWhenLinkTest() throws Fault {
+    Response response = invokePost("link", "path");
+    assertTrue(response.hasLink("path"), "#hasLink did not found a Link");
+    logMsg("#hasEntity found the Link as expected");
+  }
+
+  /*
+   * @testName: hasLinkWhenNoLinkTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:862;
+   * 
+   * @test_Strategy: Check if link for relation exists.
+   */
+  @Test
+  public void hasLinkWhenNoLinkTest() throws Fault {
+    Response response = invokeGet("entity");
+    assertFalse(response.hasLink("rel"), "#has Link did found some Link");
+    logMsg("#hasLink has not found any Link as expected");
+  }
+
+  /*
+   * @testName: readEntityClassTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:863;
+   * 
+   * @test_Strategy: Read the message entity input stream as an instance of
+   * specified Java type using a MessageBodyReader that supports mapping the
+   * message entity stream onto the requested type
+   */
+  @Test
+  public void readEntityClassTest() throws Fault {
+    Response response = invokeGet("entity");
+    response.bufferEntity();
+    String line;
+
+    Reader reader = response.readEntity(Reader.class);
+    line = readLine(reader);
+    assertTrue(ResponseTest.ENTITY.equals(line), "#readEntity(Reader)={"+ line+
+        "} differs from expected"+ ResponseTest.ENTITY);
+
+    byte[] buffer = new byte[0];
+    buffer = response.readEntity(buffer.getClass());
+    line = new String(buffer);
+    assertTrue(ResponseTest.ENTITY.equals(line), "#readEntity(byte[].class)={"+
+        line+ "} differs from expected"+ ResponseTest.ENTITY);
+
+    logMsg("Got expected", line);
+  }
+
+  /*
+   * @testName: readEntityClassIsNullWhenNoEntityTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:863;
+   * 
+   * @test_Strategy: If the message does not contain an entity body null is
+   * returned.
+   */
+  @Test
+  public void readEntityClassIsNullWhenNoEntityTest() throws Fault {
+    Response response = invokeGet("status?status=200");
+    String entity = response.readEntity(String.class);
+    assertTrue(entity == null || "".equals(entity),
+        "entity is not null or zero length"+ entity);
+    logMsg("Null or zero length entity returned when no entity as expected");
+  }
+
+  /*
+   * @testName: readEntityClassCloseIsCalledTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:863;
+   * 
+   * @test_Strategy: Unless the supplied entity type is an input stream, this
+   * method automatically closes the consumed response entity stream if it is
+   * not buffered.
+   */
+  @Test
+  public void readEntityClassCloseIsCalledTest() throws Fault {
+    AtomicInteger ai = setCorruptedStream();
+    final Response response = invokeGet("corrupted");
+    catchCorruptedStreamException(new Runnable() {
+      @Override
+      public void run() {
+        response.readEntity(String.class);
+      }
+    });
+    assertEquals(ai.get(), CorruptedInputStream.CLOSEVALUE,
+        "Close has not been called");
+    logMsg("Close() has been called on an entity stream as expected");
+  }
+
+  /*
+   * @testName: readEntityClassCloseIsNotCalledOnInputStreamTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:863;
+   * 
+   * @test_Strategy: Unless the supplied entity type is an input stream, this
+   * method automatically closes the consumed response entity stream if it is
+   * not buffered.
+   */
+  @Test
+  public void readEntityClassCloseIsNotCalledOnInputStreamTest() throws Fault {
+    AtomicInteger ai = setCorruptedStream();
+    Response response = invokeGet("corrupted");
+    try {
+      response.readEntity(InputStream.class);
+      logMsg("Close() has not been called on entity stream as expected");
+    } catch (Exception e) {
+      throw new Fault("Close was called", e);
+    }
+    assertTrue(ai.get() == 0, "Close was called");
+  }
+
+  /*
+   * @testName: readEntityClassThrowsProcessingExceptionTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:863;
+   * 
+   * @test_Strategy: Method throws an ProcessingException if the content of the
+   * message cannot be mapped to an entity of the requested type
+   */
+  @Test
+  public void readEntityClassThrowsProcessingExceptionTest() throws Fault {
+    Response response = invokeGet("entity");
+    try {
+      response.readEntity(Void.class);
+      throw new Fault(
+          "No exception has been thrown when reader for entity class is not known");
+    } catch (ProcessingException e) {
+      logMsg("ProcessingException has been thrown as expected");
+    }
+  }
+
+  /*
+   * @testName: readEntityClassThrowsIllegalStateExceptionTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:863;
+   * 
+   * @test_Strategy: if the entity is not backed by an input stream, or if the
+   * entity input stream has been fully consumed already and has not been
+   * buffered prior consuming.
+   */
+  @Test
+  public void readEntityClassThrowsIllegalStateExceptionTest() throws Fault {
+    Client client = ClientBuilder.newClient(); // create a new client
+    WebTarget target = client.target( // with no bufferEntity called
+        "http://" + _hostname + ":" + _port + getContextRoot()).path("entity");
+    Response response = target.request(MediaType.TEXT_PLAIN_TYPE).buildGet()
+        .invoke();
+    String entity = response.readEntity(String.class);
+    assertTrue(ResponseTest.ENTITY.equals(entity),
+        "#readEntity(String.class)={"+ entity+ "} differs from expected"+
+        ResponseTest.ENTITY);
+    try {
+      response.readEntity(Reader.class);
+      throw new Fault(
+          "No exception has been thrown when reader for entity is not buffered");
+    } catch (IllegalStateException e) {
+      logMsg("IllegalStateException has been thrown as expected");
+    }
+  }
+
+  /*
+   * @testName: readEntityGenericTypeTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:866;
+   * 
+   * @test_Strategy: Read the message entity input stream as an instance of
+   * specified Java type using a MessageBodyReader that supports mapping the
+   * message entity stream onto the requested type
+   */
+  @Test
+  public void readEntityGenericTypeTest() throws Fault {
+    Response response = invokeGet("entity");
+    response.bufferEntity();
+    String line;
+
+    Reader reader = response.readEntity(generic(Reader.class));
+    line = readLine(reader);
+    assertTrue(ResponseTest.ENTITY.equals(line),
+        "#readEntity(GenericType<Reader>)={"+ line+ "} differs from expected"+
+        ResponseTest.ENTITY);
+
+    byte[] buffer = new byte[0];
+    buffer = response.readEntity(generic(buffer.getClass()));
+    assertTrue(buffer != null,
+        "response.readEntity(GenericType<byte[]>) is null");
+    line = new String(buffer);
+    assertTrue(ResponseTest.ENTITY.equals(line),
+        "#readEntity(GenericType<byte[]>)={"+ line+ "} differs from expected"+
+        ResponseTest.ENTITY);
+
+    logMsg("Got expected", line);
+  }
+
+  /*
+   * @testName: readEntityGenericIsNullWhenNoEntityTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:866;
+   * 
+   * @test_Strategy: If the message does not contain an entity body null is
+   * returned.
+   */
+  @Test
+  public void readEntityGenericIsNullWhenNoEntityTest() throws Fault {
+    String request = buildRequest(Request.GET, "status?status=200");
+    setProperty(Property.REQUEST, request);
+    invoke();
+    Response response = getResponse();
+    String entity = response.readEntity(generic(String.class));
+    assertTrue(entity == null || "".equals(entity),
+        "entity is not null or zero length"+ entity);
+    logMsg("Null or zero length entity returned when no entity as expected");
+  }
+
+  /*
+   * @testName: readEntityGenericCloseIsCalledTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:866;
+   * 
+   * @test_Strategy: Unless the supplied entity type is an input stream, this
+   * method automatically closes the consumed response entity stream if it is
+   * not buffered.
+   */
+  @Test
+  public void readEntityGenericCloseIsCalledTest() throws Fault {
+    AtomicInteger ai = setCorruptedStream();
+    final Response response = invokeGet("corrupted");
+    catchCorruptedStreamException(new Runnable() {
+      @Override
+      public void run() {
+        response.readEntity(generic(String.class));
+      }
+    });
+    assertTrue(ai.get() == CorruptedInputStream.CLOSEVALUE,
+        "Close has not been called");
+    logMsg("Close() has been called on an entity stream as expected");
+  }
+
+  /*
+   * @testName: readEntityGenericTypeCloseIsNotCalledOnInputStreamTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:866;
+   * 
+   * @test_Strategy: Unless the supplied entity type is an input stream, this
+   * method automatically closes the consumed response entity stream if it is
+   * not buffered.
+   */
+  @Test
+  public void readEntityGenericTypeCloseIsNotCalledOnInputStreamTest()
+      throws Fault {
+    AtomicInteger ai = setCorruptedStream();
+    Response response = invokeGet("corrupted");
+    try {
+      response.readEntity(generic(InputStream.class));
+      logMsg("Close() has not been called on entity stream as expected");
+    } catch (Exception e) {
+      throw new Fault("Close was called", e);
+    }
+    assertTrue(ai.get() == 0, "Close was called");
+  }
+
+  /*
+   * @testName: readEntityGenericTypeThrowsProcessingExceptionTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:866;
+   * 
+   * @test_Strategy: Method throws an ProcessingException if the content of the
+   * message cannot be mapped to an entity of the requested type
+   */
+  @Test
+  public void readEntityGenericTypeThrowsProcessingExceptionTest()
+      throws Fault {
+    Response response = invokeGet("entity");
+    try {
+      response.readEntity(generic(Void.class));
+      throw new Fault(
+          "No exception has been thrown when reader for entity class is not known");
+    } catch (ProcessingException e) {
+      logMsg("ProcessingException has been thrown as expected");
+    }
+  }
+
+  /*
+   * @testName: readEntityGenericTypeThrowsIllegalStateExceptionTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:866;
+   * 
+   * @test_Strategy: if the entity is not backed by an input stream, or if the
+   * entity input stream has been fully consumed already and has not been
+   * buffered prior consuming.
+   */
+  @Test
+  public void readEntityGenericTypeThrowsIllegalStateExceptionTest()
+      throws Fault {
+    Client client = ClientBuilder.newClient(); // create a new client
+    WebTarget target = client.target( // with no bufferEntity called
+        "http://" + _hostname + ":" + _port + getContextRoot()).path("entity");
+    Response response = target.request(MediaType.TEXT_PLAIN_TYPE).buildGet()
+        .invoke();
+    String entity = response.readEntity(generic(String.class));
+    assertTrue(ResponseTest.ENTITY.equals(entity),
+        "#readEntity(GenericType<byte[]>)={"+ entity+ "} differs from expected"+
+        ResponseTest.ENTITY);
+    try {
+      response.readEntity(generic(Reader.class));
+      throw new Fault(
+          "No exception has been thrown when reader for entity is not buffered");
+    } catch (IllegalStateException e) {
+      logMsg("IllegalStateException has been thrown as expected");
+    }
+  }
+
+  /*
+   * @testName: readEntityClassAnnotationTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:869;
+   * 
+   * @test_Strategy: Read the message entity input stream as an instance of
+   * specified Java type using a MessageBodyReader that supports mapping the
+   * message entity stream onto the requested type. annotations - annotations
+   * that will be passed to the MessageBodyReader.
+   */
+  @Test
+  public void readEntityClassAnnotationTest() throws Fault {
+    Date date = Calendar.getInstance().getTime();
+    String sDate = String.valueOf(date.getTime());
+    Annotation[] annotations = AnnotatedClass.class.getAnnotations();
+    int expected = DateReaderWriter.ANNOTATION_CONSUMES
+        | DateReaderWriter.ANNOTATION_PROVIDER;
+
+    AtomicInteger ai = new AtomicInteger();
+    DateReaderWriter drw = new DateReaderWriter(ai);
+    addProvider(drw);
+
+    Response response = invokeGet("date?date=" + sDate);
+    response.bufferEntity();
+
+    Date entity = response.readEntity(Date.class, annotations);
+    assertTrue(date.equals(entity), "#readEntity(Date, annotations)={"+ entity+
+        "} differs from expected"+ date);
+
+    assertTrue(ai.get() == expected, ai.get()+ "differes from expected"+
+        expected+ "which suggest a problem with annotation passing");
+
+    String responseDate = response.readEntity(String.class, annotations);
+    assertTrue(sDate.equals(responseDate),
+        "#readEntity(String.class, annotations)={"+ responseDate+
+        "} differs from expected"+ sDate);
+
+    assertTrue(ai.get() == expected, ai.get()+ "differes from expected"+
+        expected+ "which suggest a problem with annotation passing");
+
+    logMsg("Got expected date", date);
+  }
+
+  /*
+   * @testName: readEntityClassAnnotationIsNullWhenNoEntityTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:869;
+   * 
+   * @test_Strategy: If the message does not contain an entity body null is
+   * returned.
+   */
+  @Test
+  public void readEntityClassAnnotationIsNullWhenNoEntityTest() throws Fault {
+    Annotation[] annotations = AnnotatedClass.class.getAnnotations();
+    Response response = invokeGet("status?status=200");
+    String entity = response.readEntity(String.class, annotations);
+    assertTrue(entity == null || "".equals(entity),
+        "entity is not null or zero length"+ entity);
+    logMsg("Null or zero length entity returned when no entity as expected");
+  }
+
+  /*
+   * @testName: readEntityClassAnnotationCloseIsCalledTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:869;
+   * 
+   * @test_Strategy: Unless the supplied entity type is an input stream, this
+   * method automatically closes the consumed response entity stream if it is
+   * not buffered.
+   */
+  @Test
+  public void readEntityClassAnnotationCloseIsCalledTest() throws Fault {
+    final Annotation[] annotations = AnnotatedClass.class.getAnnotations();
+    AtomicInteger ai = setCorruptedStream();
+    final Response response = invokeGet("corrupted");
+    catchCorruptedStreamException(new Runnable() {
+      @Override
+      public void run() {
+        response.readEntity(String.class, annotations);
+      }
+    });
+    assertEqualsInt(ai.get(), CorruptedInputStream.CLOSEVALUE,
+        "Close has not been called");
+    logMsg("Close() has been called on an entity stream as expected");
+  }
+
+  /*
+   * @testName: readEntityClassAnnotationCloseIsNotCalledOnInputStreamTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:869;
+   * 
+   * @test_Strategy: Unless the supplied entity type is an input stream, this
+   * method automatically closes the consumed response entity stream if it is
+   * not buffered.
+   */
+  @Test
+  public void readEntityClassAnnotationCloseIsNotCalledOnInputStreamTest()
+      throws Fault {
+    Annotation[] annotations = AnnotatedClass.class.getAnnotations();
+    AtomicInteger ai = setCorruptedStream();
+    Response response = invokeGet("corrupted");
+    try {
+      response.readEntity(InputStream.class, annotations);
+      logMsg("Close() has not been called on entity stream as expected");
+    } catch (ProcessingException e) {
+      throw new Fault("Close was called", e);
+    }
+    assertTrue(ai.get() == 0, "Close was called");
+  }
+
+  /*
+   * @testName: readEntityClassAnnotationThrowsProcessingExceptionTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:869;
+   * 
+   * @test_Strategy: Method throws an ProcessingException if the content of the
+   * message cannot be mapped to an entity of the requested type
+   */
+  @Test
+  public void readEntityClassAnnotationThrowsProcessingExceptionTest()
+      throws Fault {
+    Annotation[] annotations = AnnotatedClass.class.getAnnotations();
+    Response response = invokeGet("entity");
+    try {
+      response.readEntity(Void.class, annotations);
+      throw new Fault(
+          "No exception has been thrown when reader for entity class is not known");
+    } catch (ProcessingException e) {
+      logMsg("ProcessingException has been thrown as expected");
+    }
+  }
+
+  /*
+   * @testName: readEntityClassAnnotationThrowsIllegalStateExceptionTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:869;
+   * 
+   * @test_Strategy: if the entity is not backed by an input stream, or if the
+   * entity input stream has been fully consumed already and has not been
+   * buffered prior consuming.
+   */
+  @Test
+  public void readEntityClassAnnotationThrowsIllegalStateExceptionTest()
+      throws Fault {
+    Annotation[] annotations = AnnotatedClass.class.getAnnotations();
+    Client client = ClientBuilder.newClient(); // create a new client
+    WebTarget target = client.target( // with no bufferEntity called
+        "http://" + _hostname + ":" + _port + getContextRoot()).path("entity");
+    Response response = target.request(MediaType.TEXT_PLAIN_TYPE).buildGet()
+        .invoke();
+    String entity = response.readEntity(String.class, annotations);
+    assertTrue(ResponseTest.ENTITY.equals(entity),
+        "#readEntity(String.class, annotations)={"+ entity+
+        "} differs from expected"+ ResponseTest.ENTITY);
+    try {
+      response.readEntity(Reader.class, annotations);
+      throw new Fault(
+          "No exception has been thrown when reader for entity is not buffered");
+    } catch (IllegalStateException e) {
+      logMsg("IllegalStateException has been thrown as expected");
+    }
+  }
+
+  /*
+   * @testName: readEntityGenericTypeAnnotationTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:872;
+   * 
+   * @test_Strategy: Read the message entity input stream as an instance of
+   * specified Java type using a MessageBodyReader that supports mapping the
+   * message entity stream onto the requested type. annotations - annotations
+   * that will be passed to the MessageBodyReader.
+   */
+  @Test
+  public void readEntityGenericTypeAnnotationTest() throws Fault {
+    Date date = Calendar.getInstance().getTime();
+    String sDate = String.valueOf(date.getTime());
+    Annotation[] annotations = AnnotatedClass.class.getAnnotations();
+    int expected = DateReaderWriter.ANNOTATION_CONSUMES
+        | DateReaderWriter.ANNOTATION_PROVIDER;
+
+    AtomicInteger ai = new AtomicInteger();
+    DateReaderWriter drw = new DateReaderWriter(ai);
+    addProvider(drw);
+
+    Response response = invokeGet("date?date=" + sDate);
+    response.bufferEntity();
+
+    Date entity = response.readEntity(generic(Date.class), annotations);
+    assertTrue(date.equals(entity), "#readEntity(Date, annotations)={"+ entity+
+        "} differs from expected"+ date);
+
+    assertTrue(ai.get() == expected, ai.get()+ "differes from expected"+
+        expected+ "which suggest a problem with annotation passing");
+
+    String responseDate = response.readEntity(generic(String.class),
+        annotations);
+    assertTrue(sDate.equals(responseDate),
+        "#readEntity(String.class, annotations)={"+ responseDate+
+        "} differs from expected"+ sDate);
+
+    assertTrue(ai.get() == expected, ai.get()+ "differes from expected"+
+        expected+ "which suggest a problem with annotation passing");
+
+    logMsg("Got expected date", date);
+  }
+
+  /*
+   * @testName: readEntityGenericTypeAnnotationIsNullWhenNoEntityTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:872;
+   * 
+   * @test_Strategy: If the message does not contain an entity body null is
+   * returned.
+   */
+  @Test
+  public void readEntityGenericTypeAnnotationIsNullWhenNoEntityTest()
+      throws Fault {
+    Annotation[] annotations = AnnotatedClass.class.getAnnotations();
+    Response response = invokeGet("status?status=200");
+    String entity = response.readEntity(generic(String.class), annotations);
+    assertTrue(entity == null || "".equals(entity),
+        "entity is not null or zero length"+ entity);
+    logMsg("Null or zero length entity returned when no entity as expected");
+  }
+
+  /*
+   * @testName: readEntityGenericTypeAnnotationCloseIsCalledTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:872;
+   * 
+   * @test_Strategy: Unless the supplied entity type is an input stream, this
+   * method automatically closes the consumed response entity stream if it is
+   * not buffered.
+   */
+  @Test
+  public void readEntityGenericTypeAnnotationCloseIsCalledTest() throws Fault {
+    final Annotation[] annotations = AnnotatedClass.class.getAnnotations();
+    AtomicInteger ai = setCorruptedStream();
+    final Response response = invokeGet("corrupted");
+    catchCorruptedStreamException(new Runnable() {
+      @Override
+      public void run() {
+        response.readEntity(generic(String.class), annotations);
+      }
+    });
+    assertEqualsInt(ai.get(), CorruptedInputStream.CLOSEVALUE,
+        "Close has not been called");
+    logMsg("Close() has been called on an entity stream as expected");
+  }
+
+  /*
+   * @testName: readEntityGenericTypeAnnotationCloseIsNotCalledOnInputStreamTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:872;
+   * 
+   * @test_Strategy: Unless the supplied entity type is an input stream, this
+   * method automatically closes the consumed response entity stream if it is
+   * not buffered.
+   */
+  @Test
+  public void readEntityGenericTypeAnnotationCloseIsNotCalledOnInputStreamTest()
+      throws Fault {
+    Annotation[] annotations = AnnotatedClass.class.getAnnotations();
+    AtomicInteger ai = setCorruptedStream();
+    Response response = invokeGet("corrupted");
+    try {
+      response.readEntity(generic(InputStream.class), annotations);
+    } catch (ProcessingException e) {
+      fault("Close was called", e);
+    }
+    assertEqualsInt(ai.get(), 0, "Close was called");
+    logMsg("Close() has not been called on entity stream as expected");
+  }
+
+  /*
+   * @testName: readEntityGenericTypeAnnotationThrowsProcessingExceptionTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:872;
+   * 
+   * @test_Strategy: Method throws an ProcessingException if the content of the
+   * message cannot be mapped to an entity of the requested type
+   */
+  @Test
+  public void readEntityGenericTypeAnnotationThrowsProcessingExceptionTest()
+      throws Fault {
+    Annotation[] annotations = AnnotatedClass.class.getAnnotations();
+    Response response = invokeGet("entity");
+    try {
+      response.readEntity(generic(Void.class), annotations);
+      throw new Fault(
+          "No exception has been thrown when reader for entity class is not known");
+    } catch (ProcessingException e) {
+      logMsg("ProcessingException has been thrown as expected");
+    }
+  }
+
+  /*
+   * @testName: readEntityGenericTypeAnnotationThrowsIllegalStateExceptionTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:872;
+   * 
+   * @test_Strategy: if the entity is not backed by an input stream, or if the
+   * entity input stream has been fully consumed already and has not been
+   * buffered prior consuming.
+   */
+  @Test
+  public void readEntityGenericTypeAnnotationThrowsIllegalStateExceptionTest()
+      throws Fault {
+    Annotation[] annotations = AnnotatedClass.class.getAnnotations();
+    Client client = ClientBuilder.newClient(); // create a new client
+    WebTarget target = client.target( // with no bufferEntity called
+        "http://" + _hostname + ":" + _port + getContextRoot()).path("entity");
+    Response response = target.request(MediaType.TEXT_PLAIN_TYPE).buildGet()
+        .invoke();
+    String entity = response.readEntity(generic(String.class), annotations);
+    assertTrue(ResponseTest.ENTITY.equals(entity),
+        "#readEntity(GenericType<String>, annotations)={"+ entity+
+        "} differs from expected"+ ResponseTest.ENTITY);
+    try {
+      response.readEntity(generic(Reader.class), annotations);
+      throw new Fault(
+          "No exception has been thrown when reader for entity is not buffered");
+    } catch (IllegalStateException e) {
+      logMsg("IllegalStateException has been thrown as expected");
+    }
+  }
+
+    /*
+   * @testName: responseCreatedRelativeURITest
+   *
+   * @assertion_ids: JAXRS:JAVADOC:121;
+   *
+   * @test_Strategy: The resource calls Response.created() to set the Location header with a
+   * relative URI. The relative URI should be converted into an absolute URI by resolving it
+   * relative to the base URI.
+   */
+  @Test
+  public void responseCreatedRelativeURITest()
+      throws Fault {
+    String resourceUrl = getAbsoluteUrl();
+    String expected = resourceUrl.substring(0, resourceUrl.length() - "resource".length()) + "created";
+    Response response = invokeGet("created");
+    try {
+      assertTrue(expected.equals(response.getHeaderString("location")),
+        "#response.getHeaderString(\"location\") [" +
+        response.getHeaderString("location") + "] differs from "+ expected);
+    } finally {
+      response.close();
+    }
+  }
+
+  // ////////////////////////////////////////////////////////////////////
+  protected <T> GenericType<T> generic(Class<T> clazz) {
+    return new GenericType<T>(clazz);
+  }
+
+  protected Response invokeGet(String method) throws Fault {
+    String request = buildRequest(Request.GET, method);
+    setProperty(Property.REQUEST_HEADERS,
+        buildAccept(MediaType.TEXT_PLAIN_TYPE));
+    setProperty(Property.REQUEST, request);
+    invoke();
+    return getResponse();
+  }
+
+  protected Response invokePost(String method, Object entity) throws Fault {
+    String request = buildRequest(Request.POST, method);
+    setProperty(Property.REQUEST, request);
+    setRequestContentEntity(entity);
+    invoke();
+    return getResponse();
+  }
+
+  protected String readLine(Reader reader) throws Fault {
+    String line = null;
+    BufferedReader buffered = new BufferedReader(reader);
+    try {
+      line = buffered.readLine();
+    } catch (IOException e) {
+      try {
+        buffered.close();
+      } catch (IOException ie) {
+      }
+      throw new Fault(e);
+    }
+    return line;
+  }
+
+  protected AtomicInteger setCorruptedStream() {
+    final AtomicInteger ai = new AtomicInteger(0);
+    ClientResponseFilter filter = new ClientResponseFilter() {
+      @Override
+      public void filter(ClientRequestContext arg0,
+          ClientResponseContext response) throws IOException {
+        CorruptedInputStream cis = new CorruptedInputStream(
+            ResponseTest.ENTITY.getBytes(), ai);
+        cis.setCorrupted(true);
+        response.setEntityStream(cis);
+      }
+    };
+    addProvider(filter);
+
+    // do not use new entity stream in logging filter for the case of priority
+    // disfunction, the CorruptedInputStream would be then replaced, wrongly
+    // informing about not closing the stream
+    super.setPrintEntity(false);
+
+    return ai;
+  }
+
+  protected long getCurrentTimeMillis() {
+    long millis = System.currentTimeMillis() / 1000;
+    millis *= 1000;
+    return millis;
+  }
+
+  protected String langToString(Object object) {
+    Locale locale = null;
+    if (object instanceof List)
+      object = ((List<?>) object).iterator().next();
+    if (object instanceof Locale)
+      locale = (Locale) object;
+    String value = locale == null ? object.toString() : locale.toString();
+    return value.replace("_", "-");
+  }
+
+  protected void catchCorruptedStreamException(Runnable runnable) throws Fault {
+    try {
+      runnable.run();
+    } catch (ProcessingException e) {
+      // it is corrupted, #close throws IOException
+      assertNotNull(e.getCause(), "unknown exception thrown", e);
+      assertEquals(e.getCause().getMessage(), CorruptedInputStream.IOETEXT,
+          "unknown exception thrown", e);
+    }
+  }
+
+  protected void catchCorruptedStreamExceptionOnBufferEntity(
+      final Response response) throws Fault {
+    catchCorruptedStreamException(new Runnable() {
+      @Override
+      public void run() {
+        // The original entity input stream is
+        // consumed and automatically closed
+        response.bufferEntity();
+      }
+    });
+  }
+
+  //////////////////////////////////////////////////////////////////////////////////////////////
+  // Even though the test itself do not set the headers, possibly the vendor's
+  ////////////////////////////////////////////////////////////////////////////////////////////// container
+  ////////////////////////////////////////////////////////////////////////////////////////////// does.
+  // In that case, the ResponseFilter checks the value; if it is not expected
+  ////////////////////////////////////////////////////////////////////////////////////////////// null,
+  ////////////////////////////////////////////////////////////////////////////////////////////// the
+  ////////////////////////////////////////////////////////////////////////////////////////////// response
+  // should return the same value the response context does.
+
+  private <T> void assertHeaderNull(T actualHeader,
+      ResponseHeaderValue<T> filterValue, String method) throws Fault {
+    if (filterValue.value == null) {
+      assertNull(actualHeader, "response#" + method + "() should be null, was ",
+          actualHeader);
+      logMsg("response#" + method + "() was null as expected");
+    } else {
+      assertEquals(filterValue.value, actualHeader,
+          "response#" + method + "() was set to " + filterValue.value,
+          "by container but was ", actualHeader);
+      logMsg("response#" + method + "() was set to " + actualHeader
+          + " as preset by container");
+    }
+  }
+
+  class ResponseHeaderValue<T> {
+    private T value;
+  }
+
+  abstract class HeaderNotPresent<T> implements ClientResponseFilter {
+    private ResponseHeaderValue<T> headerValue;
+
+    public HeaderNotPresent(ResponseHeaderValue<T> headerValue) {
+      this.headerValue = headerValue;
+    }
+
+    @Override
+    public void filter(ClientRequestContext requestContext,
+        ClientResponseContext responseContext) throws IOException {
+      setHeader(responseContext, headerValue);
+    }
+
+    protected abstract void setHeader(ClientResponseContext responseContext,
+        ResponseHeaderValue<T> header);
+  }
+
+}
diff --git a/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/core/response/ResponseTest.java b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/core/response/ResponseTest.java
new file mode 100644
index 0000000..7874bab
--- /dev/null
+++ b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/core/response/ResponseTest.java
@@ -0,0 +1,306 @@
+/*
+ * Copyright (c) 2007, 2020 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 jakarta.ws.rs.tck.ee.rs.core.response;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Locale;
+import java.util.StringTokenizer;
+
+import jakarta.ws.rs.tck.common.provider.StringBean;
+import jakarta.ws.rs.tck.common.provider.StringBeanRuntimeDelegate;
+
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.POST;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.Produces;
+import jakarta.ws.rs.QueryParam;
+import jakarta.ws.rs.core.CacheControl;
+import jakarta.ws.rs.core.EntityTag;
+import jakarta.ws.rs.core.HttpHeaders;
+import jakarta.ws.rs.core.Link;
+import jakarta.ws.rs.core.MediaType;
+import jakarta.ws.rs.core.NewCookie;
+import jakarta.ws.rs.core.Response;
+import jakarta.ws.rs.core.Response.ResponseBuilder;
+import jakarta.ws.rs.core.Response.Status;
+import jakarta.ws.rs.ext.RuntimeDelegate;
+
+@Path("resource")
+public class ResponseTest {
+  public static final String ENTITY = "ENtiTy";
+
+  @GET
+  @Path("status")
+  @Produces(value = "text/plain")
+  public Response statusTest(@QueryParam("status") int status) {
+    StringBuffer sb = new StringBuffer();
+    sb.append("status code in request = " + status);
+    ResponseBuilder builder = Response.status(status);
+    Response res = builder.header("TESTHEADER", sb.toString()).build();
+    return res;
+  }
+
+  @GET
+  @Path("entity")
+  @Produces(MediaType.TEXT_PLAIN)
+  public String entity() {
+    return ENTITY;
+  }
+
+  @GET
+  @Path("corrupted")
+  public CorruptedInputStream corrupted() {
+    return new CorruptedInputStream(ENTITY.getBytes(), null);
+  }
+
+  @GET
+  @Path("date")
+  public String date(@QueryParam("date") String date) {
+    return date;
+  }
+
+  @POST
+  @Path("allowedmethods")
+  public Response getAllowedMethods(String methods) {
+    ResponseBuilder builder = Response.ok();
+    StringTokenizer tokenizer = new StringTokenizer(methods);
+    List<String> allowed = new LinkedList<String>();
+    while (tokenizer.hasMoreTokens())
+      allowed.add(tokenizer.nextToken());
+    builder.allow(allowed.toArray(new String[0]));
+    return builder.build();
+  }
+
+  @GET
+  @Path("cookies")
+  public Response getCookies() {
+    NewCookie cookie1 = new NewCookie("c1", "v1");
+    NewCookie cookie2 = new NewCookie("c2", "v2");
+    Response response = Response.ok().cookie(cookie1).cookie(cookie2).build();
+    return response;
+  }
+
+  @POST
+  @Path("date")
+  public Response getDate(String date) throws InterruptedException {
+    ResponseBuilder builder = Response.ok();
+    Thread.sleep(1500L);
+    if (date != null && date.length() != 0) {
+      long millis = Long.parseLong(date);
+      Date dateFromMillis = new Date(millis);
+      builder = builder.header(HttpHeaders.DATE, dateFromMillis);
+    }
+    Response response = builder.build();
+    return response;
+  }
+
+  @POST
+  @Path("entitytag")
+  public Response getEntityTag(String tag) {
+    ResponseBuilder builder;
+    if (tag != null && tag.length() != 0) {
+      EntityTag entityTag = new EntityTag(tag);
+      builder = Response.notModified(entityTag);
+    } else
+      builder = Response.ok();
+    Response response = builder.build();
+    return response;
+  }
+
+  @POST
+  @Path("headers")
+  public Response getHeaders(String headers) {
+    CacheControl ccl = new CacheControl();
+    NewCookie cookie = new NewCookie("cookie", "eikooc");
+    String encoding = "gzip";
+    Date date = Calendar.getInstance().getTime();
+    ResponseBuilder builder = Response.ok();
+    if (headers != null && headers.length() != 0) {
+      builder = builder.cacheControl(ccl).cookie(cookie).encoding(encoding)
+          .expires(date).language(Locale.CANADA_FRENCH);
+    }
+    return builder.build();
+  }
+
+  @POST
+  @Path("headerstring")
+  public Response getHeaderString(String headers) {
+    StringBuilder builder = new StringBuilder("s1");
+    StringBuffer buffer = new StringBuffer("s2");
+    StringBean bean = new StringBean("s3");
+    ResponseBuilder response = Response.ok();
+    if (headers != null && headers.length() != 0)
+      response = response.header(builder.toString(), builder)
+          .header(buffer.toString(), buffer).header(bean.get(), bean);
+    return response.build();
+  }
+
+  @POST
+  @Path("language")
+  public Response getLanguage(String lang) {
+    ResponseBuilder builder = Response.ok();
+    Locale locale = null;
+    if (Locale.CANADA_FRENCH.getCountry().equals(lang))
+      locale = Locale.CANADA_FRENCH;
+    if (locale != null)
+      builder = builder.language(locale);
+    return builder.build();
+  }
+
+  @POST
+  @Path("lastmodified")
+  public Response lastModified(String date) {
+    ResponseBuilder builder = Response.ok();
+    if (date != null && date.length() != 0) {
+      long millis = Long.parseLong(date);
+      Date dateFromMillis = new Date(millis);
+      builder = builder.lastModified(dateFromMillis);
+    }
+    Response response = builder.build();
+    return response;
+  }
+
+  @POST
+  @Path("length")
+  public Response getLength(String entity) {
+    Response response = null;
+    if (entity == null || entity.length() == 0)
+      response = Response.ok().build();
+    else
+      response = Response.ok(entity)
+          .header(HttpHeaders.CONTENT_LENGTH, entity.length()).build();
+    return response;
+  }
+
+  @POST
+  @Path("link")
+  public Response getLink(String rel) {
+    ResponseBuilder builder = Response.ok();
+    if (rel != null && rel.length() != 0)
+      builder.links(createLink("path", rel));
+    return builder.build();
+  }
+
+  @POST
+  @Path("linkbuilder")
+  public Response getLinkBuilder(String rel) {
+    Link link1 = createLink("path1", rel);
+    Response response = Response.ok().links(link1).build();
+    Link builderLink = response.getLinkBuilder(rel).build();
+    response = Response.ok().links(builderLink).build();
+    return response;
+  }
+
+  @GET
+  @Path("links")
+  public Response getLinks() {
+    Link link1 = createLink("path1", "rel1");
+    Link link2 = createLink("path2", "rel2");
+    Response response = Response.ok().links(link1, link2).build();
+    return response;
+  }
+
+  @POST
+  @Path("location")
+  public Response getLocation(String path) {
+    URI location = createUri(path);
+    Response response = Response.ok().location(location).build();
+    return response;
+  }
+
+  @POST
+  @Path("mediatype")
+  public Response getMediaType(String mediaType) {
+    MediaType media = MediaType.WILDCARD_TYPE;
+    if (mediaType.equals(MediaType.APPLICATION_ATOM_XML))
+      media = MediaType.APPLICATION_ATOM_XML_TYPE;
+    Response response = Response.ok().type(media).build();
+    return response;
+  }
+
+  @POST
+  @Path("statusinfo")
+  public Response getStatusInfo(String status) {
+    Status stat = Status.valueOf(status);
+    Response response = Response.status(stat).build();
+    return response;
+  }
+
+  // For the methods that checks for the header delegate this is the way
+  // to add header delegate by switching runtimedelegate
+  // As long as the runtime delegate is one only for whole classloader
+  @Path("setstringbeanruntime")
+  @GET
+  public Response setStringBeanRuntime() {
+    RuntimeDelegate original = RuntimeDelegate.getInstance();
+    if (!(original instanceof StringBeanRuntimeDelegate)) {
+      StringBeanRuntimeDelegate sbrd = new StringBeanRuntimeDelegate(original);
+      RuntimeDelegate.setInstance(sbrd);
+    }
+    return Response.ok().build();
+  }
+
+  // We need to switch back to the original runtime delegate since
+  // we cannot be sure what happen when the war with our runtimedelegate gets
+  // undeployed
+  @Path("setoriginalruntime")
+  @GET
+  public Response setOriginalRuntime() {
+    Response response = null;
+    RuntimeDelegate stringBeanDelegate = RuntimeDelegate.getInstance();
+    if (stringBeanDelegate instanceof StringBeanRuntimeDelegate) {
+      RuntimeDelegate original = ((StringBeanRuntimeDelegate) stringBeanDelegate)
+          .getOriginal();
+      RuntimeDelegate.setInstance(original);
+      response = Response.ok().build();
+    } else
+      response = Response.status(Status.NO_CONTENT).build();
+    return response;
+  }
+
+  @Path("created")
+  @GET
+  public Response setLocationHeader() {
+    try {
+      Response response = Response.created(new URI("created")).status(200).build();
+      return response;
+    } catch (URISyntaxException e) {
+       throw new RuntimeException(e);
+    }
+  }
+
+  // ////////////////////////////////////////////////////////////////////
+  protected static Link createLink(String path, String rel) {
+    return Link.fromUri(createUri(path)).rel(rel).build();
+  }
+
+  protected static URI createUri(String path) {
+    URI uri;
+    try {
+      uri = new URI("http://localhost.tck:888/url404/" + path);
+    } catch (URISyntaxException e) {
+      throw new RuntimeException(e);
+    }
+    return uri;
+  }
+
+}
diff --git a/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/core/response/TSAppConfig.java b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/core/response/TSAppConfig.java
new file mode 100644
index 0000000..16b355c
--- /dev/null
+++ b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/core/response/TSAppConfig.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2007, 2020 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 jakarta.ws.rs.tck.ee.rs.core.response;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import jakarta.ws.rs.tck.common.provider.PrintingErrorHandler;
+import jakarta.ws.rs.tck.common.provider.StringBeanHeaderDelegate;
+
+import jakarta.ws.rs.core.Application;
+
+/**
+ *
+ * @author diannejiao
+ */
+public class TSAppConfig extends Application {
+
+  public java.util.Set<java.lang.Class<?>> getClasses() {
+    Set<Class<?>> resources = new HashSet<Class<?>>();
+    resources.add(ResponseTest.class);
+    resources.add(StringBeanHeaderDelegate.class);
+    resources.add(PrintingErrorHandler.class);
+    return resources;
+  }
+}
diff --git a/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/core/responsebuilder/AnnotatedClass.java b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/core/responsebuilder/AnnotatedClass.java
new file mode 100644
index 0000000..5e495b1
--- /dev/null
+++ b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/core/responsebuilder/AnnotatedClass.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2012, 2020 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 jakarta.ws.rs.tck.ee.rs.core.responsebuilder;
+
+import jakarta.ws.rs.Consumes;
+import jakarta.ws.rs.ext.Provider;
+
+@Provider
+@Consumes
+/**
+ * This is the dummy class to get annotations from it
+ */
+public abstract class AnnotatedClass {
+
+}
diff --git a/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/core/responsebuilder/DateClientReaderWriter.java b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/core/responsebuilder/DateClientReaderWriter.java
new file mode 100644
index 0000000..6c0db80
--- /dev/null
+++ b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/core/responsebuilder/DateClientReaderWriter.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2012, 2020 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 jakarta.ws.rs.tck.ee.rs.core.responsebuilder;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+import java.util.Date;
+
+import jakarta.ws.rs.WebApplicationException;
+import jakarta.ws.rs.core.MediaType;
+import jakarta.ws.rs.core.MultivaluedMap;
+import jakarta.ws.rs.ext.MessageBodyReader;
+import jakarta.ws.rs.ext.MessageBodyWriter;
+import jakarta.ws.rs.ext.Provider;
+
+@Provider
+public class DateClientReaderWriter
+    implements MessageBodyReader<Date>, MessageBodyWriter<Date> {
+  private StringBuilder atom;
+
+  public DateClientReaderWriter(StringBuilder atom) {
+    super();
+    this.atom = atom;
+  }
+
+  @Override
+  public long getSize(Date arg0, Class<?> arg1, Type arg2, Annotation[] arg3,
+      MediaType arg4) {
+    return String.valueOf(Long.MAX_VALUE).length()
+        + DateContainerReaderWriter.SPLITTER.length();
+  }
+
+  @Override
+  public boolean isWriteable(Class<?> arg0, Type arg1, Annotation[] arg2,
+      MediaType arg3) {
+    return arg0 == Date.class;
+  }
+
+  @Override
+  public void writeTo(Date date, Class<?> arg1, Type arg2, Annotation[] arg3,
+      MediaType arg4, MultivaluedMap<String, Object> arg5, OutputStream stream)
+      throws IOException, WebApplicationException {
+    stream.write(dateToString(date).getBytes());
+  }
+
+  @Override
+  public boolean isReadable(Class<?> arg0, Type arg1, Annotation[] arg2,
+      MediaType arg3) {
+    return isWriteable(arg0, arg1, arg2, arg3);
+  }
+
+  @Override
+  public Date readFrom(Class<Date> arg0, Type arg1, Annotation[] arg2,
+      MediaType arg3, MultivaluedMap<String, String> arg4, InputStream arg5)
+      throws IOException, WebApplicationException {
+    InputStreamReader reader = new InputStreamReader(arg5);
+    BufferedReader br = new BufferedReader(reader);
+    String data = br.readLine();
+    String[] split = data == null ? new String[] { "0" }
+        : data.split(DateContainerReaderWriter.SPLITTER);
+    long date = Long.parseLong(split[0]);
+    atom.append(split[1]);
+    return new Date(date);
+  }
+
+  public static final String dateToString(Date date) {
+    return String.valueOf(date.getTime());
+  }
+}
diff --git a/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/core/responsebuilder/DateContainerReaderWriter.java b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/core/responsebuilder/DateContainerReaderWriter.java
new file mode 100644
index 0000000..02f6865
--- /dev/null
+++ b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/core/responsebuilder/DateContainerReaderWriter.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2012, 2020 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 jakarta.ws.rs.tck.ee.rs.core.responsebuilder;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+import java.util.Date;
+
+import jakarta.ws.rs.WebApplicationException;
+import jakarta.ws.rs.core.MediaType;
+import jakarta.ws.rs.core.MultivaluedMap;
+import jakarta.ws.rs.ext.MessageBodyReader;
+import jakarta.ws.rs.ext.MessageBodyWriter;
+import jakarta.ws.rs.ext.Provider;
+
+@Provider
+public class DateContainerReaderWriter
+    implements MessageBodyReader<Date>, MessageBodyWriter<Date> {
+
+  public static final int ANNOTATION_NONE = 0;
+
+  public static final int ANNOTATION_CONSUMES = 1 << 2;
+
+  public static final int ANNOTATION_PROVIDER = 1 << 3;
+
+  public static final int ANNOTATION_UNKNOWN = 1 << 7;
+
+  public static final String SPLITTER = " ANNOTATION_VALUE ";
+
+  @Override
+  public long getSize(Date arg0, Class<?> arg1, Type arg2, Annotation[] arg3,
+      MediaType arg4) {
+    Annotation[] annotations = AnnotatedClass.class.getAnnotations();
+    return String.valueOf(Long.MAX_VALUE).length() + SPLITTER.length()
+        + annotations[0].annotationType().getName().length()
+        + annotations[1].annotationType().getName().length();
+  }
+
+  @Override
+  public boolean isWriteable(Class<?> arg0, Type arg1, Annotation[] arg2,
+      MediaType arg3) {
+    return arg0 == Date.class;
+  }
+
+  @Override
+  public void writeTo(Date date, Class<?> arg1, Type arg2, Annotation[] arg3,
+      MediaType arg4, MultivaluedMap<String, Object> arg5, OutputStream stream)
+      throws IOException, WebApplicationException {
+    String annotation = parseAnnotations(arg3);
+    stream.write(dateToString(date).getBytes());
+    stream.write(SPLITTER.getBytes());
+    stream.write(annotation.getBytes());
+  }
+
+  @Override
+  public boolean isReadable(Class<?> arg0, Type arg1, Annotation[] arg2,
+      MediaType arg3) {
+    return isWriteable(arg0, arg1, arg2, arg3);
+  }
+
+  @Override
+  public Date readFrom(Class<Date> arg0, Type arg1, Annotation[] arg2,
+      MediaType arg3, MultivaluedMap<String, String> arg4, InputStream arg5)
+      throws IOException, WebApplicationException {
+    InputStreamReader reader = new InputStreamReader(arg5);
+    BufferedReader br = new BufferedReader(reader);
+    long date = Long.parseLong(br.readLine());
+    return new Date(date);
+  }
+
+  protected String parseAnnotations(Annotation[] annotations) {
+    StringBuilder value = new StringBuilder();
+    if (annotations != null)
+      for (Annotation annotation : annotations)
+        value.append(annotation.annotationType().getName()).append(", ");
+    return value.toString();
+  }
+
+  public static final String dateToString(Date date) {
+    return String.valueOf(date.getTime());
+  }
+}
diff --git a/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/core/responsebuilder/JAXRSClientIT.java b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/core/responsebuilder/JAXRSClientIT.java
new file mode 100644
index 0000000..3e28970
--- /dev/null
+++ b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/core/responsebuilder/JAXRSClientIT.java
@@ -0,0 +1,140 @@
+/*
+ * Copyright (c) 2012, 2020 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 jakarta.ws.rs.tck.ee.rs.core.responsebuilder;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.Reader;
+import java.lang.annotation.Annotation;
+import java.util.Calendar;
+import java.util.Date;
+import java.io.InputStream;
+
+import jakarta.ws.rs.tck.common.client.JaxrsCommonClient;
+import jakarta.ws.rs.tck.lib.util.TestUtil;
+
+import jakarta.ws.rs.core.GenericType;
+import jakarta.ws.rs.core.Response;
+
+import org.jboss.arquillian.junit5.ArquillianExtension;
+import org.jboss.arquillian.container.test.api.Deployment;
+import org.jboss.shrinkwrap.api.ShrinkWrap;
+import org.jboss.shrinkwrap.api.asset.StringAsset;
+import org.jboss.shrinkwrap.api.spec.WebArchive;
+import org.jboss.shrinkwrap.api.exporter.ZipExporter;
+
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assertions.fail;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.junit.jupiter.api.TestInfo;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.AfterEach;
+
+/*
+ * @class.setup_props: webServerHost;
+ *                     webServerPort;
+ */
+@ExtendWith(ArquillianExtension.class)
+public class JAXRSClientIT extends JaxrsCommonClient {
+
+  private static final long serialVersionUID = 1L;
+
+  public JAXRSClientIT() {
+    setup();
+    setContextRoot("/jaxrs_ee_core_responsebuilder_web/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{
+
+    InputStream inStream = JAXRSClientIT.class.getClassLoader().getResourceAsStream("jakarta/ws/rs/tck/ee/rs/core/responsebuilder/web.xml.template");
+    String webXml = editWebXmlString(inStream);
+
+    WebArchive archive = ShrinkWrap.create(WebArchive.class, "jaxrs_ee_core_responsebuilder_web.war");
+    archive.addClasses(TSAppConfig.class, Resource.class, AnnotatedClass.class, DateContainerReaderWriter.class);
+    archive.setWebXML(new StringAsset(webXml));
+    return archive;
+
+  }
+
+
+  /* Run test */
+
+  /*
+   * @testName: entityObjectTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:879;
+   * 
+   * @test_Strategy: Set the message entity content encoding.
+   */
+  @Test
+  public void entityObjectTest() throws Fault {
+    Date date = Calendar.getInstance().getTime();
+    String entity = DateContainerReaderWriter.dateToString(date);
+    StringBuilder sb = new StringBuilder();
+    DateClientReaderWriter rw = new DateClientReaderWriter(sb);
+    addProvider(rw);
+
+    setProperty(Property.REQUEST, buildRequest(Request.POST, "entity"));
+    setProperty(Property.CONTENT, entity);
+    invoke();
+
+    Response response = getResponse();
+    Date responseDate = response.readEntity(Date.class);
+    assertTrue(date.equals(responseDate), "entity date"+ date+
+        "differs from acquired"+ responseDate);
+
+    Annotation[] annotations = AnnotatedClass.class.getAnnotations();
+    for (Annotation annotation : annotations) {
+      String name = annotation.annotationType().getName();
+      assertTrue(sb.toString().contains(name), sb+ "does not contain"+ name+
+          ", annotations not passed to MessageBodyWriter?");
+    }
+  }
+
+  // ////////////////////////////////////////////////////////////////////
+  protected <T> GenericType<T> generic(Class<T> clazz) {
+    return new GenericType<T>(clazz);
+  }
+
+  protected String readLine(Reader reader) throws Fault {
+    String line = null;
+    BufferedReader buffered = new BufferedReader(reader);
+    try {
+      line = buffered.readLine();
+    } catch (IOException e) {
+      try {
+        buffered.close();
+      } catch (IOException ie) {
+      }
+      throw new Fault(e);
+    }
+    return line;
+  }
+}
diff --git a/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/core/responsebuilder/Resource.java b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/core/responsebuilder/Resource.java
new file mode 100644
index 0000000..8bb17fd
--- /dev/null
+++ b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/core/responsebuilder/Resource.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2012, 2020 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 jakarta.ws.rs.tck.ee.rs.core.responsebuilder;
+
+import java.lang.annotation.Annotation;
+import java.util.Date;
+
+import jakarta.ws.rs.POST;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.core.Response;
+
+@Path("resource")
+public class Resource {
+  @POST
+  @Path("entity")
+  public Response entity(Date date) {
+    Annotation[] annotations = AnnotatedClass.class.getAnnotations();
+    Response response = Response.ok().entity(date, annotations).build();
+    return response;
+  }
+
+}
diff --git a/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/core/responsebuilder/TSAppConfig.java b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/core/responsebuilder/TSAppConfig.java
new file mode 100644
index 0000000..527a686
--- /dev/null
+++ b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/core/responsebuilder/TSAppConfig.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2012, 2020 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 jakarta.ws.rs.tck.ee.rs.core.responsebuilder;
+
+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(DateContainerReaderWriter.class);
+    return resources;
+  }
+}
diff --git a/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/core/securitycontext/JAXRSClient.java b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/core/securitycontext/JAXRSClient.java
new file mode 100644
index 0000000..32aba1c
--- /dev/null
+++ b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/core/securitycontext/JAXRSClient.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2012, 2020 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 jakarta.ws.rs.tck.ee.rs.core.securitycontext;
+
+import java.util.Properties;
+
+import org.apache.commons.httpclient.Header;
+
+import jakarta.ws.rs.tck.common.webclient.http.HttpResponse;
+import jakarta.ws.rs.tck.common.JAXRSCommonClient;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import jakarta.ws.rs.core.Response;
+
+/*
+ * @class.setup_props: webServerHost;
+ *                     webServerPort;
+ */
+public abstract class JAXRSClient extends JAXRSCommonClient {
+  private static final long serialVersionUID = 1L;
+
+  protected static final String URL = "Context";
+
+  protected HttpResponse response;
+
+  protected String wwwAuthenticate;
+
+  protected String user;
+
+  protected String password;
+
+  protected String authuser;
+
+  protected String authpassword;
+
+  public void setup() {
+    user = System.getProperty("user");
+    password = System.getProperty("password");
+    authuser = System.getProperty("authuser");
+    authpassword = System.getProperty("authpassword");
+    assertTrue(!isNullOrEmpty(user), "user was not set");
+    assertTrue(!isNullOrEmpty(password),
+        "password was not set");
+    assertTrue(!isNullOrEmpty(authuser),
+        "authuser was not set");
+    assertTrue(!isNullOrEmpty(authpassword),
+        "authpassword was not set");
+    super.setup();
+  }
+
+  public void noAuthorizationTest() throws Fault {
+    setProperty(STATUS_CODE, getStatusCode(Response.Status.UNAUTHORIZED));
+    invokeRequest();
+    assertTrue(wwwAuthenticate != null,
+        "Expected authentication request missing!");
+  }
+
+  protected void invokeRequest() throws Fault {
+    setProperty(REQUEST, buildRequest("GET", URL));
+    invoke();
+    response = _testCase.getResponse();
+    Header header = response.getResponseHeader("WWW-Authenticate");
+    wwwAuthenticate = header == null ? null : header.getValue();
+  }
+}
diff --git a/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/core/securitycontext/TSAppConfig.java b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/core/securitycontext/TSAppConfig.java
new file mode 100644
index 0000000..f7ef354
--- /dev/null
+++ b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/core/securitycontext/TSAppConfig.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2012, 2020 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 jakarta.ws.rs.tck.ee.rs.core.securitycontext;
+
+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(TestServlet.class);
+    return resources;
+  }
+}
diff --git a/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/core/securitycontext/TestServlet.java b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/core/securitycontext/TestServlet.java
new file mode 100644
index 0000000..c3b05ba
--- /dev/null
+++ b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/core/securitycontext/TestServlet.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2012, 2020 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 jakarta.ws.rs.tck.ee.rs.core.securitycontext;
+
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.core.Context;
+import jakarta.ws.rs.core.Response;
+import jakarta.ws.rs.core.SecurityContext;
+
+@Path("/Servlet")
+public class TestServlet {
+  public static enum Security {
+    SECURED, UNSECURED
+  };
+
+  public static enum Scheme {
+    BASIC, DIGEST, NOSCHEME
+  }
+
+  public static enum Role {
+    DIRECTOR, OTHERROLE, NOROLE
+  }
+
+  private static void addSecuredInfo(SecurityContext context,
+      StringBuilder sb) {
+    Security security;
+    security = context.isSecure() ? Security.SECURED : Security.UNSECURED;
+    sb.append(security).append("|");
+  }
+
+  private static void addSchemaInfo(SecurityContext context, StringBuilder sb) {
+    Scheme scheme;
+    String authScheme = context.getAuthenticationScheme();
+    if (authScheme == null)
+      scheme = Scheme.NOSCHEME;
+    else if (authScheme.equalsIgnoreCase(Scheme.BASIC.name()))
+      scheme = Scheme.BASIC;
+    else
+      scheme = Scheme.DIGEST;
+    sb.append(scheme).append("|");
+  }
+
+  private static void addRoleInfo(SecurityContext context, StringBuilder sb) {
+    java.security.Principal userPrincipal = context.getUserPrincipal();
+    String principal = userPrincipal == null ? "" : userPrincipal.getName();
+    sb.append(principal).append("|");
+  }
+
+  private static void addPrincipalInfo(SecurityContext context,
+      StringBuilder sb) {
+    Role role;
+    if (context.isUserInRole(Role.DIRECTOR.name()))
+      role = Role.DIRECTOR;
+    else if (context.isUserInRole(Role.OTHERROLE.name()))
+      role = Role.OTHERROLE;
+    else
+      role = Role.NOROLE;
+    sb.append(role).append("|");
+  }
+
+  @GET
+  @Path("/Context")
+  public Response test(@Context SecurityContext context) {
+    StringBuilder sb = new StringBuilder();
+    addSecuredInfo(context, sb);
+    addPrincipalInfo(context, sb);
+    addRoleInfo(context, sb);
+    addSchemaInfo(context, sb);
+    return Response.ok(sb.toString()).build();
+  }
+
+}
diff --git a/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/core/securitycontext/basic/JAXRSBasicClientIT.java b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/core/securitycontext/basic/JAXRSBasicClientIT.java
new file mode 100644
index 0000000..b692372
--- /dev/null
+++ b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/core/securitycontext/basic/JAXRSBasicClientIT.java
@@ -0,0 +1,173 @@
+/*
+ * Copyright (c) 2012, 2020 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 jakarta.ws.rs.tck.ee.rs.core.securitycontext.basic;
+
+import java.io.InputStream;
+import java.io.IOException;
+import jakarta.ws.rs.tck.lib.util.TestUtil;
+import jakarta.ws.rs.tck.ee.rs.core.securitycontext.TestServlet;
+import jakarta.ws.rs.tck.ee.rs.core.securitycontext.TestServlet.Scheme;
+
+import jakarta.ws.rs.core.Response;
+
+import org.jboss.arquillian.junit5.ArquillianExtension;
+import org.jboss.arquillian.container.test.api.Deployment;
+import org.jboss.shrinkwrap.api.ShrinkWrap;
+import org.jboss.shrinkwrap.api.asset.StringAsset;
+import org.jboss.shrinkwrap.api.spec.WebArchive;
+import org.jboss.shrinkwrap.api.exporter.ZipExporter;
+
+import static org.junit.jupiter.api.Assertions.fail;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.junit.jupiter.api.TestInfo;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.AfterEach;
+
+/*
+ * @class.setup_props: webServerHost;
+ *                     webServerPort;
+ *                     user;
+ *                     password;
+ *                     authuser;
+ *                     authpassword;
+ */
+@ExtendWith(ArquillianExtension.class)
+public class JAXRSBasicClientIT
+    extends jakarta.ws.rs.tck.ee.rs.core.securitycontext.JAXRSClient {
+
+  private static final long serialVersionUID = 340277879725875946L;
+
+  public JAXRSBasicClientIT() {
+    setup();
+    setContextRoot("/jaxrs_ee_core_securitycontext_basic_web/Servlet");
+  }
+
+  @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 {
+
+    InputStream inStream = JAXRSBasicClientIT.class.getClassLoader().getResourceAsStream("jakarta/ws/rs/tck/ee/rs/core/securitycontext/basic/web.xml.template");
+    String webXml = editWebXmlString(inStream);
+
+    WebArchive archive = ShrinkWrap.create(WebArchive.class, "jaxrs_ee_core_securitycontext_basic_web.war");
+    archive.addClasses(jakarta.ws.rs.tck.ee.rs.core.securitycontext.TSAppConfig.class, jakarta.ws.rs.tck.ee.rs.core.securitycontext.TestServlet.class);
+    archive.setWebXML(new StringAsset(webXml));
+    archive.addAsResource("jakarta/ws/rs/tck/ee/rs/core/securitycontext/basic/jaxrs_ee_core_securitycontext_basic_web.ear.sun-application.xml");
+    archive.addAsResource("jakarta/ws/rs/tck/ee/rs/core/securitycontext/basic/jaxrs_ee_core_securitycontext_basic_web.war.sun-web.xml");
+    return archive;
+
+  }
+
+  /* Run test */
+
+  /*
+   * @testName: noAuthorizationTest
+   * 
+   * @assertion_ids:
+   * 
+   * @test_Strategy: Send no authorization, make sure of 401 response
+   */
+  @Test
+  public void noAuthorizationTest() throws Fault {
+    super.noAuthorizationTest();
+  }
+
+  /*
+   * @testName: basicAuthorizationAdminTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:169; JAXRS:JAVADOC:170; JAXRS:JAVADOC:171;
+   * JAXRS:JAVADOC:172; JAXRS:SPEC:40;
+   * 
+   * @test_Strategy: Send basic authorization, check security context
+   */
+  //@Test
+  public void basicAuthorizationAdminTest() throws Fault {
+    setProperty(Property.STATUS_CODE, getStatusCode(Response.Status.OK));
+    setProperty(Property.BASIC_AUTH_USER, user);
+    setProperty(Property.BASIC_AUTH_PASSWD, password);
+
+    setProperty(Property.SEARCH_STRING, TestServlet.Security.UNSECURED.name());
+    setProperty(Property.SEARCH_STRING, TestServlet.Role.DIRECTOR.name());
+    setProperty(Property.SEARCH_STRING, user);
+    setProperty(Property.SEARCH_STRING, TestServlet.Scheme.BASIC.name());
+    invokeRequest();
+  }
+
+  /*
+   * @testName: basicAuthorizationIncorrectUserTest
+   * 
+   * @assertion_ids:
+   * 
+   * @test_Strategy: Send basic authorization, check security context
+   */
+  @Test
+  public void basicAuthorizationIncorrectUserTest() throws Fault {
+    setProperty(Property.STATUS_CODE,
+        getStatusCode(Response.Status.UNAUTHORIZED));
+    setProperty(Property.BASIC_AUTH_USER, Scheme.NOSCHEME.name());
+    setProperty(Property.BASIC_AUTH_PASSWD, password);
+    invokeRequest();
+  }
+
+  /*
+   * @testName: basicAuthorizationIncorrectPasswordTest
+   * 
+   * @assertion_ids:
+   * 
+   * @test_Strategy: Send basic authorization, check security context
+   */
+  @Test
+  public void basicAuthorizationIncorrectPasswordTest() throws Fault {
+    setProperty(Property.STATUS_CODE,
+        getStatusCode(Response.Status.UNAUTHORIZED));
+    setProperty(Property.BASIC_AUTH_USER, authuser);
+    setProperty(Property.BASIC_AUTH_PASSWD, password);
+    invokeRequest();
+  }
+
+  /*
+   * @testName: basicAuthorizationStandardUserTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:169; JAXRS:JAVADOC:170; JAXRS:JAVADOC:171;
+   * JAXRS:JAVADOC:172; JAXRS:SPEC:40;
+   * 
+   * @test_Strategy: Send basic authorization with made up Realm, check security
+   * context
+   */
+  //@Test
+  public void basicAuthorizationStandardUserTest() throws Fault {
+    setProperty(Property.STATUS_CODE, getStatusCode(Response.Status.OK));
+    setProperty(Property.BASIC_AUTH_USER, authuser);
+    setProperty(Property.BASIC_AUTH_PASSWD, authpassword);
+
+    setProperty(Property.SEARCH_STRING, TestServlet.Security.UNSECURED.name());
+    setProperty(Property.SEARCH_STRING, TestServlet.Role.OTHERROLE.name());
+    setProperty(Property.SEARCH_STRING, authuser);
+    setProperty(Property.SEARCH_STRING, TestServlet.Scheme.BASIC.name());
+    invokeRequest();
+  }
+}
diff --git a/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/core/securitycontext/common.xml b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/core/securitycontext/common.xml
new file mode 100644
index 0000000..3b846be
--- /dev/null
+++ b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/core/securitycontext/common.xml
@@ -0,0 +1,58 @@
+<!--
+
+    Copyright (c) 2012, 2018 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
+
+-->
+
+<project name="jaxrs_ee_core_securitycontext" basedir="." default="package" >    
+    <property name="resource.classes" 
+              value="com/sun/ts/tests/jaxrs/ee/rs/core/securitycontext/TestServlet.class,
+    				 com/sun/ts/tests/jaxrs/ee/rs/core/securitycontext/TestServlet$Security.class,
+    				 com/sun/ts/tests/jaxrs/ee/rs/core/securitycontext/TestServlet$Scheme.class,
+					 com/sun/ts/tests/jaxrs/ee/rs/core/securitycontext/TestServlet$Role.class,
+    				 com/sun/ts/tests/jaxrs/ee/rs/core/securitycontext/TestServlet$Principal.class"/>
+    <property name="appconfig.class"
+              value="com/sun/ts/tests/jaxrs/ee/rs/core/securitycontext/TSAppConfig.class" />
+              
+	<include file="../../../../common/common.xml"/>              
+                     
+	<target name="package" depends="build.TSAppConfig">
+		<ant antfile="${ts.home}/src/com/sun/ts/tests/jaxrs/common/common.xml" target="package"/>
+        <antcall target="copy.sun-web.xml"/>        
+        <antcall target="copy.sun-application.xml"/>        		   
+	</target>    
+	    
+    <target name="copy.sun-web.xml"> 
+        <copy failonerror="true" 
+        file="${app.name}_web.war.sun-web.xml" 
+        tofile="${ts.home}/dist/${pkg.dir}/${app.name}_web.war.sun-web.xml"/>
+    </target>
+    
+    <target name="copy.sun-application.xml">
+        <copy failonerror="true"
+              file="${app.name}_web.ear.sun-application.xml"
+              tofile="${ts.home}/dist/${pkg.dir}/${app.name}_web.ear.sun-application.xml" />    
+    </target>
+	
+	<target name="check.TSAppConfig.built">
+		<available file="${ts.home}/classes/${appconfig.class}" property="ts.app.config.present"/>
+	</target>
+	
+	<target name="build.TSAppConfig" depends="check.TSAppConfig.built" unless="ts.app.config.present">
+		<echo>BUILDING</echo>
+		<ant antfile="../build.xml" useNativeBasedir="true" target="compile"/>
+	</target>	
+    
+</project>
diff --git a/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/core/uriinfo/JAXRSClientIT.java b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/core/uriinfo/JAXRSClientIT.java
new file mode 100644
index 0000000..9d4a4e8
--- /dev/null
+++ b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/core/uriinfo/JAXRSClientIT.java
@@ -0,0 +1,432 @@
+/*
+ * Copyright (c) 2007, 2018 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 jakarta.ws.rs.tck.ee.rs.core.uriinfo;
+
+import jakarta.ws.rs.tck.common.JAXRSCommonClient;
+import jakarta.ws.rs.tck.lib.util.TestUtil;
+import java.io.InputStream;
+import java.io.IOException;
+
+import org.jboss.arquillian.junit5.ArquillianExtension;
+import org.jboss.arquillian.container.test.api.Deployment;
+import org.jboss.shrinkwrap.api.ShrinkWrap;
+import org.jboss.shrinkwrap.api.asset.StringAsset;
+import org.jboss.shrinkwrap.api.spec.WebArchive;
+import org.jboss.shrinkwrap.api.exporter.ZipExporter;
+
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assertions.fail;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.junit.jupiter.api.TestInfo;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.AfterEach;
+
+/*
+ * @class.setup_props: webServerHost;
+ *                     webServerPort;
+ */
+@ExtendWith(ArquillianExtension.class)
+public class JAXRSClientIT extends JAXRSCommonClient {
+
+  private static final long serialVersionUID = -5479757659703717839L;
+
+  protected static final String ROOT = "jaxrs_ee_core_uriinfo_web";
+
+  protected static final String RESOURCE = "resource";
+
+  public JAXRSClientIT() {
+    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{
+
+    InputStream inStream = JAXRSClientIT.class.getClassLoader().getResourceAsStream("jakarta/ws/rs/tck/ee/rs/core/uriinfo/web.xml.template");
+    String webXml = editWebXmlString(inStream);
+
+    WebArchive archive = ShrinkWrap.create(WebArchive.class, "jaxrs_ee_core_uriinfo_web.war");
+    archive.addClasses(TSAppConfig.class, URIInfoTest.class);
+    archive.setWebXML(new StringAsset(webXml));
+    return archive;
+
+  }
+
+
+  /* Run test */
+
+  /*
+   * @testName: queryTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:249; JAXRS:JAVADOC:97;
+   * 
+   * @test_Strategy: Client send a request with query parameters to a resource,
+   * which handles the request using UriInfo. Verify that
+   * UriInfo.getQueryParameters() works.
+   */
+  @Test
+  public void queryTest() throws Fault {
+    setProperty(Property.REQUEST,
+        buildRequest(GET, "query?stringtest=cts&inttest=-2147483648?"));
+    setProperty(Property.UNORDERED_SEARCH_STRING,
+        "stringtest=cts|inttest=-2147483648?");
+    invoke();
+  }
+
+  /*
+   * @testName: queryTest1
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:250; JAXRS:JAVADOC:97;
+   * 
+   * @test_Strategy: Client send a request with query parameters to a resource,
+   * which handles the request using UriInfo. Verify that
+   * UriInfo.getQueryParameters(true) works.
+   */
+  @Test
+  public void queryTest1() throws Fault {
+    setProperty(Property.REQUEST, buildRequest(GET,
+        "query1?stringtest=cts%20&inttest=-2147483648?%2010"));
+    setProperty(Property.UNORDERED_SEARCH_STRING,
+        "stringtest=cts |inttest=-2147483648? 10");
+    invoke();
+  }
+
+  /*
+   * @testName: queryTest2
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:250; JAXRS:JAVADOC:97;
+   * 
+   * @test_Strategy: Client send a request with query parameters to a resource,
+   * which handles the request using UriInfo. Verify that
+   * UriInfo.getQueryParameters(false) works.
+   */
+  @Test
+  public void queryTest2() throws Fault {
+    setProperty(Property.REQUEST,
+        buildRequest(GET, "query2?stringtest=cts%20&inttest=-2147483648%2010"));
+    setProperty(Property.UNORDERED_SEARCH_STRING,
+        "stringtest=cts%20|inttest=-2147483648%2010");
+    invoke();
+  }
+
+  /*
+   * @testName: aPathTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:236; JAXRS:JAVADOC:237;
+   * 
+   * @test_Strategy: Client send a request to a resource, which handles the
+   * request using UriInfo. Verify that UriInfo.getAbsolutePath() and
+   * getAbsolutePathBuilder() work.
+   */
+  @Test
+  public void aPathTest() throws Fault {
+    setProperty(Property.REQUEST, buildRequest(GET, "apath"));
+    setProperty(Property.SEARCH_STRING,
+        "http://" + _hostname + ":" + _port + getContextRoot() + "/apath");
+    setProperty(Property.UNEXPECTED_RESPONSE_MATCH, "FAILED");
+    invoke();
+  }
+
+  /*
+   * @testName: baseUriTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:238; JAXRS:JAVADOC:239;
+   * 
+   * @test_Strategy: Client send a request to a resource, which handles the
+   * request using UriInfo. Verify that UriInfo.getBaseUri() and
+   * getBaseUriBuilder() work.
+   */
+  @Test
+  public void baseUriTest() throws Fault {
+    setProperty(Property.REQUEST, buildRequest(GET, "baseuri"));
+    setProperty(Property.SEARCH_STRING,
+        "http://" + _hostname + ":" + _port + "/" + ROOT);
+    setProperty(Property.UNEXPECTED_RESPONSE_MATCH, "FAILED");
+    invoke();
+  }
+
+  /*
+   * @testName: pathTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:243;
+   * 
+   * @test_Strategy: Client send a request to a resource, which handles the
+   * request using UriInfo. Verify that UriInfo.getPath() work.
+   */
+  @Test
+  public void pathTest() throws Fault {
+    setProperty(Property.REQUEST, buildRequest(GET, "path"));
+    setProperty(Property.SEARCH_STRING, RESOURCE + "/path");
+    setProperty(Property.UNEXPECTED_RESPONSE_MATCH, ROOT);
+    invoke();
+  }
+
+  /*
+   * @testName: pathTest1
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:244;
+   * 
+   * @test_Strategy: Client send a request to a resource, which handles the
+   * request using UriInfo. Verify that UriInfo.getPath(true) work.
+   */
+  @Test
+  public void pathTest1() throws Fault {
+    setProperty(Property.REQUEST, buildRequest(GET, "path1%20/%2010"));
+    setProperty(Property.SEARCH_STRING, RESOURCE + "/path1 / 10");
+    setProperty(Property.UNEXPECTED_RESPONSE_MATCH, ROOT);
+    invoke();
+  }
+
+  /*
+   * @testName: pathTest2
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:244;
+   * 
+   * @test_Strategy: Client send a request to a resource, which handles the
+   * request using UriInfo. Verify that UriInfo.getPath(false) work.
+   */
+  @Test
+  public void pathTest2() throws Fault {
+    setProperty(Property.REQUEST, buildRequest(GET, "path2%20/%2010"));
+    setProperty(Property.SEARCH_STRING, RESOURCE + "/path2%20/%2010");
+    setProperty(Property.UNEXPECTED_RESPONSE_MATCH, ROOT);
+    invoke();
+  }
+
+  /*
+   * @testName: pathSegTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:247;
+   * 
+   * @test_Strategy: Client send a request to a resource, which handles the
+   * request using UriInfo. Verify that UriInfo.getPathSegments() work.
+   */
+  @Test
+  public void pathSegTest() throws Fault {
+    setProperty(Property.REQUEST, buildRequest(GET, "pathseg"));
+    setProperty(Property.UNORDERED_SEARCH_STRING, RESOURCE);
+    setProperty(Property.UNORDERED_SEARCH_STRING, "pathseg");
+    setProperty(Property.UNEXPECTED_RESPONSE_MATCH, ROOT);
+    invoke();
+  }
+
+  /*
+   * @testName: pathSegTest1
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:248;
+   * 
+   * @test_Strategy: Client send a request to a resource, which handles the
+   * request using UriInfo. Verify that UriInfo.getPathSegments(true) work.
+   */
+  @Test
+  public void pathSegTest1() throws Fault {
+    setProperty(Property.REQUEST, buildRequest(GET, "pathseg1%20/%2010"));
+    setProperty(Property.UNORDERED_SEARCH_STRING, RESOURCE);
+    setProperty(Property.UNORDERED_SEARCH_STRING, "pathseg1 / 10/");
+    setProperty(Property.UNEXPECTED_RESPONSE_MATCH, ROOT);
+    invoke();
+  }
+
+  /*
+   * @testName: pathSegTest2
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:248;
+   * 
+   * @test_Strategy: Client send a request to a resource, which handles the
+   * request using UriInfo. Verify that UriInfo.getPathSegments(false) work.
+   */
+  @Test
+  public void pathSegTest2() throws Fault {
+    setProperty(Property.REQUEST, buildRequest(GET, "pathseg2%20/%2010"));
+    setProperty(Property.UNORDERED_SEARCH_STRING, RESOURCE);
+    setProperty(Property.UNORDERED_SEARCH_STRING, "pathseg2%20/%2010/");
+    setProperty(Property.UNEXPECTED_RESPONSE_MATCH, ROOT);
+    invoke();
+  }
+
+  /*
+   * @testName: pathParamTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:245; JAXRS:JAVADOC:97;
+   * 
+   * @test_Strategy: Client send a request to a resource, which handles the
+   * request using UriInfo. Verify that UriInfo.getPathParameters() work.
+   */
+  @Test
+  public void pathParamTest() throws Fault {
+    setProperty(Property.REQUEST, buildRequest(GET, "pathparam/a/b"));
+    setProperty(Property.UNORDERED_SEARCH_STRING, "a=a|b=b");
+    invoke();
+  }
+
+  /*
+   * @testName: pathParamTest1
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:246; JAXRS:JAVADOC:97;
+   * 
+   * @test_Strategy: Client send a request to a resource, which handles the
+   * request using UriInfo. Verify that UriInfo.getPathParameters(true) work.
+   */
+  @Test
+  public void pathParamTest1() throws Fault {
+    setProperty(Property.REQUEST, buildRequest(GET, "pathparam1/%20/%2010"));
+    setProperty(Property.UNORDERED_SEARCH_STRING, "a= |b= 10");
+    setProperty(Property.UNEXPECTED_RESPONSE_MATCH, ROOT);
+    invoke();
+  }
+
+  /*
+   * @testName: pathParamTest2
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:246; JAXRS:JAVADOC:97;
+   * 
+   * @test_Strategy: Client send a request to a resource, which handles the
+   * request using UriInfo. Verify that UriInfo.getPathParameters(false) work.
+   */
+  @Test
+  public void pathParamTest2() throws Fault {
+    setProperty(Property.REQUEST, buildRequest(GET, "pathparam2/%20/%2010"));
+    setProperty(Property.UNORDERED_SEARCH_STRING, "a=%20|b=%2010");
+    setProperty(Property.UNEXPECTED_RESPONSE_MATCH, ROOT);
+    invoke();
+  }
+
+  /*
+   * @testName: requestURITest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:251; JAXRS:JAVADOC:252;
+   * 
+   * @test_Strategy: Client send a request with query parameters to a resource,
+   * which handles the request using UriInfo. Verify that getRequestUri() and
+   * getRequestUriBuilder() work.
+   */
+  @Test
+  public void requestURITest() throws Fault {
+    setProperty(Property.REQUEST,
+        buildRequest(GET, "request?stringtest=cts&inttest=-2147483648"));
+    setProperty(Property.UNORDERED_SEARCH_STRING,
+        "http://" + _hostname + ":" + _port + getContextRoot()
+            + "/request?stringtest=cts&inttest=-2147483648");
+    setProperty(Property.UNEXPECTED_RESPONSE_MATCH, "FAILED");
+    invoke();
+  }
+
+  /*
+   * @testName: getMatchedResourcesTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:240; JAXRS:SPEC:40;
+   * 
+   * @test_Strategy: Client send a request with query parameters to a resource,
+   * which handles the request using UriInfo. Verify that getMatchedResources()
+   * work.
+   */
+  @Test
+  public void getMatchedResourcesTest() throws Fault {
+    setProperty(Property.REQUEST, buildRequest(GET, "resource"));
+    setProperty(Property.SEARCH_STRING, URIInfoTest.class.getName());
+    invoke();
+  }
+
+  /*
+   * @testName: getMatchedURIsTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:241;
+   * 
+   * @test_Strategy: Client send a request with query parameters to a resource,
+   * which handles the request using UriInfo. Verify that getMatchedURIs() work.
+   */
+  @Test
+  public void getMatchedURIsTest() throws Fault {
+    setProperty(Property.REQUEST, buildRequest(GET, "uri"));
+    setProperty(Property.SEARCH_STRING, RESOURCE + "/uri");
+    setProperty(Property.SEARCH_STRING, RESOURCE);
+    setProperty(Property.SEARCH_STRING, "number=2");
+    invoke();
+  }
+
+  /*
+   * @testName: getMatchedURIsTest1
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:242;
+   * 
+   * @test_Strategy: Client send a request with query parameters to a resource,
+   * which handles the request using UriInfo. Verify that getMatchedURIs(true)
+   * work.
+   */
+  @Test
+  public void getMatchedURIsTest1() throws Fault {
+    setProperty(Property.REQUEST, buildRequest(GET, "uri1"));
+    setProperty(Property.SEARCH_STRING, RESOURCE + "/uri1");
+    setProperty(Property.SEARCH_STRING, RESOURCE);
+    setProperty(Property.SEARCH_STRING, "number=2");
+    invoke();
+  }
+
+  /*
+   * @testName: getMatchedURIsTest2
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:242;
+   * 
+   * @test_Strategy: Client send a request with query parameters to a resource,
+   * which handles the request using UriInfo. Verify that getMatchedURIs(false)
+   * work.
+   */
+  @Test
+  public void getMatchedURIsTest2() throws Fault {
+    setProperty(Property.REQUEST, buildRequest(GET, "uri2"));
+    setProperty(Property.SEARCH_STRING, RESOURCE + "/uri2");
+    setProperty(Property.SEARCH_STRING, RESOURCE);
+    setProperty(Property.SEARCH_STRING, "number=2");
+    invoke();
+  }
+
+  /*
+   * @testName: getNormalizedUriTest
+   * 
+   * @assertion_ids: JAXRS:SPEC:61;
+   * 
+   * @test_Strategy: The normalized request URI MUST be reflected in the URIs
+   * obtained from an injected UriInfo
+   */
+  @Test
+  public void getNormalizedUriTest() throws Fault {
+    setProperty(Property.REQUEST, buildRequest(GET, URIInfoTest.DECODED));
+    invoke();
+    assertBodyGreaterThanOne();
+
+    setProperty(Property.REQUEST, buildRequest(GET, URIInfoTest.ENCODED));
+    invoke();
+    assertBodyGreaterThanOne();
+  }
+
+  private void assertBodyGreaterThanOne() throws Fault {
+    int i = Integer.parseInt(getResponseBody());
+    assertTrue(i > 1, "Got unexpected response body"+ getResponseBody());
+  }
+}
diff --git a/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/core/uriinfo/TSAppConfig.java b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/core/uriinfo/TSAppConfig.java
new file mode 100644
index 0000000..346b2e7
--- /dev/null
+++ b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/core/uriinfo/TSAppConfig.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2007, 2020 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 jakarta.ws.rs.tck.ee.rs.core.uriinfo;
+
+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(URIInfoTest.class);
+    return resources;
+  }
+}
diff --git a/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/core/uriinfo/URIInfoTest.java b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/core/uriinfo/URIInfoTest.java
new file mode 100644
index 0000000..e744479
--- /dev/null
+++ b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/core/uriinfo/URIInfoTest.java
@@ -0,0 +1,244 @@
+/*
+ * Copyright (c) 2007, 2020 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 jakarta.ws.rs.tck.ee.rs.core.uriinfo;
+
+import java.net.URI;
+
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.core.Context;
+import jakarta.ws.rs.core.PathSegment;
+import jakarta.ws.rs.core.UriBuilder;
+import jakarta.ws.rs.core.UriInfo;
+
+@Path(value = "resource")
+public class URIInfoTest {
+
+  @GET
+  @Path("/query")
+  public String queryTest(@Context UriInfo info) {
+    StringBuilder buf = new StringBuilder();
+    for (String param : info.getQueryParameters().keySet()) {
+      buf.append(param + "=" + info.getQueryParameters().getFirst(param));
+    }
+    return buf.toString();
+  }
+
+  @GET
+  @Path("/query1")
+  public String queryTest1(@Context UriInfo info) {
+    StringBuilder buf = new StringBuilder();
+    for (String param : info.getQueryParameters(true).keySet()) {
+      buf.append(param + "=" + info.getQueryParameters(true).getFirst(param));
+    }
+    return buf.toString();
+  }
+
+  @GET
+  @Path("/query2")
+  public String queryTest2(@Context UriInfo info) {
+    StringBuilder buf = new StringBuilder();
+    for (String param : info.getQueryParameters(false).keySet()) {
+      buf.append(param + "=" + info.getQueryParameters(false).getFirst(param));
+    }
+    return buf.toString();
+  }
+
+  @GET
+  @Path("/apath")
+  public String apathTest(@Context UriInfo info) {
+    StringBuilder sb = new StringBuilder();
+    URI uri = info.getAbsolutePath();
+    UriBuilder urib = info.getAbsolutePathBuilder();
+
+    sb.append(uri.toString());
+    if (!uri.toString().equals(urib.build().toString())) {
+      sb.append("Got unexpected = " + urib.build().toString());
+      sb.append("FAILED");
+    }
+    return sb.toString();
+  }
+
+  @GET
+  @Path("/path")
+  public String pathTest(@Context UriInfo info) {
+    return info.getPath();
+  }
+
+  @GET
+  @Path("/path1%20/%2010")
+  public String pathTest1(@Context UriInfo info) {
+    return info.getPath(true);
+  }
+
+  @GET
+  @Path("/path2%20/%2010")
+  public String pathTest2(@Context UriInfo info) {
+    return info.getPath(false);
+  }
+
+  @GET
+  @Path("/baseuri")
+  public String baseUriTest(@Context UriInfo info) {
+    StringBuilder sb = new StringBuilder();
+    URI uri = info.getBaseUri();
+    UriBuilder urib = info.getBaseUriBuilder();
+
+    sb.append(uri.toString());
+    if (!uri.toString().equals(urib.build().toString())) {
+      sb.append("Got unexpected = " + urib.build().toString());
+      sb.append("FAILED");
+    }
+    return sb.toString();
+  }
+
+  @GET
+  @Path("/pathparam/{a}/{b}")
+  public String pathparamTest(@Context UriInfo info) {
+    StringBuilder buf = new StringBuilder();
+    for (String param : info.getPathParameters().keySet()) {
+      buf.append(param + "=" + info.getPathParameters().getFirst(param));
+    }
+    return buf.toString();
+  }
+
+  @GET
+  @Path("/pathparam1/{a}/{b}")
+  public String pathparamTest1(@Context UriInfo info) {
+    StringBuilder buf = new StringBuilder();
+    for (String param : info.getPathParameters(true).keySet()) {
+      buf.append(param + "=" + info.getPathParameters(true).getFirst(param));
+    }
+    return buf.toString();
+  }
+
+  @GET
+  @Path("/pathparam2/{a}/{b}")
+  public String pathparamTest2(@Context UriInfo info) {
+    StringBuilder buf = new StringBuilder();
+    for (String param : info.getPathParameters(false).keySet()) {
+      buf.append(param + "=" + info.getPathParameters(false).getFirst(param));
+    }
+    return buf.toString();
+  }
+
+  @GET
+  @Path("/pathseg")
+  public String pathsegTest(@Context UriInfo info) {
+    StringBuilder buf = new StringBuilder();
+    for (PathSegment param : info.getPathSegments()) {
+      buf.append(param.getPath() + "/");
+    }
+    return buf.toString();
+  }
+
+  @GET
+  @Path("/pathseg1%20/%2010")
+  public String pathsegTest1(@Context UriInfo info) {
+    StringBuilder buf = new StringBuilder();
+    for (PathSegment param : info.getPathSegments(true)) {
+      buf.append(param.getPath() + "/");
+    }
+    return buf.toString();
+  }
+
+  @GET
+  @Path("/pathseg2%20/%2010")
+  public String pathsegTest2(@Context UriInfo info) {
+    StringBuilder buf = new StringBuilder();
+    for (PathSegment param : info.getPathSegments(false)) {
+      buf.append(param.getPath() + "/");
+    }
+    return buf.toString();
+  }
+
+  @GET
+  @Path("/request")
+  public String requestTest(@Context UriInfo info) {
+    StringBuilder sb = new StringBuilder();
+    URI uri = info.getRequestUri();
+    UriBuilder urib = info.getRequestUriBuilder();
+
+    sb.append(uri.toString());
+    if (!uri.toString().equals(urib.build().toString())) {
+      sb.append("Got unexpected = " + urib.build().toString());
+      sb.append("FAILED");
+    }
+    return sb.toString();
+  }
+
+  @GET
+  @Path("/resource")
+  public String resourcesTest(@Context UriInfo info) {
+    StringBuilder buf = new StringBuilder();
+    for (Object resource : info.getMatchedResources()) {
+      buf.append(resource.toString() + "=");
+    }
+    buf.append("number=" + info.getMatchedResources().size());
+    return buf.toString();
+  }
+
+  @GET
+  @Path("/uri")
+  public String urisTest(@Context UriInfo info) {
+    StringBuilder buf = new StringBuilder();
+    for (Object resource : info.getMatchedURIs()) {
+      buf.append(resource.toString() + "=");
+    }
+    buf.append("number=" + info.getMatchedURIs().size());
+    return buf.toString();
+  }
+
+  @GET
+  @Path("/uri1")
+  public String urisTest1(@Context UriInfo info) {
+    StringBuilder buf = new StringBuilder();
+    for (String resource : info.getMatchedURIs(true)) {
+      buf.append(resource + "=");
+    }
+    buf.append("number=" + info.getMatchedURIs(true).size());
+    return buf.toString();
+  }
+
+  @GET
+  @Path("/uri2")
+  public String urisTest2(@Context UriInfo info) {
+    StringBuilder buf = new StringBuilder();
+    for (String resource : info.getMatchedURIs(false)) {
+      buf.append(resource + "=");
+    }
+    buf.append("number=" + info.getMatchedURIs(false).size());
+    return buf.toString();
+  }
+
+  public static final String ENCODED = "%50%51%52%30%39%70%71%72/%7e%2d%2E%5f";
+
+  public static final String DECODED = "PQR09pqr/~-._";
+
+  @GET
+  @Path("{id1}/{id2}")
+  public String normalizedUri(@Context UriInfo info) {
+    int ret = 1;
+    if (!info.getAbsolutePath().toString().contains(ENCODED))
+      ret += 10;
+    if (!info.getPath().toString().contains(ENCODED))
+      ret += 100;
+    if (!info.getRequestUri().toString().contains(ENCODED))
+      ret += 1000;
+    return String.valueOf(ret);
+  }
+}
diff --git a/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/contextresolver/EnumContextResolver.java b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/contextresolver/EnumContextResolver.java
new file mode 100644
index 0000000..9a3532e
--- /dev/null
+++ b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/contextresolver/EnumContextResolver.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2012, 2020 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 jakarta.ws.rs.tck.ee.rs.ext.contextresolver;
+
+import jakarta.ws.rs.ext.ContextResolver;
+import jakarta.ws.rs.ext.Provider;
+
+/**
+ * This class is used by
+ * jakarta.ws.rs.tck.ee.rs.ext.providers.ProvidersServlet
+ */
+@Provider
+public class EnumContextResolver implements ContextResolver<EnumProvider> {
+
+  @Override
+  public EnumProvider getContext(Class<?> type) {
+    return type == EnumProvider.class ? EnumProvider.JAXRS : null;
+  }
+
+}
diff --git a/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/contextresolver/EnumProvider.java b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/contextresolver/EnumProvider.java
new file mode 100644
index 0000000..e0b69e5
--- /dev/null
+++ b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/contextresolver/EnumProvider.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2012, 2018 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 jakarta.ws.rs.tck.ee.rs.ext.contextresolver;
+
+/**
+ * This class is used by
+ * jakarta.ws.rs.tck.ee.rs.ext.providers.ProvidersServlet
+ */
+public enum EnumProvider {
+  TCK, CTS, JAXRS;
+}
diff --git a/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/contextresolver/TextPlainEnumContextResolver.java b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/contextresolver/TextPlainEnumContextResolver.java
new file mode 100644
index 0000000..5ade242
--- /dev/null
+++ b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/contextresolver/TextPlainEnumContextResolver.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2012, 2020 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 jakarta.ws.rs.tck.ee.rs.ext.contextresolver;
+
+import jakarta.ws.rs.Produces;
+import jakarta.ws.rs.core.MediaType;
+import jakarta.ws.rs.ext.ContextResolver;
+import jakarta.ws.rs.ext.Provider;
+
+/**
+ * This class is used by
+ * jakarta.ws.rs.tck.ee.rs.ext.providers.ProvidersServlet
+ */
+@Provider
+@Produces(MediaType.TEXT_PLAIN)
+public class TextPlainEnumContextResolver
+    implements ContextResolver<EnumProvider> {
+  @Override
+  public EnumProvider getContext(Class<?> type) {
+    return type == EnumProvider.class ? EnumProvider.CTS : null;
+  }
+}
diff --git a/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/exceptionmapper/AnyExceptionExceptionMapper.java b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/exceptionmapper/AnyExceptionExceptionMapper.java
new file mode 100644
index 0000000..6065478
--- /dev/null
+++ b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/exceptionmapper/AnyExceptionExceptionMapper.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2012, 2020 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 jakarta.ws.rs.tck.ee.rs.ext.exceptionmapper;
+
+import java.io.IOException;
+
+import jakarta.ws.rs.WebApplicationException;
+import jakarta.ws.rs.core.Response;
+import jakarta.ws.rs.core.Response.Status;
+import jakarta.ws.rs.ext.ExceptionMapper;
+import jakarta.ws.rs.ext.Provider;
+
+/**
+ * This class is used by
+ * jakarta.ws.rs.tck.ee.rs.ext.providers.ProvidersServlet
+ */
+@Provider
+public class AnyExceptionExceptionMapper implements ExceptionMapper<Exception> {
+
+  @Override
+  public Response toResponse(Exception arg0) {
+    Status status = Status.NO_CONTENT;
+    if (arg0 instanceof WebApplicationException)
+      return ((WebApplicationException) arg0).getResponse();
+    else if (arg0 instanceof RuntimeException)
+      throw new RuntimeException("CTS Test RuntimeException", arg0);
+    else if (arg0 instanceof IOException)
+      status = Status.SERVICE_UNAVAILABLE;
+    else if (arg0 != null)
+      status = Status.NOT_ACCEPTABLE;
+    return Response.status(status).build();
+  }
+
+}
diff --git a/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/exceptionmapper/IOExceptionExceptionMapper.java b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/exceptionmapper/IOExceptionExceptionMapper.java
new file mode 100644
index 0000000..3d37bbe
--- /dev/null
+++ b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/exceptionmapper/IOExceptionExceptionMapper.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2012, 2020 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 jakarta.ws.rs.tck.ee.rs.ext.exceptionmapper;
+
+import java.io.IOException;
+
+import jakarta.ws.rs.core.Response;
+import jakarta.ws.rs.core.Response.Status;
+import jakarta.ws.rs.ext.ExceptionMapper;
+import jakarta.ws.rs.ext.Provider;
+
+/**
+ * This class is used by
+ * jakarta.ws.rs.tck.ee.rs.ext.providers.ProvidersServlet
+ */
+@Provider
+public class IOExceptionExceptionMapper
+    implements ExceptionMapper<IOException> {
+
+  @Override
+  public Response toResponse(IOException exception) {
+    return Response.status(Status.ACCEPTED).build();
+  }
+
+}
diff --git a/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/interceptor/clientwriter/WriterClient.java b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/interceptor/clientwriter/WriterClient.java
new file mode 100644
index 0000000..f0a4b6f
--- /dev/null
+++ b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/interceptor/clientwriter/WriterClient.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2012, 2018 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 jakarta.ws.rs.tck.ee.rs.ext.interceptor.clientwriter;
+
+import java.io.IOException;
+
+import jakarta.ws.rs.tck.api.rs.ext.interceptor.TemplateInterceptorBody;
+import jakarta.ws.rs.tck.common.client.JaxrsCommonClient;
+
+/**
+ * Client with given ContextOperation enum, so that an enum name is passed as a
+ * http header to an interceptor. Due to the ContextOperation, the proper method
+ * on an interceptor is called.
+ * 
+ * @param <CONTEXTOPERATION>
+ */
+public abstract class WriterClient<CONTEXTOPERATION extends Enum<?>>
+    extends JaxrsCommonClient {
+
+  private static final long serialVersionUID = 8110273180216593061L;
+
+  /**
+   * Set the header OPERATION to a proper value Also set the entity, it is good
+   * as it is here for most of the tests. For the rest, the entity needs to be
+   * replaced.
+   */
+  protected void setOperationAndEntity(CONTEXTOPERATION op) {
+    addHeader(TemplateInterceptorBody.OPERATION, op.name());
+    setRequestContentEntity(TemplateInterceptorBody.ENTITY);
+  }
+
+  /**
+   * Invoke and convert IOException to Fault
+   */
+  protected void invoke() throws Fault {
+    try {
+      setProperty(Property.REQUEST, buildRequest(Request.POST, ""));
+      super.invoke();
+    } catch (Exception cause) {
+      if (cause instanceof IOException)
+        throw new Fault(cause.getMessage());
+      else
+        throw new Fault(cause);
+    }
+  }
+
+  /**
+   * Register providers to client configuration
+   * 
+   * @param response
+   *          ClientRequestFilter#abortWith response
+   */
+  protected abstract void addProviders();
+}
diff --git a/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/interceptor/clientwriter/interceptorcontext/JAXRSClientIT.java b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/interceptor/clientwriter/interceptorcontext/JAXRSClientIT.java
new file mode 100644
index 0000000..fdb6680
--- /dev/null
+++ b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/interceptor/clientwriter/interceptorcontext/JAXRSClientIT.java
@@ -0,0 +1,383 @@
+/*
+ * Copyright (c) 2012, 2020 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 jakarta.ws.rs.tck.ee.rs.ext.interceptor.clientwriter.interceptorcontext;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.lang.annotation.Annotation;
+import java.io.InputStream;
+
+import jakarta.ws.rs.tck.api.rs.ext.interceptor.ContextOperation;
+import jakarta.ws.rs.tck.api.rs.ext.interceptor.InputStreamReaderProvider;
+import jakarta.ws.rs.tck.api.rs.ext.interceptor.TemplateInterceptorBody;
+import jakarta.ws.rs.tck.common.util.JaxrsUtil;
+import jakarta.ws.rs.tck.lib.util.TestUtil;
+import jakarta.ws.rs.tck.ee.rs.ext.interceptor.clientwriter.WriterClient;
+import jakarta.ws.rs.tck.ee.rs.ext.interceptor.writer.interceptorcontext.WriterInterceptorOne;
+import jakarta.ws.rs.tck.ee.rs.ext.interceptor.writer.interceptorcontext.WriterInterceptorTwo;
+
+import jakarta.ws.rs.client.Entity;
+import jakarta.ws.rs.core.MediaType;
+
+import org.jboss.arquillian.junit5.ArquillianExtension;
+import org.jboss.arquillian.container.test.api.Deployment;
+import org.jboss.shrinkwrap.api.ShrinkWrap;
+import org.jboss.shrinkwrap.api.asset.StringAsset;
+import org.jboss.shrinkwrap.api.spec.WebArchive;
+import org.jboss.shrinkwrap.api.exporter.ZipExporter;
+
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assertions.fail;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.junit.jupiter.api.TestInfo;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.AfterEach;
+
+/*
+ * @class.setup_props: webServerHost;
+ *                     webServerPort;
+ */
+@ExtendWith(ArquillianExtension.class)
+public class JAXRSClientIT extends WriterClient<ContextOperation> {
+
+  private static final long serialVersionUID = -5479399808367387477L;
+
+  public JAXRSClientIT() {
+    setup();
+    setContextRoot(
+        "/jaxrs_ee_rs_ext_interceptor_clientwriter_interceptorcontext_web/resource");
+    addProviders();
+  }
+
+  @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{
+
+    InputStream inStream = JAXRSClientIT.class.getClassLoader().getResourceAsStream("jakarta/ws/rs/tck/ee/rs/ext/interceptor/clientwriter/interceptorcontext/web.xml.template");
+    String webXml = editWebXmlString(inStream);
+
+    WebArchive archive = ShrinkWrap.create(WebArchive.class, "jaxrs_ee_rs_ext_interceptor_clientwriter_interceptorcontext_web.war");
+    archive.addClasses(TSAppConfig.class, Resource.class);
+    archive.setWebXML(new StringAsset(webXml));
+    return archive;
+
+  }
+
+
+  /* Run test */
+  /*
+   * @testName: getAnnotationsTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:903; JAXRS:JAVADOC:930;
+   * 
+   * @test_Strategy: Get an array of the annotations formally declared on the
+   * artifact that initiated the intercepted entity provider invocation.
+   *
+   * WriterInterceptor.aroundWriteTo
+   */
+  @Test
+  public void getAnnotationsTest() throws Fault {
+    Annotation[] annotations = ContextOperation.class.getAnnotations();
+    Entity<String> entity = Entity.entity(TemplateInterceptorBody.ENTITY,
+        MediaType.WILDCARD_TYPE, annotations);
+    setOperationAndEntity(ContextOperation.GETANNOTATIONS);
+    setRequestContentEntity(entity);
+    for (Annotation a : annotations)
+      setProperty(Property.UNORDERED_SEARCH_STRING,
+          a.annotationType().getName());
+    invoke();
+  }
+
+  /*
+   * @testName: getGenericTypeTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:904; JAXRS:JAVADOC:930;
+   * 
+   * @test_Strategy: Get an array of the annotations formally declared on the
+   * artifact that initiated the intercepted entity provider invocation.
+   *
+   * WriterInterceptor.aroundWriteTo
+   */
+  @Test
+  public void getGenericTypeTest() throws Fault {
+    setOperationAndEntity(ContextOperation.GETGENERICTYPE);
+    setProperty(Property.SEARCH_STRING, String.class.getName());
+    invoke();
+  }
+
+  /*
+   * @testName: getMediaTypeTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:905; JAXRS:JAVADOC:930;
+   * 
+   * @test_Strategy: Get media type of HTTP entity.
+   *
+   * WriterInterceptor.aroundWriteTo
+   */
+  @Test
+  public void getMediaTypeTest() throws Fault {
+    Entity<String> entity = Entity.entity(TemplateInterceptorBody.ENTITY,
+        MediaType.APPLICATION_JSON_TYPE);
+    setOperationAndEntity(ContextOperation.GETMEDIATYPE);
+    setRequestContentEntity(entity);
+    setProperty(Property.SEARCH_STRING, MediaType.APPLICATION_JSON);
+    invoke();
+  }
+
+  /*
+   * @testName: getPropertyIsNullTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:906; JAXRS:JAVADOC:930;
+   * 
+   * @test_Strategy: Returns null if there is no property by that name.
+   *
+   * WriterInterceptor.aroundWriteTo
+   */
+  @Test
+  public void getPropertyIsNullTest() throws Fault {
+    setOperationAndEntity(ContextOperation.GETPROPERTY);
+    setProperty(Property.SEARCH_STRING, TemplateInterceptorBody.NULL);
+    invoke();
+  }
+
+  /*
+   * @testName: getPropertyNamesTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:1007; JAXRS:JAVADOC:930;
+   * 
+   * @test_Strategy: Returns an enumeration containing the property names
+   * available within the context of the current request/response exchange
+   * context.
+   *
+   * WriterInterceptor.aroundWriteTo
+   */
+  @Test
+  public void getPropertyNamesTest() throws Fault {
+    setOperationAndEntity(ContextOperation.GETPROPERTYNAMES);
+    for (int i = 0; i != 5; i++)
+      setProperty(Property.UNORDERED_SEARCH_STRING,
+          TemplateInterceptorBody.PROPERTY + i);
+    invoke();
+  }
+
+  /*
+   * @testName: getPropertyNamesIsReadOnlyTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:1007; JAXRS:JAVADOC:930;
+   * 
+   * @test_Strategy: Returns immutable java.util.Collection containing the
+   * property names available within the context of the current request/response
+   * exchange context.
+   * 
+   * WriterInterceptor.aroundWriteTo
+   */
+  @Test
+  public void getPropertyNamesIsReadOnlyTest() throws Fault {
+    setOperationAndEntity(ContextOperation.GETPROPERTYNAMESISREADONLY);
+    setProperty(Property.UNORDERED_SEARCH_STRING, TemplateInterceptorBody.NULL);
+    invoke();
+  }
+
+  /*
+   * @testName: getTypeTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:908; JAXRS:JAVADOC:930;
+   * 
+   * @test_Strategy: Get Java type supported by corresponding message body
+   * provider.
+   *
+   * WriterInterceptor.aroundWriteTo
+   */
+  @Test
+  public void getTypeTest() throws Fault {
+    setOperationAndEntity(ContextOperation.GETTYPE);
+    setProperty(Property.SEARCH_STRING, String.class.getName());
+    invoke();
+  }
+
+  /*
+   * @testName: removePropertyTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:909; JAXRS:JAVADOC:930;
+   * 
+   * @test_Strategy: Removes a property with the given name from the current
+   * request/response exchange context. After removal, subsequent calls to
+   * getProperty(java.lang.String) to retrieve the property value will return
+   * null.
+   *
+   * WriterInterceptor.aroundWriteTo
+   */
+  @Test
+  public void removePropertyTest() throws Fault {
+    setOperationAndEntity(ContextOperation.REMOVEPROPERTY);
+    setProperty(Property.SEARCH_STRING, TemplateInterceptorBody.NULL);
+    invoke();
+  }
+
+  /*
+   * @testName: setAnnotationsTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:910; JAXRS:JAVADOC:930;
+   * 
+   * @test_Strategy: Update annotations on the formal declaration of the
+   * artifact that initiated the intercepted entity provider invocation.
+   *
+   * WriterInterceptor.aroundWriteTo
+   */
+  @Test
+  public void setAnnotationsTest() throws Fault {
+    Annotation[] annotations = WriterInterceptorOne.class.getAnnotations();
+    setOperationAndEntity(ContextOperation.SETANNOTATIONS);
+    for (Annotation a : annotations)
+      setProperty(Property.UNORDERED_SEARCH_STRING,
+          a.annotationType().getName());
+    invoke();
+  }
+
+  /*
+   * @testName: setAnnotationsNullThrowsNPETest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:910; JAXRS:JAVADOC:930;
+   * 
+   * @test_Strategy: Throws NullPointerException - in case the input parameter
+   * is null.
+   *
+   * WriterInterceptor.aroundWriteTo
+   */
+  @Test
+  public void setAnnotationsNullThrowsNPETest() throws Fault {
+    setOperationAndEntity(ContextOperation.SETANNOTATIONSNULL);
+    setProperty(Property.SEARCH_STRING, TemplateInterceptorBody.NPE);
+    invoke();
+  }
+
+  /*
+   * @testName: setGenericTypeTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:911; JAXRS:JAVADOC:930;
+   * 
+   * @test_Strategy: Update type of the object to be produced or written.
+   *
+   * WriterInterceptor.aroundWriteTo
+   */
+  @Test
+  public void setGenericTypeTest() throws Fault {
+    setOperationAndEntity(ContextOperation.SETGENERICTYPE);
+    setProperty(Property.SEARCH_STRING, "[B");
+    invoke();
+  }
+
+  /*
+   * @testName: setMediaTypeTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:912; JAXRS:JAVADOC:930;
+   * 
+   * @test_Strategy: Update media type of HTTP entity.
+   *
+   * WriterInterceptor.aroundWriteTo
+   */
+  @Test
+  public void setMediaTypeTest() throws Fault {
+    setOperationAndEntity(ContextOperation.SETMEDIATYPE);
+    setProperty(Property.SEARCH_STRING, MediaType.APPLICATION_FORM_URLENCODED);
+    invoke();
+  }
+
+  /*
+   * @testName: setPropertyTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:913; JAXRS:JAVADOC:930;
+   * 
+   * @test_Strategy: Binds an object to a given property name in the current
+   * request/response exchange context. If the name specified is already used
+   * for a property, this method will replace the value of the property with the
+   * new value.
+   *
+   * WriterInterceptor.aroundWriteTo
+   */
+  @Test
+  public void setPropertyTest() throws Fault {
+    setOperationAndEntity(ContextOperation.SETPROPERTY);
+    setProperty(Property.SEARCH_STRING, TemplateInterceptorBody.ENTITY2);
+    invoke();
+  }
+
+  /*
+   * @testName: setPropertyNullTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:913; JAXRS:JAVADOC:930;
+   * 
+   * @test_Strategy: If a null value is passed, the effect is the same as
+   * calling the removeProperty(String) method.
+   *
+   * WriterInterceptor.aroundWriteTo
+   */
+  @Test
+  public void setPropertyNullTest() throws Fault {
+    setOperationAndEntity(ContextOperation.SETPROPERTYNULL);
+    setProperty(Property.SEARCH_STRING, TemplateInterceptorBody.NULL);
+    invoke();
+  }
+
+  /*
+   * @testName: setTypeTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:914; JAXRS:JAVADOC:930;
+   * 
+   * @test_Strategy: Update Java type before calling message body provider.
+   *
+   * WriterInterceptor.aroundWriteTo
+   */
+  @Test
+  public void setTypeTest() throws Fault {
+    ByteArrayInputStream bais = new ByteArrayInputStream(
+        TemplateInterceptorBody.ENTITY.getBytes());
+    Reader reader = new InputStreamReader(bais);
+    setOperationAndEntity(ContextOperation.SETTYPE);
+    setRequestContentEntity(reader);
+    addProvider(InputStreamReaderProvider.class);
+    invoke();
+    InputStreamReader isr = getResponseBody(InputStreamReader.class);
+    try {
+      String entity = JaxrsUtil.readFromReader(isr);
+      assertTrue(entity.contains(InputStreamReader.class.getName()),
+          "Expected"+ InputStreamReader.class.getName()+ "not found");
+      logMsg("#setType set correct type", entity);
+    } catch (IOException e) {
+      throw new Fault(e);
+    }
+  }
+
+  // /////////////////////////////////////////////////////////////////////
+  @Override
+  protected void addProviders() {
+    addProvider(WriterInterceptorTwo.class);
+    addProvider(new WriterInterceptorOne());
+  }
+}
diff --git a/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/interceptor/clientwriter/interceptorcontext/Resource.java b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/interceptor/clientwriter/interceptorcontext/Resource.java
new file mode 100644
index 0000000..45c0545
--- /dev/null
+++ b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/interceptor/clientwriter/interceptorcontext/Resource.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2012, 2020 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 jakarta.ws.rs.tck.ee.rs.ext.interceptor.clientwriter.interceptorcontext;
+
+import jakarta.ws.rs.POST;
+import jakarta.ws.rs.Path;
+
+@Path("resource")
+public class Resource {
+
+  @POST
+  public String post(String entity) {
+    return entity;
+  }
+
+}
diff --git a/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/interceptor/clientwriter/interceptorcontext/TSAppConfig.java b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/interceptor/clientwriter/interceptorcontext/TSAppConfig.java
new file mode 100644
index 0000000..070c688
--- /dev/null
+++ b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/interceptor/clientwriter/interceptorcontext/TSAppConfig.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2012, 2020 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 jakarta.ws.rs.tck.ee.rs.ext.interceptor.clientwriter.interceptorcontext;
+
+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);
+    return resources;
+  }
+}
diff --git a/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/interceptor/clientwriter/writerinterceptorcontext/JAXRSClientIT.java b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/interceptor/clientwriter/writerinterceptorcontext/JAXRSClientIT.java
new file mode 100644
index 0000000..4cdb0e5
--- /dev/null
+++ b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/interceptor/clientwriter/writerinterceptorcontext/JAXRSClientIT.java
@@ -0,0 +1,272 @@
+/*
+ * Copyright (c) 2012, 2018 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 jakarta.ws.rs.tck.ee.rs.ext.interceptor.clientwriter.writerinterceptorcontext;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import jakarta.ws.rs.tck.api.rs.ext.interceptor.TemplateInterceptorBody;
+import jakarta.ws.rs.tck.common.client.TextCaser;
+import jakarta.ws.rs.tck.common.provider.StringBeanEntityProvider;
+import jakarta.ws.rs.tck.lib.util.TestUtil;
+import jakarta.ws.rs.tck.ee.rs.ext.interceptor.clientwriter.WriterClient;
+import jakarta.ws.rs.tck.ee.rs.ext.interceptor.writer.writerinterceptorcontext.ContextOperation;
+import jakarta.ws.rs.tck.ee.rs.ext.interceptor.writer.writerinterceptorcontext.OnWriteExceptionThrowingStringBean;
+import jakarta.ws.rs.tck.ee.rs.ext.interceptor.writer.writerinterceptorcontext.ProceedException;
+import jakarta.ws.rs.tck.ee.rs.ext.interceptor.writer.writerinterceptorcontext.WriterInterceptorOne;
+import jakarta.ws.rs.tck.ee.rs.ext.interceptor.writer.writerinterceptorcontext.WriterInterceptorTwo;
+
+import org.jboss.arquillian.junit5.ArquillianExtension;
+import org.jboss.arquillian.container.test.api.Deployment;
+import org.jboss.shrinkwrap.api.ShrinkWrap;
+import org.jboss.shrinkwrap.api.asset.StringAsset;
+import org.jboss.shrinkwrap.api.spec.WebArchive;
+import org.jboss.shrinkwrap.api.exporter.ZipExporter;
+
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assertions.fail;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.junit.jupiter.api.TestInfo;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.AfterEach;
+
+/*
+ * @class.setup_props: webServerHost;
+ *                     webServerPort;
+ */
+@ExtendWith(ArquillianExtension.class)
+public class JAXRSClientIT extends WriterClient<ContextOperation> {
+
+  private static final long serialVersionUID = 2500912584762173255L;
+
+  public JAXRSClientIT() {
+    setup();
+    setContextRoot(
+        "/jaxrs_ee_rs_ext_interceptor_clientwriter_writerinterceptorcontext_web/resource");
+    addProviders();
+  }
+
+  @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{
+
+    InputStream inStream = JAXRSClientIT.class.getClassLoader().getResourceAsStream("jakarta/ws/rs/tck/ee/rs/ext/interceptor/clientwriter/writerinterceptorcontext/web.xml.template");
+    String webXml = editWebXmlString(inStream);
+
+    WebArchive archive = ShrinkWrap.create(WebArchive.class, "jaxrs_ee_rs_ext_interceptor_clientwriter_writerinterceptorcontext_web.war");
+    archive.addClasses(TSAppConfig.class, Resource.class);
+    archive.setWebXML(new StringAsset(webXml));
+    return archive;
+
+  }
+
+
+  /* Run test */
+  /*
+   * @testName: getEntityTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:933; JAXRS:JAVADOC:930;
+   * 
+   * @test_Strategy: Get object to be written as HTTP entity.
+   *
+   * WriterInterceptor.aroundWriteTo
+   */
+  @Test
+  public void getEntityTest() throws Fault {
+    setOperationAndEntity(ContextOperation.GETENTITY);
+    setProperty(Property.SEARCH_STRING, TemplateInterceptorBody.ENTITY);
+    invoke();
+  }
+
+  /*
+   * @testName: getHeadersOperationOnlyTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:934; JAXRS:JAVADOC:930;
+   * 
+   * @test_Strategy: Get mutable map of HTTP headers.
+   *
+   * WriterInterceptor.aroundWriteTo
+   */
+  @Test
+  public void getHeadersOperationOnlyTest() throws Fault {
+    setOperationAndEntity(ContextOperation.GETHEADERS);
+    setProperty(Property.SEARCH_STRING_IGNORE_CASE,
+        TemplateInterceptorBody.OPERATION);
+    invoke();
+  }
+
+  /*
+   * @testName: getHeadersTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:934; JAXRS:JAVADOC:930;
+   * 
+   * @test_Strategy: Get mutable map of HTTP headers.
+   *
+   * WriterInterceptor.aroundWriteTo
+   */
+  @Test
+  public void getHeadersTest() throws Fault {
+    Property p = Property.UNORDERED_SEARCH_STRING;
+    setOperationAndEntity(ContextOperation.GETHEADERS);
+    setProperty(p, TemplateInterceptorBody.OPERATION);
+    setTextCaser(TextCaser.LOWER);
+    for (int i = 0; i != 5; i++) {
+      addHeader(TemplateInterceptorBody.PROPERTY + i, "any");
+      setProperty(p, TemplateInterceptorBody.PROPERTY + i);
+    }
+    invoke();
+  }
+
+  /*
+   * @testName: getHeadersIsMutableTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:934; JAXRS:JAVADOC:930;
+   * 
+   * @test_Strategy: Get mutable map of HTTP headers.
+   *
+   * WriterInterceptor.aroundWriteTo
+   */
+  @Test
+  public void getHeadersIsMutableTest() throws Fault {
+    setOperationAndEntity(ContextOperation.GETHEADERSISMUTABLE);
+    setProperty(Property.SEARCH_STRING, TemplateInterceptorBody.PROPERTY);
+    invoke();
+  }
+
+  /*
+   * @testName: getOutputStreamTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:935; JAXRS:JAVADOC:930;
+   * 
+   * @test_Strategy: Get the output stream for the object to be written.
+   * 
+   * WriterInterceptor.aroundWriteTo
+   */
+  @Test
+  public void getOutputStreamTest() throws Fault {
+    Property p = Property.UNORDERED_SEARCH_STRING;
+    setOperationAndEntity(ContextOperation.GETOUTPUTSTREAM);
+    setProperty(p, TemplateInterceptorBody.ENTITY);
+    setProperty(p, TemplateInterceptorBody.NULL);
+    invoke();
+  }
+
+  /*
+   * @testName: proceedThrowsIOExceptionTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:936; JAXRS:JAVADOC:937; JAXRS:JAVADOC:930;
+   * JAXRS:JAVADOC:931;
+   * 
+   * @test_Strategy: Proceed to the next interceptor in the chain.
+   * Throws:IOException - if an IO exception arises.
+   * 
+   * proceed is actually called in every clientwriter.writerinterceptorcontext
+   * test
+   *
+   * WriterInterceptor.aroundWriteTo
+   * 
+   * WriterInterceptor.aroundWriteTo throws IOException
+   */
+  @Test
+  public void proceedThrowsIOExceptionTest() throws Fault {
+    setOperationAndEntity(ContextOperation.PROCEEDTHROWSIOEXCEPTION);
+    setProperty(Property.SEARCH_STRING, TemplateInterceptorBody.IOE);
+    invoke();
+  }
+
+  /*
+   * @testName: proceedThrowsWebApplicationExceptionTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:936; JAXRS:JAVADOC:1009; JAXRS:JAVADOC:930;
+   * 
+   * @test_Strategy: Proceed to the next interceptor in the chain.
+   * Throws:WebApplicationException - thrown by the wrapped {@code
+   * MessageBodyWriter.writeTo} method.
+   * 
+   * proceed is actually called in every clientwriter.writerinterceptorcontext
+   * test
+   *
+   * WriterInterceptor.aroundWriteTo
+   */
+  @Test
+  public void proceedThrowsWebApplicationExceptionTest() throws Fault {
+    addProvider(StringBeanEntityProvider.class);
+    addHeader(TemplateInterceptorBody.OPERATION,
+        ContextOperation.PROCEEDTHROWSWEBAPPEXCEPTION.name());
+    setRequestContentEntity(
+        new OnWriteExceptionThrowingStringBean(TemplateInterceptorBody.ENTITY));
+    try {
+      invoke();
+    } catch (Exception e) {
+      ProceedException p = assertCause(e, ProceedException.class,
+          "Proceed did not throw exception");
+      assertContains(p.getMessage(), TemplateInterceptorBody.WAE,
+          "Unexpected message received", p.getMessage());
+      logMsg(p.getMessage());
+    }
+  }
+
+  /*
+   * @testName: setEntityTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:938; JAXRS:JAVADOC:930;
+   * 
+   * @test_Strategy: Update object to be written as HTTP entity.
+   *
+   * WriterInterceptor.aroundWriteTo
+   */
+  @Test
+  public void setEntityTest() throws Fault {
+    setOperationAndEntity(ContextOperation.SETENTITY);
+    setProperty(Property.SEARCH_STRING, TemplateInterceptorBody.OPERATION);
+    invoke();
+  }
+
+  /*
+   * @testName: setOutputStreamTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:939; JAXRS:JAVADOC:930;
+   * 
+   * @test_Strategy: Update the output stream for the object to be written.
+   *
+   * WriterInterceptor.aroundWriteTo
+   */
+  @Test
+  public void setOutputStreamTest() throws Fault {
+    setOperationAndEntity(ContextOperation.SETOUTPUTSTREAM);
+    setProperty(Property.SEARCH_STRING,
+        TemplateInterceptorBody.ENTITY.replace('t', 'x'));
+    invoke();
+  }
+
+  // /////////////////////////////////////////////////////////////////////
+  @Override
+  protected void addProviders() {
+    addProvider(new WriterInterceptorTwo());
+    addProvider(WriterInterceptorOne.class);
+  }
+}
diff --git a/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/interceptor/clientwriter/writerinterceptorcontext/Resource.java b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/interceptor/clientwriter/writerinterceptorcontext/Resource.java
new file mode 100644
index 0000000..14e1c30
--- /dev/null
+++ b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/interceptor/clientwriter/writerinterceptorcontext/Resource.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2012, 2020 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 jakarta.ws.rs.tck.ee.rs.ext.interceptor.clientwriter.writerinterceptorcontext;
+
+import jakarta.ws.rs.POST;
+import jakarta.ws.rs.Path;
+
+@Path("resource")
+public class Resource {
+
+  @POST
+  public String post(String entity) {
+    return entity;
+  }
+
+}
diff --git a/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/interceptor/clientwriter/writerinterceptorcontext/TSAppConfig.java b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/interceptor/clientwriter/writerinterceptorcontext/TSAppConfig.java
new file mode 100644
index 0000000..18ef1de
--- /dev/null
+++ b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/interceptor/clientwriter/writerinterceptorcontext/TSAppConfig.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2012, 2020 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 jakarta.ws.rs.tck.ee.rs.ext.interceptor.clientwriter.writerinterceptorcontext;
+
+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);
+    return resources;
+  }
+}
diff --git a/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/interceptor/containerreader/ReaderClient.java b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/interceptor/containerreader/ReaderClient.java
new file mode 100644
index 0000000..22949b1
--- /dev/null
+++ b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/interceptor/containerreader/ReaderClient.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2012, 2018 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 jakarta.ws.rs.tck.ee.rs.ext.interceptor.containerreader;
+
+import java.io.IOException;
+
+import jakarta.ws.rs.tck.api.rs.ext.interceptor.TemplateInterceptorBody;
+import jakarta.ws.rs.tck.common.client.JaxrsCommonClient;
+
+/**
+ * Client with given ContextOperation enum, so that an enum name is passed as a
+ * http header to an interceptor. Due to the ContextOperation, the proper method
+ * on an interceptor is called.
+ * 
+ * @param <CONTEXTOPERATION>
+ */
+public abstract class ReaderClient<CONTEXTOPERATION extends Enum<?>>
+    extends JaxrsCommonClient {
+
+  private static final long serialVersionUID = 8110273180216593061L;
+
+  /**
+   * Set the header OPERATION to a proper value Also set the entity, it is good
+   * as it is here for most of the tests. For the rest, the entity needs to be
+   * replaced.
+   */
+  protected void setOperationAndEntity(CONTEXTOPERATION op) {
+    addHeader(TemplateInterceptorBody.OPERATION, op.name());
+    setRequestContentEntity(TemplateInterceptorBody.ENTITY);
+  }
+
+  /**
+   * Invoke and convert IOException to Fault
+   */
+  protected void invoke() throws Fault {
+    invoke("string");
+  }
+
+  /**
+   * Invoke and convert IOException to Fault
+   */
+  protected void invoke(String method) throws Fault {
+    try {
+      setProperty(Property.REQUEST, buildRequest(Request.POST, method));
+      super.invoke();
+    } catch (Exception cause) {
+      if (cause instanceof IOException)
+        throw new Fault(cause.getMessage());
+      else
+        throw new Fault(cause);
+    }
+  }
+}
diff --git a/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/interceptor/containerreader/interceptorcontext/JAXRSClientIT.java b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/interceptor/containerreader/interceptorcontext/JAXRSClientIT.java
new file mode 100644
index 0000000..604dcc2
--- /dev/null
+++ b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/interceptor/containerreader/interceptorcontext/JAXRSClientIT.java
@@ -0,0 +1,402 @@
+/*
+ * Copyright (c) 2012, 2020 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 jakarta.ws.rs.tck.ee.rs.ext.interceptor.containerreader.interceptorcontext;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Method;
+import java.io.InputStream;
+
+import jakarta.ws.rs.tck.api.rs.ext.interceptor.ContextOperation;
+import jakarta.ws.rs.tck.api.rs.ext.interceptor.InputStreamReaderProvider;
+import jakarta.ws.rs.tck.api.rs.ext.interceptor.TemplateInterceptorBody;
+import jakarta.ws.rs.tck.common.client.TextCaser;
+import jakarta.ws.rs.tck.common.util.JaxrsUtil;
+import jakarta.ws.rs.tck.lib.util.TestUtil;
+import jakarta.ws.rs.tck.ee.rs.ext.interceptor.containerreader.ReaderClient;
+import jakarta.ws.rs.tck.ee.rs.ext.interceptor.writer.interceptorcontext.WriterInterceptorOne;
+import jakarta.ws.rs.client.Entity;
+import jakarta.ws.rs.core.MediaType;
+
+import org.jboss.arquillian.junit5.ArquillianExtension;
+import org.jboss.arquillian.container.test.api.Deployment;
+import org.jboss.shrinkwrap.api.ShrinkWrap;
+import org.jboss.shrinkwrap.api.asset.StringAsset;
+import org.jboss.shrinkwrap.api.spec.WebArchive;
+import org.jboss.shrinkwrap.api.exporter.ZipExporter;
+
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assertions.fail;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.junit.jupiter.api.TestInfo;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.AfterEach;
+
+/*
+ * @class.setup_props: webServerHost;
+ *                     webServerPort;
+ */
+@ExtendWith(ArquillianExtension.class)
+public class JAXRSClientIT extends ReaderClient<ContextOperation> {
+
+  private static final long serialVersionUID = 6573164759617152350L;
+
+  public JAXRSClientIT() {
+    setup();
+    setContextRoot(
+        "/jaxrs_ee_rs_ext_interceptor_containerreader_interceptorcontext_web/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{
+
+    InputStream inStream = JAXRSClientIT.class.getClassLoader().getResourceAsStream("jakarta/ws/rs/tck/ee/rs/ext/interceptor/containerreader/interceptorcontext/web.xml.template");
+    String webXml = editWebXmlString(inStream);
+
+    WebArchive archive = ShrinkWrap.create(WebArchive.class, "jaxrs_ee_rs_ext_interceptor_containerreader_interceptorcontext_web.war");
+    archive.addClasses(TSAppConfig.class,
+      jakarta.ws.rs.tck.common.util.JaxrsUtil.class,
+      jakarta.ws.rs.tck.common.JAXRSCommonClient.class,
+      jakarta.ws.rs.tck.api.rs.ext.interceptor.ContextOperation.class,
+      jakarta.ws.rs.tck.api.rs.ext.interceptor.InputStreamReaderProvider.class,
+      jakarta.ws.rs.tck.api.rs.ext.interceptor.InterceptorBodyOne.class,
+      jakarta.ws.rs.tck.api.rs.ext.interceptor.InterceptorBodyTwo.class,
+      jakarta.ws.rs.tck.api.rs.ext.interceptor.InterceptorCallbackMethods.class,
+      jakarta.ws.rs.tck.api.rs.ext.interceptor.TemplateInterceptorBody.class,
+      jakarta.ws.rs.tck.api.rs.ext.interceptor.reader.interceptorcontext.ReaderInterceptorOne.class,
+      jakarta.ws.rs.tck.api.rs.ext.interceptor.reader.interceptorcontext.ReaderInterceptorTwo.class,
+      Resource.class);
+    archive.addPackages(false, "jakarta.ws.rs.tck.common.client",
+      "jakarta.ws.rs.tck.common.webclient", 
+      "jakarta.ws.rs.tck.common.webclient.handler",
+      "jakarta.ws.rs.tck.common.webclient.http",
+      "jakarta.ws.rs.tck.common.webclient.validation",
+      "jakarta.ws.rs.tck.api.rs.ext.interceptor",
+      "jakarta.ws.rs.tck.api.rs.ext.interceptor.reader"
+    );
+    archive.setWebXML(new StringAsset(webXml));
+    return archive;
+
+  }
+
+
+  /* Run test */
+  /*
+   * @testName: getAnnotationsTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:903; JAXRS:JAVADOC:920;
+   * 
+   * @test_Strategy: Get an array of the annotations formally declared on the
+   * artifact that initiated the intercepted entity provider invocation.
+   * 
+   * ReaderInterceptor.aroundReadFrom
+   */
+  @Test
+  public void getAnnotationsTest() throws Fault {
+    Method m;
+    try {
+      m = Resource.class.getMethod("post", String.class);
+    } catch (Exception e) {
+      throw new Fault(e);
+    }
+    Annotation[] annotations = m.getParameterAnnotations()[0];
+    Entity<String> entity = Entity.entity(TemplateInterceptorBody.ENTITY,
+        MediaType.WILDCARD_TYPE, annotations);
+    setOperationAndEntity(ContextOperation.GETANNOTATIONS);
+    setRequestContentEntity(entity);
+    setTextCaser(TextCaser.LOWER); // Case insensitive
+    for (Annotation a : annotations)
+      setProperty(Property.UNORDERED_SEARCH_STRING,
+          a.annotationType().getName());
+    invoke();
+  }
+
+  /*
+   * @testName: getGenericTypeTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:904; JAXRS:JAVADOC:920;
+   * 
+   * @test_Strategy: Get an array of the annotations formally declared on the
+   * artifact that initiated the intercepted entity provider invocation.
+   * 
+   * ReaderInterceptor.aroundReadFrom
+   */
+  @Test
+  public void getGenericTypeTest() throws Fault {
+    setOperationAndEntity(ContextOperation.GETGENERICTYPE);
+    setProperty(Property.SEARCH_STRING, String.class.getName());
+    invoke();
+  }
+
+  /*
+   * @testName: getMediaTypeTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:905; JAXRS:JAVADOC:920;
+   * 
+   * @test_Strategy: Get media type of HTTP entity.
+   * 
+   * ReaderInterceptor.aroundReadFrom
+   */
+  @Test
+  public void getMediaTypeTest() throws Fault {
+    Entity<String> entity = Entity.entity(TemplateInterceptorBody.ENTITY,
+        MediaType.APPLICATION_JSON_TYPE);
+    setOperationAndEntity(ContextOperation.GETMEDIATYPE);
+    setRequestContentEntity(entity);
+    setProperty(Property.SEARCH_STRING, MediaType.APPLICATION_JSON);
+    invoke();
+  }
+
+  /*
+   * @testName: getPropertyIsNullTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:906; JAXRS:JAVADOC:920;
+   * 
+   * @test_Strategy: Returns null if there is no property by that name.
+   * 
+   * ReaderInterceptor.aroundReadFrom
+   */
+  @Test
+  public void getPropertyIsNullTest() throws Fault {
+    setOperationAndEntity(ContextOperation.GETPROPERTY);
+    setProperty(Property.SEARCH_STRING, TemplateInterceptorBody.NULL);
+    invoke();
+  }
+
+  /*
+   * @testName: getPropertyNamesTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:1007; JAXRS:JAVADOC:920;
+   * 
+   * @test_Strategy: Returns immutable java.util.Collection containing the
+   * property names available within the context of the current request/response
+   * exchange context.
+   * 
+   * ReaderInterceptor.aroundReadFrom
+   */
+  @Test
+  public void getPropertyNamesTest() throws Fault {
+    setOperationAndEntity(ContextOperation.GETPROPERTYNAMES);
+    for (int i = 0; i != 5; i++)
+      setProperty(Property.UNORDERED_SEARCH_STRING,
+          TemplateInterceptorBody.PROPERTY + i);
+    invoke();
+  }
+
+  /*
+   * @testName: getPropertyNamesIsReadOnlyTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:1007; JAXRS:JAVADOC:920;
+   * 
+   * @test_Strategy: Returns immutable java.util.Collection containing the
+   * property names available within the context of the current request/response
+   * exchange context.
+   * 
+   * ReaderInterceptor.aroundReadFrom
+   */
+  @Test
+  public void getPropertyNamesIsReadOnlyTest() throws Fault {
+    setOperationAndEntity(ContextOperation.GETPROPERTYNAMESISREADONLY);
+    setProperty(Property.UNORDERED_SEARCH_STRING, TemplateInterceptorBody.NULL);
+    invoke();
+  }
+
+  /*
+   * @testName: getTypeTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:908; JAXRS:JAVADOC:920;
+   * 
+   * @test_Strategy: Get Java type supported by corresponding message body
+   * provider.
+   * 
+   * ReaderInterceptor.aroundReadFrom
+   */
+  @Test
+  public void getTypeTest() throws Fault {
+    setOperationAndEntity(ContextOperation.GETTYPE);
+    setProperty(Property.SEARCH_STRING, String.class.getName());
+    invoke();
+  }
+
+  /*
+   * @testName: removePropertyTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:909; JAXRS:JAVADOC:920;
+   * 
+   * @test_Strategy: Removes a property with the given name from the current
+   * request/response exchange context. After removal, subsequent calls to
+   * getProperty(java.lang.String) to retrieve the property value will return
+   * null.
+   * 
+   * ReaderInterceptor.aroundReadFrom
+   */
+  @Test
+  public void removePropertyTest() throws Fault {
+    setOperationAndEntity(ContextOperation.REMOVEPROPERTY);
+    setProperty(Property.SEARCH_STRING, TemplateInterceptorBody.NULL);
+    invoke();
+  }
+
+  /*
+   * @testName: setAnnotationsTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:910; JAXRS:JAVADOC:920;
+   * 
+   * @test_Strategy: Update annotations on the formal declaration of the
+   * artifact that initiated the intercepted entity provider invocation.
+   * 
+   * ReaderInterceptor.aroundReadFrom
+   */
+  @Test
+  public void setAnnotationsTest() throws Fault {
+    Annotation[] annotations = WriterInterceptorOne.class.getAnnotations();
+    setOperationAndEntity(ContextOperation.SETANNOTATIONS);
+    setTextCaser(TextCaser.LOWER);
+    for (Annotation a : annotations)
+      setProperty(Property.UNORDERED_SEARCH_STRING,
+          a.annotationType().getName());
+    invoke();
+  }
+
+  /*
+   * @testName: setAnnotationsNullThrowsNPETest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:910; JAXRS:JAVADOC:920;
+   * 
+   * @test_Strategy: Throws NullPointerException - in case the input parameter
+   * is null.
+   * 
+   * ReaderInterceptor.aroundReadFrom
+   */
+  @Test
+  public void setAnnotationsNullThrowsNPETest() throws Fault {
+    setOperationAndEntity(ContextOperation.SETANNOTATIONSNULL);
+    setProperty(Property.SEARCH_STRING, TemplateInterceptorBody.NPE);
+    invoke();
+  }
+
+  /*
+   * @testName: setGenericTypeTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:911; JAXRS:JAVADOC:920;
+   * 
+   * @test_Strategy: Update type of the object to be produced or written.
+   * 
+   * ReaderInterceptor.aroundReadFrom
+   */
+  @Test
+  public void setGenericTypeTest() throws Fault {
+    setOperationAndEntity(ContextOperation.SETGENERICTYPE);
+    setProperty(Property.SEARCH_STRING, "[B");
+    invoke();
+  }
+
+  /*
+   * @testName: setMediaTypeTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:912; JAXRS:JAVADOC:920;
+   * 
+   * @test_Strategy: Update media type of HTTP entity.
+   * 
+   * ReaderInterceptor.aroundReadFrom
+   */
+  @Test
+  public void setMediaTypeTest() throws Fault {
+    setOperationAndEntity(ContextOperation.SETMEDIATYPE);
+    setProperty(Property.SEARCH_STRING, MediaType.APPLICATION_FORM_URLENCODED);
+    invoke();
+  }
+
+  /*
+   * @testName: setPropertyTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:913; JAXRS:JAVADOC:920;
+   * 
+   * @test_Strategy: Binds an object to a given property name in the current
+   * request/response exchange context. If the name specified is already used
+   * for a property, this method will replace the value of the property with the
+   * new value.
+   * 
+   * ReaderInterceptor.aroundReadFrom
+   */
+  @Test
+  public void setPropertyTest() throws Fault {
+    setOperationAndEntity(ContextOperation.SETPROPERTY);
+    setProperty(Property.SEARCH_STRING, TemplateInterceptorBody.ENTITY2);
+    invoke();
+  }
+
+  /*
+   * @testName: setPropertyNullTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:913; JAXRS:JAVADOC:920;
+   * 
+   * @test_Strategy: If a null value is passed, the effect is the same as
+   * calling the removeProperty(String) method.
+   * 
+   * ReaderInterceptor.aroundReadFrom
+   */
+  @Test
+  public void setPropertyNullTest() throws Fault {
+    setOperationAndEntity(ContextOperation.SETPROPERTYNULL);
+    setProperty(Property.SEARCH_STRING, TemplateInterceptorBody.NULL);
+    invoke();
+  }
+
+  /*
+   * @testName: setTypeTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:914; JAXRS:JAVADOC:920;
+   * 
+   * @test_Strategy: Update Java type before calling message body provider.
+   * 
+   * ReaderInterceptor.aroundReadFrom
+   */
+  @Test
+  public void setTypeTest() throws Fault {
+    ByteArrayInputStream bais = new ByteArrayInputStream(
+        TemplateInterceptorBody.ENTITY.getBytes());
+    Reader reader = new InputStreamReader(bais);
+    setOperationAndEntity(ContextOperation.SETTYPE);
+    setRequestContentEntity(reader);
+    addProvider(InputStreamReaderProvider.class);
+    invoke("inputstreamreader");
+    InputStreamReader isr = getResponseBody(InputStreamReader.class);
+    try {
+      String entity = JaxrsUtil.readFromReader(isr);
+      assertTrue(entity.contains(InputStreamReader.class.getName()),
+          "Expected"+ InputStreamReader.class.getName()+ "not found");
+      logMsg("#setType set correct type", entity);
+    } catch (IOException e) {
+      throw new Fault(e);
+    }
+  }
+}
diff --git a/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/interceptor/containerreader/interceptorcontext/Resource.java b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/interceptor/containerreader/interceptorcontext/Resource.java
new file mode 100644
index 0000000..1997acc
--- /dev/null
+++ b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/interceptor/containerreader/interceptorcontext/Resource.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2012, 2020 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 jakarta.ws.rs.tck.ee.rs.ext.interceptor.containerreader.interceptorcontext;
+
+import java.io.IOException;
+import java.io.InputStreamReader;
+
+import jakarta.ws.rs.tck.common.util.JaxrsUtil;
+
+import jakarta.validation.constraints.NotNull;
+import jakarta.validation.constraints.Size;
+import jakarta.ws.rs.POST;
+import jakarta.ws.rs.Path;
+
+@Path("resource")
+public class Resource {
+
+  @POST
+  @Path("string")
+  public String post(@NotNull @Size(min = 2) String entity) {
+    return entity;
+  }
+
+  @POST
+  @Path("inputstreamreader")
+  public String post(InputStreamReader reader) throws IOException {
+    String entity = JaxrsUtil.readFromReader(reader);
+    reader.close();
+    return entity;
+  }
+
+}
diff --git a/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/interceptor/containerreader/interceptorcontext/TSAppConfig.java b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/interceptor/containerreader/interceptorcontext/TSAppConfig.java
new file mode 100644
index 0000000..451b74a
--- /dev/null
+++ b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/interceptor/containerreader/interceptorcontext/TSAppConfig.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2012, 2020 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 jakarta.ws.rs.tck.ee.rs.ext.interceptor.containerreader.interceptorcontext;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import jakarta.ws.rs.tck.api.rs.ext.interceptor.InputStreamReaderProvider;
+import jakarta.ws.rs.tck.api.rs.ext.interceptor.reader.interceptorcontext.ReaderInterceptorOne;
+import jakarta.ws.rs.tck.api.rs.ext.interceptor.reader.interceptorcontext.ReaderInterceptorTwo;
+
+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(ReaderInterceptorOne.class);
+    resources.add(ReaderInterceptorTwo.class);
+    resources.add(InputStreamReaderProvider.class);
+    return resources;
+  }
+}
diff --git a/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/interceptor/containerreader/readerinterceptorcontext/JAXRSClientIT.java b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/interceptor/containerreader/readerinterceptorcontext/JAXRSClientIT.java
new file mode 100644
index 0000000..c54b3ef
--- /dev/null
+++ b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/interceptor/containerreader/readerinterceptorcontext/JAXRSClientIT.java
@@ -0,0 +1,230 @@
+/*
+ * Copyright (c) 2012, 2018 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 jakarta.ws.rs.tck.ee.rs.ext.interceptor.containerreader.readerinterceptorcontext;
+
+import java.io.InputStream;
+import java.io.IOException;
+import jakarta.ws.rs.tck.api.rs.ext.interceptor.TemplateInterceptorBody;
+import jakarta.ws.rs.tck.api.rs.ext.interceptor.reader.readerinterceptorcontext.ContextOperation;
+import jakarta.ws.rs.tck.common.client.TextCaser;
+import jakarta.ws.rs.tck.lib.util.TestUtil;
+import jakarta.ws.rs.tck.ee.rs.ext.interceptor.containerreader.ReaderClient;
+
+import org.jboss.arquillian.junit5.ArquillianExtension;
+import org.jboss.arquillian.container.test.api.Deployment;
+import org.jboss.shrinkwrap.api.ShrinkWrap;
+import org.jboss.shrinkwrap.api.asset.StringAsset;
+import org.jboss.shrinkwrap.api.spec.WebArchive;
+import org.jboss.shrinkwrap.api.exporter.ZipExporter;
+
+import static org.junit.jupiter.api.Assertions.fail;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.junit.jupiter.api.TestInfo;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.AfterEach;
+
+/*
+ * @class.setup_props: webServerHost;
+ *                     webServerPort;
+ */
+@ExtendWith(ArquillianExtension.class)
+public class JAXRSClientIT extends ReaderClient<ContextOperation> {
+
+  private static final long serialVersionUID = 3006391868445878375L;
+
+  public JAXRSClientIT() {
+    setup();
+    setContextRoot(
+        "/jaxrs_ee_rs_ext_interceptor_containerreader_readerinterceptorcontext_web/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{
+
+    InputStream inStream = JAXRSClientIT.class.getClassLoader().getResourceAsStream("jakarta/ws/rs/tck/ee/rs/ext/interceptor/containerreader/readerinterceptorcontext/web.xml.template");
+    String webXml = editWebXmlString(inStream);
+
+    WebArchive archive = ShrinkWrap.create(WebArchive.class, "jaxrs_ee_rs_ext_interceptor_containerreader_readerinterceptorcontext_web.war");
+    archive.addClasses(TSAppConfig.class, Resource.class,
+      jakarta.ws.rs.tck.common.util.JaxrsUtil.class,
+      jakarta.ws.rs.tck.common.provider.StringBean.class,
+      jakarta.ws.rs.tck.api.rs.ext.interceptor.ContextOperation.class,
+      jakarta.ws.rs.tck.api.rs.ext.interceptor.InputStreamReaderProvider.class,
+      jakarta.ws.rs.tck.api.rs.ext.interceptor.InterceptorBodyOne.class,
+      jakarta.ws.rs.tck.api.rs.ext.interceptor.InterceptorBodyTwo.class,
+      jakarta.ws.rs.tck.api.rs.ext.interceptor.InterceptorCallbackMethods.class,
+      jakarta.ws.rs.tck.api.rs.ext.interceptor.TemplateInterceptorBody.class,
+      jakarta.ws.rs.tck.api.rs.ext.interceptor.reader.ReaderClient.class,
+      jakarta.ws.rs.tck.api.rs.ext.interceptor.reader.TemplateReaderInterceptor.class,
+      jakarta.ws.rs.tck.api.rs.ext.interceptor.reader.readerinterceptorcontext.ExceptionThrowingStringBean.class,
+      jakarta.ws.rs.tck.api.rs.ext.interceptor.reader.readerinterceptorcontext.ExceptionThrowingStringBeanEntityProvider.class,
+      jakarta.ws.rs.tck.api.rs.ext.interceptor.reader.readerinterceptorcontext.ReaderInterceptorOne.class,
+      jakarta.ws.rs.tck.api.rs.ext.interceptor.reader.readerinterceptorcontext.ReaderInterceptorTwo.class,
+      jakarta.ws.rs.tck.api.rs.ext.interceptor.reader.readerinterceptorcontext.InterceptorOneBody.class,
+      jakarta.ws.rs.tck.api.rs.ext.interceptor.reader.readerinterceptorcontext.InterceptorTwoBody.class
+    );
+    archive.setWebXML(new StringAsset(webXml));
+    return archive;
+
+  }
+
+
+  /* Run test */
+
+  /*
+   * @testName: getHeadersOperationOnlyTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:923; JAXRS:JAVADOC:920;
+   * 
+   * @test_Strategy: Get mutable map of HTTP headers.
+   * 
+   * ReaderInterceptor.aroundReadFrom
+   */
+  @Test
+  public void getHeadersOperationOnlyTest() throws Fault {
+    setOperationAndEntity(ContextOperation.GETHEADERS);
+    setProperty(Property.SEARCH_STRING_IGNORE_CASE,
+        TemplateInterceptorBody.OPERATION);
+    setPrintEntity(true);
+    invoke();
+  }
+
+  /*
+   * @testName: getHeadersHeadersSetTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:923; JAXRS:JAVADOC:920;
+   * 
+   * @test_Strategy: Get mutable map of HTTP headers.
+   * 
+   * ReaderInterceptor.aroundReadFrom
+   */
+  @Test
+  public void getHeadersHeadersSetTest() throws Fault {
+    Property p = Property.UNORDERED_SEARCH_STRING;
+    setOperationAndEntity(ContextOperation.GETHEADERS);
+    setProperty(p, TemplateInterceptorBody.OPERATION);
+    setTextCaser(TextCaser.LOWER);
+    for (int i = 0; i != 5; i++) {
+      addHeader(TemplateInterceptorBody.PROPERTY + i, "any");
+      setProperty(p, TemplateInterceptorBody.PROPERTY + i);
+    }
+    invoke();
+  }
+
+  /* Run test */
+  /*
+   * @testName: getHeadersIsMutableTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:923; JAXRS:JAVADOC:920;
+   * 
+   * @test_Strategy: Get mutable map of HTTP headers.
+   * 
+   * ReaderInterceptor.aroundReadFrom
+   */
+  @Test
+  public void getHeadersIsMutableTest() throws Fault {
+    setOperationAndEntity(ContextOperation.GETHEADERSISMUTABLE);
+    setProperty(Property.SEARCH_STRING, TemplateInterceptorBody.PROPERTY);
+    invoke();
+  }
+
+  /*
+   * @testName: getInputStreamTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:924; JAXRS:JAVADOC:920;
+   * 
+   * @test_Strategy: Get the input stream of the object to be read.
+   * 
+   * ReaderInterceptor.aroundReadFrom
+   */
+  @Test
+  public void getInputStreamTest() throws Fault {
+    String entity = "getInputStreamEntity";
+    setOperationAndEntity(ContextOperation.GETINPUTSTREAM);
+    setRequestContentEntity(entity);
+    setProperty(Property.SEARCH_STRING, entity);
+    invoke();
+  }
+
+  /*
+   * @testName: proceedThrowsIOExceptionTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:925; JAXRS:JAVADOC:926; JAXRS:JAVADOC:920;
+   * 
+   * @test_Strategy: Throws: IOException - if an IO error arises
+   * 
+   * proceed is actually called in every
+   * containerreader.readerinterceptorcontext test
+   * 
+   * ReaderInterceptor.aroundReadFrom
+   */
+  @Test
+  public void proceedThrowsIOExceptionTest() throws Fault {
+    setOperationAndEntity(ContextOperation.PROCEEDTHROWSIOEXCEPTION);
+    setProperty(Property.SEARCH_STRING, TemplateInterceptorBody.IOE);
+    invoke();
+  }
+
+  /*
+   * @testName: proceedThrowsWebApplicationExceptionTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:925; JAXRS:JAVADOC:1008; JAXRS:JAVADOC:920;
+   * 
+   * @test_Strategy: Throws: WebApplicationException - thrown by the wrapped
+   * {@code MessageBodyReader.readFrom} method.
+   * 
+   * Proceed is tested in any of the interceptor tests.
+   * 
+   * ReaderInterceptor.aroundReadFrom
+   */
+  @Test
+  public void proceedThrowsWebApplicationExceptionTest() throws Fault {
+    setOperationAndEntity(ContextOperation.PROCEEDTHROWSWEBAPPEXCEPTION);
+    setProperty(Property.SEARCH_STRING, TemplateInterceptorBody.WAE);
+    invoke("errorbean");
+  }
+
+  /*
+   * @testName: setInputStreamTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:927; JAXRS:JAVADOC:920;
+   * 
+   * @test_Strategy: Update the input stream of the object to be read.
+   * 
+   * ReaderInterceptor.aroundReadFrom
+   */
+  @Test
+  public void setInputStreamTest() throws Fault {
+    setOperationAndEntity(ContextOperation.SETINPUTSTREAM);
+    setProperty(Property.SEARCH_STRING, TemplateInterceptorBody.ENTITY2);
+    invoke();
+  }
+
+  // =====================
+
+}
diff --git a/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/interceptor/containerreader/readerinterceptorcontext/Resource.java b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/interceptor/containerreader/readerinterceptorcontext/Resource.java
new file mode 100644
index 0000000..2a08540
--- /dev/null
+++ b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/interceptor/containerreader/readerinterceptorcontext/Resource.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2012, 2020 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 jakarta.ws.rs.tck.ee.rs.ext.interceptor.containerreader.readerinterceptorcontext;
+
+import jakarta.ws.rs.tck.api.rs.ext.interceptor.reader.readerinterceptorcontext.ExceptionThrowingStringBean;
+
+import jakarta.ws.rs.POST;
+import jakarta.ws.rs.Path;
+
+@Path("resource")
+public class Resource {
+
+  @POST
+  @Path("string")
+  public String post(String entity) {
+    return entity;
+  }
+
+  @POST
+  @Path("errorbean")
+  public String errorBean(ExceptionThrowingStringBean bean) {
+    return bean.get();
+  }
+
+}
diff --git a/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/interceptor/containerreader/readerinterceptorcontext/TSAppConfig.java b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/interceptor/containerreader/readerinterceptorcontext/TSAppConfig.java
new file mode 100644
index 0000000..cad2721
--- /dev/null
+++ b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/interceptor/containerreader/readerinterceptorcontext/TSAppConfig.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2012, 2020 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 jakarta.ws.rs.tck.ee.rs.ext.interceptor.containerreader.readerinterceptorcontext;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import jakarta.ws.rs.tck.api.rs.ext.interceptor.reader.readerinterceptorcontext.ExceptionThrowingStringBeanEntityProvider;
+import jakarta.ws.rs.tck.api.rs.ext.interceptor.reader.readerinterceptorcontext.ReaderInterceptorOne;
+import jakarta.ws.rs.tck.api.rs.ext.interceptor.reader.readerinterceptorcontext.ReaderInterceptorTwo;
+
+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(ReaderInterceptorOne.class);
+    resources.add(ReaderInterceptorTwo.class);
+    resources.add(ExceptionThrowingStringBeanEntityProvider.class);
+    return resources;
+  }
+}
diff --git a/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/interceptor/containerwriter/WriterClient.java b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/interceptor/containerwriter/WriterClient.java
new file mode 100644
index 0000000..840f835
--- /dev/null
+++ b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/interceptor/containerwriter/WriterClient.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2012, 2018 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 jakarta.ws.rs.tck.ee.rs.ext.interceptor.containerwriter;
+
+import jakarta.ws.rs.tck.common.client.JaxrsCommonClient;
+
+/**
+ * Client with given ContextOperation enum, so that an enum name is passed as a
+ * http header to an interceptor. Due to the ContextOperation, the proper method
+ * on an interceptor is called.
+ * 
+ * @param <CONTEXTOPERATION>
+ */
+public abstract class WriterClient<CONTEXTOPERATION extends Enum<?>>
+    extends JaxrsCommonClient {
+
+  private static final long serialVersionUID = -9222693803307311300L;
+
+  /**
+   * Invoke and convert CONTEXTOPERATION to a path
+   */
+  protected void invoke(CONTEXTOPERATION op) throws Fault {
+    setProperty(Property.REQUEST,
+        buildRequest(Request.GET, op.name().toLowerCase()));
+    super.invoke();
+  }
+
+  /**
+   * Invoke and convert CONTEXTOPERATION to a path
+   */
+  protected void invoke(CONTEXTOPERATION op, Request method) throws Fault {
+    setProperty(Property.REQUEST,
+        buildRequest(method, op.name().toLowerCase()));
+    super.invoke();
+  }
+
+}
diff --git a/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/interceptor/containerwriter/interceptorcontext/JAXRSClientIT.java b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/interceptor/containerwriter/interceptorcontext/JAXRSClientIT.java
new file mode 100644
index 0000000..a588331
--- /dev/null
+++ b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/interceptor/containerwriter/interceptorcontext/JAXRSClientIT.java
@@ -0,0 +1,350 @@
+/*
+ * Copyright (c) 2012, 2020 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 jakarta.ws.rs.tck.ee.rs.ext.interceptor.containerwriter.interceptorcontext;
+
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.lang.annotation.Annotation;
+import java.io.InputStream;
+
+import jakarta.ws.rs.tck.api.rs.ext.interceptor.ContextOperation;
+import jakarta.ws.rs.tck.api.rs.ext.interceptor.InputStreamReaderProvider;
+import jakarta.ws.rs.tck.api.rs.ext.interceptor.TemplateInterceptorBody;
+import jakarta.ws.rs.tck.common.util.JaxrsUtil;
+import jakarta.ws.rs.tck.lib.util.TestUtil;
+import jakarta.ws.rs.tck.ee.rs.ext.interceptor.containerwriter.WriterClient;
+
+import jakarta.ws.rs.core.MediaType;
+
+import org.jboss.arquillian.junit5.ArquillianExtension;
+import org.jboss.arquillian.container.test.api.Deployment;
+import org.jboss.shrinkwrap.api.ShrinkWrap;
+import org.jboss.shrinkwrap.api.asset.StringAsset;
+import org.jboss.shrinkwrap.api.spec.WebArchive;
+import org.jboss.shrinkwrap.api.exporter.ZipExporter;
+
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assertions.fail;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.junit.jupiter.api.TestInfo;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.AfterEach;
+
+/*
+ * @class.setup_props: webServerHost;
+ *                     webServerPort;
+ */
+@ExtendWith(ArquillianExtension.class)
+public class JAXRSClientIT extends WriterClient<ContextOperation> {
+
+  private static final long serialVersionUID = -3980167967224950515L;
+
+  public JAXRSClientIT() {
+    setup();
+    setContextRoot(
+        "/jaxrs_ee_rs_ext_interceptor_containerwriter_interceptorcontext_web/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{
+
+    InputStream inStream = JAXRSClientIT.class.getClassLoader().getResourceAsStream("jakarta/ws/rs/tck/ee/rs/ext/interceptor/containerwriter/interceptorcontext/web.xml.template");
+    String webXml = editWebXmlString(inStream);
+
+    WebArchive archive = ShrinkWrap.create(WebArchive.class, "jaxrs_ee_rs_ext_interceptor_containerwriter_interceptorcontext_web.war");
+    archive.addClasses(TSAppConfig.class, 
+      jakarta.ws.rs.tck.common.util.JaxrsUtil.class,
+      jakarta.ws.rs.tck.ee.rs.ext.interceptor.writer.TemplateWriterInterceptor.class,
+      Resource.class);
+    archive.addPackages(false, "jakarta.ws.rs.tck.api.rs.ext.interceptor",
+      "jakarta.ws.rs.tck.ee.rs.ext.interceptor.writer.interceptorcontext");
+    archive.setWebXML(new StringAsset(webXml));
+    return archive;
+
+  }
+
+
+  /* Run test */
+  /*
+   * @testName: getAnnotationsTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:903; JAXRS:JAVADOC:930;
+   * 
+   * @test_Strategy: Get an array of the annotations formally declared on the
+   * artifact that initiated the intercepted entity provider invocation.
+   *
+   * WriterInterceptor.aroundWriteTo
+   */
+  @Test
+  public void getAnnotationsTest() throws Fault {
+    Annotation[] annotations = ContextOperation.class.getAnnotations();
+    for (Annotation a : annotations)
+      setProperty(Property.UNORDERED_SEARCH_STRING,
+          a.annotationType().getName());
+    invoke(ContextOperation.GETANNOTATIONS);
+  }
+
+  /*
+   * @testName: getGenericTypeTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:904; JAXRS:JAVADOC:930;
+   * 
+   * @test_Strategy: Get an array of the annotations formally declared on the
+   * artifact that initiated the intercepted entity provider invocation.
+   *
+   * WriterInterceptor.aroundWriteTo
+   */
+  @Test
+  public void getGenericTypeTest() throws Fault {
+    setProperty(Property.SEARCH_STRING, String.class.getName());
+    invoke(ContextOperation.GETGENERICTYPE);
+  }
+
+  /*
+   * @testName: getMediaTypeTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:905; JAXRS:JAVADOC:930;
+   * 
+   * @test_Strategy: Get media type of HTTP entity.
+   *
+   * WriterInterceptor.aroundWriteTo
+   */
+  @Test
+  public void getMediaTypeTest() throws Fault {
+    setProperty(Property.SEARCH_STRING, MediaType.APPLICATION_JSON);
+    invoke(ContextOperation.GETMEDIATYPE);
+  }
+
+  /*
+   * @testName: getPropertyIsNullTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:906; JAXRS:JAVADOC:930;
+   * 
+   * @test_Strategy: Returns null if there is no property by that name.
+   *
+   * WriterInterceptor.aroundWriteTo
+   */
+  @Test
+  public void getPropertyIsNullTest() throws Fault {
+    setProperty(Property.SEARCH_STRING, TemplateInterceptorBody.NULL);
+    invoke(ContextOperation.GETPROPERTY);
+  }
+
+  /*
+   * @testName: getPropertyNamesIsReadOnlyTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:1007; JAXRS:JAVADOC:930;
+   * 
+   * @test_Strategy: Returns immutable java.util.Collection containing the
+   * property names available within the context of the current request/response
+   * exchange context.
+   * 
+   * WriterInterceptor.aroundWriteTo
+   */
+  @Test
+  public void getPropertyNamesIsReadOnlyTest() throws Fault {
+    setProperty(Property.UNORDERED_SEARCH_STRING, TemplateInterceptorBody.NULL);
+    invoke(ContextOperation.GETPROPERTYNAMESISREADONLY);
+  }
+
+  /*
+   * @testName: getPropertyNamesTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:1007; JAXRS:JAVADOC:930;
+   * 
+   * @test_Strategy: Returns an enumeration containing the property names
+   * available within the context of the current request/response exchange
+   * context.
+   *
+   * WriterInterceptor.aroundWriteTo
+   */
+  @Test
+  public void getPropertyNamesTest() throws Fault {
+    for (int i = 0; i != 5; i++)
+      setProperty(Property.UNORDERED_SEARCH_STRING,
+          TemplateInterceptorBody.PROPERTY + i);
+    invoke(ContextOperation.GETPROPERTYNAMES);
+  }
+
+  /*
+   * @testName: getTypeTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:908; JAXRS:JAVADOC:930;
+   * 
+   * @test_Strategy: Get Java type supported by corresponding message body
+   * provider.
+   *
+   * WriterInterceptor.aroundWriteTo
+   */
+  @Test
+  public void getTypeTest() throws Fault {
+    setProperty(Property.SEARCH_STRING, String.class.getName());
+    invoke(ContextOperation.GETTYPE);
+  }
+
+  /*
+   * @testName: removePropertyTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:909; JAXRS:JAVADOC:930;
+   * 
+   * @test_Strategy: Removes a property with the given name from the current
+   * request/response exchange context. After removal, subsequent calls to
+   * getProperty(java.lang.String) to retrieve the property value will return
+   * null.
+   *
+   * WriterInterceptor.aroundWriteTo
+   */
+  @Test
+  public void removePropertyTest() throws Fault {
+    setProperty(Property.SEARCH_STRING, TemplateInterceptorBody.NULL);
+    invoke(ContextOperation.REMOVEPROPERTY);
+  }
+
+  /*
+   * @testName: setAnnotationsTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:910; JAXRS:JAVADOC:930;
+   * 
+   * @test_Strategy: Update annotations on the formal declaration of the
+   * artifact that initiated the intercepted entity provider invocation.
+   *
+   * WriterInterceptor.aroundWriteTo
+   */
+  @Test
+  public void setAnnotationsTest() throws Fault {
+    Annotation[] annotations = ContextOperation.class.getAnnotations();
+    for (Annotation a : annotations)
+      setProperty(Property.UNORDERED_SEARCH_STRING,
+          a.annotationType().getName());
+    invoke(ContextOperation.SETANNOTATIONS);
+  }
+
+  /*
+   * @testName: setAnnotationsNullThrowsNPETest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:910; JAXRS:JAVADOC:930;
+   * 
+   * @test_Strategy: Throws NullPointerException - in case the input parameter
+   * is null.
+   *
+   * WriterInterceptor.aroundWriteTo
+   */
+  @Test
+  public void setAnnotationsNullThrowsNPETest() throws Fault {
+    setProperty(Property.SEARCH_STRING, TemplateInterceptorBody.NPE);
+    invoke(ContextOperation.SETANNOTATIONSNULL);
+  }
+
+  /*
+   * @testName: setGenericTypeTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:911; JAXRS:JAVADOC:930;
+   * 
+   * @test_Strategy: Update type of the object to be produced or written.
+   *
+   * WriterInterceptor.aroundWriteTo
+   */
+  @Test
+  public void setGenericTypeTest() throws Fault {
+    setProperty(Property.SEARCH_STRING, "[B");
+    invoke(ContextOperation.SETGENERICTYPE);
+  }
+
+  /*
+   * @testName: setMediaTypeTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:912; JAXRS:JAVADOC:930;
+   * 
+   * @test_Strategy: Update media type of HTTP entity.
+   *
+   * WriterInterceptor.aroundWriteTo
+   */
+  @Test
+  public void setMediaTypeTest() throws Fault {
+    setProperty(Property.SEARCH_STRING, MediaType.APPLICATION_FORM_URLENCODED);
+    invoke(ContextOperation.SETMEDIATYPE);
+  }
+
+  /*
+   * @testName: setPropertyTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:913; JAXRS:JAVADOC:930;
+   * 
+   * @test_Strategy: Binds an object to a given property name in the current
+   * request/response exchange context. If the name specified is already used
+   * for a property, this method will replace the value of the property with the
+   * new value.
+   *
+   * WriterInterceptor.aroundWriteTo
+   */
+  @Test
+  public void setPropertyTest() throws Fault {
+    setProperty(Property.SEARCH_STRING, TemplateInterceptorBody.ENTITY2);
+    invoke(ContextOperation.SETPROPERTY);
+  }
+
+  /*
+   * @testName: setPropertyNullTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:913; JAXRS:JAVADOC:930;
+   * 
+   * @test_Strategy: If a null value is passed, the effect is the same as
+   * calling the removeProperty(String) method.
+   *
+   * WriterInterceptor.aroundWriteTo
+   */
+  @Test
+  public void setPropertyNullTest() throws Fault {
+    setProperty(Property.SEARCH_STRING, TemplateInterceptorBody.NULL);
+    invoke(ContextOperation.SETPROPERTYNULL);
+  }
+
+  /*
+   * @testName: setTypeTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:914; JAXRS:JAVADOC:930;
+   * 
+   * @test_Strategy: Update Java type before calling message body provider.
+   *
+   * WriterInterceptor.aroundWriteTo
+   */
+  @Test
+  public void setTypeTest() throws Fault {
+    addProvider(InputStreamReaderProvider.class);
+    invoke(ContextOperation.SETTYPE);
+    InputStreamReader isr = getResponseBody(InputStreamReader.class);
+    try {
+      String entity = JaxrsUtil.readFromReader(isr);
+      assertTrue(entity.contains(InputStreamReader.class.getName()),
+          "Expected"+ InputStreamReader.class.getName()+ "not found");
+      logMsg("#setType set correct type", entity);
+    } catch (IOException e) {
+      throw new Fault(e);
+    }
+  }
+}
diff --git a/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/interceptor/containerwriter/interceptorcontext/Resource.java b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/interceptor/containerwriter/interceptorcontext/Resource.java
new file mode 100644
index 0000000..4ca8081
--- /dev/null
+++ b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/interceptor/containerwriter/interceptorcontext/Resource.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2012, 2020 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 jakarta.ws.rs.tck.ee.rs.ext.interceptor.containerwriter.interceptorcontext;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.lang.annotation.Annotation;
+
+import jakarta.ws.rs.tck.api.rs.ext.interceptor.ContextOperation;
+import jakarta.ws.rs.tck.api.rs.ext.interceptor.TemplateInterceptorBody;
+
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.PathParam;
+import jakarta.ws.rs.core.MediaType;
+import jakarta.ws.rs.core.Response;
+import jakarta.ws.rs.core.Response.ResponseBuilder;
+
+@Path("resource")
+public class Resource {
+
+  @GET
+  @Path("{id}")
+  public Response genericResponse(@PathParam("id") String path) {
+    ContextOperation op = ContextOperation.valueOf(path.toUpperCase());
+    ResponseBuilder builder = createResponseBuilderWithHeader(op);
+    switch (op) {
+    case GETANNOTATIONS:
+      Annotation[] annotations = ContextOperation.class.getAnnotations();
+      builder = builder.entity(TemplateInterceptorBody.ENTITY, annotations);
+      break;
+    case GETMEDIATYPE:
+      builder = builder.type(MediaType.APPLICATION_JSON_TYPE);
+      break;
+    case SETTYPE:
+      ByteArrayInputStream bais = new ByteArrayInputStream(
+          TemplateInterceptorBody.ENTITY.getBytes());
+      Reader reader = new InputStreamReader(bais);
+      builder = builder.entity(reader);
+      break;
+    default:
+      break;
+    }
+    Response response = builder.build();
+    return response;
+  }
+
+  // ///////////////////////////////////////////////////////////////////////
+
+  ResponseBuilder createResponseBuilderWithHeader(ContextOperation op) {
+    Response.ResponseBuilder builder = Response.ok();
+    // set a header with ContextOperation so that the filter knows what to
+    // do
+    builder = builder.header(TemplateInterceptorBody.OPERATION, op.name());
+    builder = builder.entity(TemplateInterceptorBody.ENTITY);
+    return builder;
+  }
+
+}
diff --git a/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/interceptor/containerwriter/interceptorcontext/TSAppConfig.java b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/interceptor/containerwriter/interceptorcontext/TSAppConfig.java
new file mode 100644
index 0000000..780adce
--- /dev/null
+++ b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/interceptor/containerwriter/interceptorcontext/TSAppConfig.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2012, 2020 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 jakarta.ws.rs.tck.ee.rs.ext.interceptor.containerwriter.interceptorcontext;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import jakarta.ws.rs.tck.api.rs.ext.interceptor.InputStreamReaderProvider;
+import jakarta.ws.rs.tck.ee.rs.ext.interceptor.writer.interceptorcontext.WriterInterceptorOne;
+import jakarta.ws.rs.tck.ee.rs.ext.interceptor.writer.interceptorcontext.WriterInterceptorTwo;
+
+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(WriterInterceptorOne.class);
+    resources.add(WriterInterceptorTwo.class);
+    resources.add(InputStreamReaderProvider.class);
+    return resources;
+  }
+}
diff --git a/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/interceptor/containerwriter/writerinterceptorcontext/JAXRSClientIT.java b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/interceptor/containerwriter/writerinterceptorcontext/JAXRSClientIT.java
new file mode 100644
index 0000000..76f6b40
--- /dev/null
+++ b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/interceptor/containerwriter/writerinterceptorcontext/JAXRSClientIT.java
@@ -0,0 +1,244 @@
+/*
+ * Copyright (c) 2012, 2018 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 jakarta.ws.rs.tck.ee.rs.ext.interceptor.containerwriter.writerinterceptorcontext;
+
+import java.io.InputStream;
+import java.io.IOException;
+import jakarta.ws.rs.tck.api.rs.ext.interceptor.TemplateInterceptorBody;
+import jakarta.ws.rs.tck.ee.rs.ext.interceptor.containerwriter.WriterClient;
+import jakarta.ws.rs.tck.ee.rs.ext.interceptor.writer.writerinterceptorcontext.ContextOperation;
+import jakarta.ws.rs.tck.lib.util.TestUtil;
+
+import org.jboss.arquillian.junit5.ArquillianExtension;
+import org.jboss.arquillian.container.test.api.Deployment;
+import org.jboss.shrinkwrap.api.ShrinkWrap;
+import org.jboss.shrinkwrap.api.asset.StringAsset;
+import org.jboss.shrinkwrap.api.spec.WebArchive;
+import org.jboss.shrinkwrap.api.exporter.ZipExporter;
+
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assertions.fail;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.junit.jupiter.api.TestInfo;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.AfterEach;
+
+/*
+ * @class.setup_props: webServerHost;
+ *                     webServerPort;
+ */
+@ExtendWith(ArquillianExtension.class)
+public class JAXRSClientIT extends WriterClient<ContextOperation> {
+
+  private static final long serialVersionUID = -8158424518609416304L;
+
+  public JAXRSClientIT() {
+    setup();
+    setContextRoot(
+        "/jaxrs_ee_rs_ext_interceptor_containerwriter_writerinterceptorcontext_web/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{
+
+    InputStream inStream = JAXRSClientIT.class.getClassLoader().getResourceAsStream("jakarta/ws/rs/tck/ee/rs/ext/interceptor/containerwriter/writerinterceptorcontext/web.xml.template");
+    String webXml = editWebXmlString(inStream);
+
+    WebArchive archive = ShrinkWrap.create(WebArchive.class, "jaxrs_ee_rs_ext_interceptor_containerwriter_writerinterceptorcontext_web.war");
+    archive.addClasses(TSAppConfig.class, 
+    jakarta.ws.rs.tck.common.util.JaxrsUtil.class,
+    jakarta.ws.rs.tck.common.provider.StringBean.class,
+    jakarta.ws.rs.tck.common.provider.StringBeanEntityProvider.class,
+    jakarta.ws.rs.tck.common.impl.ReplacingOutputStream.class,
+    jakarta.ws.rs.tck.ee.rs.ext.interceptor.writer.TemplateWriterInterceptor.class,
+    Resource.class);
+    archive.addPackages(false, 
+      "jakarta.ws.rs.tck.api.rs.ext.interceptor",
+      "jakarta.ws.rs.tck.ee.rs.ext.interceptor.writer.writerinterceptorcontext");
+
+    archive.setWebXML(new StringAsset(webXml));
+    return archive;
+
+  }
+
+
+  /* Run test */
+  /*
+   * @testName: getEntityTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:933; JAXRS:JAVADOC:930;
+   * 
+   * @test_Strategy: Get object to be written as HTTP entity.
+   *
+   * WriterInterceptor.aroundWriteTo
+   */
+  @Test
+  public void getEntityTest() throws Fault {
+    setProperty(Property.SEARCH_STRING, TemplateInterceptorBody.ENTITY);
+    invoke(ContextOperation.GETENTITY);
+  }
+
+  /*
+   * @testName: getHeadersOperationOnlyTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:934; JAXRS:JAVADOC:930;
+   * 
+   * @test_Strategy: Get mutable map of HTTP headers.
+   * 
+   * WriterInterceptor.aroundWriteTo
+   */
+  @Test
+  public void getHeadersOperationOnlyTest() throws Fault {
+    setProperty(Property.SEARCH_STRING, TemplateInterceptorBody.OPERATION);
+    invoke(ContextOperation.GETHEADERS);
+  }
+
+  /*
+   * @testName: getHeadersTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:934; JAXRS:JAVADOC:930;
+   * 
+   * @test_Strategy: Get mutable map of HTTP headers.
+   *
+   * WriterInterceptor.aroundWriteTo
+   */
+  @Test
+  public void getHeadersTest() throws Fault {
+    Property p = Property.UNORDERED_SEARCH_STRING;
+    setProperty(p, TemplateInterceptorBody.OPERATION);
+    for (int i = 0; i != 5; i++)
+      setProperty(p, TemplateInterceptorBody.PROPERTY + i);
+    invoke(ContextOperation.GETHEADERS);
+  }
+
+  /*
+   * @testName: getHeadersIsMutableTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:934; JAXRS:JAVADOC:930;
+   * 
+   * @test_Strategy: Get mutable map of HTTP headers.
+   *
+   * WriterInterceptor.aroundWriteTo
+   */
+  @Test
+  public void getHeadersIsMutableTest() throws Fault {
+    setProperty(Property.SEARCH_STRING, TemplateInterceptorBody.PROPERTY);
+    invoke(ContextOperation.GETHEADERSISMUTABLE);
+  }
+
+  /*
+   * @testName: getOutputStreamTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:935; JAXRS:JAVADOC:930;
+   * 
+   * @test_Strategy: Get the output stream for the object to be written.
+   *
+   * WriterInterceptor.aroundWriteTo
+   */
+  @Test
+  public void getOutputStreamTest() throws Fault {
+    Property p = Property.UNORDERED_SEARCH_STRING;
+    setProperty(p, TemplateInterceptorBody.ENTITY);
+    setProperty(p, TemplateInterceptorBody.NULL);
+    invoke(ContextOperation.GETOUTPUTSTREAM);
+  }
+
+  /*
+   * @testName: proceedThrowsIOExceptionTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:936; JAXRS:JAVADOC:937; JAXRS:JAVADOC:930;
+   * JAXRS:JAVADOC:931;
+   * 
+   * @test_Strategy: Proceed to the next interceptor in the chain.
+   * Throws:IOException - if an IO exception arises.
+   * 
+   * proceed is actually called in every clientwriter.writerinterceptorcontext
+   * test
+   *
+   * WriterInterceptor.aroundWriteTo
+   * 
+   * WriterInterceptor.aroundWriteTo throws IOException
+   */
+  @Test
+  public void proceedThrowsIOExceptionTest() throws Fault {
+    setProperty(Property.SEARCH_STRING, TemplateInterceptorBody.IOE);
+    invoke(ContextOperation.PROCEEDTHROWSIOEXCEPTION);
+  }
+
+  /*
+   * @testName: proceedThrowsWebApplicationExceptionTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:936; JAXRS:JAVADOC:1009; JAXRS:JAVADOC:930;
+   * 
+   * @test_Strategy: Proceed to the next interceptor in the chain.
+   * Throws:WebApplicationException thrown by the wrapped {@code
+   * MessageBodyWriter.writeTo} method.
+   * 
+   * proceed is actually called in every clientwriter.writerinterceptorcontext
+   * test
+   *
+   * WriterInterceptor.aroundWriteTo
+   */
+  @Test
+  public void proceedThrowsWebApplicationExceptionTest() throws Fault {
+    setProperty(Property.SEARCH_STRING, TemplateInterceptorBody.WAE);
+    invoke(ContextOperation.PROCEEDTHROWSWEBAPPEXCEPTION);
+  }
+
+  /*
+   * @testName: setEntityTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:938; JAXRS:JAVADOC:930;
+   * 
+   * @test_Strategy: Update object to be written as HTTP entity.
+   *
+   * WriterInterceptor.aroundWriteTo
+   */
+  @Test
+  public void setEntityTest() throws Fault {
+    setProperty(Property.SEARCH_STRING, TemplateInterceptorBody.OPERATION);
+    invoke(ContextOperation.SETENTITY);
+  }
+
+  /*
+   * @testName: setOutputStreamTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:939; JAXRS:JAVADOC:930;
+   * 
+   * @test_Strategy: Update the output stream for the object to be written.
+   *
+   * WriterInterceptor.aroundWriteTo
+   */
+  @Test
+  public void setOutputStreamTest() throws Fault {
+    setProperty(Property.SEARCH_STRING,
+        TemplateInterceptorBody.ENTITY.replace('t', 'x'));
+    invoke(ContextOperation.SETOUTPUTSTREAM);
+  }
+
+}
diff --git a/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/interceptor/containerwriter/writerinterceptorcontext/Resource.java b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/interceptor/containerwriter/writerinterceptorcontext/Resource.java
new file mode 100644
index 0000000..a4ad607
--- /dev/null
+++ b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/interceptor/containerwriter/writerinterceptorcontext/Resource.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2012, 2020 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 jakarta.ws.rs.tck.ee.rs.ext.interceptor.containerwriter.writerinterceptorcontext;
+
+import jakarta.ws.rs.tck.api.rs.ext.interceptor.TemplateInterceptorBody;
+import jakarta.ws.rs.tck.ee.rs.ext.interceptor.writer.writerinterceptorcontext.ContextOperation;
+import jakarta.ws.rs.tck.ee.rs.ext.interceptor.writer.writerinterceptorcontext.OnWriteExceptionThrowingStringBean;
+
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.PathParam;
+import jakarta.ws.rs.core.Response;
+import jakarta.ws.rs.core.Response.ResponseBuilder;
+
+@Path("resource")
+public class Resource {
+
+  @GET
+  @Path("{id}")
+  public Response genericResponse(@PathParam("id") String path) {
+    ContextOperation op = ContextOperation.valueOf(path.toUpperCase());
+    ResponseBuilder builder = createResponseBuilderWithHeader(op);
+    switch (op) {
+    case GETHEADERS:
+      for (int i = 0; i != 5; i++)
+        builder = builder.header(TemplateInterceptorBody.PROPERTY + i, "any");
+      break;
+    case PROCEEDTHROWSWEBAPPEXCEPTION:
+      builder.entity(new OnWriteExceptionThrowingStringBean(
+          TemplateInterceptorBody.ENTITY));
+      break;
+    default:
+      break;
+    }
+    Response response = builder.build();
+    return response;
+  }
+
+  // ///////////////////////////////////////////////////////////////////////
+
+  static ResponseBuilder createResponseBuilderWithHeader(ContextOperation op) {
+    Response.ResponseBuilder builder = Response.ok();
+    // set a header with ContextOperation so that the filter knows what to
+    // do
+    builder = builder.header(TemplateInterceptorBody.OPERATION, op.name());
+    builder = builder.entity(TemplateInterceptorBody.ENTITY);
+    return builder;
+  }
+
+}
diff --git a/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/interceptor/containerwriter/writerinterceptorcontext/TSAppConfig.java b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/interceptor/containerwriter/writerinterceptorcontext/TSAppConfig.java
new file mode 100644
index 0000000..88a442e
--- /dev/null
+++ b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/interceptor/containerwriter/writerinterceptorcontext/TSAppConfig.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2012, 2020 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 jakarta.ws.rs.tck.ee.rs.ext.interceptor.containerwriter.writerinterceptorcontext;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import jakarta.ws.rs.tck.api.rs.ext.interceptor.InputStreamReaderProvider;
+import jakarta.ws.rs.tck.common.provider.StringBeanEntityProvider;
+import jakarta.ws.rs.tck.ee.rs.ext.interceptor.writer.writerinterceptorcontext.ProceedExceptionMapper;
+import jakarta.ws.rs.tck.ee.rs.ext.interceptor.writer.writerinterceptorcontext.WriterInterceptorOne;
+import jakarta.ws.rs.tck.ee.rs.ext.interceptor.writer.writerinterceptorcontext.WriterInterceptorTwo;
+
+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(WriterInterceptorOne.class);
+    resources.add(WriterInterceptorTwo.class);
+    resources.add(InputStreamReaderProvider.class);
+    resources.add(StringBeanEntityProvider.class);
+    resources.add(ProceedExceptionMapper.class);
+    return resources;
+  }
+}
diff --git a/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/interceptor/writer/TemplateWriterInterceptor.java b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/interceptor/writer/TemplateWriterInterceptor.java
new file mode 100644
index 0000000..86c3e87
--- /dev/null
+++ b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/interceptor/writer/TemplateWriterInterceptor.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2012, 2020 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 jakarta.ws.rs.tck.ee.rs.ext.interceptor.writer;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.lang.reflect.Type;
+
+import jakarta.ws.rs.tck.api.rs.ext.interceptor.InterceptorCallbackMethods;
+import jakarta.ws.rs.tck.api.rs.ext.interceptor.TemplateInterceptorBody;
+
+import jakarta.ws.rs.core.MultivaluedMap;
+import jakarta.ws.rs.ext.WriterInterceptor;
+import jakarta.ws.rs.ext.WriterInterceptorContext;
+
+/**
+ * This class is a superclass for any interceptor @Provider. Any such provider
+ * is then given a body, inherited from TemplateInterceptorBody. The body
+ * actually contains methods with name equalIgnoreCase to ContextOperation items
+ * name, the name of the method executed is passed by http header OPERATION
+ * 
+ * @see TemplateInterceptorBody
+ * 
+ *      The injection of the body solves the issue with inheritance from two
+ *      super-classes.
+ */
+public abstract class TemplateWriterInterceptor
+    implements WriterInterceptor, InterceptorCallbackMethods {
+
+  protected WriterInterceptorContext writerCtx;
+
+  protected TemplateInterceptorBody<WriterInterceptorContext> interceptorBody;
+
+  public TemplateWriterInterceptor(
+      TemplateInterceptorBody<WriterInterceptorContext> interceptorBody) {
+    super();
+    this.interceptorBody = interceptorBody;
+  }
+
+  @Override
+  public void aroundWriteTo(WriterInterceptorContext ctx) throws IOException {
+    this.writerCtx = ctx;
+    interceptorBody.executeMethod(writerCtx, this);
+  }
+
+  @Override
+  public void writeEntity(String entity) {
+    Type type = writerCtx.getGenericType();
+    if (type instanceof Class) {
+      Class<?> clazz = ((Class<?>) type);
+      if (clazz == InputStreamReader.class) {
+        ByteArrayInputStream bis = new ByteArrayInputStream(entity.getBytes());
+        InputStreamReader reader = new InputStreamReader(bis);
+        writerCtx.setEntity(reader);
+      } else {
+        writerCtx.setEntity(entity);
+      }
+    }
+  }
+
+  @Override
+  public Object proceed() throws IOException {
+    writerCtx.proceed();
+    return null;
+  }
+
+  @Override
+  public String getHeaderString() {
+    MultivaluedMap<String, Object> headers = writerCtx.getHeaders();
+    return (String) headers.getFirst(TemplateInterceptorBody.OPERATION);
+  }
+
+}
diff --git a/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/interceptor/writer/interceptorcontext/WriterInterceptorOne.java b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/interceptor/writer/interceptorcontext/WriterInterceptorOne.java
new file mode 100644
index 0000000..73ab437
--- /dev/null
+++ b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/interceptor/writer/interceptorcontext/WriterInterceptorOne.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2012, 2020 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 jakarta.ws.rs.tck.ee.rs.ext.interceptor.writer.interceptorcontext;
+
+import jakarta.ws.rs.tck.api.rs.ext.interceptor.InterceptorBodyOne;
+import jakarta.ws.rs.tck.ee.rs.ext.interceptor.writer.TemplateWriterInterceptor;
+
+import jakarta.annotation.Priority;
+import jakarta.ws.rs.ext.Provider;
+import jakarta.ws.rs.ext.WriterInterceptorContext;
+
+@Provider
+@Priority(100)
+public class WriterInterceptorOne extends TemplateWriterInterceptor {
+
+  public WriterInterceptorOne() {
+    super(new InterceptorBodyOne<WriterInterceptorContext>());
+  }
+
+}
diff --git a/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/interceptor/writer/interceptorcontext/WriterInterceptorTwo.java b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/interceptor/writer/interceptorcontext/WriterInterceptorTwo.java
new file mode 100644
index 0000000..79145f6
--- /dev/null
+++ b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/interceptor/writer/interceptorcontext/WriterInterceptorTwo.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2012, 2020 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 jakarta.ws.rs.tck.ee.rs.ext.interceptor.writer.interceptorcontext;
+
+import jakarta.ws.rs.tck.api.rs.ext.interceptor.InterceptorBodyTwo;
+import jakarta.ws.rs.tck.ee.rs.ext.interceptor.writer.TemplateWriterInterceptor;
+
+import jakarta.annotation.Priority;
+import jakarta.ws.rs.ext.Provider;
+import jakarta.ws.rs.ext.WriterInterceptorContext;
+
+@Provider
+@Priority(200)
+public class WriterInterceptorTwo extends TemplateWriterInterceptor {
+
+  public WriterInterceptorTwo() {
+    super(new InterceptorBodyTwo<WriterInterceptorContext>());
+  }
+}
diff --git a/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/interceptor/writer/writerinterceptorcontext/ContextOperation.java b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/interceptor/writer/writerinterceptorcontext/ContextOperation.java
new file mode 100644
index 0000000..5482efa
--- /dev/null
+++ b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/interceptor/writer/writerinterceptorcontext/ContextOperation.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2012, 2018 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 jakarta.ws.rs.tck.ee.rs.ext.interceptor.writer.writerinterceptorcontext;
+
+public enum ContextOperation {
+  GETENTITY, GETHEADERS, GETHEADERSISMUTABLE, GETOUTPUTSTREAM, FROMPROCEEDTHROWSWEBAPPEXCEPTION, // On
+                                                                                                 // return
+                                                                                                 // with
+                                                                                                 // WebAppException
+                                                                                                 // The
+                                                                                                 // Exception
+                                                                                                 // is
+                                                                                                 // not
+                                                                                                 // thrown
+                                                                                                 // again
+  PROCEEDTHROWSIOEXCEPTION, PROCEEDTHROWSWEBAPPEXCEPTION, SETENTITY, SETOUTPUTSTREAM
+}
diff --git a/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/interceptor/writer/writerinterceptorcontext/InterceptorBodyOne.java b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/interceptor/writer/writerinterceptorcontext/InterceptorBodyOne.java
new file mode 100644
index 0000000..aa68c01
--- /dev/null
+++ b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/interceptor/writer/writerinterceptorcontext/InterceptorBodyOne.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2012, 2020 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 jakarta.ws.rs.tck.ee.rs.ext.interceptor.writer.writerinterceptorcontext;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+import jakarta.ws.rs.tck.api.rs.ext.interceptor.TemplateInterceptorBody;
+import jakarta.ws.rs.tck.common.impl.ReplacingOutputStream;
+import jakarta.ws.rs.tck.common.util.JaxrsUtil;
+
+import jakarta.ws.rs.WebApplicationException;
+import jakarta.ws.rs.core.MultivaluedMap;
+import jakarta.ws.rs.ext.WriterInterceptorContext;
+
+public class InterceptorBodyOne
+    extends TemplateInterceptorBody<WriterInterceptorContext> {
+
+  public void getEntity() {
+    Object entity = context.getEntity();
+    setEntity(entity);
+  }
+
+  public void getHeaders() {
+    MultivaluedMap<String, Object> headers = context.getHeaders();
+    String keys = JaxrsUtil.iterableToString(";", headers.keySet());
+    setEntity(keys);
+  }
+
+  public void getHeadersIsMutable() {
+    MultivaluedMap<String, Object> headers = context.getHeaders();
+    Object o = headers.getFirst(PROPERTY);
+    assertTrue(o == null, PROPERTY, "header allready exist");
+    headers.add(PROPERTY, PROPERTY);
+  }
+
+  public void getOutputStream() throws IOException {
+    setEntityToOutputStream(NULL);
+  }
+
+  public void proceedThrowsIOException() {
+    try {
+      context.proceed(); // Should throw IOException which is wrapped in
+      setEntity(NULL); // TemplateWriterInterceptor to RuntimeExecption
+    } catch (IOException ioe) {
+      setEntity(IOE); // let the client know
+    } catch (Throwable t) {
+      throw new RuntimeException(t);
+    }
+  }
+
+  public String proceedThrowsWebAppException() throws IOException {
+    try {
+      context.proceed(); // Should throw WebApplicationException in
+      throw new ProceedException(NULL); // TemplateWriterInterceptor
+    } catch (WebApplicationException e) {
+      throw new ProceedException(WAE);
+    } catch (IOException e) {
+      throw new ProceedException(NULL); // TemplateWriterInterceptor to
+      // RuntimeExecption
+    }
+  }
+
+  public void fromProceedThrowsWebAppException() throws IOException {
+    // intentionally blank, no need to do enything
+    // this is called on an interceptor on a response given by
+    // ProceedException.getResponse()
+  }
+
+  public void setEntity() {
+    context.setEntity(OPERATION);
+  }
+
+  public void setOutputStream() throws IOException {
+    OutputStream originalStream = context.getOutputStream();
+    OutputStream replace = new ReplacingOutputStream(originalStream, 't', 'x');
+    context.setOutputStream(replace);
+  }
+
+  private void setEntityToOutputStream(String entity) throws IOException {
+    OutputStream stream = context.getOutputStream();
+    stream.write(entity.getBytes());
+  }
+}
diff --git a/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/interceptor/writer/writerinterceptorcontext/InterceptorBodyTwo.java b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/interceptor/writer/writerinterceptorcontext/InterceptorBodyTwo.java
new file mode 100644
index 0000000..79b505a
--- /dev/null
+++ b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/interceptor/writer/writerinterceptorcontext/InterceptorBodyTwo.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2012, 2020 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 jakarta.ws.rs.tck.ee.rs.ext.interceptor.writer.writerinterceptorcontext;
+
+import java.io.IOException;
+
+import jakarta.ws.rs.tck.api.rs.ext.interceptor.TemplateInterceptorBody;
+
+import jakarta.ws.rs.core.MultivaluedMap;
+import jakarta.ws.rs.ext.WriterInterceptorContext;
+
+public class InterceptorBodyTwo
+    extends TemplateInterceptorBody<WriterInterceptorContext> {
+  @Override
+  protected Object operationMethodNotFound(String operation)
+      throws IOException {
+    return proceed();
+  }
+
+  public void getHeadersIsMutable() {
+    MultivaluedMap<String, Object> headers = context.getHeaders();
+    Object o = headers.getFirst(PROPERTY);
+    assertTrue(o != null, PROPERTY, "header NOT found");
+    setEntity(o);
+  }
+
+  public void proceedThrowsIOException() throws IOException {
+    throw new IOException("Interceptor test IoException");
+  }
+
+  public void proceedThrowsWebAppException() throws IOException {
+    context.proceed();
+  }
+
+  public void setEntity() {
+    Object entity = context.getEntity();
+    setEntity(entity);
+  }
+}
diff --git a/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/interceptor/writer/writerinterceptorcontext/OnWriteExceptionThrowingStringBean.java b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/interceptor/writer/writerinterceptorcontext/OnWriteExceptionThrowingStringBean.java
new file mode 100644
index 0000000..0951377
--- /dev/null
+++ b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/interceptor/writer/writerinterceptorcontext/OnWriteExceptionThrowingStringBean.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2013, 2020 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 jakarta.ws.rs.tck.ee.rs.ext.interceptor.writer.writerinterceptorcontext;
+
+import java.io.IOException;
+
+import jakarta.ws.rs.tck.api.rs.ext.interceptor.TemplateInterceptorBody;
+import jakarta.ws.rs.tck.common.provider.StringBean;
+
+import jakarta.ws.rs.WebApplicationException;
+
+public class OnWriteExceptionThrowingStringBean extends StringBean {
+
+  public OnWriteExceptionThrowingStringBean(String header) {
+    super(header);
+  }
+
+  @Override
+  public String get() {
+    String header = super.get();
+    if (header.equals(TemplateInterceptorBody.WAE))
+      return header;
+    else
+      throw new WebApplicationException(new IOException(header));
+  }
+}
diff --git a/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/interceptor/writer/writerinterceptorcontext/ProceedException.java b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/interceptor/writer/writerinterceptorcontext/ProceedException.java
new file mode 100644
index 0000000..67c45cd
--- /dev/null
+++ b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/interceptor/writer/writerinterceptorcontext/ProceedException.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2013, 2020 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 jakarta.ws.rs.tck.ee.rs.ext.interceptor.writer.writerinterceptorcontext;
+
+import jakarta.ws.rs.tck.api.rs.ext.interceptor.TemplateInterceptorBody;
+
+import jakarta.ws.rs.WebApplicationException;
+import jakarta.ws.rs.core.Response;
+
+public class ProceedException extends WebApplicationException {
+
+  private static final long serialVersionUID = -8012949565468746147L;
+
+  private String msg;
+
+  public ProceedException(String msg) {
+    super(
+        Response.ok(msg)
+            .header(TemplateInterceptorBody.OPERATION,
+                ContextOperation.FROMPROCEEDTHROWSWEBAPPEXCEPTION.name())
+            .build());
+    this.msg = msg;
+  }
+
+  /**
+   * Acyclic getCause() returns equivalent of this
+   */
+  @Override
+  public Throwable getCause() {
+    return new ProceedException(msg) {
+      private static final long serialVersionUID = 256996856963444570L;
+
+      @Override
+      public Throwable getCause() {
+        return null;
+      }
+    };
+  }
+
+  @Override
+  public String getMessage() {
+    return msg;
+  }
+}
diff --git a/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/interceptor/writer/writerinterceptorcontext/ProceedExceptionMapper.java b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/interceptor/writer/writerinterceptorcontext/ProceedExceptionMapper.java
new file mode 100644
index 0000000..44568c6
--- /dev/null
+++ b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/interceptor/writer/writerinterceptorcontext/ProceedExceptionMapper.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2013, 2020 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 jakarta.ws.rs.tck.ee.rs.ext.interceptor.writer.writerinterceptorcontext;
+
+import jakarta.ws.rs.core.Response;
+import jakarta.ws.rs.ext.ExceptionMapper;
+
+public class ProceedExceptionMapper
+    implements ExceptionMapper<ProceedException> {
+
+  @Override
+  public Response toResponse(ProceedException exception) {
+    return exception.getResponse();
+  }
+
+}
diff --git a/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/interceptor/writer/writerinterceptorcontext/WriterInterceptorOne.java b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/interceptor/writer/writerinterceptorcontext/WriterInterceptorOne.java
new file mode 100644
index 0000000..92dc4de
--- /dev/null
+++ b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/interceptor/writer/writerinterceptorcontext/WriterInterceptorOne.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2012, 2020 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 jakarta.ws.rs.tck.ee.rs.ext.interceptor.writer.writerinterceptorcontext;
+
+import jakarta.ws.rs.tck.ee.rs.ext.interceptor.writer.TemplateWriterInterceptor;
+
+import jakarta.annotation.Priority;
+import jakarta.ws.rs.ext.Provider;
+
+@Provider
+@Priority(100)
+public class WriterInterceptorOne extends TemplateWriterInterceptor {
+
+  public WriterInterceptorOne() {
+    super(new InterceptorBodyOne());
+  }
+
+}
diff --git a/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/interceptor/writer/writerinterceptorcontext/WriterInterceptorTwo.java b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/interceptor/writer/writerinterceptorcontext/WriterInterceptorTwo.java
new file mode 100644
index 0000000..0bae703
--- /dev/null
+++ b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/interceptor/writer/writerinterceptorcontext/WriterInterceptorTwo.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2012, 2020 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 jakarta.ws.rs.tck.ee.rs.ext.interceptor.writer.writerinterceptorcontext;
+
+import jakarta.ws.rs.tck.ee.rs.ext.interceptor.writer.TemplateWriterInterceptor;
+
+import jakarta.annotation.Priority;
+import jakarta.ws.rs.ext.Provider;
+
+@Provider
+@Priority(200)
+public class WriterInterceptorTwo extends TemplateWriterInterceptor {
+
+  public WriterInterceptorTwo() {
+    super(new InterceptorBodyTwo());
+  }
+}
diff --git a/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/messagebodyreaderwriter/EntityAnnotation.java b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/messagebodyreaderwriter/EntityAnnotation.java
new file mode 100644
index 0000000..9f5e01f
--- /dev/null
+++ b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/messagebodyreaderwriter/EntityAnnotation.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2012, 2018 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 jakarta.ws.rs.tck.ee.rs.ext.messagebodyreaderwriter;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * This class is used by
+ * jakarta.ws.rs.tck.ee.rs.ext.providers.ProvidersServlet
+ */
+@Retention(RetentionPolicy.RUNTIME)
+public @interface EntityAnnotation {
+  String value();
+}
diff --git a/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/messagebodyreaderwriter/EntityMessageReader.java b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/messagebodyreaderwriter/EntityMessageReader.java
new file mode 100644
index 0000000..d7669e7
--- /dev/null
+++ b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/messagebodyreaderwriter/EntityMessageReader.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2012, 2020 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 jakarta.ws.rs.tck.ee.rs.ext.messagebodyreaderwriter;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+
+import jakarta.ws.rs.tck.common.AbstractMessageBodyRW;
+
+import jakarta.ws.rs.WebApplicationException;
+import jakarta.ws.rs.core.MediaType;
+import jakarta.ws.rs.core.MultivaluedMap;
+import jakarta.ws.rs.core.Response.Status;
+import jakarta.ws.rs.ext.MessageBodyReader;
+import jakarta.ws.rs.ext.Provider;
+
+/**
+ * This class is used by
+ * jakarta.ws.rs.tck.ee.rs.ext.providers.ProvidersServlet
+ */
+@Provider
+public class EntityMessageReader extends AbstractMessageBodyRW
+    implements MessageBodyReader<ReadableWritableEntity> {
+
+  @Override
+  public boolean isReadable(Class<?> type, Type genericType,
+      Annotation[] annotations, MediaType mediaType) {
+    String path = getSpecifiedAnnotationValue(annotations,
+        EntityAnnotation.class);
+    if (path == null)
+      return false;
+    path = path.toLowerCase();
+    boolean readable = path.contains("body");
+    readable |= path.contains("head");
+    readable |= path.contains("ioexception");
+    readable |= path.contains("webexception");
+    readable &= MediaType.TEXT_XML_TYPE.isCompatible(mediaType);
+    readable &= ReadableWritableEntity.class.isAssignableFrom(type);
+    return readable;
+  }
+
+  @Override
+  public ReadableWritableEntity readFrom(Class<ReadableWritableEntity> type,
+      Type genericType, Annotation[] annotations, MediaType mediaType,
+      MultivaluedMap<String, String> httpHeaders, InputStream entityStream)
+      throws IOException, WebApplicationException {
+    String ea = getSpecifiedAnnotationValue(annotations, EntityAnnotation.class)
+        .toLowerCase();
+    String entity = "null";
+    if (ea.contains("body"))
+      entity = readInputStream(entityStream);
+    else if (ea.contains("head"))
+      entity = httpHeaders.getFirst(ReadableWritableEntity.NAME);
+    else if (ea.contains("ioexception"))
+      throw new IOException("CTS test IOException");
+    else if (ea.contains("webexception")) {
+      entity = httpHeaders.getFirst(ReadableWritableEntity.NAME);
+      throw new WebApplicationException(Status.valueOf(entity));
+    }
+    return ReadableWritableEntity.fromString(entity);
+  }
+
+  String readInputStream(InputStream is) throws IOException {
+    InputStreamReader isr = new InputStreamReader(is);
+    BufferedReader br = new BufferedReader(isr);
+    return br.readLine();
+  }
+}
diff --git a/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/messagebodyreaderwriter/EntityMessageWriter.java b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/messagebodyreaderwriter/EntityMessageWriter.java
index cac6e91..052313f 100644
--- a/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/messagebodyreaderwriter/EntityMessageWriter.java
+++ b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/messagebodyreaderwriter/EntityMessageWriter.java
@@ -31,7 +31,7 @@
 
 /**
  * This class is used by
- * com.sun.ts.tests.jaxrs.ee.rs.ext.providers.ProvidersServlet
+ * jakarta.ws.rs.tck.ee.rs.ext.providers.ProvidersServlet
  */
 @Provider
 public class EntityMessageWriter extends AbstractMessageBodyRW
diff --git a/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/messagebodyreaderwriter/ReadableWritableEntity.java b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/messagebodyreaderwriter/ReadableWritableEntity.java
index 5143385..cea33cb 100644
--- a/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/messagebodyreaderwriter/ReadableWritableEntity.java
+++ b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/messagebodyreaderwriter/ReadableWritableEntity.java
@@ -18,7 +18,7 @@
 
 /**
  * This class is used by
- * com.sun.ts.tests.jaxrs.ee.rs.ext.providers.ProvidersServlet
+ * jakarta.ws.rs.tck.ee.rs.ext.providers.ProvidersServlet
  */
 public class ReadableWritableEntity {
   private String entity;
diff --git a/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/paramconverter/AtomicIntegerLazyParamConverter.java b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/paramconverter/AtomicIntegerLazyParamConverter.java
new file mode 100644
index 0000000..80202f3
--- /dev/null
+++ b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/paramconverter/AtomicIntegerLazyParamConverter.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2012, 2020 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 jakarta.ws.rs.tck.ee.rs.ext.paramconverter;
+
+import java.util.concurrent.atomic.AtomicInteger;
+
+import jakarta.ws.rs.ext.ParamConverter;
+import jakarta.ws.rs.ext.ParamConverter.Lazy;
+
+@Lazy
+public class AtomicIntegerLazyParamConverter
+    implements ParamConverter<AtomicInteger> {
+
+  @Override
+  public AtomicInteger fromString(String value)
+      throws IllegalArgumentException {
+    return new AtomicInteger(Integer.parseInt(value));
+  }
+
+  @Override
+  public String toString(AtomicInteger value) throws IllegalArgumentException {
+    return String.valueOf(value.get());
+  }
+
+}
diff --git a/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/paramconverter/AtomicIntegerLazyParamConverterProvider.java b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/paramconverter/AtomicIntegerLazyParamConverterProvider.java
new file mode 100644
index 0000000..195fa93
--- /dev/null
+++ b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/paramconverter/AtomicIntegerLazyParamConverterProvider.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2012, 2020 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 jakarta.ws.rs.tck.ee.rs.ext.paramconverter;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import jakarta.ws.rs.ext.ParamConverter;
+import jakarta.ws.rs.ext.ParamConverterProvider;
+import jakarta.ws.rs.ext.Provider;
+
+@Provider
+public class AtomicIntegerLazyParamConverterProvider
+    implements ParamConverterProvider {
+
+  @SuppressWarnings("unchecked")
+  @Override
+  public <T> ParamConverter<T> getConverter(Class<T> rawType, Type genericType,
+      Annotation[] annotations) {
+    if (rawType == AtomicInteger.class)
+      return (ParamConverter<T>) new AtomicIntegerLazyParamConverter();
+    return null;
+  }
+
+}
diff --git a/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/paramconverter/DataSourceParamConverter.java b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/paramconverter/DataSourceParamConverter.java
new file mode 100644
index 0000000..1ad24ff
--- /dev/null
+++ b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/paramconverter/DataSourceParamConverter.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2012, 2020 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 jakarta.ws.rs.tck.ee.rs.ext.paramconverter;
+
+import jakarta.ws.rs.tck.common.impl.StringDataSource;
+
+import jakarta.activation.DataSource;
+import jakarta.ws.rs.core.MediaType;
+import jakarta.ws.rs.ext.ParamConverter;
+
+public class DataSourceParamConverter implements ParamConverter<DataSource> {
+
+  @Override
+  public DataSource fromString(String value) throws IllegalArgumentException {
+    StringDataSource sds = new StringDataSource(value,
+        MediaType.TEXT_PLAIN_TYPE);
+    return sds;
+  }
+
+  @Override
+  public String toString(DataSource value) throws IllegalArgumentException {
+    return value.getName();
+  }
+
+}
diff --git a/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/paramconverter/DataSourceParamConverterProvider.java b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/paramconverter/DataSourceParamConverterProvider.java
new file mode 100644
index 0000000..33b5b6a
--- /dev/null
+++ b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/paramconverter/DataSourceParamConverterProvider.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2012, 2020 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 jakarta.ws.rs.tck.ee.rs.ext.paramconverter;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+
+import jakarta.activation.DataSource;
+import jakarta.ws.rs.ext.ParamConverter;
+import jakarta.ws.rs.ext.ParamConverterProvider;
+import jakarta.ws.rs.ext.Provider;
+
+@Provider
+public class DataSourceParamConverterProvider
+    implements ParamConverterProvider {
+
+  @SuppressWarnings("unchecked")
+  @Override
+  public <T> ParamConverter<T> getConverter(Class<T> rawType, Type genericType,
+      Annotation[] annotations) {
+    if (DataSource.class.isAssignableFrom(rawType))
+      return (ParamConverter<T>) new DataSourceParamConverter();
+    return null;
+  }
+
+}
diff --git a/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/paramconverter/JAXRSClientIT.java b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/paramconverter/JAXRSClientIT.java
new file mode 100644
index 0000000..f75f5d1
--- /dev/null
+++ b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/paramconverter/JAXRSClientIT.java
@@ -0,0 +1,548 @@
+/*
+ * Copyright (c) 2012, 2020 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 jakarta.ws.rs.tck.ee.rs.ext.paramconverter;
+
+import java.io.InputStream;
+import java.io.IOException;
+import jakarta.ws.rs.tck.common.client.JaxrsCommonClient;
+import jakarta.ws.rs.tck.lib.util.TestUtil;
+
+import jakarta.ws.rs.core.MediaType;
+import jakarta.ws.rs.core.Response.Status;
+
+import org.jboss.arquillian.junit5.ArquillianExtension;
+import org.jboss.arquillian.container.test.api.Deployment;
+import org.jboss.shrinkwrap.api.ShrinkWrap;
+import org.jboss.shrinkwrap.api.asset.StringAsset;
+import org.jboss.shrinkwrap.api.spec.WebArchive;
+import org.jboss.shrinkwrap.api.exporter.ZipExporter;
+
+import static org.junit.jupiter.api.Assertions.fail;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.junit.jupiter.api.TestInfo;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.AfterEach;
+
+/*
+ * @class.setup_props: webServerHost;
+ *                     webServerPort;
+ */
+@ExtendWith(ArquillianExtension.class)
+public class JAXRSClientIT extends JaxrsCommonClient {
+
+  private static final long serialVersionUID = 863071027768369551L;
+
+  public JAXRSClientIT() {
+    setup();
+    setContextRoot("/jaxrs_ee_ext_paramconverter_web");
+  }
+
+  @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{
+
+    InputStream inStream = JAXRSClientIT.class.getClassLoader().getResourceAsStream("jakarta/ws/rs/tck/ee/rs/ext/paramconverter/web.xml.template");
+    String webXml = editWebXmlString(inStream);
+
+    WebArchive archive = ShrinkWrap.create(WebArchive.class, "jaxrs_ee_ext_paramconverter_web.war");
+    archive.addClasses(Resource.class, Locator.class, DataSourceParamConverter.class, DataSourceParamConverterProvider.class,
+      StringBeanParamConverter.class, StringBeanParamConverterProvider.class, AtomicIntegerLazyParamConverter.class, AtomicIntegerLazyParamConverterProvider.class, 
+      jakarta.ws.rs.tck.common.provider.PrintingErrorHandler.class,
+      jakarta.ws.rs.tck.common.provider.StringBean.class, 
+      jakarta.ws.rs.tck.common.impl.StringDataSource.class, 
+      TSAppConfig.class);
+    archive.setWebXML(new StringAsset(webXml));
+    return archive;
+
+  }
+
+
+  /* Run test */
+
+  /*
+   * @testName: isParamCoverterInApplicationSingletonsUsedTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:919;
+   * 
+   * @test_Strategy: Providers implementing ParamConverterProvider contract must
+   * be either programmatically registered in a JAX-RS runtime
+   */
+  @Test
+  public void isParamCoverterInApplicationSingletonsUsedTest() throws Fault {
+    String query = "ABCDEFGH";
+    setPropertyRequest(Request.GET, "dsquery?param=", query);
+    setProperty(Property.SEARCH_STRING, query);
+    invoke();
+  }
+
+  /*
+   * @testName: isParamCoverterInApplicationClassesUsedTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:919;
+   * 
+   * @test_Strategy: Providers implementing ParamConverterProvider contract must
+   * be either programmatically registered in a JAX-RS runtime
+   */
+  @Test
+  public void isParamCoverterInApplicationClassesUsedTest() throws Fault {
+    String query = "ABCDEFGH";
+    setPropertyRequest(Request.GET, "sbquery?param=", query);
+    setProperty(Property.SEARCH_STRING, query);
+    invoke();
+  }
+
+  /*
+   * @testName: atomicIntegerPassesTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:919;
+   * 
+   * @test_Strategy: Providers implementing ParamConverterProvider contract must
+   * be either programmatically registered in a JAX-RS runtime
+   */
+  @Test
+  public void atomicIntegerPassesTest() throws Fault {
+    String query = "10";
+    setPropertyRequest(Request.GET, "aiquery?param=", query);
+    setProperty(Property.SEARCH_STRING, query);
+    invoke();
+  }
+
+  /*
+   * @testName: atomicIntegerIsLazyDeployableAndThrowsErrorTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:919;
+   * 
+   * @test_Strategy: Providers implementing ParamConverterProvider contract must
+   * be either programmatically registered in a JAX-RS runtime
+   */
+  @Test
+  public void atomicIntegerIsLazyDeployableAndThrowsErrorTest() throws Fault {
+    setPropertyRequest(Request.GET, "aiquery");
+    setProperty(Property.STATUS_CODE, getStatusCode(Status.NOT_ACCEPTABLE));
+    invoke();
+  }
+
+  /*
+   * @testName: pathParamUsesParamConvertorTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:915;
+   * 
+   * @test_Strategy: Parse the supplied value and create an instance of
+   */
+  @Test
+  public void pathParamUsesParamConvertorTest() throws Fault {
+    String query = "ABCDEFGH";
+    setPropertyRequest(Request.GET, "sbpath/", query);
+    setProperty(Property.SEARCH_STRING, query);
+    invoke();
+  }
+
+  /*
+   * @testName: matrixParamUsesParamConvertorTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:915;
+   * 
+   * @test_Strategy: Parse the supplied value and create an instance of
+   */
+  @Test
+  public void matrixParamUsesParamConvertorTest() throws Fault {
+    String query = "ABCDEFGH";
+    setPropertyRequest(Request.GET, "sbmatrix;param=", query);
+    setProperty(Property.SEARCH_STRING, query);
+    invoke();
+  }
+
+  /*
+   * @testName: formParamUsesParamConvertorTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:915;
+   * 
+   * @test_Strategy: Parse the supplied value and create an instance of
+   */
+  @Test
+  public void formParamUsesParamConvertorTest() throws Fault {
+    String query = "ABCDEFGH";
+    setProperty(Property.REQUEST_HEADERS,
+        buildContentType(MediaType.APPLICATION_FORM_URLENCODED_TYPE));
+    setPropertyRequest(Request.POST, "sbform/");
+    setProperty(Property.CONTENT, "param=" + query);
+    setProperty(Property.SEARCH_STRING, query);
+    invoke();
+  }
+
+  /*
+   * @testName: cookieParamUsesParamConvertorTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:915;
+   * 
+   * @test_Strategy: Parse the supplied value and create an instance of
+   */
+  @Test
+  public void cookieParamUsesParamConvertorTest() throws Fault {
+    String query = "ABCDEFGH";
+    buildCookie(query);
+    setPropertyRequest(Request.GET, "sbcookie");
+    setProperty(Property.SEARCH_STRING, query);
+    invoke();
+  }
+
+  /*
+   * @testName: headerParamUsesParamConvertorTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:915;
+   * 
+   * @test_Strategy: Parse the supplied value and create an instance of
+   */
+  @Test
+  public void headerParamUsesParamConvertorTest() throws Fault {
+    String query = "ABCDEFGH";
+    setProperty(Property.REQUEST_HEADERS, "param:" + query);
+    setPropertyRequest(Request.GET, "sbheader");
+    setProperty(Property.SEARCH_STRING, query);
+    invoke();
+  }
+
+  /*
+   * @testName: defaultValueInQueryParamTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:915;
+   * 
+   * @test_Strategy: selected ParamConverter instance MUST be used eagerly by a
+   * JAX-RS runtime to convert any default value in the resource or provider
+   * model, that is during the application deployment, before any value default
+   * or otherwise is actually required
+   */
+  @Test
+  public void defaultValueInQueryParamTest() throws Fault {
+    setPropertyRequest(Request.GET, "sbquery");
+    setProperty(Property.SEARCH_STRING, Resource.DEFAULT);
+    invoke();
+  }
+
+  /*
+   * @testName: defaultValueInMatrixParamTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:915;
+   * 
+   * @test_Strategy: selected ParamConverter instance MUST be used eagerly by a
+   * JAX-RS runtime to convert any default value in the resource or provider
+   * model, that is during the application deployment, before any value default
+   * or otherwise is actually required
+   */
+  @Test
+  public void defaultValueInMatrixParamTest() throws Fault {
+    setPropertyRequest(Request.GET, "sbmatrix;");
+    setProperty(Property.SEARCH_STRING, Resource.DEFAULT);
+    invoke();
+  }
+
+  /*
+   * @testName: defaultValueInPathParamTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:915;
+   * 
+   * @test_Strategy: selected ParamConverter instance MUST be used eagerly by a
+   * JAX-RS runtime to convert any default value in the resource or provider
+   * model, that is during the application deployment, before any value default
+   * or otherwise is actually required
+   */
+  @Test
+  public void defaultValueInPathParamTest() throws Fault {
+    setPropertyRequest(Request.GET, "sbpath/default");
+    setProperty(Property.SEARCH_STRING, Resource.DEFAULT);
+    invoke();
+  }
+
+  /*
+   * @testName: defaultValueInFormParamTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:915;
+   * 
+   * @test_Strategy: selected ParamConverter instance MUST be used eagerly by a
+   * JAX-RS runtime to convert any default value in the resource or provider
+   * model, that is during the application deployment, before any value default
+   * or otherwise is actually required
+   */
+  @Test
+  public void defaultValueInFormParamTest() throws Fault {
+    setProperty(Property.REQUEST_HEADERS,
+        buildContentType(MediaType.APPLICATION_FORM_URLENCODED_TYPE));
+    setPropertyRequest(Request.POST, "sbform/");
+    setProperty(Property.SEARCH_STRING, Resource.DEFAULT);
+    invoke();
+  }
+
+  /*
+   * @testName: defaultValueInCookieParamTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:915;
+   * 
+   * @test_Strategy: selected ParamConverter instance MUST be used eagerly by a
+   * JAX-RS runtime to convert any default value in the resource or provider
+   * model, that is during the application deployment, before any value default
+   * or otherwise is actually required
+   */
+  @Test
+  public void defaultValueInCookieParamTest() throws Fault {
+    setPropertyRequest(Request.GET, "sbcookie");
+    setProperty(Property.SEARCH_STRING, Resource.DEFAULT);
+    invoke();
+  }
+
+  /*
+   * @testName: defaultValueInHeaderParamTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:915;
+   * 
+   * @test_Strategy: selected ParamConverter instance MUST be used eagerly by a
+   * JAX-RS runtime to convert any default value in the resource or provider
+   * model, that is during the application deployment, before any value default
+   * or otherwise is actually required
+   */
+  @Test
+  public void defaultValueInHeaderParamTest() throws Fault {
+    setPropertyRequest(Request.GET, "sbheader");
+    setProperty(Property.SEARCH_STRING, Resource.DEFAULT);
+    invoke();
+  }
+
+  /*
+   * @testName: queryParamInLocatorTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:915;
+   * 
+   * @test_Strategy: Parse the supplied value and create an instance of
+   */
+  @Test
+  public void queryParamInLocatorTest() throws Fault {
+    String query = "ABCDEFGH";
+    setPropertyRequestInLocator(Request.GET, "sbquery/sbquery?param=", query);
+    setProperty(Property.SEARCH_STRING, query);
+    invoke();
+  }
+
+  /*
+   * @testName: defaultValueQueryParamInLocatorTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:915;
+   * 
+   * @test_Strategy: selected ParamConverter instance MUST be used eagerly by a
+   * JAX-RS runtime to convert any default value
+   */
+  @Test
+  public void defaultValueQueryParamInLocatorTest() throws Fault {
+    String query = "ABCDEFGH";
+    setPropertyRequestInLocator(Request.GET, "sbquery/sbquery?", query);
+    setProperty(Property.SEARCH_STRING, Resource.DEFAULT);
+    invoke();
+  }
+
+  /*
+   * @testName: pathParamInLocatorTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:915;
+   * 
+   * @test_Strategy: Parse the supplied value and create an instance of
+   */
+  @Test
+  public void pathParamInLocatorTest() throws Fault {
+    String query = "ABCDEFGH";
+    setPropertyRequestInLocator(Request.GET, "sbpath/sbpath/", query);
+    setProperty(Property.SEARCH_STRING, query);
+    invoke();
+  }
+
+  /*
+   * @testName: defaultValuePathParamInLocatorTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:915;
+   * 
+   * @test_Strategy: selected ParamConverter instance MUST be used eagerly by a
+   * JAX-RS runtime to convert any default value
+   */
+  @Test
+  public void defaultValuePathParamInLocatorTest() throws Fault {
+    setPropertyRequestInLocator(Request.GET, "sbpath/sbpath/default");
+    setProperty(Property.SEARCH_STRING, Resource.DEFAULT);
+    invoke();
+  }
+
+  /*
+   * @testName: matrixParamInLocatorTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:915;
+   * 
+   * @test_Strategy: Parse the supplied value and create an instance of
+   */
+  @Test
+  public void matrixParamInLocatorTest() throws Fault {
+    String query = "ABCDEFGH";
+    setPropertyRequestInLocator(Request.GET, "sbmatrix/sbmatrix;param=", query);
+    setProperty(Property.SEARCH_STRING, query);
+    invoke();
+  }
+
+  /*
+   * @testName: defaultValueMatrixParamInLocatorTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:915;
+   * 
+   * @test_Strategy: selected ParamConverter instance MUST be used eagerly by a
+   * JAX-RS runtime to convert any default value
+   */
+  @Test
+  public void defaultValueMatrixParamInLocatorTest() throws Fault {
+    setPropertyRequestInLocator(Request.GET, "sbmatrix/sbmatrix");
+    setProperty(Property.SEARCH_STRING, Resource.DEFAULT);
+    invoke();
+  }
+
+  /*
+   * @testName: formParamInLocatorTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:915;
+   * 
+   * @test_Strategy: Parse the supplied value and create an instance of
+   */
+  @Test
+  public void formParamInLocatorTest() throws Fault {
+    String query = "ABCDEFGH";
+    setProperty(Property.REQUEST_HEADERS,
+        buildContentType(MediaType.APPLICATION_FORM_URLENCODED_TYPE));
+    setPropertyRequestInLocator(Request.POST, "sbform/sbform");
+    setProperty(Property.CONTENT, "param=" + query);
+    setProperty(Property.SEARCH_STRING, query);
+    invoke();
+  }
+
+  /*
+   * @testName: defaultValueFormParamInLocatorTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:915;
+   * 
+   * @test_Strategy: selected ParamConverter instance MUST be used eagerly by a
+   * JAX-RS runtime to convert any default value
+   */
+  @Test
+  public void defaultValueFormParamInLocatorTest() throws Fault {
+    setProperty(Property.REQUEST_HEADERS,
+        buildContentType(MediaType.APPLICATION_FORM_URLENCODED_TYPE));
+    setPropertyRequestInLocator(Request.POST, "sbform/sbform");
+    setProperty(Property.SEARCH_STRING, Resource.DEFAULT);
+    invoke();
+  }
+
+  /*
+   * @testName: cookieParamInLocatorTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:915;
+   * 
+   * @test_Strategy: Parse the supplied value and create an instance of
+   */
+  @Test
+  public void cookieParamInLocatorTest() throws Fault {
+    String query = "ABCDEFGH";
+    buildCookie(query);
+    setPropertyRequestInLocator(Request.GET, "sbcookie/sbcookie");
+    setProperty(Property.SEARCH_STRING, query);
+    invoke();
+  }
+
+  /*
+   * @testName: defaultValueCookieParamInLocatorTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:915;
+   * 
+   * @test_Strategy: selected ParamConverter instance MUST be used eagerly by a
+   * JAX-RS runtime to convert any default value
+   */
+  @Test
+  public void defaultValueCookieParamInLocatorTest() throws Fault {
+    setPropertyRequestInLocator(Request.GET, "sbcookie/sbcookie");
+    setProperty(Property.SEARCH_STRING, Resource.DEFAULT);
+    invoke();
+  }
+
+  /*
+   * @testName: headerParamInLocatorTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:915;
+   * 
+   * @test_Strategy: Parse the supplied value and create an instance of
+   */
+  @Test
+  public void headerParamInLocatorTest() throws Fault {
+    String query = "ABCDEFGH";
+    setProperty(Property.REQUEST_HEADERS, "param:" + query);
+    setPropertyRequestInLocator(Request.GET, "sbheader/sbheader");
+    setProperty(Property.SEARCH_STRING, query);
+    invoke();
+  }
+
+  /*
+   * @testName: defaultValueHeaderParamInLocatorTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:915;
+   * 
+   * @test_Strategy: selected ParamConverter instance MUST be used eagerly by a
+   * JAX-RS runtime to convert any default value
+   */
+  @Test
+  public void defaultValueHeaderParamInLocatorTest() throws Fault {
+    setPropertyRequestInLocator(Request.GET, "sbheader/sbheader");
+    setProperty(Property.SEARCH_STRING, Resource.DEFAULT);
+    invoke();
+  }
+
+  // ////////////////////////////////////////////////////////////////////
+  private//
+  void setPropertyRequestInResource(Request request, String... resource) {
+    StringBuilder sb = new StringBuilder("resource/");
+    for (String r : resource)
+      sb.append(r);
+    setProperty(Property.REQUEST, buildRequest(request, sb.toString()));
+  }
+
+  private void setPropertyRequest(Request request, String... resource) {
+    setPropertyRequestInResource(request, resource);
+  }
+
+  private//
+  void setPropertyRequestInLocator(Request request, String... resource) {
+    StringBuilder sb = new StringBuilder("locator/");
+    for (String r : resource)
+      sb.append(r);
+    setProperty(Property.REQUEST, buildRequest(request, sb.toString()));
+  }
+
+  private void buildCookie(String cookieValue) {
+    StringBuilder sb = new StringBuilder();
+    sb.append("Cookie: param=").append(cookieValue);
+    setProperty(Property.REQUEST_HEADERS, sb.toString());
+  }
+
+}
diff --git a/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/paramconverter/Locator.java b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/paramconverter/Locator.java
new file mode 100644
index 0000000..6f32344
--- /dev/null
+++ b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/paramconverter/Locator.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2012, 2020 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 jakarta.ws.rs.tck.ee.rs.ext.paramconverter;
+
+import jakarta.ws.rs.Consumes;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.core.MediaType;
+
+@Path("locator")
+public class Locator {
+
+  @Path("sbquery")
+  public Resource stringBeanQuery() {
+    return new Resource();
+  }
+
+  @Path("sbpath")
+  public Resource stringBeanPath() {
+    return new Resource();
+  }
+
+  @Path("sbmatrix")
+  public Resource stringBeanMatrix() {
+    return new Resource();
+  }
+
+  @Path("sbform")
+  @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
+  public Resource stringBeanForm() {
+    return new Resource();
+  }
+
+  @Path("sbcookie")
+  public Resource stringBeanCookie() {
+    return new Resource();
+  }
+
+  @Path("sbheader")
+  public Resource stringBeanHeader() {
+    return new Resource();
+  }
+
+}
diff --git a/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/paramconverter/Resource.java b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/paramconverter/Resource.java
new file mode 100644
index 0000000..6f2b061
--- /dev/null
+++ b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/paramconverter/Resource.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2012, 2020 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 jakarta.ws.rs.tck.ee.rs.ext.paramconverter;
+
+import java.util.concurrent.atomic.AtomicInteger;
+
+import jakarta.ws.rs.tck.common.provider.StringBean;
+
+import jakarta.activation.DataSource;
+import jakarta.ws.rs.Consumes;
+import jakarta.ws.rs.CookieParam;
+import jakarta.ws.rs.DefaultValue;
+import jakarta.ws.rs.FormParam;
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.HeaderParam;
+import jakarta.ws.rs.MatrixParam;
+import jakarta.ws.rs.POST;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.PathParam;
+import jakarta.ws.rs.QueryParam;
+import jakarta.ws.rs.core.MediaType;
+
+@Path("resource")
+public class Resource {
+  public static final String NULL = "NULL";
+
+  public static final String DEFAULT = "DEFAULT";
+
+  @Path("sbquery")
+  @GET
+  public String stringBeanQuery(
+      @DefaultValue(DEFAULT) @QueryParam("param") StringBean param) {
+    return param.get();
+  }
+
+  @Path("dsquery")
+  @GET
+  public String dataSourceQuery(@QueryParam("param") DataSource param) {
+    return param.getName();
+  }
+
+  @Path("aiquery")
+  @GET
+  public String atomicIntegerQuery(
+      @DefaultValue(DEFAULT) @QueryParam("param") AtomicInteger param) {
+    return String.valueOf(param.get());
+  }
+
+  @Path("sbpath/{param}")
+  @GET
+  public String stringBeanPath(@PathParam("param") StringBean param) {
+    return param.get();
+  }
+
+  @Path("sbpath/default")
+  @GET
+  public String stringBeanPathNeverHere(
+      @DefaultValue(DEFAULT) @PathParam("param") StringBean param) {
+    return param.get();
+  }
+
+  @Path("sbmatrix")
+  @GET
+  public String stringBeanMatrix(
+      @DefaultValue(DEFAULT) @MatrixParam("param") StringBean param) {
+    return param.get();
+  }
+
+  @Path("sbform")
+  @POST
+  @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
+  public String stringBeanForm(
+      @DefaultValue(DEFAULT) @FormParam("param") StringBean param) {
+    return param.get();
+  }
+
+  @Path("sbcookie")
+  @GET
+  public String stringBeanCookie(
+      @DefaultValue(DEFAULT) @CookieParam("param") StringBean param) {
+    return param.get();
+  }
+
+  @Path("sbheader")
+  @GET
+  public String stringBeanHeader(
+      @DefaultValue(DEFAULT) @HeaderParam("param") StringBean param) {
+    return param.get();
+  }
+}
diff --git a/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/paramconverter/StringBeanParamConverter.java b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/paramconverter/StringBeanParamConverter.java
new file mode 100644
index 0000000..1a03c70
--- /dev/null
+++ b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/paramconverter/StringBeanParamConverter.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2012, 2020 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 jakarta.ws.rs.tck.ee.rs.ext.paramconverter;
+
+import jakarta.ws.rs.tck.common.provider.StringBean;
+
+import jakarta.ws.rs.ext.ParamConverter;
+
+public class StringBeanParamConverter implements ParamConverter<StringBean> {
+
+  @Override
+  public StringBean fromString(String value) throws IllegalArgumentException {
+    return new StringBean(value);
+  }
+
+  @Override
+  public String toString(StringBean value) throws IllegalArgumentException {
+    return value.get();
+  }
+
+}
diff --git a/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/paramconverter/StringBeanParamConverterProvider.java b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/paramconverter/StringBeanParamConverterProvider.java
new file mode 100644
index 0000000..02d46e9
--- /dev/null
+++ b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/paramconverter/StringBeanParamConverterProvider.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2012, 2020 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 jakarta.ws.rs.tck.ee.rs.ext.paramconverter;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+
+import jakarta.ws.rs.tck.common.provider.StringBean;
+
+import jakarta.ws.rs.ext.ParamConverter;
+import jakarta.ws.rs.ext.ParamConverterProvider;
+import jakarta.ws.rs.ext.Provider;
+
+@Provider
+public class StringBeanParamConverterProvider
+    implements ParamConverterProvider {
+
+  @SuppressWarnings("unchecked")
+  @Override
+  public <T> ParamConverter<T> getConverter(Class<T> rawType, Type genericType,
+      Annotation[] annotations) {
+    if (rawType == StringBean.class)
+      return (ParamConverter<T>) new StringBeanParamConverter();
+    return null;
+  }
+
+}
diff --git a/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/paramconverter/TSAppConfig.java b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/paramconverter/TSAppConfig.java
new file mode 100644
index 0000000..dfe52e2
--- /dev/null
+++ b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/paramconverter/TSAppConfig.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2012, 2020 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 jakarta.ws.rs.tck.ee.rs.ext.paramconverter;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import jakarta.ws.rs.tck.common.provider.PrintingErrorHandler;
+
+import jakarta.ws.rs.core.Application;
+
+public class TSAppConfig extends Application {
+
+  @Override
+  public java.util.Set<java.lang.Class<?>> getClasses() {
+    Set<Class<?>> resources = new HashSet<Class<?>>();
+    resources.add(Resource.class);
+    resources.add(Locator.class);
+    resources.add(StringBeanParamConverterProvider.class);
+    resources.add(AtomicIntegerLazyParamConverterProvider.class);
+    resources.add(PrintingErrorHandler.class);
+    return resources;
+  }
+
+  @Override
+  public Set<Object> getSingletons() {
+    Set<Object> set = new HashSet<Object>();
+    set.add(new DataSourceParamConverterProvider());
+    return set;
+  }
+}
diff --git a/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/providers/JAXRSProvidersClientIT.java b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/providers/JAXRSProvidersClientIT.java
new file mode 100644
index 0000000..d369738
--- /dev/null
+++ b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/providers/JAXRSProvidersClientIT.java
@@ -0,0 +1,513 @@
+/*
+ * Copyright (c) 2012, 2020 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 jakarta.ws.rs.tck.ee.rs.ext.providers;
+
+import jakarta.ws.rs.tck.ee.rs.ext.contextresolver.EnumProvider;
+import jakarta.ws.rs.tck.ee.rs.ext.messagebodyreaderwriter.ReadableWritableEntity;
+import java.io.InputStream;
+import java.io.IOException;
+import jakarta.ws.rs.tck.lib.util.TestUtil;
+import jakarta.ws.rs.tck.common.JAXRSCommonClient;
+
+import jakarta.ws.rs.tck.common.webclient.http.HttpResponse;
+import jakarta.ws.rs.core.MediaType;
+import jakarta.ws.rs.core.Response.Status;
+
+import org.jboss.arquillian.junit5.ArquillianExtension;
+import org.jboss.arquillian.container.test.api.Deployment;
+import org.jboss.shrinkwrap.api.ShrinkWrap;
+import org.jboss.shrinkwrap.api.asset.StringAsset;
+import org.jboss.shrinkwrap.api.spec.WebArchive;
+import org.jboss.shrinkwrap.api.exporter.ZipExporter;
+
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assertions.fail;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.junit.jupiter.api.TestInfo;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.AfterEach;
+
+/*
+ * @class.setup_props: webServerHost;
+ *                     webServerPort;
+ */
+@ExtendWith(ArquillianExtension.class)
+public class JAXRSProvidersClientIT
+    //extends jakarta.ws.rs.tck.ee.rs.core.application.JAXRSClientIT {
+    extends JAXRSCommonClient {
+
+  private static final long serialVersionUID = -935293219512493643L;
+
+  protected int expectedSingletons = 1;
+
+  protected int expectedClasses = 1;
+
+  public JAXRSProvidersClientIT() {
+    setup();
+    TSAppConfig cfg = new TSAppConfig();
+    setContextRoot("/jaxrs_ee_ext_providers_web/ProvidersServlet");
+    expectedClasses = cfg.getClasses().size();
+    expectedSingletons = cfg.getSingletons().size();
+  }
+
+  @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{
+
+    InputStream inStream = JAXRSProvidersClientIT.class.getClassLoader().getResourceAsStream("jakarta/ws/rs/tck/ee/rs/ext/providers/web.xml.template");
+    String webXml = editWebXmlString(inStream);
+
+    WebArchive archive = ShrinkWrap.create(WebArchive.class, "jaxrs_ee_ext_providers_web.war");
+    archive.addClasses(TSAppConfig.class, ProvidersServlet.class, 
+      jakarta.ws.rs.tck.common.AbstractMessageBodyRW.class, 
+      jakarta.ws.rs.tck.ee.rs.core.application.ApplicationServlet.class,
+      jakarta.ws.rs.tck.ee.rs.core.application.ApplicationHolderSingleton.class,
+      jakarta.ws.rs.tck.ee.rs.ext.contextresolver.EnumProvider.class,
+      jakarta.ws.rs.tck.ee.rs.ext.contextresolver.EnumContextResolver.class,
+      jakarta.ws.rs.tck.ee.rs.ext.contextresolver.TextPlainEnumContextResolver.class,
+      jakarta.ws.rs.tck.ee.rs.ext.exceptionmapper.AnyExceptionExceptionMapper.class,
+      jakarta.ws.rs.tck.ee.rs.ext.exceptionmapper.IOExceptionExceptionMapper.class,
+      jakarta.ws.rs.tck.ee.rs.ext.messagebodyreaderwriter.EntityAnnotation.class,
+      jakarta.ws.rs.tck.ee.rs.ext.messagebodyreaderwriter.EntityMessageReader.class,
+      jakarta.ws.rs.tck.ee.rs.ext.messagebodyreaderwriter.EntityMessageWriter.class,
+      jakarta.ws.rs.tck.ee.rs.ext.messagebodyreaderwriter.ReadableWritableEntity.class
+    );
+    archive.setWebXML(new StringAsset(webXml));
+    return archive;
+
+  }
+
+  /* Run test */
+
+  /*
+   * @testName: getSingletonsTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:23
+   * 
+   * @test_Strategy: Check that the implementation returns set of
+   * TSAppConfig.CLASSLIST
+   */
+  @Test
+  public void getSingletonsTest() throws Fault {
+    //super.getSingletonsTest();
+    setProperty(REQUEST, buildRequest(GET, "GetSingletons"));
+    setProperty(STATUS_CODE, getStatusCode(Status.OK));
+    invoke();
+    assertTrue(getReturnedNumber() == expectedSingletons,
+        "Application.getSingletons() return incorrect value:"+
+        getReturnedNumber());
+  }
+
+  /*
+   * @testName: getClassesTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:22
+   * 
+   * @test_Strategy: Check the implementation injects TSAppConfig
+   */
+  @Test
+  public void getClassesTest() throws Fault {
+    //super.getClassesTest();
+    setProperty(REQUEST, buildRequest(GET, "GetClasses"));
+    setProperty(STATUS_CODE, getStatusCode(Status.OK));
+    invoke();
+    assertTrue(getReturnedNumber() == expectedClasses,
+        "Application.getClasses() return incorrect value:"+
+        getReturnedNumber());
+  }
+
+  /*
+   * @testName: isRegisteredTextPlainContextResolverTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:269; JAXRS:JAVADOC:280; JAXRS:JAVADOC:299;
+   * JAXRS:SPEC:40; JAXRS:SPEC:80; JAXRS:SPEC:81;
+   * 
+   * @test_Strategy: Register ContextResolver and try to get proper Provider
+   * 
+   * When injecting an instance of one of the types listed in section 9.2, the
+   * instance supplied MUST be capable of selecting the correct context for a
+   * particular request.
+   * 
+   * Context providers MAY return null from the getContext method if they do not
+   * wish to provide their context for a particular Java type.
+   * 
+   * Context provider implementations MAY restrict the media types they support
+   * using the @Produces annotation.
+   */
+  @Test
+  public void isRegisteredTextPlainContextResolverTest() throws Fault {
+    setProperty(Property.REQUEST,
+        buildRequest(GET, "isRegisteredTextPlainContextResolver"));
+    setProperty(Property.STATUS_CODE, getStatusCode(Status.OK));
+    invoke();
+  }
+
+  /*
+   * @testName: isRegisteredAppJsonContextResolverTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:269; JAXRS:JAVADOC:280; JAXRS:JAVADOC:299;
+   * JAXRS:SPEC:40; JAXRS:SPEC:80; JAXRS:SPEC:81;
+   * 
+   * @test_Strategy: Register ContextResolver and try to get proper Provider
+   * 
+   * When injecting an instance of one of the types listed in section 9.2, the
+   * instance supplied MUST be capable of selecting the correct context for a
+   * particular request.
+   * 
+   * Context providers MAY return null from the getContext method if they do not
+   * wish to provide their context for a particular Java type.
+   * 
+   * Context provider implementations MAY restrict the media types they support
+   * using the @Produces annotation. Absence implies that any media type is
+   * supported.
+   */
+  @Test
+  public void isRegisteredAppJsonContextResolverTest() throws Fault {
+    setProperty(Property.REQUEST,
+        buildRequest(GET, "isRegisteredAppJsonContextResolver"));
+    setProperty(Property.STATUS_CODE, getStatusCode(Status.OK));
+    invoke();
+  }
+
+  /*
+   * @testName: isRegisteredExceptionMapperRuntimeExceptionTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:270; JAXRS:JAVADOC:281; JAXRS:SPEC:40;
+   * 
+   * @test_Strategy: Try to get proper ExceptionMapper
+   */
+  @Test
+  public void isRegisteredExceptionMapperRuntimeExceptionTest() throws Fault {
+    setProperty(Property.REQUEST,
+        buildRequest(GET, "isRegisteredExceptionMapperRuntimeEx"));
+    setProperty(Property.STATUS_CODE,
+        getStatusCode(Status.INTERNAL_SERVER_ERROR));
+    invoke();
+  }
+
+  /*
+   * @testName: isRegisteredExceptionMapperNullExceptionTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:281;
+   * 
+   * @test_Strategy: Try to get proper ExceptionMapper
+   */
+  @Test
+  public void isRegisteredExceptionMapperNullExceptionTest() throws Fault {
+    setProperty(Property.REQUEST,
+        buildRequest(GET, "isRegisteredExceptionMapperNullEx"));
+    setProperty(Property.STATUS_CODE, getStatusCode(Status.NO_CONTENT));
+    invoke();
+  }
+
+  /*
+   * @testName: isRegisteredRuntimeExceptionExceptionMapperTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:281; JAXRS:JAVADOC:300; JAXRS:SPEC:40;
+   * 
+   * @test_Strategy: Try to get RuntimeExceptionExceptionMapper but there is
+   * none
+   */
+  @Test
+  public void isRegisteredRuntimeExceptionExceptionMapperTest() throws Fault {
+    setProperty(Property.REQUEST,
+        buildRequest(GET, "isRegisteredRuntimeExceptionMapper"));
+    setProperty(Property.STATUS_CODE, getStatusCode(Status.OK));
+    invoke();
+  }
+
+  /*
+   * @testName: isRegisteredIOExceptionExceptionMapperTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:281;
+   * 
+   * @test_Strategy: Try to get IOExceptionExceptionMapper
+   */
+  @Test
+  public void isRegisteredIOExceptionExceptionMapperTest() throws Fault {
+    setProperty(Property.REQUEST,
+        buildRequest(GET, "isRegisteredIOExceptionMapper"));
+    setProperty(Property.STATUS_CODE, getStatusCode(Status.ACCEPTED));
+    invoke();
+  }
+
+  /*
+   * @testName: isRegisteredMessageBodyWriterWildcardTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:87; JAXRS:JAVADOC:276; JAXRS:JAVADOC:283;
+   * JAXRS:JAVADOC:299; JAXRS:SPEC:40;
+   * 
+   * @test_Strategy: Check what is returned for wildcard is for text/plain
+   */
+  @Test
+  public void isRegisteredMessageBodyWriterWildcardTest() throws Fault {
+    setProperty(Property.REQUEST,
+        buildRequest(GET, "isRegisteredWriterWildcard"));
+    setProperty(Property.STATUS_CODE, getStatusCode(Status.OK));
+    invoke();
+  }
+
+  /*
+   * @testName: isRegisteredMessageBodyWriterXmlTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:87; JAXRS:JAVADOC:276; JAXRS:JAVADOC:283;
+   * JAXRS:JAVADOC:299; JAXRS:SPEC:40;
+   * 
+   * @test_Strategy: Check BodyWriter is returned for text/xml
+   */
+  @Test
+  public void isRegisteredMessageBodyWriterXmlTest() throws Fault {
+    setProperty(Property.REQUEST,
+        buildRequest(GET, "isRegisteredMessageWriterXml"));
+    setProperty(Property.STATUS_CODE, getStatusCode(Status.OK));
+    invoke();
+  }
+
+  /*
+   * @testName: isRegisteredMessageBodyReaderWildcardTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:87; JAXRS:JAVADOC:276; JAXRS:JAVADOC:282;
+   * JAXRS:JAVADOC:299; JAXRS:SPEC:40;
+   * 
+   * @test_Strategy: Check what is returned for wildcard is for text/plain
+   */
+  @Test
+  public void isRegisteredMessageBodyReaderWildcardTest() throws Fault {
+    setProperty(Property.REQUEST,
+        buildRequest(GET, "isRegisteredMessageReaderWildCard"));
+    setProperty(Property.STATUS_CODE, getStatusCode(Status.OK));
+    invoke();
+  }
+
+  /*
+   * @testName: isRegisteredMessageBodReaderXmlTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:87; JAXRS:JAVADOC:276; JAXRS:JAVADOC:282;
+   * JAXRS:JAVADOC:299; JAXRS:SPEC:40;
+   * 
+   * @test_Strategy: Check BodyReader is returned for text/xml
+   */
+  @Test
+  public void isRegisteredMessageBodReaderXmlTest() throws Fault {
+    setProperty(Property.REQUEST,
+        buildRequest(GET, "isRegisteredMessageReaderXml"));
+    setProperty(Property.STATUS_CODE, getStatusCode(Status.OK));
+    invoke();
+  }
+
+  /*
+   * @testName: writeBodyEntityUsingWriterTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:87; JAXRS:JAVADOC:276; JAXRS:JAVADOC:283;
+   * JAXRS:JAVADOC:132; JAXRS:JAVADOC:275; JAXRS:JAVADOC:276; JAXRS:JAVADOC:304;
+   * 
+   * @test_Strategy: Check BodyWriter is used for text/xml to write entity
+   */
+  @Test
+  public void writeBodyEntityUsingWriterTest() throws Fault {
+    String ename = EnumProvider.JAXRS.name();
+    String search = new ReadableWritableEntity(ename).toXmlString();
+    setProperty(Property.REQUEST_HEADERS, "Accept: " + MediaType.TEXT_XML);
+    setProperty(Property.REQUEST,
+        buildRequest(GET, "writeBodyEntityUsingWriter"));
+    setProperty(Property.STATUS_CODE, getStatusCode(Status.OK));
+    setProperty(Property.SEARCH_STRING, search);
+    invoke();
+  }
+
+  /*
+   * @testName: writeHeaderEntityUsingWriterTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:87; JAXRS:JAVADOC:276; JAXRS:JAVADOC:132;
+   * JAXRS:JAVADOC:275; JAXRS:JAVADOC:277; JAXRS:JAVADOC:304;
+   * 
+   * @test_Strategy: Check HeaderWriter is used for text/xml to write entity
+   */
+  @Test
+  public void writeHeaderEntityUsingWriterTest() throws Fault {
+    String ename = EnumProvider.JAXRS.name();
+    String search = new ReadableWritableEntity(ename).toXmlString();
+    setProperty(Property.REQUEST_HEADERS, "Accept: " + MediaType.TEXT_XML);
+    setProperty(Property.REQUEST,
+        buildRequest(GET, "writeHeaderEntityUsingWriter"));
+    setProperty(Property.STATUS_CODE, getStatusCode(Status.OK));
+    setProperty(Property.EXPECTED_HEADERS,
+        ReadableWritableEntity.NAME + ":" + search);
+    invoke();
+  }
+
+  /*
+   * @testName: writeIOExceptionUsingWriterTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:281; JAXRS:JAVADOC:304; JAXRS:JAVADOC:87;
+   * JAXRS:JAVADOC:132; JAXRS:JAVADOC:277; JAXRS:JAVADOC:278;
+   * 
+   * @test_Strategy: Check EntityWriter is used and IOException is written using
+   * mapper
+   */
+  @Test
+  public void writeIOExceptionUsingWriterTest() throws Fault {
+    setProperty(Property.REQUEST_HEADERS, "Accept: " + MediaType.TEXT_XML);
+    setProperty(Property.REQUEST,
+        buildRequest(GET, "writeIOExceptionUsingWriter"));
+    // Depending whether the response has been committed
+    setProperty(Property.STATUS_CODE, getStatusCode(Status.ACCEPTED));
+    setProperty(Property.STATUS_CODE,
+        getStatusCode(Status.INTERNAL_SERVER_ERROR));
+    invoke();
+  }
+
+  /*
+   * @testName: writeIOExceptionWithoutWriterTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:304; JAXRS:JAVADOC:281; JAXRS:SPEC:16.2;
+   * 
+   * @test_Strategy: Check IOExceptionExceptionMapper is chosen
+   */
+  @Test
+  public void writeIOExceptionWithoutWriterTest() throws Fault {
+    setProperty(Property.REQUEST_HEADERS, "Accept: " + MediaType.TEXT_XML);
+    setProperty(Property.REQUEST,
+        buildRequest(GET, "writeIOExceptionWithoutWriter"));
+    setProperty(Property.STATUS_CODE, getStatusCode(Status.ACCEPTED));
+    invoke();
+  }
+
+  /*
+   * @testName: readEntityFromHeaderTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:271; JAXRS:JAVADOC:272; JAXRS:JAVADOC:138;
+   * JAXRS:JAVADOC:304; JAXRS:JAVADOC:282;
+   * 
+   * @test_Strategy: Put entity to header and read it using reader
+   */
+  @Test
+  public void readEntityFromHeaderTest() throws Fault {
+    ReadableWritableEntity entity;
+    entity = new ReadableWritableEntity(EnumProvider.JAXRS.name());
+    String header = ReadableWritableEntity.NAME + ":" + entity.toXmlString();
+    setProperty(Property.REQUEST_HEADERS,
+        "Content-Type: " + MediaType.TEXT_XML);
+    setProperty(Property.REQUEST_HEADERS, header);
+    setProperty(Property.REQUEST, buildRequest("POST", "readEntityFromHeader"));
+    setProperty(Property.STATUS_CODE, getStatusCode(Status.OK));
+    invoke();
+  }
+
+  /*
+   * @testName: readEntityFromBodyTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:271; JAXRS:JAVADOC:272; JAXRS:JAVADOC:138;
+   * JAXRS:JAVADOC:304; JAXRS:JAVADOC:282;
+   * 
+   * @test_Strategy: Put entity to body and read it using reader
+   */
+  @Test
+  public void readEntityFromBodyTest() throws Fault {
+    ReadableWritableEntity entity;
+    entity = new ReadableWritableEntity(EnumProvider.JAXRS.name());
+    setProperty(Property.REQUEST_HEADERS,
+        "Content-Type: " + MediaType.TEXT_XML);
+    setProperty(Property.REQUEST, buildRequest("POST", "readEntityFromBody"));
+    setProperty(Property.CONTENT, entity.toXmlString());
+    setProperty(Property.STATUS_CODE, getStatusCode(Status.OK));
+    invoke();
+  }
+
+  /*
+   * @testName: readEntityIOExceptionTest
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:273; JAXRS:JAVADOC:138; JAXRS:JAVADOC:304;
+   * JAXRS:JAVADOC:282; JAXRS:JAVADOC:271; JAXRS:JAVADOC:272;
+   * 
+   * @test_Strategy: Put entity to body and read it using reader
+   */
+  @Test
+  public void readEntityIOExceptionTest() throws Fault {
+    setProperty(Property.REQUEST_HEADERS,
+        "Content-Type: " + MediaType.TEXT_XML);
+    setProperty(Property.REQUEST,
+        buildRequest("POST", "readEntityIOException"));
+    setProperty(Property.STATUS_CODE, getStatusCode(Status.ACCEPTED));
+    invoke();
+  }
+
+  /*
+   * @testName: readEntityWebException400Test
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:274; JAXRS:JAVADOC:138; JAXRS:JAVADOC:304;
+   * JAXRS:JAVADOC:282; JAXRS:JAVADOC:271; JAXRS:JAVADOC:272; JAXRS:SPEC:16.2;
+   * 
+   * @test_Strategy: Put entity to body and read it using reader
+   */
+  @Test
+  public void readEntityWebException400Test() throws Fault {
+    String code = ReadableWritableEntity.NAME + ":" + Status.BAD_REQUEST.name();
+    setProperty(Property.REQUEST_HEADERS,
+        "Content-Type: " + MediaType.TEXT_XML);
+    setProperty(Property.REQUEST,
+        buildRequest("POST", "readEntityWebException"));
+    setProperty(Property.REQUEST_HEADERS, code);
+    setProperty(Property.STATUS_CODE, getStatusCode(Status.BAD_REQUEST));
+    invoke();
+  }
+
+  /*
+   * @testName: readEntityWebException410Test
+   * 
+   * @assertion_ids: JAXRS:JAVADOC:274; JAXRS:JAVADOC:138; JAXRS:JAVADOC:304;
+   * JAXRS:JAVADOC:282; JAXRS:JAVADOC:271; JAXRS:JAVADOC:272; JAXRS:SPEC:16.2;
+   * 
+   * @test_Strategy: Put entity to body and read it using reader
+   */
+  @Test
+  public void readEntityWebException410Test() throws Fault {
+    String code = ReadableWritableEntity.NAME + ":" + Status.GONE.name();
+    setProperty(Property.REQUEST_HEADERS,
+        "Content-Type: " + MediaType.TEXT_XML);
+    setProperty(Property.REQUEST,
+        buildRequest("POST", "readEntityWebException"));
+    setProperty(Property.REQUEST_HEADERS, code);
+    setProperty(Property.STATUS_CODE, getStatusCode(Status.GONE));
+    invoke();
+  }
+  
+  // ///////////////////////////////////////////////////////////////////////
+
+  protected int getReturnedNumber() throws Fault {
+    HttpResponse response = _testCase.getResponse();
+    String body;
+    try {
+      body = response.getResponseBodyAsString();
+    } catch (IOException e) {
+      throw new Fault(e);
+    }
+    return Integer.parseInt(body);
+  }
+
+
+}
diff --git a/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/providers/ProvidersServlet.java b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/providers/ProvidersServlet.java
new file mode 100644
index 0000000..fb7560b
--- /dev/null
+++ b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/providers/ProvidersServlet.java
@@ -0,0 +1,254 @@
+/*
+ * Copyright (c) 2012, 2020 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 jakarta.ws.rs.tck.ee.rs.ext.providers;
+
+import java.io.IOException;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Method;
+
+import jakarta.ws.rs.tck.ee.rs.core.application.ApplicationServlet;
+import jakarta.ws.rs.tck.ee.rs.ext.contextresolver.EnumProvider;
+import jakarta.ws.rs.tck.ee.rs.ext.exceptionmapper.AnyExceptionExceptionMapper;
+import jakarta.ws.rs.tck.ee.rs.ext.messagebodyreaderwriter.EntityAnnotation;
+import jakarta.ws.rs.tck.ee.rs.ext.messagebodyreaderwriter.ReadableWritableEntity;
+
+import jakarta.ws.rs.Consumes;
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.POST;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.Produces;
+import jakarta.ws.rs.core.Context;
+import jakarta.ws.rs.core.MediaType;
+import jakarta.ws.rs.core.Response;
+import jakarta.ws.rs.core.Response.Status;
+import jakarta.ws.rs.ext.ContextResolver;
+import jakarta.ws.rs.ext.ExceptionMapper;
+import jakarta.ws.rs.ext.MessageBodyReader;
+import jakarta.ws.rs.ext.MessageBodyWriter;
+import jakarta.ws.rs.ext.Providers;
+
+@Path("ProvidersServlet")
+public class ProvidersServlet extends ApplicationServlet {
+  @Context
+  Providers providers;
+
+  private EnumProvider getEnumProvider(MediaType type) {
+    ContextResolver<EnumProvider> scr = providers
+        .getContextResolver(EnumProvider.class, type);
+    EnumProvider ep = scr.getContext(EnumProvider.class);
+    return ep;
+  }
+
+  Response getResponseByEnumProvider(EnumProvider expected,
+      EnumProvider given) {
+    Status status = Status.NO_CONTENT;
+    if (given != null)
+      status = given != expected ? Status.NOT_ACCEPTABLE : Status.OK;
+    return Response.status(status).build();
+  }
+
+  @GET
+  @Path("isRegisteredContextResolver")
+  public Response isRegisteredContextResolver() {
+    EnumProvider ep = getEnumProvider(MediaType.WILDCARD_TYPE);
+    return getResponseByEnumProvider(EnumProvider.JAXRS, ep);
+  }
+
+  @GET
+  @Path("isRegisteredTextPlainContextResolver")
+  public Response isRegisteredTextPlainContextResolver() {
+    EnumProvider ep = getEnumProvider(MediaType.TEXT_PLAIN_TYPE);
+    return getResponseByEnumProvider(EnumProvider.CTS, ep);
+  }
+
+  @GET
+  @Path("isRegisteredAppJsonContextResolver")
+  public Response isRegisteredAppJsonContextResolver() {
+    EnumProvider ep = getEnumProvider(MediaType.APPLICATION_JSON_TYPE);
+    return getResponseByEnumProvider(EnumProvider.JAXRS, ep);
+  }
+
+  @GET
+  @Path("isRegisteredExceptionMapperRuntimeEx")
+  public Response isRegisteredExceptionMapperRuntimeException() {
+    ExceptionMapper<Exception> em = providers
+        .getExceptionMapper(Exception.class);
+    return em.toResponse(new RuntimeException());
+  }
+
+  @GET
+  @Path("isRegisteredExceptionMapperNullEx")
+  public Response isRegisteredExceptionMapperNullException() {
+    ExceptionMapper<Exception> em = providers
+        .getExceptionMapper(Exception.class);
+    return em.toResponse(null);
+  }
+
+  @GET
+  @Path("isRegisteredRuntimeExceptionMapper")
+  public Response isRegisteredRuntimeExceptionMapper() {
+    ExceptionMapper<RuntimeException> em = providers
+        .getExceptionMapper(RuntimeException.class);
+    Status status = Status.NOT_ACCEPTABLE;
+    if (em != null && AnyExceptionExceptionMapper.class.isInstance(em))
+      status = Status.OK;
+    // This serverError() is to get ResponseBuilder with status != OK
+    return Response.serverError().status(status).build();
+  }
+
+  @GET
+  @Path("isRegisteredIOExceptionMapper")
+  public Response isRegisteredIOExceptionExceptionMapper() {
+    ExceptionMapper<IOException> em = providers
+        .getExceptionMapper(IOException.class);
+    return em.toResponse(new IOException());
+  }
+
+  @GET
+  @Path("isRegisteredMessageReaderWildCard")
+  public Response isRegisteredEntityMessageReaderWildcard() {
+    MessageBodyReader<ReadableWritableEntity> reader;
+    reader = providers.getMessageBodyReader(ReadableWritableEntity.class, null,
+        getArgumentAnnotations("readEntityFromBody"), MediaType.WILDCARD_TYPE);
+    Status status = reader == null ? Status.NOT_ACCEPTABLE : Status.OK;
+    return Response.status(status).build();
+  }
+
+  @GET
+  @Path("isRegisteredMessageReaderXml")
+  public Response isRegisteredEntityMessageReaderXml() {
+    MessageBodyReader<ReadableWritableEntity> reader;
+    reader = providers.getMessageBodyReader(ReadableWritableEntity.class, null,
+        getArgumentAnnotations("readEntityFromBody"), MediaType.TEXT_XML_TYPE);
+    Status status = reader == null ? Status.NOT_ACCEPTABLE : Status.OK;
+    return Response.status(status).build();
+  }
+
+  @GET
+  @Path("isRegisteredWriterWildcard")
+  public Response isRegisteredWriterWildCard() {
+    MessageBodyWriter<ReadableWritableEntity> writer;
+    writer = providers.getMessageBodyWriter(ReadableWritableEntity.class, null,
+        getMethodAnnotations("writeBodyEntityUsingWriter"),
+        MediaType.WILDCARD_TYPE);
+    Status status = writer == null ? Status.NOT_ACCEPTABLE : Status.OK;
+    return Response.status(status).build();
+  }
+
+  @GET
+  @Path("isRegisteredMessageWriterXml")
+  public Response isRegisteredWriterXml() {
+    MessageBodyWriter<ReadableWritableEntity> entity;
+    entity = providers.getMessageBodyWriter(ReadableWritableEntity.class, null,
+        getMethodAnnotations("writeBodyEntityUsingWriter"),
+        MediaType.TEXT_XML_TYPE);
+    Status status = entity == null ? Status.NOT_ACCEPTABLE : Status.OK;
+    return Response.status(status).build();
+  }
+
+  @GET
+  @Produces(MediaType.TEXT_XML)
+  @Path("writeBodyEntityUsingWriter")
+  public Response writeBodyEntityUsingWriter() {
+    ReadableWritableEntity rwe = new ReadableWritableEntity(
+        EnumProvider.JAXRS.name());
+    return Response.ok(rwe).build();
+  }
+
+  @GET
+  @Produces(MediaType.TEXT_XML)
+  @Path("writeHeaderEntityUsingWriter")
+  public Response writeHeaderEntityUsingWriter() {
+    ReadableWritableEntity rwe = new ReadableWritableEntity(
+        EnumProvider.JAXRS.name());
+    return Response.ok(rwe).build();
+  }
+
+  @GET
+  @Produces(MediaType.TEXT_XML)
+  @Path("writeIOExceptionWithoutWriter")
+  public Response writeIOExceptionWithoutWriter() throws IOException {
+    throw new IOException("123 exception");
+  }
+
+  @GET
+  @Produces(MediaType.TEXT_XML)
+  @Path("writeIOExceptionUsingWriter")
+  public Response writeIOExceptionUsingWriter() throws IOException {
+    ReadableWritableEntity rwe = new ReadableWritableEntity("");
+    return Response.ok(rwe).build();
+  }
+
+  @POST
+  @Consumes(MediaType.TEXT_XML)
+  @Path("readEntityFromHeader")
+  public Response readEntityFromHeader(
+      @EntityAnnotation("Header") ReadableWritableEntity entity) {
+    Status status = Status.NO_CONTENT;
+    if (entity != null) {
+      boolean b = entity.toString().equals(EnumProvider.JAXRS.name());
+      status = b ? Status.OK : Status.NOT_ACCEPTABLE;
+    }
+    return Response.status(status).build();
+  }
+
+  @POST
+  @Consumes(MediaType.TEXT_XML)
+  @Path("readEntityFromBody")
+  public Response readEntityFromBody(
+      @EntityAnnotation("Body") ReadableWritableEntity entity) {
+    Status status = Status.NO_CONTENT;
+    if (entity != null) {
+      boolean b = entity.toString().equals(EnumProvider.JAXRS.name());
+      status = b ? Status.OK : Status.NOT_ACCEPTABLE;
+    }
+    return Response.status(status).build();
+  }
+
+  @POST
+  @Consumes(MediaType.TEXT_XML)
+  @Path("readEntityIOException")
+  public Response readEntityIOException(
+      @EntityAnnotation("IOException") ReadableWritableEntity entity) {
+    return Response.ok().build();
+  }
+
+  @POST
+  @Consumes(MediaType.TEXT_XML)
+  @Path("readEntityWebException")
+  public Response readEntityWebException(
+      @EntityAnnotation("WebException") ReadableWritableEntity entity) {
+    return Response.ok().build();
+  }
+
+  private Annotation[] getMethodAnnotations(String methodName) {
+    Method[] methods = getClass().getMethods();
+    for (Method method : methods)
+      if (method.getName().equals(methodName))
+        return method.getAnnotations();
+    return null;
+  }
+
+  private Annotation[] getArgumentAnnotations(String methodName) {
+    Method[] methods = getClass().getMethods();
+    for (Method method : methods)
+      if (method.getName().equals(methodName))
+        return method.getParameterAnnotations()[0];
+    return null;
+  }
+
+}
diff --git a/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/providers/TSAppConfig.java b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/providers/TSAppConfig.java
new file mode 100644
index 0000000..a2fc9b8
--- /dev/null
+++ b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/providers/TSAppConfig.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2012, 2020 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 jakarta.ws.rs.tck.ee.rs.ext.providers;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import jakarta.ws.rs.tck.ee.rs.core.application.ApplicationHolderSingleton;
+import jakarta.ws.rs.tck.ee.rs.core.application.ApplicationServlet;
+import jakarta.ws.rs.tck.ee.rs.ext.contextresolver.EnumContextResolver;
+import jakarta.ws.rs.tck.ee.rs.ext.contextresolver.EnumProvider;
+import jakarta.ws.rs.tck.ee.rs.ext.contextresolver.TextPlainEnumContextResolver;
+import jakarta.ws.rs.tck.ee.rs.ext.exceptionmapper.AnyExceptionExceptionMapper;
+import jakarta.ws.rs.tck.ee.rs.ext.exceptionmapper.IOExceptionExceptionMapper;
+import jakarta.ws.rs.tck.ee.rs.ext.messagebodyreaderwriter.EntityMessageReader;
+import jakarta.ws.rs.tck.ee.rs.ext.messagebodyreaderwriter.EntityMessageWriter;
+import jakarta.ws.rs.tck.ee.rs.ext.messagebodyreaderwriter.ReadableWritableEntity;
+
+import jakarta.ws.rs.core.Application;
+
+public class TSAppConfig extends Application {
+
+  @Override
+  public java.util.Set<java.lang.Class<?>> getClasses() {
+    Set<Class<?>> resources = new HashSet<Class<?>>();
+    resources.add(ProvidersServlet.class);
+    resources.add(EnumContextResolver.class);
+    resources.add(ApplicationServlet.class);
+    resources.add(TextPlainEnumContextResolver.class);
+    resources.add(AnyExceptionExceptionMapper.class);
+    resources.add(IOExceptionExceptionMapper.class);
+    resources.add(EntityMessageWriter.class);
+    resources.add(EntityMessageReader.class);
+    return resources;
+  }
+
+  @Override
+  public Set<Object> getSingletons() {
+    Set<Object> singletons = new HashSet<Object>();
+    singletons.add(EnumProvider.CTS);
+    singletons.add(new ReadableWritableEntity(""));
+    singletons.add(new ApplicationHolderSingleton(this));
+    return singletons;
+  }
+
+}
diff --git a/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/runtimedelegate/common.xml b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/runtimedelegate/common.xml
new file mode 100644
index 0000000..c08b530
--- /dev/null
+++ b/jaxrs-tck/src/main/java/jakarta/ws/rs/tck/ee/rs/ext/runtimedelegate/common.xml
@@ -0,0 +1,29 @@
+<!--
+
+    Copyright (c) 2012, 2018 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
+
+-->
+
+<project name="jaxrs_ee_ext_runtime_delegate_common" basedir="." default="usage">
+
+	<import file="../../../../../../../../../../bin/xml/ts.import.xml" />
+
+	<target name="compile">
+		<ant antfile="../../../../api/rs/ext/runtimedelegate/build.xml" useNativeBasedir="true" target="compile" />
+		<ts.javac includes="${pkg.dir}/**/*.java,
+                  com/sun/ts/tests/jaxrs/common/*.java" />
+	</target>
+
+</project>
diff --git a/jaxrs-tck/src/main/resources/jakarta/ws/rs/tck/ee/rs/client/clientrequestcontext/web.xml.template b/jaxrs-tck/src/main/resources/jakarta/ws/rs/tck/ee/rs/client/clientrequestcontext/web.xml.template
new file mode 100644
index 0000000..e125eef
--- /dev/null
+++ b/jaxrs-tck/src/main/resources/jakarta/ws/rs/tck/ee/rs/client/clientrequestcontext/web.xml.template
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Copyright (c) 2012, 2020 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_SPEC_CLIENT_CLIENTREQUESTCONTEXT</servlet-name>
+        <servlet-class>servlet_adaptor</servlet-class>
+        <init-param>
+            <param-name>jakarta.ws.rs.Application</param-name>
+            <param-value>jakarta.ws.rs.tck.ee.rs.client.clientrequestcontext.TSAppConfig</param-value>
+        </init-param>
+        <load-on-startup>1</load-on-startup>
+    </servlet>
+    <servlet-mapping>
+        <servlet-name>CTS_JAXRS_SPEC_CLIENT_CLIENTREQUESTCONTEXT</servlet-name>
+        <url-pattern>/*</url-pattern>
+    </servlet-mapping>
+    <session-config>
+        <session-timeout>30</session-timeout>
+    </session-config>
+</web-app>
diff --git a/jaxrs-tck/src/main/resources/jakarta/ws/rs/tck/ee/rs/client/invocationbuilder/web.xml.template b/jaxrs-tck/src/main/resources/jakarta/ws/rs/tck/ee/rs/client/invocationbuilder/web.xml.template
new file mode 100644
index 0000000..79cf8d0
--- /dev/null
+++ b/jaxrs-tck/src/main/resources/jakarta/ws/rs/tck/ee/rs/client/invocationbuilder/web.xml.template
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Copyright (c) 2012, 2020 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_SPEC_CLIENT_INVOCATIONBUILDER</servlet-name>
+        <servlet-class>servlet_adaptor</servlet-class>
+        <init-param>
+            <param-name>jakarta.ws.rs.Application</param-name>
+            <param-value>jakarta.ws.rs.tck.ee.rs.client.invocationbuilder.TSAppConfig</param-value>
+        </init-param>
+        <load-on-startup>1</load-on-startup>
+    </servlet>
+    <servlet-mapping>
+        <servlet-name>CTS_JAXRS_SPEC_CLIENT_INVOCATIONBUILDER</servlet-name>
+        <url-pattern>/*</url-pattern>
+    </servlet-mapping>
+    <session-config>
+        <session-timeout>30</session-timeout>
+    </session-config>
+</web-app>
diff --git a/jaxrs-tck/src/main/resources/jakarta/ws/rs/tck/ee/rs/client/syncinvoker/web.xml.template b/jaxrs-tck/src/main/resources/jakarta/ws/rs/tck/ee/rs/client/syncinvoker/web.xml.template
new file mode 100644
index 0000000..119e198
--- /dev/null
+++ b/jaxrs-tck/src/main/resources/jakarta/ws/rs/tck/ee/rs/client/syncinvoker/web.xml.template
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Copyright (c) 2012, 2020 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_SPEC_CLIENT_SYNCINVOKER</servlet-name>
+        <servlet-class>servlet_adaptor</servlet-class>
+        <init-param>
+            <param-name>jakarta.ws.rs.Application</param-name>
+            <param-value>jakarta.ws.rs.tck.ee.rs.client.syncinvoker.TSAppConfig</param-value>
+        </init-param>
+        <load-on-startup>1</load-on-startup>
+    </servlet>
+    <servlet-mapping>
+        <servlet-name>CTS_JAXRS_SPEC_CLIENT_SYNCINVOKER</servlet-name>
+        <url-pattern>/*</url-pattern>
+    </servlet-mapping>
+    <session-config>
+        <session-timeout>30</session-timeout>
+    </session-config>
+</web-app>
diff --git a/jaxrs-tck/src/main/resources/jakarta/ws/rs/tck/ee/rs/core/application/web.xml.template b/jaxrs-tck/src/main/resources/jakarta/ws/rs/tck/ee/rs/core/application/web.xml.template
new file mode 100644
index 0000000..07ea02f
--- /dev/null
+++ b/jaxrs-tck/src/main/resources/jakarta/ws/rs/tck/ee/rs/core/application/web.xml.template
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Copyright (c) 2007, 2020 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>CTSJAXRSAPPSERVLET</servlet-name>
+        <servlet-class>servlet_adaptor</servlet-class>
+        <init-param>
+            <param-name>jakarta.ws.rs.Application</param-name>
+            <param-value>jakarta.ws.rs.tck.ee.rs.core.application.TSAppConfig</param-value>
+        </init-param>
+        <load-on-startup>1</load-on-startup>
+    </servlet>
+    <servlet-mapping>
+        <servlet-name>CTSJAXRSAPPSERVLET</servlet-name>
+        <url-pattern>/*</url-pattern>
+    </servlet-mapping>
+    <session-config>
+        <session-timeout>30</session-timeout>
+    </session-config>
+</web-app>
diff --git a/jaxrs-tck/src/main/resources/jakarta/ws/rs/tck/ee/rs/core/configurable/web.xml.template b/jaxrs-tck/src/main/resources/jakarta/ws/rs/tck/ee/rs/core/configurable/web.xml.template
new file mode 100644
index 0000000..3ecbaa2
--- /dev/null
+++ b/jaxrs-tck/src/main/resources/jakarta/ws/rs/tck/ee/rs/core/configurable/web.xml.template
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Copyright (c) 2013, 2020 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>CTSJAXRSConfigurable</servlet-name>
+        <servlet-class>servlet_adaptor</servlet-class>
+        <init-param>
+            <param-name>jakarta.ws.rs.Application</param-name>
+            <param-value>jakarta.ws.rs.tck.ee.rs.core.configurable.TSAppConfig</param-value>
+        </init-param>
+        <load-on-startup>1</load-on-startup>
+    </servlet>
+    <servlet-mapping>
+        <servlet-name>CTSJAXRSConfigurable</servlet-name>
+        <url-pattern>/*</url-pattern>
+    </servlet-mapping>
+    <session-config>
+        <session-timeout>30</session-timeout>
+    </session-config>
+</web-app>
diff --git a/jaxrs-tck/src/main/resources/jakarta/ws/rs/tck/ee/rs/core/configuration/web.xml.template b/jaxrs-tck/src/main/resources/jakarta/ws/rs/tck/ee/rs/core/configuration/web.xml.template
new file mode 100644
index 0000000..bebac5a
--- /dev/null
+++ b/jaxrs-tck/src/main/resources/jakarta/ws/rs/tck/ee/rs/core/configuration/web.xml.template
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Copyright (c) 2013, 2020 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>CTSJAXRSConfiguration</servlet-name>
+        <servlet-class>servlet_adaptor</servlet-class>
+        <init-param>
+            <param-name>jakarta.ws.rs.Application</param-name>
+            <param-value>jakarta.ws.rs.tck.ee.rs.core.configurable.TSAppConfig</param-value>
+        </init-param>
+        <load-on-startup>1</load-on-startup>
+    </servlet>
+    <servlet-mapping>
+        <servlet-name>CTSJAXRSConfiguration</servlet-name>
+        <url-pattern>/*</url-pattern>
+    </servlet-mapping>
+    <session-config>
+        <session-timeout>30</session-timeout>
+    </session-config>
+</web-app>
diff --git a/jaxrs-tck/src/main/resources/jakarta/ws/rs/tck/ee/rs/core/headers/web.xml.template b/jaxrs-tck/src/main/resources/jakarta/ws/rs/tck/ee/rs/core/headers/web.xml.template
new file mode 100644
index 0000000..0ca9800
--- /dev/null
+++ b/jaxrs-tck/src/main/resources/jakarta/ws/rs/tck/ee/rs/core/headers/web.xml.template
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Copyright (c) 2007, 2020 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>CTSJAX-RSCOREHEADERS</servlet-name>
+        <servlet-class>servlet_adaptor</servlet-class>
+        <init-param>
+            <param-name>jakarta.ws.rs.Application</param-name>
+            <param-value>jakarta.ws.rs.tck.ee.rs.core.headers.TSAppConfig</param-value>
+        </init-param>
+        <load-on-startup>1</load-on-startup>
+    </servlet>
+    <servlet-mapping>
+        <servlet-name>CTSJAX-RSCOREHEADERS</servlet-name>
+        <url-pattern>/*</url-pattern>
+    </servlet-mapping>
+    <session-config>
+        <session-timeout>30</session-timeout>
+    </session-config>
+</web-app>
diff --git a/jaxrs-tck/src/main/resources/jakarta/ws/rs/tck/ee/rs/core/response/web.xml.template b/jaxrs-tck/src/main/resources/jakarta/ws/rs/tck/ee/rs/core/response/web.xml.template
new file mode 100644
index 0000000..dcab3cf
--- /dev/null
+++ b/jaxrs-tck/src/main/resources/jakarta/ws/rs/tck/ee/rs/core/response/web.xml.template
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Copyright (c) 2007, 2020 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>CTSJAX-RSRESPONSE</servlet-name>
+        <servlet-class>servlet_adaptor</servlet-class>
+        <init-param>
+            <param-name>jakarta.ws.rs.Application</param-name>
+            <param-value>jakarta.ws.rs.tck.ee.rs.core.response.TSAppConfig</param-value>
+        </init-param>
+        <load-on-startup>1</load-on-startup>
+    </servlet>
+    <servlet-mapping>
+        <servlet-name>CTSJAX-RSRESPONSE</servlet-name>
+        <url-pattern>/*</url-pattern>
+    </servlet-mapping>
+    <session-config>
+        <session-timeout>30</session-timeout>
+    </session-config>
+</web-app>
diff --git a/jaxrs-tck/src/main/resources/jakarta/ws/rs/tck/ee/rs/core/responsebuilder/web.xml.template b/jaxrs-tck/src/main/resources/jakarta/ws/rs/tck/ee/rs/core/responsebuilder/web.xml.template
new file mode 100644
index 0000000..20b661e
--- /dev/null
+++ b/jaxrs-tck/src/main/resources/jakarta/ws/rs/tck/ee/rs/core/responsebuilder/web.xml.template
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Copyright (c) 2012, 2020 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_RESPONSEBUILDER</servlet-name>
+        <servlet-class>servlet_adaptor</servlet-class>
+        <init-param>
+            <param-name>jakarta.ws.rs.Application</param-name>
+            <param-value>jakarta.ws.rs.tck.ee.rs.core.responsebuilder.TSAppConfig</param-value>
+        </init-param>
+        <load-on-startup>1</load-on-startup>
+    </servlet>
+    <servlet-mapping>
+        <servlet-name>CTS_JAXRS_RESPONSEBUILDER</servlet-name>
+        <url-pattern>/*</url-pattern>
+    </servlet-mapping>
+    <session-config>
+        <session-timeout>30</session-timeout>
+    </session-config>
+</web-app>
diff --git a/jaxrs-tck/src/main/resources/jakarta/ws/rs/tck/ee/rs/core/securitycontext/basic/jaxrs_ee_core_securitycontext_basic_web.ear.sun-application.xml b/jaxrs-tck/src/main/resources/jakarta/ws/rs/tck/ee/rs/core/securitycontext/basic/jaxrs_ee_core_securitycontext_basic_web.ear.sun-application.xml
new file mode 100644
index 0000000..0e9e638
--- /dev/null
+++ b/jaxrs-tck/src/main/resources/jakarta/ws/rs/tck/ee/rs/core/securitycontext/basic/jaxrs_ee_core_securitycontext_basic_web.ear.sun-application.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Copyright (c) 2012, 2018 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
+
+-->
+
+<!DOCTYPE sun-application PUBLIC "-//Sun Microsystems, Inc.//DTD Sun ONE Application Server 8.0 J2EE Application 1.4//EN" "http://www.sun.com/software/sunone/appserver/dtds/sun-application_1_4-0.dtd">
+<sun-application>
+  <web>
+    <web-uri>jaxrs_ee_core_securitycontext_basic_web.war</web-uri>
+    <context-root>jaxrs_ee_core_securitycontext_basic_web</context-root>
+  </web>
+  <unique-id>0</unique-id>
+  <security-role-mapping>
+    <role-name>DIRECTOR</role-name>
+    <principal-name>j2ee</principal-name>
+  </security-role-mapping>
+  <security-role-mapping>
+    <role-name>OTHERROLE</role-name>
+    <principal-name>javajoe</principal-name>
+  </security-role-mapping>  
+</sun-application>
diff --git a/jaxrs-tck/src/main/resources/jakarta/ws/rs/tck/ee/rs/core/securitycontext/basic/jaxrs_ee_core_securitycontext_basic_web.war.sun-web.xml b/jaxrs-tck/src/main/resources/jakarta/ws/rs/tck/ee/rs/core/securitycontext/basic/jaxrs_ee_core_securitycontext_basic_web.war.sun-web.xml
new file mode 100644
index 0000000..5f9a0f3
--- /dev/null
+++ b/jaxrs-tck/src/main/resources/jakarta/ws/rs/tck/ee/rs/core/securitycontext/basic/jaxrs_ee_core_securitycontext_basic_web.war.sun-web.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Copyright (c) 2012, 2018 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
+
+-->
+
+<!DOCTYPE sun-web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Sun ONE Application Server 8.0 Servlet 2.4//EN" "http://www.sun.com/software/sunone/appserver/dtds/sun-web-app_2_5-0.dtd">
+<sun-web-app>
+  <context-root>jaxrs_ee_core_securitycontext_basic_web</context-root>
+  <security-role-mapping>
+    <role-name>DIRECTOR</role-name>
+    <principal-name>j2ee</principal-name>
+  </security-role-mapping>
+  <security-role-mapping>
+    <role-name>OTHERROLE</role-name>
+    <principal-name>javajoe</principal-name>
+  </security-role-mapping>    
+</sun-web-app>
diff --git a/jaxrs-tck/src/main/resources/jakarta/ws/rs/tck/ee/rs/core/securitycontext/basic/web.xml.template b/jaxrs-tck/src/main/resources/jakarta/ws/rs/tck/ee/rs/core/securitycontext/basic/web.xml.template
new file mode 100644
index 0000000..8b45684
--- /dev/null
+++ b/jaxrs-tck/src/main/resources/jakarta/ws/rs/tck/ee/rs/core/securitycontext/basic/web.xml.template
@@ -0,0 +1,76 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Copyright (c) 2012, 2020 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>CTSJAXRSSECURITYCONTEXTBASIC</servlet-name>
+        <servlet-class>servlet_adaptor</servlet-class>
+        <init-param>
+            <param-name>jakarta.ws.rs.Application</param-name>
+            <param-value>jakarta.ws.rs.tck.ee.rs.core.securitycontext.TSAppConfig</param-value>
+        </init-param>
+        <load-on-startup>1</load-on-startup>        
+		<security-role-ref>
+		        <role-name>staff</role-name>
+		        <role-link>DIRECTOR</role-link>
+		</security-role-ref>
+		<security-role-ref>
+		        <role-name>guest</role-name>
+		        <role-link>OTHERROLE</role-link>
+		</security-role-ref>
+    </servlet>
+	<security-constraint>
+	    <display-name>Servlet</display-name>
+	    <web-resource-collection>
+	        <web-resource-name>Servlet</web-resource-name>
+	        <description></description>
+	        <url-pattern>/Servlet/*</url-pattern>
+	        <http-method>GET</http-method>
+	        <http-method>POST</http-method>
+	        <http-method>HEAD</http-method>
+	        <http-method>PUT</http-method>
+	    </web-resource-collection>
+	    <auth-constraint>
+	        <description>Have to be a USER</description>
+	        <role-name>DIRECTOR</role-name>
+	        <role-name>OTHERROLE</role-name>
+	    </auth-constraint>
+	    <user-data-constraint>
+	      <transport-guarantee>NONE</transport-guarantee>
+	    </user-data-constraint>
+	</security-constraint>
+    <servlet-mapping>
+        <servlet-name>CTSJAXRSSECURITYCONTEXTBASIC</servlet-name>
+        <url-pattern>/*</url-pattern>
+    </servlet-mapping>
+    <session-config>
+        <session-timeout>30</session-timeout>
+    </session-config>
+	<login-config>
+	    <auth-method>BASIC</auth-method>
+	</login-config>
+	<security-role>
+		<description>director</description>
+		<role-name>DIRECTOR</role-name>
+	</security-role>
+	<security-role>
+		<description>some other role name</description>
+		<role-name>OTHERROLE</role-name>
+	</security-role>
+</web-app>
diff --git a/jaxrs-tck/src/main/resources/jakarta/ws/rs/tck/ee/rs/core/uriinfo/web.xml.template b/jaxrs-tck/src/main/resources/jakarta/ws/rs/tck/ee/rs/core/uriinfo/web.xml.template
new file mode 100644
index 0000000..12132bc
--- /dev/null
+++ b/jaxrs-tck/src/main/resources/jakarta/ws/rs/tck/ee/rs/core/uriinfo/web.xml.template
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Copyright (c) 2007, 2020 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>CTSJAX-RSURIINFO</servlet-name>
+        <servlet-class>servlet_adaptor</servlet-class>
+        <init-param>
+            <param-name>jakarta.ws.rs.Application</param-name>
+            <param-value>jakarta.ws.rs.tck.ee.rs.core.uriinfo.TSAppConfig</param-value>
+        </init-param>
+        <load-on-startup>1</load-on-startup>
+    </servlet>
+    <servlet-mapping>
+        <servlet-name>CTSJAX-RSURIINFO</servlet-name>
+        <url-pattern>/*</url-pattern>
+    </servlet-mapping>
+    <session-config>
+        <session-timeout>30</session-timeout>
+    </session-config>
+</web-app>
diff --git a/jaxrs-tck/src/main/resources/jakarta/ws/rs/tck/ee/rs/ext/interceptor/clientwriter/interceptorcontext/web.xml.template b/jaxrs-tck/src/main/resources/jakarta/ws/rs/tck/ee/rs/ext/interceptor/clientwriter/interceptorcontext/web.xml.template
new file mode 100644
index 0000000..10730d2
--- /dev/null
+++ b/jaxrs-tck/src/main/resources/jakarta/ws/rs/tck/ee/rs/ext/interceptor/clientwriter/interceptorcontext/web.xml.template
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Copyright (c) 2012, 2020 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>CTSJAXRS_CLIENT_WRITER_INTERCEPTOR</servlet-name>
+        <servlet-class>servlet_adaptor</servlet-class>
+        <init-param>
+            <param-name>jakarta.ws.rs.Application</param-name>
+            <param-value>jakarta.ws.rs.tck.ee.rs.ext.interceptor.clientwriter.interceptorcontext.TSAppConfig</param-value>
+        </init-param>
+        <load-on-startup>1</load-on-startup>
+    </servlet>
+    <servlet-mapping>
+        <servlet-name>CTSJAXRS_CLIENT_WRITER_INTERCEPTOR</servlet-name>
+        <url-pattern>/*</url-pattern>
+    </servlet-mapping>
+    <session-config>
+        <session-timeout>30</session-timeout>
+    </session-config>
+</web-app>
diff --git a/jaxrs-tck/src/main/resources/jakarta/ws/rs/tck/ee/rs/ext/interceptor/clientwriter/writerinterceptorcontext/web.xml.template b/jaxrs-tck/src/main/resources/jakarta/ws/rs/tck/ee/rs/ext/interceptor/clientwriter/writerinterceptorcontext/web.xml.template
new file mode 100644
index 0000000..4289c5a
--- /dev/null
+++ b/jaxrs-tck/src/main/resources/jakarta/ws/rs/tck/ee/rs/ext/interceptor/clientwriter/writerinterceptorcontext/web.xml.template
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Copyright (c) 2012, 2020 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>CTSJAXRS_CLIENT_WRITER_WRITERINTERCEPTOR</servlet-name>
+        <servlet-class>servlet_adaptor</servlet-class>
+        <init-param>
+            <param-name>jakarta.ws.rs.Application</param-name>
+            <param-value>jakarta.ws.rs.tck.ee.rs.ext.interceptor.clientwriter.writerinterceptorcontext.TSAppConfig</param-value>
+        </init-param>
+        <load-on-startup>1</load-on-startup>
+    </servlet>
+    <servlet-mapping>
+        <servlet-name>CTSJAXRS_CLIENT_WRITER_WRITERINTERCEPTOR</servlet-name>
+        <url-pattern>/*</url-pattern>
+    </servlet-mapping>
+    <session-config>
+        <session-timeout>30</session-timeout>
+    </session-config>
+</web-app>
diff --git a/jaxrs-tck/src/main/resources/jakarta/ws/rs/tck/ee/rs/ext/interceptor/containerreader/interceptorcontext/web.xml.template b/jaxrs-tck/src/main/resources/jakarta/ws/rs/tck/ee/rs/ext/interceptor/containerreader/interceptorcontext/web.xml.template
new file mode 100644
index 0000000..67a5a61
--- /dev/null
+++ b/jaxrs-tck/src/main/resources/jakarta/ws/rs/tck/ee/rs/ext/interceptor/containerreader/interceptorcontext/web.xml.template
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Copyright (c) 2012, 2020 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>CTSJAXRS_CONTAINER_READER_INTERCEPTOR</servlet-name>
+        <servlet-class>servlet_adaptor</servlet-class>
+        <init-param>
+            <param-name>jakarta.ws.rs.Application</param-name>
+            <param-value>jakarta.ws.rs.tck.ee.rs.ext.interceptor.containerreader.interceptorcontext.TSAppConfig</param-value>
+        </init-param>
+        <load-on-startup>1</load-on-startup>
+    </servlet>
+    <servlet-mapping>
+        <servlet-name>CTSJAXRS_CONTAINER_READER_INTERCEPTOR</servlet-name>
+        <url-pattern>/*</url-pattern>
+    </servlet-mapping>
+    <session-config>
+        <session-timeout>30</session-timeout>
+    </session-config>
+</web-app>
diff --git a/jaxrs-tck/src/main/resources/jakarta/ws/rs/tck/ee/rs/ext/interceptor/containerreader/readerinterceptorcontext/web.xml.template b/jaxrs-tck/src/main/resources/jakarta/ws/rs/tck/ee/rs/ext/interceptor/containerreader/readerinterceptorcontext/web.xml.template
new file mode 100644
index 0000000..d683a97
--- /dev/null
+++ b/jaxrs-tck/src/main/resources/jakarta/ws/rs/tck/ee/rs/ext/interceptor/containerreader/readerinterceptorcontext/web.xml.template
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Copyright (c) 2012, 2020 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>CTSJAXRS_CONTAINER_READER_READERINTERCEPTOR</servlet-name>
+        <servlet-class>servlet_adaptor</servlet-class>
+        <init-param>
+            <param-name>jakarta.ws.rs.Application</param-name>
+            <param-value>jakarta.ws.rs.tck.ee.rs.ext.interceptor.containerreader.readerinterceptorcontext.TSAppConfig</param-value>
+        </init-param>
+        <load-on-startup>1</load-on-startup>
+    </servlet>
+    <servlet-mapping>
+        <servlet-name>CTSJAXRS_CONTAINER_READER_READERINTERCEPTOR</servlet-name>
+        <url-pattern>/*</url-pattern>
+    </servlet-mapping>
+    <session-config>
+        <session-timeout>30</session-timeout>
+    </session-config>
+</web-app>
diff --git a/jaxrs-tck/src/main/resources/jakarta/ws/rs/tck/ee/rs/ext/interceptor/containerwriter/interceptorcontext/web.xml.template b/jaxrs-tck/src/main/resources/jakarta/ws/rs/tck/ee/rs/ext/interceptor/containerwriter/interceptorcontext/web.xml.template
new file mode 100644
index 0000000..570b1ec
--- /dev/null
+++ b/jaxrs-tck/src/main/resources/jakarta/ws/rs/tck/ee/rs/ext/interceptor/containerwriter/interceptorcontext/web.xml.template
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Copyright (c) 2012, 2020 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>CTSJAXRS_CONTAINER_WRITER_INTERCEPTOR</servlet-name>
+        <servlet-class>servlet_adaptor</servlet-class>
+        <init-param>
+            <param-name>jakarta.ws.rs.Application</param-name>
+            <param-value>jakarta.ws.rs.tck.ee.rs.ext.interceptor.containerwriter.interceptorcontext.TSAppConfig</param-value>
+        </init-param>
+        <load-on-startup>1</load-on-startup>
+    </servlet>
+    <servlet-mapping>
+        <servlet-name>CTSJAXRS_CONTAINER_WRITER_INTERCEPTOR</servlet-name>
+        <url-pattern>/*</url-pattern>
+    </servlet-mapping>
+    <session-config>
+        <session-timeout>30</session-timeout>
+    </session-config>
+</web-app>
diff --git a/jaxrs-tck/src/main/resources/jakarta/ws/rs/tck/ee/rs/ext/interceptor/containerwriter/writerinterceptorcontext/web.xml.template b/jaxrs-tck/src/main/resources/jakarta/ws/rs/tck/ee/rs/ext/interceptor/containerwriter/writerinterceptorcontext/web.xml.template
new file mode 100644
index 0000000..7088145
--- /dev/null
+++ b/jaxrs-tck/src/main/resources/jakarta/ws/rs/tck/ee/rs/ext/interceptor/containerwriter/writerinterceptorcontext/web.xml.template
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Copyright (c) 2012, 2020 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>CTSJAXRS_CONTAINER_WRITER_WRITERINTERCEPTOR</servlet-name>
+        <servlet-class>servlet_adaptor</servlet-class>
+        <init-param>
+            <param-name>jakarta.ws.rs.Application</param-name>
+            <param-value>jakarta.ws.rs.tck.ee.rs.ext.interceptor.containerwriter.writerinterceptorcontext.TSAppConfig</param-value>
+        </init-param>
+        <load-on-startup>1</load-on-startup>
+    </servlet>
+    <servlet-mapping>
+        <servlet-name>CTSJAXRS_CONTAINER_WRITER_WRITERINTERCEPTOR</servlet-name>
+        <url-pattern>/*</url-pattern>
+    </servlet-mapping>
+    <session-config>
+        <session-timeout>30</session-timeout>
+    </session-config>
+</web-app>
diff --git a/jaxrs-tck/src/main/resources/jakarta/ws/rs/tck/ee/rs/ext/paramconverter/web.xml.template b/jaxrs-tck/src/main/resources/jakarta/ws/rs/tck/ee/rs/ext/paramconverter/web.xml.template
new file mode 100644
index 0000000..605baf7
--- /dev/null
+++ b/jaxrs-tck/src/main/resources/jakarta/ws/rs/tck/ee/rs/ext/paramconverter/web.xml.template
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Copyright (c) 2012, 2020 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>CTSJAXRSEXTPARAMCONVERTER</servlet-name>
+        <servlet-class>servlet_adaptor</servlet-class>
+        <init-param>
+            <param-name>jakarta.ws.rs.Application</param-name>
+            <param-value>jakarta.ws.rs.tck.ee.rs.ext.paramconverter.TSAppConfig</param-value>
+        </init-param>
+        <load-on-startup>1</load-on-startup>
+    </servlet>
+    <servlet-mapping>
+        <servlet-name>CTSJAXRSEXTPARAMCONVERTER</servlet-name>
+        <url-pattern>/*</url-pattern>
+    </servlet-mapping>
+    <session-config>
+        <session-timeout>30</session-timeout>
+    </session-config>
+</web-app>
diff --git a/jaxrs-tck/src/main/resources/jakarta/ws/rs/tck/ee/rs/ext/providers/web.xml.template b/jaxrs-tck/src/main/resources/jakarta/ws/rs/tck/ee/rs/ext/providers/web.xml.template
new file mode 100644
index 0000000..7a17b02
--- /dev/null
+++ b/jaxrs-tck/src/main/resources/jakarta/ws/rs/tck/ee/rs/ext/providers/web.xml.template
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Copyright (c) 2012, 2020 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>CTSJAXRSEXTPROVIDERS</servlet-name>
+        <servlet-class>servlet_adaptor</servlet-class>
+        <init-param>
+            <param-name>jakarta.ws.rs.Application</param-name>
+            <param-value>jakarta.ws.rs.tck.ee.rs.ext.providers.TSAppConfig</param-value>
+        </init-param>
+        <load-on-startup>1</load-on-startup>
+    </servlet>
+    <servlet-mapping>
+        <servlet-name>CTSJAXRSEXTPROVIDERS</servlet-name>
+        <url-pattern>/*</url-pattern>
+    </servlet-mapping>
+    <session-config>
+        <session-timeout>30</session-timeout>
+    </session-config>
+</web-app>
diff --git a/jersey-tck/pom.xml b/jersey-tck/pom.xml
index 79dd4f5..8f10525 100644
--- a/jersey-tck/pom.xml
+++ b/jersey-tck/pom.xml
@@ -134,6 +134,10 @@
                                 <webServerHost>localhost</webServerHost>
                                 <webServerPort>8080</webServerPort>
                                 <junit.log.traceflag>true</junit.log.traceflag>
+                                <user>j2ee</user>
+                                <password>j2ee</password>
+                                <authuser>javajoe</authuser>
+                                <authpassword>javajoe</authpassword>
                                 <porting.ts.url.class.1>jakarta.ws.rs.tck.lib.implementation.sun.common.SunRIURL</porting.ts.url.class.1>
                             </systemPropertyVariables>
                             <environmentVariables>