MP rest client review comments implemented

Signed-off-by: David Kral <david.k.kral@oracle.com>
diff --git a/bom/pom.xml b/bom/pom.xml
index f8ed3cc..5b02437 100644
--- a/bom/pom.xml
+++ b/bom/pom.xml
@@ -249,7 +249,7 @@
                 <version>${project.version}</version>
             </dependency>
             <dependency>
-                <groupId>org.glassfish.jersey.ext</groupId>
+                <groupId>org.glassfish.jersey.ext.microprofile</groupId>
                 <artifactId>jersey-mp-rest-client</artifactId>
                 <version>${project.version}</version>
             </dependency>
diff --git a/core-client/src/main/java/org/glassfish/jersey/client/JerseyWebTarget.java b/core-client/src/main/java/org/glassfish/jersey/client/JerseyWebTarget.java
index 26df84f..c7d54be 100644
--- a/core-client/src/main/java/org/glassfish/jersey/client/JerseyWebTarget.java
+++ b/core-client/src/main/java/org/glassfish/jersey/client/JerseyWebTarget.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2019 Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -26,7 +26,6 @@
 import javax.ws.rs.core.UriBuilder;
 
 import org.glassfish.jersey.internal.guava.Preconditions;
-import org.glassfish.jersey.internal.inject.InjectionManager;
 
 /**
  * Jersey implementation of {@link javax.ws.rs.client.WebTarget JAX-RS client target}
diff --git a/ext/microprofile/mp-rest-client/pom.xml b/ext/microprofile/mp-rest-client/pom.xml
index dc47382..2fc179e 100644
--- a/ext/microprofile/mp-rest-client/pom.xml
+++ b/ext/microprofile/mp-rest-client/pom.xml
@@ -20,8 +20,8 @@
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
     <parent>
-        <artifactId>jersey-microprofile</artifactId>
-        <groupId>org.glassfish.jersey.ext</groupId>
+        <artifactId>project</artifactId>
+        <groupId>org.glassfish.jersey.ext.microprofile</groupId>
         <version>2.29-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
@@ -60,9 +60,14 @@
             <version>${project.version}</version>
         </dependency>
         <dependency>
+            <groupId>org.glassfish.jersey.ext.cdi</groupId>
+            <artifactId>jersey-cdi1x</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
             <groupId>jakarta.json</groupId>
             <artifactId>jakarta.json-api</artifactId>
-            <version>1.1.5</version>
+            <version>${jsonp.ri.version}</version>
         </dependency>
         <dependency>
             <groupId>javax.enterprise</groupId>
@@ -73,107 +78,10 @@
             <groupId>org.glassfish</groupId>
             <artifactId>jsonp-jaxrs</artifactId>
         </dependency>
-        <dependency>
-            <groupId>org.jboss.weld.se</groupId>
-            <artifactId>weld-se-core</artifactId>
-            <version>3.0.3.Final</version>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.glassfish.jersey.test-framework</groupId>
-            <artifactId>jersey-test-framework-core</artifactId>
-            <version>${project.version}</version>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.glassfish.jersey.test-framework.providers</groupId>
-            <artifactId>jersey-test-framework-provider-bundle</artifactId>
-            <version>${project.version}</version>
-            <type>pom</type>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>io.smallrye</groupId>
-            <artifactId>smallrye-config</artifactId>
-            <version>1.3.6</version>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.eclipse.microprofile.rest.client</groupId>
-            <artifactId>microprofile-rest-client-tck</artifactId>
-            <version>1.2.1</version>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.testng</groupId>
-            <artifactId>testng</artifactId>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>com.github.tomakehurst</groupId>
-            <artifactId>wiremock</artifactId>
-            <version>2.21.0</version>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.jboss.arquillian.testng</groupId>
-            <artifactId>arquillian-testng-container</artifactId>
-            <version>1.4.1.Final</version>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.jboss.arquillian.container</groupId>
-            <artifactId>arquillian-container-test-spi</artifactId>
-            <version>1.4.1.Final</version>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.jboss.arquillian.container</groupId>
-            <artifactId>arquillian-weld-embedded</artifactId>
-            <version>2.0.1.Final</version>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>io.opentracing</groupId>
-            <artifactId>opentracing-noop</artifactId>
-            <version>0.30.0</version>
-            <scope>test</scope>
-        </dependency>
     </dependencies>
 
     <build>
-        <plugins>
-            <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-surefire-plugin</artifactId>
-                <configuration>
-                    <!--<parallel>classes</parallel>
-                    <perCoreThreadCount>true</perCoreThreadCount>
-                    <threadCount>1</threadCount>
-                    <forkCount>1C</forkCount>
-                    <reuseForks>true</reuseForks>-->
-                    <suiteXmlFiles>
-                        <suiteXmlFile>tck-suite.xml</suiteXmlFile>
-                    </suiteXmlFiles>
-                </configuration>
-            </plugin>
-            <plugin>
-                <groupId>uk.co.deliverymind</groupId>
-                <artifactId>wiremock-maven-plugin</artifactId>
-                <version>2.7.0</version>
-                <executions>
-                    <execution>
-                        <phase>test-compile</phase>
-                        <goals>
-                            <goal>run</goal>
-                        </goals>
-                        <configuration>
-                            <dir>target/classes</dir>
-                            <params>--port=8765 --verbose</params>
-                        </configuration>
-                    </execution>
-                </executions>
-            </plugin>
+       <plugins>
             <plugin>
                 <groupId>org.apache.felix</groupId>
                 <artifactId>maven-bundle-plugin</artifactId>
@@ -194,9 +102,4 @@
         </plugins>
     </build>
 
-<!--    <properties>-->
-<!--        <surefire.security.argline>-Djava.security.manager -Djava.security.policy=${project.build.directory}/test-classes/server.policy</surefire.security.argline>-->
-<!--    </properties>-->
-
-
 </project>
\ No newline at end of file
diff --git a/ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/BeanClassModel.java b/ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/BeanClassModel.java
index d5c4d74..a074469 100644
--- a/ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/BeanClassModel.java
+++ b/ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/BeanClassModel.java
@@ -52,16 +52,11 @@
      * Create new instance of bean annotated parameter.
      *
      * @param interfaceModel rest client interface model
-     * @param beanClass bean annotated parameter class
+     * @param beanClass      bean annotated parameter class
      * @return new instance
      */
     static BeanClassModel fromClass(InterfaceModel interfaceModel, Class<?> beanClass) {
         return new Builder(interfaceModel, beanClass)
-                .processPathFields()
-                .processHeaderFields()
-                .processCookieFields()
-                .processQueryFields()
-                .processMatrixFields()
                 .build();
     }
 
@@ -83,7 +78,7 @@
      * Resolves bean path parameters.
      *
      * @param webTarget web target path
-     * @param instance actual method parameter value
+     * @param instance  actual method parameter value
      * @return updated web target path
      */
     @SuppressWarnings("unchecked")
@@ -103,7 +98,7 @@
     /**
      * Resolves bean header parameters.
      *
-     * @param headers headers
+     * @param headers  headers
      * @param instance actual method parameter value
      * @return updated headers
      */
@@ -124,7 +119,7 @@
     /**
      * Resolves bean cookie parameters.
      *
-     * @param cookies cookies
+     * @param cookies  cookies
      * @param instance actual method parameter value
      * @return updated cookies
      */
@@ -145,13 +140,13 @@
     /**
      * Resolves bean query parameters.
      *
-     * @param query queries
+     * @param query    queries
      * @param instance actual method parameter value
      * @return updated queries
      */
     @SuppressWarnings("unchecked")
     Map<String, Object[]> resolveQuery(Map<String, Object[]> query,
-                                              Object instance) {
+                                       Object instance) {
         parameterModels.stream()
                 .filter(paramModel -> paramModel.handles(QueryParam.class))
                 .forEach(parameterModel -> {
@@ -167,12 +162,12 @@
      * Resolves bean matrix parameters.
      *
      * @param webTarget web target path
-     * @param instance actual method parameter value
+     * @param instance  actual method parameter value
      * @return updated web target path
      */
     @SuppressWarnings("unchecked")
     WebTarget resolveMatrix(WebTarget webTarget,
-                                       Object instance) {
+                            Object instance) {
         AtomicReference<WebTarget> toReturn = new AtomicReference<>(webTarget);
         parameterModels.stream()
                 .filter(paramModel -> paramModel.handles(MatrixParam.class))
@@ -185,17 +180,16 @@
         return toReturn.get();
     }
 
-
     /**
      * Resolves bean form parameters.
      *
-     * @param form web form
+     * @param form     web form
      * @param instance actual method parameter value
      * @return updated web form
      */
     @SuppressWarnings("unchecked")
     Form resolveForm(Form form,
-                          Object instance) {
+                     Object instance) {
         parameterModels.stream()
                 .filter(paramModel -> paramModel.handles(FormParam.class))
                 .forEach(parameterModel -> {
@@ -235,52 +229,27 @@
             this.beanClass = beanClass;
         }
 
-        /**
-         * Parses all {@link PathParam} annotated fields from bean class.
-         *
-         * @return updated builder instance
-         */
-        Builder processPathFields() {
-            return processFieldsByParameterClass(PathParam.class);
+        private void processPathFields() {
+            processFieldsByParameterClass(PathParam.class);
         }
 
-        /**
-         * Parses all {@link HeaderParam} annotated fields from bean class.
-         *
-         * @return updated builder instance
-         */
-        Builder processHeaderFields() {
-            return processFieldsByParameterClass(HeaderParam.class);
+        private void processHeaderFields() {
+            processFieldsByParameterClass(HeaderParam.class);
         }
 
-        /**
-         * Parses all {@link CookieParam} annotated fields from bean class.
-         *
-         * @return updated builder instance
-         */
-        Builder processCookieFields() {
-            return processFieldsByParameterClass(CookieParam.class);
+        private void processCookieFields() {
+            processFieldsByParameterClass(CookieParam.class);
         }
 
-        /**
-         * Parses all {@link QueryParam} annotated fields from bean class.
-         *
-         * @return updated builder instance
-         */
-        Builder processQueryFields() {
-            return processFieldsByParameterClass(QueryParam.class);
+        private void processQueryFields() {
+            processFieldsByParameterClass(QueryParam.class);
         }
 
-        /**
-         * Parses all {@link MatrixParam} annotated fields from bean class.
-         *
-         * @return updated builder instance
-         */
-        Builder processMatrixFields() {
-            return processFieldsByParameterClass(MatrixParam.class);
+        private void processMatrixFields() {
+            processFieldsByParameterClass(MatrixParam.class);
         }
 
-        private Builder processFieldsByParameterClass(Class<? extends Annotation> parameterClass) {
+        private void processFieldsByParameterClass(Class<? extends Annotation> parameterClass) {
             for (Field field : beanClass.getDeclaredFields()) {
                 if (field.isAnnotationPresent(parameterClass)) {
                     Parameter parameter = Parameter.create(parameterClass, parameterClass, false,
@@ -290,7 +259,6 @@
                                                         parameter, -1));
                 }
             }
-            return this;
         }
 
         /**
@@ -299,6 +267,11 @@
          * @return new instance
          */
         BeanClassModel build() {
+            processPathFields();
+            processHeaderFields();
+            processCookieFields();
+            processQueryFields();
+            processMatrixFields();
             return new BeanClassModel(this);
         }
     }
diff --git a/ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/BeanParamModel.java b/ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/BeanParamModel.java
index 348382e..edd8253 100644
--- a/ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/BeanParamModel.java
+++ b/ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/BeanParamModel.java
@@ -17,6 +17,7 @@
 package org.glassfish.jersey.microprofile.restclient;
 
 import java.lang.annotation.Annotation;
+import java.util.IdentityHashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.stream.Collectors;
@@ -39,6 +40,26 @@
  */
 class BeanParamModel extends ParamModel<Object> {
 
+    private static final Map<Class<?>, ParamHandler> PARAM_HANDLERS = new IdentityHashMap<>();
+
+    static {
+        PARAM_HANDLERS.put(PathParam.class,
+                           (model, requestPart, instance) -> model.resolvePath((WebTarget) requestPart, instance));
+        PARAM_HANDLERS.put(HeaderParam.class,
+                           (model, requestPart, instance) -> model.resolveHeaders((MultivaluedMap<String, Object>) requestPart,
+                                                                                  instance));
+        PARAM_HANDLERS.put(CookieParam.class,
+                           (model, requestPart, instance) -> model.resolveCookies((Map<String, String>) requestPart, instance));
+        PARAM_HANDLERS.put(QueryParam.class,
+                           (model, requestPart, instance) -> model.resolveQuery((Map<String, Object[]>) requestPart,
+                                                                                  instance));
+        PARAM_HANDLERS.put(MatrixParam.class,
+                           (model, requestPart, instance) -> model.resolveMatrix((WebTarget) requestPart, instance));
+        PARAM_HANDLERS.put(FormParam.class,
+                           (model, requestPart, instance) -> model.resolveForm((Form) requestPart,
+                                                                                  instance));
+    }
+
     private BeanClassModel beanClassModel;
 
     BeanParamModel(Builder builder) {
@@ -48,30 +69,18 @@
 
     @Override
     public Object handleParameter(Object requestPart, Class<?> annotationClass, Object instance) {
-        if (PathParam.class.equals(annotationClass)) {
-            return beanClassModel.resolvePath((WebTarget) requestPart, instance);
-        } else if (HeaderParam.class.equals(annotationClass)) {
-            return beanClassModel.resolveHeaders((MultivaluedMap<String, Object>) requestPart, instance);
-        } else if (CookieParam.class.equals(annotationClass)) {
-            return beanClassModel.resolveCookies((Map<String, String>) requestPart, instance);
-        } else if (QueryParam.class.equals(annotationClass)) {
-            return beanClassModel.resolveQuery((Map<String, Object[]>) requestPart, instance);
-        } else if (MatrixParam.class.equals(annotationClass)) {
-            return beanClassModel.resolveMatrix((WebTarget) requestPart, instance);
-        } else if (FormParam.class.equals(annotationClass)) {
-            return beanClassModel.resolveForm((Form) requestPart, instance);
+        ParamHandler handler = PARAM_HANDLERS.get(annotationClass);
+
+        if (null == handler) {
+            throw new UnsupportedOperationException(annotationClass.getName() + " is not supported!");
         }
-        throw new UnsupportedOperationException(annotationClass.getName() + " is not supported!");
+
+        return handler.handle(beanClassModel, requestPart, instance);
     }
 
     @Override
     public boolean handles(Class<Annotation> annotation) {
-        return PathParam.class.equals(annotation)
-                || HeaderParam.class.equals(annotation)
-                || CookieParam.class.equals(annotation)
-                || QueryParam.class.equals(annotation)
-                || MatrixParam.class.equals(annotation)
-                || FormParam.class.equals(annotation);
+        return PARAM_HANDLERS.containsKey(annotation);
     }
 
     /**
diff --git a/ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/ConfigWrapper.java b/ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/ConfigWrapper.java
index 466ab38..fec7869 100644
--- a/ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/ConfigWrapper.java
+++ b/ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/ConfigWrapper.java
@@ -1,3 +1,19 @@
+/*
+ * Copyright (c) 2019 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 org.glassfish.jersey.microprofile.restclient;
 
 import java.util.Collection;
@@ -75,7 +91,9 @@
     @Override
     public Map<Class<?>, Integer> getContracts(Class<?> componentClass) {
         Map<Class<?>, Integer> map = new HashMap<>(jerseyBuilderConfig.getContracts(componentClass));
-        if (customProviders.containsKey(componentClass)) map.putAll(customProviders.get(componentClass));
+        if (customProviders.containsKey(componentClass)) {
+            map.putAll(customProviders.get(componentClass));
+        }
         return map;
     }
 
diff --git a/ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/CookieParamModel.java b/ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/CookieParamModel.java
index 9477c34..7daf367 100644
--- a/ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/CookieParamModel.java
+++ b/ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/CookieParamModel.java
@@ -30,10 +30,10 @@
 
     private final String cookieParamName;
 
-    CookieParamModel(Builder builder) {
+    CookieParamModel(Builder builder, CookieParam annotation) {
         super(builder);
-        cookieParamName = builder.cookieParamName();
-    }
+        cookieParamName = annotation.value();
+}
 
     @Override
     Map<String, String> handleParameter(Map<String, String> requestPart, Class<?> annotationClass, Object instance) {
diff --git a/ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/DefaultResponseExceptionMapper.java b/ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/DefaultResponseExceptionMapper.java
index b699182..1099040 100644
--- a/ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/DefaultResponseExceptionMapper.java
+++ b/ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/DefaultResponseExceptionMapper.java
@@ -26,7 +26,7 @@
  *
  * @author David Kral
  */
-public class DefaultResponseExceptionMapper implements ResponseExceptionMapper {
+class DefaultResponseExceptionMapper implements ResponseExceptionMapper {
     @Override
     public Throwable toThrowable(Response response) {
         return new WebApplicationException("Unknown error, status code " + response.getStatus(), response);
diff --git a/ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/ExecutorServiceWrapper.java b/ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/ExecutorServiceWrapper.java
index c3a8dd6..54599e8 100644
--- a/ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/ExecutorServiceWrapper.java
+++ b/ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/ExecutorServiceWrapper.java
@@ -1,3 +1,19 @@
+/*
+ * Copyright (c) 2019 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 org.glassfish.jersey.microprofile.restclient;
 
 import java.util.Collection;
diff --git a/ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/FormParamModel.java b/ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/FormParamModel.java
index 7a8f738..46ed76e 100644
--- a/ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/FormParamModel.java
+++ b/ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/FormParamModel.java
@@ -31,9 +31,9 @@
 
     private final String formParamName;
 
-    FormParamModel(Builder builder) {
+    FormParamModel(Builder builder, FormParam annotation) {
         super(builder);
-        formParamName = builder.formParamName();
+        formParamName = annotation.value();
     }
 
     @Override
diff --git a/ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/HeaderParamModel.java b/ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/HeaderParamModel.java
index 3417ada..17d53c4 100644
--- a/ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/HeaderParamModel.java
+++ b/ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/HeaderParamModel.java
@@ -31,9 +31,9 @@
 
     private String headerParamName;
 
-    HeaderParamModel(Builder builder) {
+    HeaderParamModel(Builder builder, HeaderParam annotation) {
         super(builder);
-        this.headerParamName = builder.headerParamName();
+        this.headerParamName = annotation.value();
     }
 
     @Override
diff --git a/ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/HeadersContext.java b/ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/HeadersContext.java
index 77bcffe..8de244e 100644
--- a/ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/HeadersContext.java
+++ b/ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/HeadersContext.java
@@ -25,7 +25,7 @@
  *
  * @author David Kral
  */
-public final class HeadersContext {
+final class HeadersContext {
 
     /**
      * Headers context thread local, used by internal implementations of header filters.
@@ -38,7 +38,7 @@
      * The instance associated with the current thread.
      * @return context for current thread or {@code empty} if none associated
      */
-    public static Optional<HeadersContext> get() {
+    static Optional<HeadersContext> get() {
         return Optional.ofNullable(HEADERS_CONTEXT.get());
     }
 
@@ -49,7 +49,7 @@
      * @param contextSupplier supplier for header context to be associated with the thread if none is
      * @return an instance associated with the current context, either from other provider, or from contextSupplier
      */
-    public static HeadersContext compute(Supplier<HeadersContext> contextSupplier) {
+    static HeadersContext compute(Supplier<HeadersContext> contextSupplier) {
         HeadersContext headersContext = HEADERS_CONTEXT.get();
         if (null == headersContext) {
             set(contextSupplier.get());
@@ -63,14 +63,14 @@
      *
      * @param context context to associate
      */
-    public static void set(HeadersContext context) {
+    static void set(HeadersContext context) {
         HEADERS_CONTEXT.set(context);
     }
 
     /**
      * Remove the header context associated with current thread.
      */
-    public static void remove() {
+    static void remove() {
         HEADERS_CONTEXT.remove();
     }
 
@@ -81,11 +81,11 @@
      * @return a new header context (not associated with current thread)
      * @see #set(HeadersContext)
      */
-    public static HeadersContext create(MultivaluedMap<String, String> inboundHeaders) {
+    static HeadersContext create(MultivaluedMap<String, String> inboundHeaders) {
         return new HeadersContext(inboundHeaders);
     }
 
-    public HeadersContext(MultivaluedMap<String, String> inboundHeaders) {
+    private HeadersContext(MultivaluedMap<String, String> inboundHeaders) {
         this.inboundHeaders = inboundHeaders;
     }
 
@@ -95,7 +95,7 @@
      *
      * @return map of inbound headers
      */
-    public MultivaluedMap<String, String> inboundHeaders() {
+    MultivaluedMap<String, String> inboundHeaders() {
         return inboundHeaders;
     }
 
diff --git a/ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/HeadersRequestFilter.java b/ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/HeadersRequestFilter.java
index 64ece19..28e284a 100644
--- a/ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/HeadersRequestFilter.java
+++ b/ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/HeadersRequestFilter.java
@@ -16,10 +16,14 @@
 
 package org.glassfish.jersey.microprofile.restclient;
 
+import java.io.IOException;
+
 import javax.ws.rs.ConstrainedTo;
 import javax.ws.rs.RuntimeType;
 import javax.ws.rs.container.ContainerRequestContext;
 import javax.ws.rs.container.ContainerRequestFilter;
+import javax.ws.rs.container.ContainerResponseContext;
+import javax.ws.rs.container.ContainerResponseFilter;
 
 /**
  * Server side request filter used for propagation of request headers to server client request.
@@ -27,11 +31,15 @@
  * @author David Kral
  */
 @ConstrainedTo(RuntimeType.SERVER)
-public class HeadersRequestFilter implements ContainerRequestFilter {
+public class HeadersRequestFilter implements ContainerRequestFilter, ContainerResponseFilter {
 
     @Override
     public void filter(ContainerRequestContext requestContext) {
         HeadersContext.compute(() -> HeadersContext.create(requestContext.getHeaders()));
     }
 
+    @Override
+    public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) throws IOException {
+        HeadersContext.remove();
+    }
 }
diff --git a/ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/InterfaceModel.java b/ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/InterfaceModel.java
index 35a19f5..259110c 100644
--- a/ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/InterfaceModel.java
+++ b/ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/InterfaceModel.java
@@ -73,10 +73,10 @@
     /**
      * Creates new model based on interface class. Interface is parsed according to specific annotations.
      *
-     * @param restClientClass interface class
+     * @param restClientClass          interface class
      * @param responseExceptionMappers registered exception mappers
-     * @param paramConverterProviders registered parameter providers
-     * @param asyncInterceptors async interceptors
+     * @param paramConverterProviders  registered parameter providers
+     * @param asyncInterceptors        async interceptors
      * @param injectionManager
      * @return new model instance
      */
@@ -91,13 +91,7 @@
                            paramConverterProviders,
                            asyncInterceptors,
                            injectionManager,
-                           beanManager)
-                .pathValue(restClientClass.getAnnotation(Path.class))
-                .produces(restClientClass.getAnnotation(Produces.class))
-                .consumes(restClientClass.getAnnotation(Consumes.class))
-                .clientHeaders(restClientClass.getAnnotationsByType(ClientHeaderParam.class))
-                .clientHeadersFactory(restClientClass.getAnnotation(RegisterClientHeaders.class))
-                .build();
+                           beanManager).build();
     }
 
     private InterfaceModel(Builder builder) {
@@ -216,8 +210,6 @@
     }
 
     /**
-     *
-     *
      * @return
      */
     public InjectionManager getInjectionManager() {
@@ -355,6 +347,11 @@
          * @return new instance
          */
         InterfaceModel build() {
+            pathValue(restClientClass.getAnnotation(Path.class));
+            produces(restClientClass.getAnnotation(Produces.class));
+            consumes(restClientClass.getAnnotation(Consumes.class));
+            clientHeaders(restClientClass.getAnnotationsByType(ClientHeaderParam.class));
+            clientHeadersFactory(restClientClass.getAnnotation(RegisterClientHeaders.class));
             validateHeaderDuplicityNames();
             return new InterfaceModel(this);
         }
diff --git a/ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/MatrixParamModel.java b/ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/MatrixParamModel.java
index 440a414..1788d31 100644
--- a/ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/MatrixParamModel.java
+++ b/ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/MatrixParamModel.java
@@ -35,10 +35,11 @@
      * Creates new matrix model.
      *
      * @param builder
+     * @param annotation
      */
-    MatrixParamModel(Builder builder) {
+    MatrixParamModel(Builder builder, MatrixParam annotation) {
         super(builder);
-        matrixParamName = builder.matrixParamName();
+        matrixParamName = annotation.value();
     }
 
     @Override
diff --git a/ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/MethodModel.java b/ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/MethodModel.java
index e7a2925..c70f7e4 100644
--- a/ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/MethodModel.java
+++ b/ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/MethodModel.java
@@ -46,6 +46,7 @@
 import javax.ws.rs.Consumes;
 import javax.ws.rs.CookieParam;
 import javax.ws.rs.DELETE;
+import javax.ws.rs.FormParam;
 import javax.ws.rs.GET;
 import javax.ws.rs.HeaderParam;
 import javax.ws.rs.MatrixParam;
@@ -57,6 +58,7 @@
 import javax.ws.rs.client.Entity;
 import javax.ws.rs.client.Invocation;
 import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.Form;
 import javax.ws.rs.core.GenericType;
 import javax.ws.rs.core.HttpHeaders;
 import javax.ws.rs.core.MediaType;
@@ -83,7 +85,7 @@
     private final InterfaceModel interfaceModel;
 
     private final Method method;
-    private final Class<?> returnType;
+    private final GenericType<?> returnType;
     private final String httpMethod;
     private final String path;
     private final String[] produces;
@@ -101,15 +103,7 @@
      * @return
      */
     static MethodModel from(InterfaceModel interfaceModel, Method method) {
-        return new Builder(interfaceModel, method)
-                .returnType(method.getGenericReturnType())
-                .httpMethod(parseHttpMethod(interfaceModel, method))
-                .pathValue(method.getAnnotation(Path.class))
-                .produces(method.getAnnotation(Produces.class))
-                .consumes(method.getAnnotation(Consumes.class))
-                .parameters(parameterModels(interfaceModel, method))
-                .clientHeaders(method.getAnnotationsByType(ClientHeaderParam.class))
-                .build();
+        return new Builder(interfaceModel, method).build();
     }
 
     private MethodModel(Builder builder) {
@@ -124,7 +118,7 @@
         this.clientHeaders = builder.clientHeaders;
         this.invocationInterceptors = builder.invocationInterceptors;
         if (httpMethod.isEmpty()) {
-            subResourceModel = RestClientModel.from(returnType,
+            subResourceModel = RestClientModel.from(returnType.getRawType(),
                                                     interfaceModel.getResponseExceptionMappers(),
                                                     interfaceModel.getParamConverterProviders(),
                                                     interfaceModel.getAsyncInterceptors(),
@@ -174,10 +168,12 @@
                 .findFirst()
                 .ifPresent(parameterModel -> entity.set(args[parameterModel.getParamPosition()]));
 
+        Form form = handleForm(args);
+
         WebTarget webTarget = webTargetAtomicReference.get();
         if (httpMethod.isEmpty()) {
             //sub resource method
-            return subResourceProxy(webTarget, returnType);
+            return subResourceProxy(webTarget, returnType.getRawType());
         }
         webTarget = addQueryParams(webTarget, args);
         webTarget = addMatrixParams(webTarget, args);
@@ -188,16 +184,32 @@
                 .headers(addCustomHeaders(args));
         builder = addCookies(builder, args);
 
+        Object entityToUse = entity.get();
+        if (entityToUse == null && !form.asMap().isEmpty()) {
+            entityToUse = form;
+        }
+
         Object response;
 
         if (CompletionStage.class.isAssignableFrom(method.getReturnType())) {
-            response = asynchronousCall(builder, entity.get(), method);
+            response = asynchronousCall(builder, entityToUse, method);
         } else {
-            response = synchronousCall(builder, entity.get(), method);
+            response = synchronousCall(builder, entityToUse, method);
         }
         return response;
     }
 
+    @SuppressWarnings("unchecked")
+    private Form handleForm(Object[] args) {
+        final Form form = new Form();
+        parameterModels.stream()
+                .filter(parameterModel -> parameterModel.handles(FormParam.class))
+                .forEach(parameterModel -> parameterModel.handleParameter(form,
+                                                                          FormParam.class,
+                                                                          args[parameterModel.getParamPosition()]));
+        return form;
+    }
+
     private Object synchronousCall(Invocation.Builder builder, Object entity, Method method) {
         Response response;
 
@@ -211,17 +223,15 @@
 
         evaluateResponse(response, method);
 
-        if (returnType.equals(Void.class)) {
+        if (returnType.getType().equals(Void.class)) {
             return null;
-        } else if (returnType.equals(Response.class)) {
+        } else if (returnType.getType().equals(Response.class)) {
             return response;
         }
         return response.readEntity(returnType);
     }
 
     private CompletableFuture asynchronousCall(Invocation.Builder builder, Object entity, Method method) {
-        ParameterizedType type = (ParameterizedType) method.getGenericReturnType();
-        Type actualTypeArgument = type.getActualTypeArguments()[0]; //completionStage<actualTypeArgument>
         CompletableFuture<Object> result = new CompletableFuture<>();
         Future<Response> theFuture;
         if (entity != null
@@ -237,12 +247,12 @@
             interfaceModel.getAsyncInterceptors().forEach(AsyncInvocationInterceptor::removeContext);
             try {
                 evaluateResponse(response, method);
-                if (returnType.equals(Void.class)) {
+                if (returnType.getType().equals(Void.class)) {
                     result.complete(null);
-                } else if (returnType.equals(Response.class)) {
+                } else if (returnType.getType().equals(Response.class)) {
                     result.complete(response);
                 } else {
-                    result.complete(response.readEntity(new GenericType<>(actualTypeArgument)));
+                    result.complete(response.readEntity(returnType));
                 }
             } catch (Exception e) {
                 result.completeExceptionally(e);
@@ -398,9 +408,9 @@
      * Evaluation of {@link Response} if it is applicable for any of the registered {@link ResponseExceptionMapper} providers.
      *
      * @param response obtained response
-     * @param method called method
+     * @param method   called method
      */
-    void evaluateResponse(Response response, Method method) {
+    private void evaluateResponse(Response response, Method method) {
         ResponseExceptionMapper lowestMapper = null;
         Throwable throwable = null;
         for (ResponseExceptionMapper responseExceptionMapper : interfaceModel.getResponseExceptionMappers()) {
@@ -460,7 +470,7 @@
         private final InterfaceModel interfaceModel;
         private final Method method;
 
-        private Class<?> returnType;
+        private GenericType<?> returnType;
         private String httpMethod;
         private String pathValue;
         private String[] produces;
@@ -499,7 +509,7 @@
                                                                               interfaceModel.getCreationalContext());
                         invocationInterceptors.add(new InterceptorInvocationContext
                                 .InvocationInterceptor(interceptorInstance,
-                                                      interceptor));
+                                                       interceptor));
                     }
                 }
             }
@@ -509,39 +519,34 @@
          * Return type of the method.
          *
          * @param returnType Method return type
-         * @return updated Builder instance
          */
-        Builder returnType(Type returnType) {
-            if (returnType instanceof ParameterizedType) {
-                this.returnType = (Class<?>) ((ParameterizedType) returnType).getActualTypeArguments()[0];
+        private void returnType(Type returnType) {
+            if (returnType instanceof ParameterizedType
+                    && CompletionStage.class.isAssignableFrom((Class<?>) ((ParameterizedType) returnType).getRawType())) {
+                this.returnType = new GenericType<>(((ParameterizedType) returnType).getActualTypeArguments()[0]);
             } else {
-                this.returnType = (Class<?>) returnType;
+                this.returnType = new GenericType<>(returnType);
             }
-            return this;
         }
 
         /**
          * HTTP method of the method.
          *
          * @param httpMethod HTTP method of the method
-         * @return updated Builder instance
          */
-        Builder httpMethod(String httpMethod) {
+        private void httpMethod(String httpMethod) {
             this.httpMethod = httpMethod;
-            return this;
         }
 
         /**
          * Path value from {@link Path} annotation. If annotation is null, empty String is set as path.
          *
          * @param path {@link Path} annotation
-         * @return updated Builder instance
          */
-        Builder pathValue(Path path) {
+        private void pathValue(Path path) {
             this.pathValue = path != null ? path.value() : "";
             //if only / is added to path like this "localhost:80/test" it makes invalid path "localhost:80/test/"
             this.pathValue = pathValue.equals("/") ? "" : pathValue;
-            return this;
         }
 
         /**
@@ -549,11 +554,9 @@
          * If annotation is null, value from {@link InterfaceModel} is set.
          *
          * @param produces {@link Produces} annotation
-         * @return updated Builder instance
          */
-        Builder produces(Produces produces) {
+        private void produces(Produces produces) {
             this.produces = produces == null ? interfaceModel.getProduces() : produces.value();
-            return this;
         }
 
         /**
@@ -561,35 +564,29 @@
          * If annotation is null, value from {@link InterfaceModel} is set.
          *
          * @param consumes {@link Consumes} annotation
-         * @return updated Builder instance
          */
-        Builder consumes(Consumes consumes) {
+        private void consumes(Consumes consumes) {
             this.consumes = consumes == null ? interfaceModel.getConsumes() : consumes.value();
-            return this;
         }
 
         /**
          * {@link List} of transformed method parameters.
          *
          * @param parameterModels {@link List} of parameters
-         * @return updated Builder instance
          */
-        Builder parameters(List<ParamModel> parameterModels) {
+        private void parameters(List<ParamModel> parameterModels) {
             this.parameterModels = parameterModels;
-            return this;
         }
 
         /**
          * Process data from {@link ClientHeaderParam} annotation to extract methods and values.
          *
          * @param clientHeaderParams {@link ClientHeaderParam} annotations
-         * @return updated Builder instance
          */
-        Builder clientHeaders(ClientHeaderParam[] clientHeaderParams) {
+        private void clientHeaders(ClientHeaderParam[] clientHeaderParams) {
             clientHeaders = Arrays.stream(clientHeaderParams)
                     .map(clientHeaderParam -> new ClientHeaderParamModel(interfaceModel.getRestClientClass(), clientHeaderParam))
                     .collect(Collectors.toList());
-            return this;
         }
 
         /**
@@ -598,12 +595,20 @@
          * @return new instance
          */
         MethodModel build() {
+            returnType(method.getGenericReturnType());
+            httpMethod(parseHttpMethod(interfaceModel, method));
+            pathValue(method.getAnnotation(Path.class));
+            produces(method.getAnnotation(Produces.class));
+            consumes(method.getAnnotation(Consumes.class));
+            parameters(parameterModels(interfaceModel, method));
+            clientHeaders(method.getAnnotationsByType(ClientHeaderParam.class));
+
             validateParameters();
             validateHeaderDuplicityNames();
             Optional<ParamModel> entity = parameterModels.stream()
                     .filter(ParamModel::isEntity)
                     .findFirst();
-            if (JsonValue.class.isAssignableFrom(returnType)
+            if (returnType.getType() instanceof Class && JsonValue.class.isAssignableFrom((Class<?>) returnType.getType())
                     || (
                     entity.isPresent() && entity.get().getType() instanceof Class
                             && JsonValue.class.isAssignableFrom((Class<?>) entity.get().getType()))) {
diff --git a/ext/microprofile/mp-rest-client/src/test/java/org/glassfish/jersey/microprofile/restclient/InterfaceValidationTest.java b/ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/ParamHandler.java
similarity index 64%
rename from ext/microprofile/mp-rest-client/src/test/java/org/glassfish/jersey/microprofile/restclient/InterfaceValidationTest.java
rename to ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/ParamHandler.java
index 2f1b4fd..c268918 100644
--- a/ext/microprofile/mp-rest-client/src/test/java/org/glassfish/jersey/microprofile/restclient/InterfaceValidationTest.java
+++ b/ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/ParamHandler.java
@@ -1,6 +1,5 @@
 /*
  * Copyright (c) 2019 Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2019 Payara Foundation 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
@@ -17,20 +16,22 @@
 
 package org.glassfish.jersey.microprofile.restclient;
 
-import java.util.ArrayList;
-import java.util.HashSet;
-
-import org.junit.Test;
-
 /**
+ * Handles behavior for each JAX-RS annotated element.
+ *
  * @author David Kral
  */
-public class InterfaceValidationTest {
+@FunctionalInterface
+interface ParamHandler {
 
-    @Test
-    public void testValidInterface() {
-        RestClientModel.from(CorrectInterface.class, new HashSet<>(), new HashSet<>(), new ArrayList<>(),
-                             null, null);
-    }
+    /**
+     * Handles behavior for specific annotated element.
+     *
+     * @param beanClassModel bean class model
+     * @param requestPart part of the request
+     * @param instance actual value
+     * @return updated request part
+     */
+    Object handle(BeanClassModel beanClassModel, Object requestPart, Object instance);
 
-}
\ No newline at end of file
+}
diff --git a/ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/ParamModel.java b/ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/ParamModel.java
index 800005d..02afd7d 100644
--- a/ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/ParamModel.java
+++ b/ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/ParamModel.java
@@ -19,6 +19,9 @@
 import java.lang.annotation.Annotation;
 import java.lang.reflect.AnnotatedElement;
 import java.lang.reflect.Type;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.function.BiFunction;
 
 import javax.ws.rs.BeanParam;
 import javax.ws.rs.CookieParam;
@@ -37,6 +40,26 @@
  */
 abstract class ParamModel<T> {
 
+    public static final Map<Class<? extends Annotation>,
+            BiFunction<Builder, Annotation, ParamModel<?>>> PARAM_ANNOTATIONS = new HashMap<>();
+
+    static {
+        PARAM_ANNOTATIONS.put(PathParam.class,
+                              (builder, annotation) -> new PathParamModel(builder, (PathParam) annotation));
+        PARAM_ANNOTATIONS.put(HeaderParam.class,
+                              (builder, annotation) -> new HeaderParamModel(builder, (HeaderParam) annotation));
+        PARAM_ANNOTATIONS.put(CookieParam.class,
+                              (builder, annotation) -> new CookieParamModel(builder, (CookieParam) annotation));
+        PARAM_ANNOTATIONS.put(QueryParam.class,
+                              (builder, annotation) -> new QueryParamModel(builder, (QueryParam) annotation));
+        PARAM_ANNOTATIONS.put(MatrixParam.class,
+                              (builder, annotation) -> new MatrixParamModel(builder, (MatrixParam) annotation));
+        PARAM_ANNOTATIONS.put(FormParam.class,
+                              (builder, annotation) -> new FormParamModel(builder, (FormParam) annotation));
+        PARAM_ANNOTATIONS.put(BeanParam.class,
+                              (builder, annotation) -> new BeanParamModel(builder));
+    }
+
     protected final InterfaceModel interfaceModel;
     protected final Parameter parameter;
     private final Type type;
@@ -47,24 +70,15 @@
     /**
      * Processes parameter annotations and creates new instance of the model corresponding model.
      *
-     * @param interfaceModel model of the interface
-     * @param type annotated element type
+     * @param interfaceModel   model of the interface
+     * @param type             annotated element type
      * @param annotatedElement annotated element
-     * @param position position in method params
+     * @param position         position in method params
      * @return new parameter instance
      */
     static ParamModel from(InterfaceModel interfaceModel, Type type, AnnotatedElement annotatedElement,
                            Parameter parameter, int position) {
-        return new Builder(interfaceModel, type, annotatedElement, parameter)
-                .pathParamName(annotatedElement.getAnnotation(PathParam.class))
-                .headerParamName(annotatedElement.getAnnotation(HeaderParam.class))
-                .beanParam(annotatedElement.getAnnotation(BeanParam.class))
-                .cookieParam(annotatedElement.getAnnotation(CookieParam.class))
-                .queryParam(annotatedElement.getAnnotation(QueryParam.class))
-                .matrixParam(annotatedElement.getAnnotation(MatrixParam.class))
-                .formParam(annotatedElement.getAnnotation(FormParam.class))
-                .paramPosition(position)
-                .build();
+        return new Builder(interfaceModel, type, annotatedElement, parameter, position).build();
     }
 
     ParamModel(Builder builder) {
@@ -110,9 +124,9 @@
     /**
      * Transforms parameter to be part of the request.
      *
-     * @param requestPart part of a request
+     * @param requestPart     part of a request
      * @param annotationClass annotation type
-     * @param instance actual method parameter value
+     * @param instance        actual method parameter value
      * @return updated request part
      */
     abstract T handleParameter(T requestPart, Class<?> annotationClass, Object instance);
@@ -131,143 +145,19 @@
         private Type type;
         private AnnotatedElement annotatedElement;
         private Parameter parameter;
-        private String pathParamName;
-        private String headerParamName;
-        private String cookieParamName;
-        private String queryParamName;
-        private String matrixParamName;
-        private String formParamName;
-        private boolean beanParam;
         private boolean entity;
         private int paramPosition;
 
-        private Builder(InterfaceModel interfaceModel, Type type, AnnotatedElement annotatedElement, Parameter parameter) {
+        private Builder(InterfaceModel interfaceModel,
+                        Type type,
+                        AnnotatedElement annotatedElement,
+                        Parameter parameter,
+                        int position) {
             this.interfaceModel = interfaceModel;
             this.type = type;
             this.annotatedElement = annotatedElement;
             this.parameter = parameter;
-        }
-
-        /**
-         * Path parameter name.
-         *
-         * @param pathParam {@link PathParam} annotation
-         * @return updated Builder instance
-         */
-        Builder pathParamName(PathParam pathParam) {
-            this.pathParamName = pathParam == null ? null : pathParam.value();
-            return this;
-        }
-
-        /**
-         * Header parameter name.
-         *
-         * @param headerParam {@link HeaderParam} annotation
-         * @return updated Builder instance
-         */
-        Builder headerParamName(HeaderParam headerParam) {
-            this.headerParamName = headerParam == null ? null : headerParam.value();
-            return this;
-        }
-
-        /**
-         * Bean parameter identifier.
-         *
-         * @param beanParam {@link BeanParam} annotation
-         * @return updated Builder instance
-         */
-        Builder beanParam(BeanParam beanParam) {
-            this.beanParam = beanParam != null;
-            return this;
-        }
-
-        /**
-         * Cookie parameter.
-         *
-         * @param cookieParam {@link CookieParam} annotation
-         * @return updated Builder instance
-         */
-        Builder cookieParam(CookieParam cookieParam) {
-            this.cookieParamName = cookieParam == null ? null : cookieParam.value();
-            return this;
-        }
-
-        /**
-         * Query parameter.
-         *
-         * @param queryParam {@link QueryParam} annotation
-         * @return updated Builder instance
-         */
-        Builder queryParam(QueryParam queryParam) {
-            this.queryParamName = queryParam == null ? null : queryParam.value();
-            return this;
-        }
-
-        /**
-         * Matrix parameter.
-         *
-         * @param matrixParam {@link MatrixParam} annotation
-         * @return updated Builder instance
-         */
-        Builder matrixParam(MatrixParam matrixParam) {
-            this.matrixParamName = matrixParam == null ? null : matrixParam.value();
-            return this;
-        }
-
-        /**
-         * Form parameter.
-         *
-         * @param formParam {@link FormParam} annotation
-         * @return updated Builder instance
-         */
-        Builder formParam(FormParam formParam) {
-            this.formParamName = formParam == null ? null : formParam.value();
-            return this;
-        }
-
-        /**
-         * Position of parameter in method parameters
-         *
-         * @param paramPosition Parameter position
-         * @return updated Builder instance
-         */
-        Builder paramPosition(int paramPosition) {
-            this.paramPosition = paramPosition;
-            return this;
-        }
-
-        /**
-         * Returns path param name;
-         *
-         * @return path param name
-         */
-        String pathParamName() {
-            return pathParamName;
-        }
-
-        /**
-         * Returns header param name;
-         *
-         * @return header param name
-         */
-        String headerParamName() {
-            return headerParamName;
-        }
-
-        String cookieParamName() {
-            return cookieParamName;
-        }
-
-        String queryParamName() {
-            return queryParamName;
-        }
-
-        String matrixParamName() {
-            return matrixParamName;
-        }
-
-        String formParamName() {
-            return matrixParamName;
+            this.paramPosition = position;
         }
 
         /**
@@ -276,21 +166,13 @@
          * @return new instance
          */
         ParamModel build() {
-            if (pathParamName != null) {
-                return new PathParamModel(this);
-            } else if (headerParamName != null) {
-                return new HeaderParamModel(this);
-            } else if (beanParam) {
-                return new BeanParamModel(this);
-            } else if (cookieParamName != null) {
-                return new CookieParamModel(this);
-            } else if (queryParamName != null) {
-                return new QueryParamModel(this);
-            } else if (matrixParamName != null) {
-                return new MatrixParamModel(this);
-            } else if (formParamName != null) {
-                return new FormParamModel(this);
+            for (Class<? extends Annotation> paramAnnotation : PARAM_ANNOTATIONS.keySet()) {
+                Annotation annot = annotatedElement.getAnnotation(paramAnnotation);
+                if (annot != null) {
+                    return PARAM_ANNOTATIONS.get(paramAnnotation).apply(this, annot);
+                }
             }
+
             entity = true;
             return new ParamModel(this) {
                 @Override
diff --git a/ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/PathParamModel.java b/ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/PathParamModel.java
index 4c8768c..6c8cd5f 100644
--- a/ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/PathParamModel.java
+++ b/ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/PathParamModel.java
@@ -30,9 +30,9 @@
 
     private final String pathParamName;
 
-    PathParamModel(Builder builder) {
+    PathParamModel(Builder builder, PathParam annotation) {
         super(builder);
-        pathParamName = builder.pathParamName();
+        pathParamName = annotation.value();
     }
 
     public String getPathParamName() {
diff --git a/ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/QueryParamModel.java b/ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/QueryParamModel.java
index ce96099..1f6fcfe 100644
--- a/ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/QueryParamModel.java
+++ b/ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/QueryParamModel.java
@@ -30,9 +30,9 @@
 
     private final String queryParamName;
 
-    QueryParamModel(Builder builder) {
+    QueryParamModel(Builder builder, QueryParam annotation) {
         super(builder);
-        queryParamName = builder.queryParamName();
+        queryParamName = annotation.value();
     }
 
     @Override
diff --git a/ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/RequestHeaderAutoDiscoverable.java b/ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/RequestHeaderAutoDiscoverable.java
index bcda814..05b2155 100644
--- a/ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/RequestHeaderAutoDiscoverable.java
+++ b/ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/RequestHeaderAutoDiscoverable.java
@@ -20,13 +20,13 @@
 import javax.ws.rs.RuntimeType;
 import javax.ws.rs.core.FeatureContext;
 
-import org.glassfish.jersey.internal.spi.AutoDiscoverable;
+import org.glassfish.jersey.internal.spi.ForcedAutoDiscoverable;
 
 /**
  * Auto discoverable feature to bind into jersey runtime.
  */
 @ConstrainedTo(RuntimeType.SERVER)
-public class RequestHeaderAutoDiscoverable implements AutoDiscoverable {
+public class RequestHeaderAutoDiscoverable implements ForcedAutoDiscoverable {
     @Override
     public void configure(FeatureContext context) {
         if (!context.getConfiguration().isRegistered(HeadersRequestFilter.class)) {
diff --git a/ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/RestClientBuilderImpl.java b/ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/RestClientBuilderImpl.java
index 1d96c4b..00116a7 100644
--- a/ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/RestClientBuilderImpl.java
+++ b/ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/RestClientBuilderImpl.java
@@ -37,11 +37,6 @@
 import java.util.stream.Collectors;
 
 import javax.annotation.Priority;
-import javax.enterprise.inject.spi.BeanManager;
-import javax.enterprise.inject.spi.CDI;
-import javax.naming.Context;
-import javax.naming.InitialContext;
-import javax.naming.NamingException;
 import javax.ws.rs.Priorities;
 import javax.ws.rs.client.Client;
 import javax.ws.rs.client.ClientBuilder;
@@ -61,6 +56,7 @@
 import org.eclipse.microprofile.rest.client.ext.ResponseExceptionMapper;
 import org.eclipse.microprofile.rest.client.spi.RestClientListener;
 import org.glassfish.jersey.client.Initializable;
+import org.glassfish.jersey.ext.cdi1x.internal.CdiUtil;
 import org.glassfish.jersey.internal.inject.InjectionManager;
 import org.glassfish.jersey.internal.inject.InjectionManagerSupplier;
 import org.glassfish.jersey.internal.util.ReflectionHelper;
@@ -71,7 +67,7 @@
  * @author David Kral
  * @author Patrik Dudits
  */
-public class RestClientBuilderImpl implements RestClientBuilder {
+class RestClientBuilderImpl implements RestClientBuilder {
 
     private static final String CONFIG_DISABLE_DEFAULT_MAPPER = "microprofile.rest.client.disable.default.mapper";
     private static final String CONFIG_PROVIDERS = "/mp-rest/providers";
@@ -137,21 +133,7 @@
         }
 
         //Provider registration part
-        Object providersFromJerseyConfig = clientBuilder.getConfiguration()
-                .getProperty(interfaceClass.getName() + CONFIG_PROVIDERS);
-        if (providersFromJerseyConfig instanceof String && !((String) providersFromJerseyConfig).isEmpty()) {
-            String[] providerArray = ((String) providersFromJerseyConfig).split(PROVIDER_SEPARATOR);
-            processConfigProviders(interfaceClass, providerArray);
-        }
-        Optional<String> providersFromConfig = config.getOptionalValue(interfaceClass.getName() + CONFIG_PROVIDERS, String.class);
-        if (providersFromConfig.isPresent() && !providersFromConfig.get().isEmpty()) {
-            String[] providerArray = providersFromConfig.get().split(PROVIDER_SEPARATOR);
-            processConfigProviders(interfaceClass, providerArray);
-        }
-        RegisterProvider[] registerProviders = interfaceClass.getAnnotationsByType(RegisterProvider.class);
-        for (RegisterProvider registerProvider : registerProviders) {
-            register(registerProvider.value(), registerProvider.priority() < 0 ? Priorities.USER : registerProvider.priority());
-        }
+        processProviders(interfaceClass);
         InjectionManagerExposer injectionManagerExposer = new InjectionManagerExposer();
         register(injectionManagerExposer);
 
@@ -160,16 +142,7 @@
         }
 
         //We need to check first if default exception mapper was not disabled by property on builder.
-        Object disableDefaultMapperJersey = clientBuilder.getConfiguration().getProperty(CONFIG_DISABLE_DEFAULT_MAPPER);
-        if (disableDefaultMapperJersey != null && disableDefaultMapperJersey.equals(Boolean.FALSE)) {
-            register(new DefaultResponseExceptionMapper());
-        } else if (disableDefaultMapperJersey == null) {
-            //If property was not set on Jersey ClientBuilder, we need to check config.
-            Optional<Boolean> disableDefaultMapperConfig = config.getOptionalValue(CONFIG_DISABLE_DEFAULT_MAPPER, boolean.class);
-            if (!disableDefaultMapperConfig.isPresent() || !disableDefaultMapperConfig.get()) {
-                register(new DefaultResponseExceptionMapper());
-            }
-        }
+        registerExceptionMapper();
 
         //AsyncInterceptors initialization
         List<AsyncInvocationInterceptor> asyncInterceptors = asyncInterceptorFactories.stream()
@@ -190,8 +163,7 @@
                                                                paramConverterProviders,
                                                                asyncInterceptors,
                                                                injectionManagerExposer.injectionManager,
-                                                               lookupBeanManager());
-
+                                                               CdiUtil.getBeanManager());
 
         return (T) Proxy.newProxyInstance(interfaceClass.getClassLoader(),
                                           new Class[] {interfaceClass},
@@ -199,29 +171,37 @@
         );
     }
 
-    private BeanManager lookupBeanManager() {
-        Context initialContext = null;
-        try {
-            initialContext = new InitialContext();
-            return (BeanManager) initialContext.lookup("java:comp/BeanManager");
-        } catch (NamingException e) {
-            // no bean manager in JNDI
-        } finally {
-            if (initialContext != null) {
-                try {
-                    initialContext.close();
-                } catch (NamingException e) {
-                }
+    private void registerExceptionMapper() {
+        Object disableDefaultMapperJersey = clientBuilder.getConfiguration().getProperty(CONFIG_DISABLE_DEFAULT_MAPPER);
+        if (disableDefaultMapperJersey != null && disableDefaultMapperJersey.equals(Boolean.FALSE)) {
+            register(new DefaultResponseExceptionMapper());
+        } else if (disableDefaultMapperJersey == null) {
+            //If property was not set on Jersey ClientBuilder, we need to check config.
+            Optional<Boolean> disableDefaultMapperConfig = config.getOptionalValue(CONFIG_DISABLE_DEFAULT_MAPPER, boolean.class);
+            if (!disableDefaultMapperConfig.isPresent() || !disableDefaultMapperConfig.get()) {
+                register(new DefaultResponseExceptionMapper());
             }
         }
-        try {
-            if (CDI.current() != null) {
-                return CDI.current().getBeanManager();
-            }
-        } catch (IllegalStateException e) {
-            // CDI unavailable
+    }
+
+    private <T> void processProviders(Class<T> interfaceClass) {
+        Object providersFromJerseyConfig = clientBuilder.getConfiguration()
+                .getProperty(interfaceClass.getName() + CONFIG_PROVIDERS);
+        if (providersFromJerseyConfig instanceof String && !((String) providersFromJerseyConfig).isEmpty()) {
+            String[] providerArray = ((String) providersFromJerseyConfig).split(PROVIDER_SEPARATOR);
+            processConfigProviders(interfaceClass, providerArray);
         }
-        return null;
+        Optional<String> providersFromConfig = config.getOptionalValue(interfaceClass.getName() + CONFIG_PROVIDERS, String.class);
+        providersFromConfig.ifPresent(providers -> {
+            if (!providers.isEmpty()) {
+                String[] providerArray = providersFromConfig.get().split(PROVIDER_SEPARATOR);
+                processConfigProviders(interfaceClass, providerArray);
+            }
+        });
+        RegisterProvider[] registerProviders = interfaceClass.getAnnotationsByType(RegisterProvider.class);
+        for (RegisterProvider registerProvider : registerProviders) {
+            register(registerProvider.value(), registerProvider.priority() < 0 ? Priorities.USER : registerProvider.priority());
+        }
     }
 
     private void processConfigProviders(Class<?> restClientInterface, String[] providerArray) {
@@ -264,86 +244,86 @@
     }
 
     @Override
-    public RestClientBuilder register(Class<?> aClass) {
-        if (isSupportedCustomProvider(aClass)) {
-            register(ReflectionUtil.createInstance(aClass));
+    public RestClientBuilder register(Class<?> componentClass) {
+        if (isSupportedCustomProvider(componentClass)) {
+            register(ReflectionUtil.createInstance(componentClass));
         } else {
-            clientBuilder.register(aClass);
+            clientBuilder.register(componentClass);
         }
         return this;
     }
 
     @Override
-    public RestClientBuilder register(Class<?> aClass, int i) {
-        if (isSupportedCustomProvider(aClass)) {
-            register(ReflectionUtil.createInstance(aClass), i);
+    public RestClientBuilder register(Class<?> componentClass, int priority) {
+        if (isSupportedCustomProvider(componentClass)) {
+            register(ReflectionUtil.createInstance(componentClass), priority);
         } else {
-            clientBuilder.register(aClass, i);
+            clientBuilder.register(componentClass, priority);
         }
         return this;
     }
 
     @Override
-    public RestClientBuilder register(Class<?> aClass, Class<?>... classes) {
-        if (isSupportedCustomProvider(aClass)) {
-            register(ReflectionUtil.createInstance(aClass), classes);
+    public RestClientBuilder register(Class<?> componentClass, Class<?>... contracts) {
+        if (isSupportedCustomProvider(componentClass)) {
+            register(ReflectionUtil.createInstance(componentClass), contracts);
         } else {
-            clientBuilder.register(aClass, classes);
+            clientBuilder.register(componentClass, contracts);
         }
         return this;
     }
 
     @Override
-    public RestClientBuilder register(Class<?> aClass, Map<Class<?>, Integer> map) {
-        if (isSupportedCustomProvider(aClass)) {
-            register(ReflectionUtil.createInstance(aClass), map);
+    public RestClientBuilder register(Class<?> componentClass, Map<Class<?>, Integer> contracts) {
+        if (isSupportedCustomProvider(componentClass)) {
+            register(ReflectionUtil.createInstance(componentClass), contracts);
         } else {
-            clientBuilder.register(aClass, map);
+            clientBuilder.register(componentClass, contracts);
         }
         return this;
     }
 
     @Override
-    public RestClientBuilder register(Object o) {
-        if (o instanceof ResponseExceptionMapper) {
-            ResponseExceptionMapper mapper = (ResponseExceptionMapper) o;
-            registerCustomProvider(o, -1);
+    public RestClientBuilder register(Object component) {
+        if (component instanceof ResponseExceptionMapper) {
+            ResponseExceptionMapper mapper = (ResponseExceptionMapper) component;
+            registerCustomProvider(component, -1);
             clientBuilder.register(mapper, mapper.getPriority());
         } else {
-            clientBuilder.register(o);
-            registerCustomProvider(o, -1);
+            clientBuilder.register(component);
+            registerCustomProvider(component, -1);
         }
         return this;
     }
 
     @Override
-    public RestClientBuilder register(Object o, int i) {
-        clientBuilder.register(o, i);
-        registerCustomProvider(o, i);
+    public RestClientBuilder register(Object component, int priority) {
+        clientBuilder.register(component, priority);
+        registerCustomProvider(component, priority);
         return this;
     }
 
     @Override
-    public RestClientBuilder register(Object o, Class<?>... classes) {
-        for (Class<?> clazz : classes) {
-            if (isSupportedCustomProvider(clazz)) {
-                register(o);
+    public RestClientBuilder register(Object component, Class<?>... contracts) {
+        for (Class<?> contract : contracts) {
+            if (isSupportedCustomProvider(contract)) {
+                register(component);
             }
         }
-        clientBuilder.register(o, classes);
+        clientBuilder.register(component, contracts);
         return this;
     }
 
     @Override
-    public RestClientBuilder register(Object o, Map<Class<?>, Integer> map) {
-        if (isSupportedCustomProvider(o.getClass())) {
-            if (o instanceof ResponseExceptionMapper) {
-                registerCustomProvider(o, map.get(ResponseExceptionMapper.class));
-            } else if (o instanceof ParamConverterProvider) {
-                registerCustomProvider(o, map.get(ParamConverterProvider.class));
+    public RestClientBuilder register(Object component, Map<Class<?>, Integer> contracts) {
+        if (isSupportedCustomProvider(component.getClass())) {
+            if (component instanceof ResponseExceptionMapper) {
+                registerCustomProvider(component, contracts.get(ResponseExceptionMapper.class));
+            } else if (component instanceof ParamConverterProvider) {
+                registerCustomProvider(component, contracts.get(ParamConverterProvider.class));
             }
         }
-        clientBuilder.register(o, map);
+        clientBuilder.register(component, contracts);
         return this;
     }
 
diff --git a/ext/microprofile/mp-rest-client/src/main/resources/META-INF/beans.xml b/ext/microprofile/mp-rest-client/src/main/resources/META-INF/beans.xml
deleted file mode 100644
index f472ff4..0000000
--- a/ext/microprofile/mp-rest-client/src/main/resources/META-INF/beans.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-
-    Copyright (c) 2019 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
-
--->
-
-<beans xmlns="http://xmlns.jcp.org/xml/ns/javaee"
-        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-        xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
-                           http://xmlns.jcp.org/xml/ns/javaee/beans_2_0.xsd"
-        version="2.0"
-        bean-discovery-mode="none">
-</beans>
diff --git a/ext/microprofile/mp-rest-client/src/main/resources/META-INF/services/org.glassfish.jersey.internal.spi.AutoDiscoverable b/ext/microprofile/mp-rest-client/src/main/resources/META-INF/services/org.glassfish.jersey.internal.spi.ForcedAutoDiscoverable
similarity index 100%
rename from ext/microprofile/mp-rest-client/src/main/resources/META-INF/services/org.glassfish.jersey.internal.spi.AutoDiscoverable
rename to ext/microprofile/mp-rest-client/src/main/resources/META-INF/services/org.glassfish.jersey.internal.spi.ForcedAutoDiscoverable
diff --git a/ext/microprofile/mp-rest-client/src/test/resources/server.policy b/ext/microprofile/mp-rest-client/src/test/resources/server.policy
deleted file mode 100644
index edff3db..0000000
--- a/ext/microprofile/mp-rest-client/src/test/resources/server.policy
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Copyright (c) 2019 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
- */
-
-grant {
-  permission java.util.PropertyPermission "idea.launcher.bin.path", "read";
-  permission java.lang.RuntimePermission "loadLibrary.C:\\Program Files\\JetBrains\\IntelliJ IDEA 2019.1\\bin\\breakgen64.dll";
-  permission java.lang.RuntimePermission "accessDeclaredMembers";
-  permission java.lang.RuntimePermission "getClassLoader";
-  permission java.lang.RuntimePermission "createClassLoader";
-  permission java.lang.RuntimePermission "setContextClassLoader";
-  permission java.lang.RuntimePermission "getProtectionDomain";
-  permission java.lang.RuntimePermission "getenv.*";
-  permission java.lang.RuntimePermission "setIO";
-  permission java.io.FilePermission "C:\\Program Files\\JetBrains\\IntelliJ IDEA 2019.1\\bin\\breakgen64.dll", "read";
-  permission java.util.PropertyPermission "idea.launcher.port", "read";
-  permission java.util.PropertyPermission "idea.launcher.bin.path", "read";
-  permission java.util.PropertyPermission "jcommander.debug", "read";
-  permission java.util.PropertyPermission "user.dir", "read";
-  permission java.util.PropertyPermission "debug", "read";
-  permission java.util.PropertyPermission "arquillian.debug", "read";
-  permission java.util.PropertyPermission "trace", "read";
-  permission java.util.PropertyPermission "testng.test.classpath", "read";
-  permission java.util.PropertyPermission "localscoping", "read";
-  permission java.util.PropertyPermission "outfile", "read";
-  permission java.util.PropertyPermission "org.eclipse.microprofile.*", "read";
-  permission java.util.PropertyPermission "arquillian.xml", "read";
-  permission java.util.PropertyPermission "*", "read,write";
-  permission java.net.SocketPermission "127.0.0.1:*", "connect,resolve";
-  permission java.net.SocketPermission "*", "connect,resolve";
-  permission java.io.FilePermission "<<ALL FILES>>", "read,write,delete";
-  permission java.lang.reflect.ReflectPermission "suppressAccessChecks";
-  permission java.net.NetPermission "getProxySelector";
-  permission java.net.NetPermission "specifyStreamHandler";
-  permission java.lang.management.ManagementPermission "monitor";
-};
-
-grant codebase "file:${java.home}/-" {
-  permission java.security.AllPermission;
-};
-
-grant codebase "file:${settings.localRepository}/-" {
-  permission java.security.AllPermission;
-};
-
-grant codebase "file:${project.build.directory}/test-classes/-" {
-  permission java.util.PropertyPermission "idea.launcher.bin.path", "read";
-  permission java.lang.RuntimePermission "loadLibrary.C:\\Program Files\\JetBrains\\IntelliJ IDEA 2019.1\\bin\\breakgen64.dll";
-  permission java.io.FilePermission "C:\\Program Files\\JetBrains\\IntelliJ IDEA 2019.1\\bin\\breakgen64.dll", "read";
-  permission java.util.PropertyPermission "idea.launcher.port", "read";
-  permission java.util.PropertyPermission "idea.launcher.bin.path", "read";
-
-  permission java.io.FilePermission "<<ALL FILES>>", "read,write,delete";
-  permission java.net.SocketPermission "*", "connect,resolve";
-};
-
-grant codebase "file:${project.build.directory}/classes/-" {
-  permission java.util.PropertyPermission "idea.launcher.bin.path", "read";
-  permission java.lang.RuntimePermission "loadLibrary.C:\\Program Files\\JetBrains\\IntelliJ IDEA 2019.1\\bin\\breakgen64.dll";
-  permission java.io.FilePermission "C:\\Program Files\\JetBrains\\IntelliJ IDEA 2019.1\\bin\\breakgen64.dll", "read";
-  permission java.util.PropertyPermission "idea.launcher.port", "read";
-  permission java.util.PropertyPermission "idea.launcher.bin.path", "read";
-
-  permission java.io.FilePermission "<<ALL FILES>>", "read,write,delete";
-  permission java.net.SocketPermission "*", "connect,resolve";
-};
diff --git a/ext/microprofile/pom.xml b/ext/microprofile/pom.xml
index 7a50ddf..3cac0c8 100644
--- a/ext/microprofile/pom.xml
+++ b/ext/microprofile/pom.xml
@@ -9,7 +9,8 @@
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
-    <artifactId>jersey-microprofile</artifactId>
+    <groupId>org.glassfish.jersey.ext.microprofile</groupId>
+    <artifactId>project</artifactId>
     <packaging>pom</packaging>
 
     <modules>
diff --git a/tests/integration/microprofile/rest-client/pom.xml b/tests/integration/microprofile/rest-client/pom.xml
new file mode 100644
index 0000000..43ec537
--- /dev/null
+++ b/tests/integration/microprofile/rest-client/pom.xml
@@ -0,0 +1,123 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+        xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <artifactId>project</artifactId>
+        <groupId>org.glassfish.jersey.tests.integration</groupId>
+        <version>2.29-SNAPSHOT</version>
+        <relativePath>../../pom.xml</relativePath>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>jersey-rest-client-tck</artifactId>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.glassfish.jersey.ext.microprofile</groupId>
+            <artifactId>jersey-mp-rest-client</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <!-- Overrides CDI from parent pom -->
+        <dependency>
+            <groupId>javax.enterprise</groupId>
+            <artifactId>cdi-api</artifactId>
+            <version>2.0</version>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.weld.se</groupId>
+            <artifactId>weld-se-core</artifactId>
+            <version>3.0.3.Final</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>io.smallrye</groupId>
+            <artifactId>smallrye-config</artifactId>
+            <version>1.3.6</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.eclipse.microprofile.rest.client</groupId>
+            <artifactId>microprofile-rest-client-tck</artifactId>
+            <version>1.2.1</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.testng</groupId>
+            <artifactId>testng</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>com.github.tomakehurst</groupId>
+            <artifactId>wiremock</artifactId>
+            <version>2.21.0</version>
+            <scope>test</scope>
+        </dependency>
+<!--        <dependency>-->
+<!--            <groupId>org.jboss.arquillian.testng</groupId>-->
+<!--            <artifactId>arquillian-testng-container</artifactId>-->
+<!--            <version>1.4.1.Final</version>-->
+<!--            <scope>test</scope>-->
+<!--        </dependency>-->
+<!--        <dependency>-->
+<!--            <groupId>org.jboss.arquillian.container</groupId>-->
+<!--            <artifactId>arquillian-container-test-spi</artifactId>-->
+<!--            <version>1.4.1.Final</version>-->
+<!--            <scope>test</scope>-->
+<!--        </dependency>-->
+<!--        <dependency>-->
+<!--            <groupId>org.jboss.arquillian.container</groupId>-->
+<!--            <artifactId>arquillian-weld-embedded</artifactId>-->
+<!--            <version>2.0.1.Final</version>-->
+<!--            <scope>test</scope>-->
+<!--        </dependency>-->
+        <dependency>
+            <groupId>org.glassfish.jersey.test-framework</groupId>
+            <artifactId>jersey-test-framework-core</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+            <artifactId>jersey-test-framework-provider-bundle</artifactId>
+            <type>pom</type>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-surefire-plugin</artifactId>
+                <configuration>
+                    <suiteXmlFiles>
+                        <suiteXmlFile>tck-suite.xml</suiteXmlFile>
+                    </suiteXmlFiles>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>uk.co.deliverymind</groupId>
+                <artifactId>wiremock-maven-plugin</artifactId>
+                <version>2.7.0</version>
+                <executions>
+                    <execution>
+                        <phase>test-compile</phase>
+                        <goals>
+                            <goal>run</goal>
+                        </goals>
+                        <configuration>
+                            <dir>target/classes</dir>
+                            <params>--port=8765 --verbose</params>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+
+    <properties>
+        <surefire.security.argline>-Djava.security.manager -Djava.security.policy=${project.build.directory}/test-classes/server.policy</surefire.security.argline>
+    </properties>
+
+
+</project>
\ No newline at end of file
diff --git a/ext/microprofile/mp-rest-client/src/test/java/org/glassfish/jersey/message/internal/StringMessageProvider.java b/tests/integration/microprofile/rest-client/src/test/java/org/glassfish/jersey/message/internal/StringMessageProvider.java
similarity index 100%
rename from ext/microprofile/mp-rest-client/src/test/java/org/glassfish/jersey/message/internal/StringMessageProvider.java
rename to tests/integration/microprofile/rest-client/src/test/java/org/glassfish/jersey/message/internal/StringMessageProvider.java
diff --git a/ext/microprofile/mp-rest-client/src/test/java/org/glassfish/jersey/microprofile/restclient/ApplicationResource.java b/tests/integration/microprofile/rest-client/src/test/java/org/glassfish/jersey/restclient/ApplicationResource.java
similarity index 84%
rename from ext/microprofile/mp-rest-client/src/test/java/org/glassfish/jersey/microprofile/restclient/ApplicationResource.java
rename to tests/integration/microprofile/rest-client/src/test/java/org/glassfish/jersey/restclient/ApplicationResource.java
index caf3bb6..0f6f8f6 100644
--- a/ext/microprofile/mp-rest-client/src/test/java/org/glassfish/jersey/microprofile/restclient/ApplicationResource.java
+++ b/tests/integration/microprofile/rest-client/src/test/java/org/glassfish/jersey/restclient/ApplicationResource.java
@@ -14,7 +14,10 @@
  * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
  */
 
-package org.glassfish.jersey.microprofile.restclient;
+package org.glassfish.jersey.restclient;
+
+import java.util.List;
+import java.util.Map;
 
 import javax.ws.rs.GET;
 import javax.ws.rs.POST;
@@ -28,7 +31,12 @@
 public interface ApplicationResource {
 
     @GET
-    String getValue();
+    List<String> getValue();
+
+
+    @GET
+    @Path("map")
+    Map<String, String> getTestMap();
 
     @POST
     String postAppendValue(String value);
diff --git a/ext/microprofile/mp-rest-client/src/test/java/org/glassfish/jersey/microprofile/restclient/ApplicationResourceImpl.java b/tests/integration/microprofile/rest-client/src/test/java/org/glassfish/jersey/restclient/ApplicationResourceImpl.java
similarity index 65%
copy from ext/microprofile/mp-rest-client/src/test/java/org/glassfish/jersey/microprofile/restclient/ApplicationResourceImpl.java
copy to tests/integration/microprofile/rest-client/src/test/java/org/glassfish/jersey/restclient/ApplicationResourceImpl.java
index 4194b40..10c1a45 100644
--- a/ext/microprofile/mp-rest-client/src/test/java/org/glassfish/jersey/microprofile/restclient/ApplicationResourceImpl.java
+++ b/tests/integration/microprofile/rest-client/src/test/java/org/glassfish/jersey/restclient/ApplicationResourceImpl.java
@@ -14,19 +14,33 @@
  * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
  */
 
-package org.glassfish.jersey.microprofile.restclient;
+package org.glassfish.jersey.restclient;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
 
 /**
  * Created by David Kral.
  */
 public class ApplicationResourceImpl implements ApplicationResource {
     @Override
-    public String getValue() {
-        return "This is default value!";
+    public List<String> getValue() {
+        return Arrays.asList("This is default value!", "Test");
+    }
+
+    @Override
+    public Map<String, String> getTestMap() {
+        Map<String, String> testMap = new HashMap<>();
+        testMap.put("firstKey", "firstValue");
+        testMap.put("secondKey", "secondValue");
+        return testMap;
     }
 
     @Override
     public String postAppendValue(String value) {
         return null;
     }
+
 }
diff --git a/ext/microprofile/mp-rest-client/src/test/java/org/glassfish/jersey/microprofile/restclient/CorrectInterface.java b/tests/integration/microprofile/rest-client/src/test/java/org/glassfish/jersey/restclient/CorrectInterface.java
similarity index 89%
rename from ext/microprofile/mp-rest-client/src/test/java/org/glassfish/jersey/microprofile/restclient/CorrectInterface.java
rename to tests/integration/microprofile/rest-client/src/test/java/org/glassfish/jersey/restclient/CorrectInterface.java
index efe6c15..8a15121 100644
--- a/ext/microprofile/mp-rest-client/src/test/java/org/glassfish/jersey/microprofile/restclient/CorrectInterface.java
+++ b/tests/integration/microprofile/rest-client/src/test/java/org/glassfish/jersey/restclient/CorrectInterface.java
@@ -14,7 +14,7 @@
  * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
  */
 
-package org.glassfish.jersey.microprofile.restclient;
+package org.glassfish.jersey.restclient;
 
 import javax.ws.rs.BeanParam;
 import javax.ws.rs.GET;
@@ -43,7 +43,8 @@
     void secondMethod(@PathParam("first") String first, String second);
 
     @POST
-    @ClientHeaderParam(name = "test", value = "org.glassfish.jersey.restclient.CustomHeaderGenerator.customHeader")
+    @ClientHeaderParam(name = "test",
+                       value = "org.glassfish.jersey.org.glassfish.jersey.restclient.CustomHeaderGenerator.customHeader")
     void thirdMethod(@PathParam("first") String first);
 
     @GET
diff --git a/ext/microprofile/mp-rest-client/src/test/java/org/glassfish/jersey/microprofile/restclient/RestClientModelTest.java b/tests/integration/microprofile/rest-client/src/test/java/org/glassfish/jersey/restclient/RestClientModelTest.java
similarity index 75%
rename from ext/microprofile/mp-rest-client/src/test/java/org/glassfish/jersey/microprofile/restclient/RestClientModelTest.java
rename to tests/integration/microprofile/rest-client/src/test/java/org/glassfish/jersey/restclient/RestClientModelTest.java
index 046f528..186b3c6 100644
--- a/ext/microprofile/mp-rest-client/src/test/java/org/glassfish/jersey/microprofile/restclient/RestClientModelTest.java
+++ b/tests/integration/microprofile/rest-client/src/test/java/org/glassfish/jersey/restclient/RestClientModelTest.java
@@ -14,10 +14,12 @@
  * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
  */
 
-package org.glassfish.jersey.microprofile.restclient;
+package org.glassfish.jersey.restclient;
 
 import java.net.URI;
 import java.net.URISyntaxException;
+import java.util.List;
+import java.util.Map;
 
 import org.eclipse.microprofile.rest.client.RestClientBuilder;
 import org.glassfish.jersey.server.ResourceConfig;
@@ -42,7 +44,16 @@
         ApplicationResource app = RestClientBuilder.newBuilder()
                 .baseUri(new URI("http://localhost:9998"))
                 .build(ApplicationResource.class);
-        assertEquals("This is default value!", app.getValue());
+        List<String> collection = app.getValue();
+        assertEquals(2, collection.size());
+        assertEquals("This is default value!", collection.get(0));
+        assertEquals("Test", collection.get(1));
+
+        Map<String, String> map = app.getTestMap();
+        assertEquals(2, map.size());
+        assertEquals("firstValue", map.get("firstKey"));
+        assertEquals("secondValue", map.get("secondKey"));
+
         assertEquals("Hi", app.sayHi());
     }
 }
diff --git a/ext/microprofile/mp-rest-client/src/test/resources/arquillian.xml b/tests/integration/microprofile/rest-client/src/test/resources/arquillian.xml
similarity index 100%
rename from ext/microprofile/mp-rest-client/src/test/resources/arquillian.xml
rename to tests/integration/microprofile/rest-client/src/test/resources/arquillian.xml
diff --git a/ext/microprofile/mp-rest-client/src/test/java/org/glassfish/jersey/microprofile/restclient/ApplicationResourceImpl.java b/tests/integration/microprofile/rest-client/src/test/resources/server.policy
similarity index 66%
rename from ext/microprofile/mp-rest-client/src/test/java/org/glassfish/jersey/microprofile/restclient/ApplicationResourceImpl.java
rename to tests/integration/microprofile/rest-client/src/test/resources/server.policy
index 4194b40..0a3ee57 100644
--- a/ext/microprofile/mp-rest-client/src/test/java/org/glassfish/jersey/microprofile/restclient/ApplicationResourceImpl.java
+++ b/tests/integration/microprofile/rest-client/src/test/resources/server.policy
@@ -14,19 +14,6 @@
  * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
  */
 
-package org.glassfish.jersey.microprofile.restclient;
-
-/**
- * Created by David Kral.
- */
-public class ApplicationResourceImpl implements ApplicationResource {
-    @Override
-    public String getValue() {
-        return "This is default value!";
-    }
-
-    @Override
-    public String postAppendValue(String value) {
-        return null;
-    }
-}
+grant {
+  permission java.security.AllPermission;
+};
diff --git a/ext/microprofile/mp-rest-client/tck-suite.xml b/tests/integration/microprofile/rest-client/tck-suite.xml
similarity index 100%
rename from ext/microprofile/mp-rest-client/tck-suite.xml
rename to tests/integration/microprofile/rest-client/tck-suite.xml
diff --git a/tests/integration/pom.xml b/tests/integration/pom.xml
index da87c12..8f6c1fc 100644
--- a/tests/integration/pom.xml
+++ b/tests/integration/pom.xml
@@ -136,6 +136,7 @@
         <module>tracing-support</module>
         <module>microprofile/config/helidon</module>
         <module>microprofile/config/webapp</module>
+<!--        <module>microprofile/rest-client</module>-->
     </modules>
 
     <profiles>