You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cxf.apache.org by am...@apache.org on 2020/01/16 19:46:46 UTC

[cxf] branch 3.3.x-fixes updated (f5299b7 -> 90f626c)

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

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


    from f5299b7  Recording .gitmergeinfo Changes
     new c7fcd92  CXF-8188: Inject into ClientHeadersFactory
     new c35124b  CXF-8188: Code review comments
     new 90f626c  CXF-8188: Ensure CreationalContexts are released

The 3 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .gitignore                                         |  2 +
 .../cxf/microprofile/client/cdi/CDIFacade.java     | 81 +++++++++++++++++++++
 .../client/cdi/CDIInterceptorWrapper.java          | 10 +--
 .../cxf/microprofile/client/cdi/CDIUtils.java      | 78 ++++++++++++++++++++
 .../cxf/microprofile/client/cdi/Instance.java      | 19 +++--
 .../client/proxy/MicroProfileClientProxyImpl.java  | 82 ++++++++++++++++------
 .../microprofile/client/cdi/RestClientCdiTest.java | 74 +++++++++++++++++++
 ...Filter.java => InjectClientHeadersFactory.java} | 31 ++++----
 .../{RestClient.java => InjectRestClient.java}     |  4 +-
 .../rest/client/JaxrsHeaderPropagationTest.java    | 16 ++++-
 .../microprofile/rest/client/JaxrsResource.java    | 11 +++
 .../rest/client/MockConfigProviderResolver.java    |  1 +
 12 files changed, 354 insertions(+), 55 deletions(-)
 create mode 100644 rt/rs/microprofile-client/src/main/java/org/apache/cxf/microprofile/client/cdi/CDIFacade.java
 create mode 100644 rt/rs/microprofile-client/src/main/java/org/apache/cxf/microprofile/client/cdi/CDIUtils.java
 copy systests/wsdl_maven/java2ws/src/main/java/org/apache/cxf/systests/java2ws/StringWrapper.java => rt/rs/microprofile-client/src/main/java/org/apache/cxf/microprofile/client/cdi/Instance.java (72%)
 copy systests/microprofile/client/jaxrs/src/test/java/org/apache/cxf/systest/microprofile/rest/client/{ReturnAllOutboundHeadersFilter.java => InjectClientHeadersFactory.java} (53%)
 copy systests/microprofile/client/jaxrs/src/test/java/org/apache/cxf/systest/microprofile/rest/client/{RestClient.java => InjectRestClient.java} (91%)


[cxf] 03/03: CXF-8188: Ensure CreationalContexts are released

Posted by am...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 90f626ca32946511583975d5ea44ba8e852a71ff
Author: Andy McCright <j....@gmail.com>
AuthorDate: Tue Jan 14 16:46:56 2020 -0600

    CXF-8188: Ensure CreationalContexts are released
    
    Code review comment - releasing contexts when the client
    proxy is closed.
    
    Signed-off-by: Andy McCright <j....@gmail.com>
---
 .../cxf/microprofile/client/cdi/CDIFacade.java     |  6 +-
 .../cxf/microprofile/client/cdi/CDIUtils.java      | 21 +++---
 .../cxf/microprofile/client/cdi/Instance.java      | 39 ++++++++++++
 .../client/proxy/MicroProfileClientProxyImpl.java  | 21 +++++-
 .../microprofile/client/cdi/RestClientCdiTest.java | 74 ++++++++++++++++++++++
 5 files changed, 146 insertions(+), 15 deletions(-)

diff --git a/rt/rs/microprofile-client/src/main/java/org/apache/cxf/microprofile/client/cdi/CDIFacade.java b/rt/rs/microprofile-client/src/main/java/org/apache/cxf/microprofile/client/cdi/CDIFacade.java
index dfa3cbb..0f18678 100644
--- a/rt/rs/microprofile-client/src/main/java/org/apache/cxf/microprofile/client/cdi/CDIFacade.java
+++ b/rt/rs/microprofile-client/src/main/java/org/apache/cxf/microprofile/client/cdi/CDIFacade.java
@@ -56,17 +56,17 @@ public final class CDIFacade {
         }
     }
 
-    public static <T> Optional<T> getInstanceFromCDI(Class<T> clazz, Bus b) {
+    public static <T> Optional<Instance<T>> getInstanceFromCDI(Class<T> clazz, Bus b) {
         return nullableOptional(() -> CDIUtils.getInstanceFromCDI(clazz, b));
     }
 
-    public static <T> Optional<T> getInstanceFromCDI(Class<T> clazz) {
+    public static <T> Optional<Instance<T>> getInstanceFromCDI(Class<T> clazz) {
         return nullableOptional(() -> CDIUtils.getInstanceFromCDI(clazz));
     }
 
     private static <T> Optional<T> nullableOptional(Callable<T> callable) {
         if (!CDI_AVAILABLE) {
-            return Optional.ofNullable(null);
+            return Optional.empty();
         }
 
         T t;
diff --git a/rt/rs/microprofile-client/src/main/java/org/apache/cxf/microprofile/client/cdi/CDIUtils.java b/rt/rs/microprofile-client/src/main/java/org/apache/cxf/microprofile/client/cdi/CDIUtils.java
index 733bc83..095fbe6 100644
--- a/rt/rs/microprofile-client/src/main/java/org/apache/cxf/microprofile/client/cdi/CDIUtils.java
+++ b/rt/rs/microprofile-client/src/main/java/org/apache/cxf/microprofile/client/cdi/CDIUtils.java
@@ -48,30 +48,31 @@ public final class CDIUtils {
     }
 
 
-    static <T> T getInstanceFromCDI(Class<T> clazz) {
+    static <T> Instance<T> getInstanceFromCDI(Class<T> clazz) {
         return getInstanceFromCDI(clazz, null);
     }
-    
-    static <T> T getInstanceFromCDI(Class<T> clazz, Bus bus) {
-        T t;
+
+    static <T> Instance<T> getInstanceFromCDI(Class<T> clazz, Bus bus) {
+        Instance<T> instance;
         try {
-            t = findBean(clazz, bus);
+            instance = findBean(clazz, bus);
         } catch (ExceptionInInitializerError | NoClassDefFoundError | IllegalStateException ex) {
             // expected if no CDI implementation is available
-            t = null;
+            instance = null;
         } catch (NoSuchElementException ex) {
             // expected if ClientHeadersFactory is not managed by CDI
-            t = null;
+            instance = null;
         }
-        return t;
+        return instance;
     }
 
     @SuppressWarnings("unchecked")
-    private static <T> T findBean(Class<T> clazz, Bus bus) {
+    private static <T> Instance<T> findBean(Class<T> clazz, Bus bus) {
         BeanManager beanManager = bus == null ? getCurrentBeanManager() : getCurrentBeanManager(bus);
         Bean<?> bean = beanManager.getBeans(clazz).iterator().next();
         CreationalContext<?> ctx = beanManager.createCreationalContext(bean);
-        T instance = (T) beanManager.getReference(bean, clazz, ctx);
+        Instance<T> instance = new Instance<>((T) beanManager.getReference(bean, clazz, ctx), 
+            beanManager.isNormalScope(bean.getScope()) ? () -> { } : ctx::release);
         return instance;
     }
 }
\ No newline at end of file
diff --git a/rt/rs/microprofile-client/src/main/java/org/apache/cxf/microprofile/client/cdi/Instance.java b/rt/rs/microprofile-client/src/main/java/org/apache/cxf/microprofile/client/cdi/Instance.java
new file mode 100644
index 0000000..b083517
--- /dev/null
+++ b/rt/rs/microprofile-client/src/main/java/org/apache/cxf/microprofile/client/cdi/Instance.java
@@ -0,0 +1,39 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.cxf.microprofile.client.cdi;
+
+public class Instance<T> {
+
+    private final T value;
+    private final Runnable releaseMethod;
+
+    Instance(T value, Runnable releaseMethod) {
+        this.value = value;
+        this.releaseMethod = releaseMethod;
+    }
+
+    public T getValue() {
+        return value;
+    }
+
+    public void release() {
+        releaseMethod.run();
+    }
+}
\ No newline at end of file
diff --git a/rt/rs/microprofile-client/src/main/java/org/apache/cxf/microprofile/client/proxy/MicroProfileClientProxyImpl.java b/rt/rs/microprofile-client/src/main/java/org/apache/cxf/microprofile/client/proxy/MicroProfileClientProxyImpl.java
index b53e34d..f9ba974 100644
--- a/rt/rs/microprofile-client/src/main/java/org/apache/cxf/microprofile/client/proxy/MicroProfileClientProxyImpl.java
+++ b/rt/rs/microprofile-client/src/main/java/org/apache/cxf/microprofile/client/proxy/MicroProfileClientProxyImpl.java
@@ -25,6 +25,7 @@ import java.lang.reflect.Type;
 import java.net.URI;
 import java.util.Arrays;
 import java.util.HashMap;
+import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
 import java.util.WeakHashMap;
@@ -62,6 +63,7 @@ import org.apache.cxf.microprofile.client.MPRestClientCallback;
 import org.apache.cxf.microprofile.client.MicroProfileClientProviderFactory;
 import org.apache.cxf.microprofile.client.cdi.CDIFacade;
 import org.apache.cxf.microprofile.client.cdi.CDIInterceptorWrapper;
+import org.apache.cxf.microprofile.client.cdi.Instance;
 import org.eclipse.microprofile.rest.client.annotation.ClientHeaderParam;
 import org.eclipse.microprofile.rest.client.annotation.RegisterClientHeaders;
 import org.eclipse.microprofile.rest.client.ext.ClientHeadersFactory;
@@ -102,6 +104,7 @@ public class MicroProfileClientProxyImpl extends ClientProxyImpl {
     private Object objectInstance;
     private Map<Class<ClientHeadersFactory>, ProviderInfo<ClientHeadersFactory>> clientHeaderFactories = 
         new WeakHashMap<>();
+    private List<Instance<?>> cdiInstances = new LinkedList<>();
 
     //CHECKSTYLE:OFF
     public MicroProfileClientProxyImpl(URI baseURI, ClassLoader loader, ClassResourceInfo cri,
@@ -425,6 +428,11 @@ public class MicroProfileClientProxyImpl extends ClientProxyImpl {
         }
     }
 
+    private ClientHeadersFactory mapClientHeadersInstance(Instance<ClientHeadersFactory> instance) {
+        cdiInstances.add(instance);
+        return instance.getValue();
+    }
+
     private void mergeHeaders(Class<ClientHeadersFactory> factoryCls, MultivaluedMap<String, String> existingHeaders) {
 
         try {
@@ -435,13 +443,16 @@ public class MicroProfileClientProxyImpl extends ClientProxyImpl {
 
             if (m != null) {
                 factory = CDIFacade.getInstanceFromCDI(factoryCls, m.getExchange().getBus())
-                        .orElse(factoryCls.newInstance());
+                                   .map(this::mapClientHeadersInstance)
+                                   .orElse(factoryCls.newInstance());
                 ProviderInfo<ClientHeadersFactory> pi = clientHeaderFactories.computeIfAbsent(factoryCls, k -> {
                     return new ProviderInfo<ClientHeadersFactory>(factory, m.getExchange().getBus(), true);
                 });
                 InjectionUtils.injectContexts(factory, pi, m);
             } else {
-                factory = CDIFacade.getInstanceFromCDI(factoryCls).orElse(factoryCls.newInstance());
+                factory = CDIFacade.getInstanceFromCDI(factoryCls)
+                                   .map(this::mapClientHeadersInstance)
+                                   .orElse(factoryCls.newInstance());
             }
 
             MultivaluedMap<String, String> updatedHeaders = factory.update(getJaxrsHeaders(m), existingHeaders);
@@ -512,4 +523,10 @@ public class MicroProfileClientProxyImpl extends ClientProxyImpl {
         }
         return headers;
     }
+
+    @Override
+    public void close() {
+        cdiInstances.forEach(Instance::release);
+        super.close();
+    }
 }
diff --git a/rt/rs/microprofile-client/src/test/java/org/apache/cxf/microprofile/client/cdi/RestClientCdiTest.java b/rt/rs/microprofile-client/src/test/java/org/apache/cxf/microprofile/client/cdi/RestClientCdiTest.java
index e2126d4..019f894 100644
--- a/rt/rs/microprofile-client/src/test/java/org/apache/cxf/microprofile/client/cdi/RestClientCdiTest.java
+++ b/rt/rs/microprofile-client/src/test/java/org/apache/cxf/microprofile/client/cdi/RestClientCdiTest.java
@@ -18,16 +18,24 @@
  */
 package org.apache.cxf.microprofile.client.cdi;
 
+import java.util.ArrayList;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
+import javax.enterprise.context.ApplicationScoped;
+import javax.enterprise.context.NormalScope;
+import javax.enterprise.context.spi.CreationalContext;
+import javax.enterprise.inject.spi.Bean;
 import javax.enterprise.inject.spi.BeanManager;
 import javax.ws.rs.Consumes;
 import javax.ws.rs.Path;
 import javax.ws.rs.Priorities;
 import javax.ws.rs.Produces;
 
+import org.apache.cxf.Bus;
+import org.apache.cxf.bus.extension.ExtensionManagerBus;
 import org.apache.cxf.microprofile.client.mock.HighPriorityClientReqFilter;
 import org.apache.cxf.microprofile.client.mock.InvokedMethodClientRequestFilter;
 import org.apache.cxf.microprofile.client.mock.LowPriorityClientReqFilter;
@@ -77,5 +85,71 @@ public class RestClientCdiTest {
         assertEquals(3, (int) priorities.get(LowPriorityClientReqFilter.class));
         assertEquals(10, (int) priorities.get(HighPriorityClientReqFilter.class));
         assertEquals(Priorities.USER, (int) priorities.get(InvokedMethodClientRequestFilter.class));
+
+        control.verify();
+    }
+
+    @Test
+    @SuppressWarnings({"unchecked", "rawTypes"})
+    public void testCreationalContextsReleasedOnClientClose() throws Exception {
+        IMocksControl control = EasyMock.createStrictControl();
+        BeanManager mockedBeanMgr = control.createMock(BeanManager.class);
+        CreationalContext<?> mockedCreationalCtx = control.createMock(CreationalContext.class);
+        Bean<?> mockedBean = control.createMock(Bean.class);
+        List<String> stringList = new ArrayList<>(Collections.singleton("abc"));
+
+        EasyMock.expect(mockedBeanMgr.getBeans(List.class))
+                .andReturn(Collections.singleton(mockedBean));
+        EasyMock.expect(mockedBeanMgr.createCreationalContext(mockedBean))
+                .andReturn((CreationalContext) mockedCreationalCtx);
+        EasyMock.expect(mockedBeanMgr.getReference(mockedBean, List.class, mockedCreationalCtx))
+                .andReturn(stringList);
+        EasyMock.expect(mockedBean.getScope())
+                .andReturn((Class) ApplicationScoped.class);
+        EasyMock.expect(mockedBeanMgr.isNormalScope(ApplicationScoped.class))
+                .andReturn(false);
+        mockedCreationalCtx.release();
+        EasyMock.expectLastCall().once();
+        control.replay();
+
+        Bus bus = new ExtensionManagerBus();
+        bus.setExtension(mockedBeanMgr, BeanManager.class);
+
+        Instance<List> i = CDIUtils.getInstanceFromCDI(List.class, bus);
+        assertEquals(stringList, i.getValue());
+        i.release();
+
+        control.verify();
+    }
+
+    @Test
+    @SuppressWarnings({"unchecked", "rawTypes"})
+    public void testCreationalContextsNotReleasedOnClientCloseUsingNormalScope() throws Exception {
+        IMocksControl control = EasyMock.createStrictControl();
+        BeanManager mockedBeanMgr = control.createMock(BeanManager.class);
+        CreationalContext<?> mockedCreationalCtx = control.createMock(CreationalContext.class);
+        Bean<?> mockedBean = control.createMock(Bean.class);
+        List<String> stringList = new ArrayList<>(Collections.singleton("xyz"));
+
+        EasyMock.expect(mockedBeanMgr.getBeans(List.class))
+                .andReturn(Collections.singleton(mockedBean));
+        EasyMock.expect(mockedBeanMgr.createCreationalContext(mockedBean))
+                .andReturn((CreationalContext) mockedCreationalCtx);
+        EasyMock.expect(mockedBeanMgr.getReference(mockedBean, List.class, mockedCreationalCtx))
+                .andReturn(stringList);
+        EasyMock.expect(mockedBean.getScope())
+                .andReturn((Class) NormalScope.class);
+        EasyMock.expect(mockedBeanMgr.isNormalScope(NormalScope.class))
+                .andReturn(true);
+        control.replay();
+
+        Bus bus = new ExtensionManagerBus();
+        bus.setExtension(mockedBeanMgr, BeanManager.class);
+
+        Instance<List> i = CDIUtils.getInstanceFromCDI(List.class, bus);
+
+        i.release();
+
+        control.verify();
     }
 }
\ No newline at end of file


[cxf] 02/03: CXF-8188: Code review comments

Posted by am...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit c35124bdfb4950c217f40663650e995abe6aeafe
Author: Andy McCright <j....@gmail.com>
AuthorDate: Mon Jan 13 16:58:22 2020 -0600

    CXF-8188: Code review comments
    
    - Caches BeanManager on the bus
    - Centralizes CDI-accessing mechanism in CDIUtils/CDIFacade
    
    Signed-off-by: Andy McCright <j....@gmail.com>
---
 .../cxf/microprofile/client/cdi/CDIFacade.java     | 48 ++++++++++++++++++++--
 .../client/cdi/CDIInterceptorWrapper.java          | 10 +----
 .../cxf/microprofile/client/cdi/CDIUtils.java      | 29 +++++++++++--
 .../client/proxy/MicroProfileClientProxyImpl.java  | 28 ++++++-------
 4 files changed, 86 insertions(+), 29 deletions(-)

diff --git a/rt/rs/microprofile-client/src/main/java/org/apache/cxf/microprofile/client/cdi/CDIFacade.java b/rt/rs/microprofile-client/src/main/java/org/apache/cxf/microprofile/client/cdi/CDIFacade.java
index c06aaa6..dfa3cbb 100644
--- a/rt/rs/microprofile-client/src/main/java/org/apache/cxf/microprofile/client/cdi/CDIFacade.java
+++ b/rt/rs/microprofile-client/src/main/java/org/apache/cxf/microprofile/client/cdi/CDIFacade.java
@@ -20,18 +20,60 @@
 package org.apache.cxf.microprofile.client.cdi;
 
 import java.util.Optional;
+import java.util.concurrent.Callable;
+
+import org.apache.cxf.Bus;
+
 
 public final class CDIFacade {
 
+    private static final boolean CDI_AVAILABLE;
+
     private CDIFacade() {
     }
 
+    static {
+        boolean b;
+        try {
+            Class.forName("javax.enterprise.inject.spi.BeanManager");
+            b = true;
+        } catch (Throwable t) {
+            b = false;
+        }
+        CDI_AVAILABLE = b;
+    }
+
+    public static Optional<Object> getBeanManager(Bus b) {
+        return nullableOptional(() -> CDIUtils.getCurrentBeanManager(b));
+    }
+
+    public static Optional<Object> getBeanManager() {
+        try {
+            return nullableOptional(() -> CDIUtils.getCurrentBeanManager());
+        } catch (Throwable t) {
+            t.printStackTrace();
+            return Optional.ofNullable(null);
+        }
+    }
+
+    public static <T> Optional<T> getInstanceFromCDI(Class<T> clazz, Bus b) {
+        return nullableOptional(() -> CDIUtils.getInstanceFromCDI(clazz, b));
+    }
+
     public static <T> Optional<T> getInstanceFromCDI(Class<T> clazz) {
+        return nullableOptional(() -> CDIUtils.getInstanceFromCDI(clazz));
+    }
+
+    private static <T> Optional<T> nullableOptional(Callable<T> callable) {
+        if (!CDI_AVAILABLE) {
+            return Optional.ofNullable(null);
+        }
+
         T t;
         try {
-            t = CDIUtils.getInstanceFromCDI(clazz);
-        } catch (ExceptionInInitializerError | NoClassDefFoundError | IllegalStateException ex) {
-            // expected if no MP Config implementation is available
+            t = callable.call();
+        } catch (Throwable ex) {
+            // expected if no CDI implementation is available
             t = null;
         }
         return Optional.ofNullable(t);
diff --git a/rt/rs/microprofile-client/src/main/java/org/apache/cxf/microprofile/client/cdi/CDIInterceptorWrapper.java b/rt/rs/microprofile-client/src/main/java/org/apache/cxf/microprofile/client/cdi/CDIInterceptorWrapper.java
index 320f36b..ae25409 100644
--- a/rt/rs/microprofile-client/src/main/java/org/apache/cxf/microprofile/client/cdi/CDIInterceptorWrapper.java
+++ b/rt/rs/microprofile-client/src/main/java/org/apache/cxf/microprofile/client/cdi/CDIInterceptorWrapper.java
@@ -47,14 +47,8 @@ public interface CDIInterceptorWrapper {
     static CDIInterceptorWrapper createWrapper(Class<?> restClient) {
         try {
             return AccessController.doPrivileged((PrivilegedExceptionAction<CDIInterceptorWrapper>) () -> {
-                Class<?> cdiClass = Class.forName("javax.enterprise.inject.spi.CDI", false,
-                                                  restClient.getClassLoader());
-                Method currentMethod = cdiClass.getMethod("current");
-                Object cdiCurrent = currentMethod.invoke(null);
-
-                Method getBeanMgrMethod = cdiClass.getMethod("getBeanManager");
-
-                return new CDIInterceptorWrapperImpl(restClient, getBeanMgrMethod.invoke(cdiCurrent));
+                Object beanManager = CDIFacade.getBeanManager().orElseThrow(() -> new Exception("CDI not available"));
+                return new CDIInterceptorWrapperImpl(restClient, beanManager);
             });
         } catch (PrivilegedActionException pae) {
             // expected for environments where CDI is not supported
diff --git a/rt/rs/microprofile-client/src/main/java/org/apache/cxf/microprofile/client/cdi/CDIUtils.java b/rt/rs/microprofile-client/src/main/java/org/apache/cxf/microprofile/client/cdi/CDIUtils.java
index 325d01e..733bc83 100644
--- a/rt/rs/microprofile-client/src/main/java/org/apache/cxf/microprofile/client/cdi/CDIUtils.java
+++ b/rt/rs/microprofile-client/src/main/java/org/apache/cxf/microprofile/client/cdi/CDIUtils.java
@@ -26,15 +26,36 @@ import javax.enterprise.inject.spi.Bean;
 import javax.enterprise.inject.spi.BeanManager;
 import javax.enterprise.inject.spi.CDI;
 
+import org.apache.cxf.Bus;
+
+
 public final class CDIUtils {
 
     private CDIUtils() {
     }
 
-    public static <T> T getInstanceFromCDI(Class<T> clazz) {
+    static BeanManager getCurrentBeanManager(Bus bus) {
+        BeanManager bm = bus.getExtension(BeanManager.class);
+        if (bm == null) {
+            bm = getCurrentBeanManager();
+            bus.setExtension(bm, BeanManager.class);
+        }
+        return bm;
+    }
+
+    static BeanManager getCurrentBeanManager() {
+        return CDI.current().getBeanManager();
+    }
+
+
+    static <T> T getInstanceFromCDI(Class<T> clazz) {
+        return getInstanceFromCDI(clazz, null);
+    }
+    
+    static <T> T getInstanceFromCDI(Class<T> clazz, Bus bus) {
         T t;
         try {
-            t = findBean(clazz);
+            t = findBean(clazz, bus);
         } catch (ExceptionInInitializerError | NoClassDefFoundError | IllegalStateException ex) {
             // expected if no CDI implementation is available
             t = null;
@@ -46,8 +67,8 @@ public final class CDIUtils {
     }
 
     @SuppressWarnings("unchecked")
-    private static <T> T findBean(Class<T> clazz) {
-        BeanManager beanManager = CDI.current().getBeanManager();
+    private static <T> T findBean(Class<T> clazz, Bus bus) {
+        BeanManager beanManager = bus == null ? getCurrentBeanManager() : getCurrentBeanManager(bus);
         Bean<?> bean = beanManager.getBeans(clazz).iterator().next();
         CreationalContext<?> ctx = beanManager.createCreationalContext(bean);
         T instance = (T) beanManager.getReference(bean, clazz, ctx);
diff --git a/rt/rs/microprofile-client/src/main/java/org/apache/cxf/microprofile/client/proxy/MicroProfileClientProxyImpl.java b/rt/rs/microprofile-client/src/main/java/org/apache/cxf/microprofile/client/proxy/MicroProfileClientProxyImpl.java
index d8dd35c..b53e34d 100644
--- a/rt/rs/microprofile-client/src/main/java/org/apache/cxf/microprofile/client/proxy/MicroProfileClientProxyImpl.java
+++ b/rt/rs/microprofile-client/src/main/java/org/apache/cxf/microprofile/client/proxy/MicroProfileClientProxyImpl.java
@@ -428,23 +428,23 @@ public class MicroProfileClientProxyImpl extends ClientProxyImpl {
     private void mergeHeaders(Class<ClientHeadersFactory> factoryCls, MultivaluedMap<String, String> existingHeaders) {
 
         try {
-            ClientHeadersFactory factory = CDIFacade.getInstanceFromCDI(factoryCls).orElse(factoryCls.newInstance());
-
-            MultivaluedMap<String, String> jaxrsHeaders;
-            if (JAXRS_UTILS_GET_CURRENT_MESSAGE_METHOD != null) {
-                Message m = (Message) JAXRS_UTILS_GET_CURRENT_MESSAGE_METHOD.invoke(null);
-                if (m != null) {
-                    ProviderInfo<ClientHeadersFactory> pi = clientHeaderFactories.computeIfAbsent(factoryCls, k -> {
-                        return new ProviderInfo<ClientHeadersFactory>(factory, m.getExchange().getBus(), true);
-                    });
-                    InjectionUtils.injectContexts(factory, pi, m);
-                }
-                jaxrsHeaders = getJaxrsHeaders(m);
+            ClientHeadersFactory factory;
+
+            Message m = JAXRS_UTILS_GET_CURRENT_MESSAGE_METHOD == null ? null
+                : (Message) JAXRS_UTILS_GET_CURRENT_MESSAGE_METHOD.invoke(null);
+
+            if (m != null) {
+                factory = CDIFacade.getInstanceFromCDI(factoryCls, m.getExchange().getBus())
+                        .orElse(factoryCls.newInstance());
+                ProviderInfo<ClientHeadersFactory> pi = clientHeaderFactories.computeIfAbsent(factoryCls, k -> {
+                    return new ProviderInfo<ClientHeadersFactory>(factory, m.getExchange().getBus(), true);
+                });
+                InjectionUtils.injectContexts(factory, pi, m);
             } else {
-                jaxrsHeaders = new MultivaluedHashMap<>();
+                factory = CDIFacade.getInstanceFromCDI(factoryCls).orElse(factoryCls.newInstance());
             }
 
-            MultivaluedMap<String, String> updatedHeaders = factory.update(jaxrsHeaders, existingHeaders);
+            MultivaluedMap<String, String> updatedHeaders = factory.update(getJaxrsHeaders(m), existingHeaders);
             existingHeaders.putAll(updatedHeaders);
         } catch (Throwable t) {
             // expected if not running in a JAX-RS server environment.


[cxf] 01/03: CXF-8188: Inject into ClientHeadersFactory

Posted by am...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit c7fcd92b2213401c54f228ea6b7ef3cf4b7932aa
Author: Andy McCright <j....@gmail.com>
AuthorDate: Sat Jan 4 16:53:07 2020 -0600

    CXF-8188: Inject into ClientHeadersFactory
    
    Signed-off-by: Andy McCright <j....@gmail.com>
---
 .gitignore                                         |  2 +
 .../cxf/microprofile/client/cdi/CDIFacade.java     | 39 +++++++++++++
 .../cxf/microprofile/client/cdi/CDIUtils.java      | 56 +++++++++++++++++++
 .../client/proxy/MicroProfileClientProxyImpl.java  | 65 +++++++++++++++-------
 ...source.java => InjectClientHeadersFactory.java} | 38 +++++--------
 .../{JaxrsResource.java => InjectRestClient.java}  | 27 ++-------
 .../rest/client/JaxrsHeaderPropagationTest.java    | 16 +++++-
 .../microprofile/rest/client/JaxrsResource.java    | 11 ++++
 .../rest/client/MockConfigProviderResolver.java    |  1 +
 9 files changed, 186 insertions(+), 69 deletions(-)

diff --git a/.gitignore b/.gitignore
index 6beab61..bb6bd9f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -19,3 +19,5 @@ node_modules/
 derby.log
 .pmdruleset.xml
 .sts4-cache/
+**/.factorypath
+.vscode/
diff --git a/rt/rs/microprofile-client/src/main/java/org/apache/cxf/microprofile/client/cdi/CDIFacade.java b/rt/rs/microprofile-client/src/main/java/org/apache/cxf/microprofile/client/cdi/CDIFacade.java
new file mode 100644
index 0000000..c06aaa6
--- /dev/null
+++ b/rt/rs/microprofile-client/src/main/java/org/apache/cxf/microprofile/client/cdi/CDIFacade.java
@@ -0,0 +1,39 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.cxf.microprofile.client.cdi;
+
+import java.util.Optional;
+
+public final class CDIFacade {
+
+    private CDIFacade() {
+    }
+
+    public static <T> Optional<T> getInstanceFromCDI(Class<T> clazz) {
+        T t;
+        try {
+            t = CDIUtils.getInstanceFromCDI(clazz);
+        } catch (ExceptionInInitializerError | NoClassDefFoundError | IllegalStateException ex) {
+            // expected if no MP Config implementation is available
+            t = null;
+        }
+        return Optional.ofNullable(t);
+    }
+}
\ No newline at end of file
diff --git a/rt/rs/microprofile-client/src/main/java/org/apache/cxf/microprofile/client/cdi/CDIUtils.java b/rt/rs/microprofile-client/src/main/java/org/apache/cxf/microprofile/client/cdi/CDIUtils.java
new file mode 100644
index 0000000..325d01e
--- /dev/null
+++ b/rt/rs/microprofile-client/src/main/java/org/apache/cxf/microprofile/client/cdi/CDIUtils.java
@@ -0,0 +1,56 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.cxf.microprofile.client.cdi;
+
+import java.util.NoSuchElementException;
+
+import javax.enterprise.context.spi.CreationalContext;
+import javax.enterprise.inject.spi.Bean;
+import javax.enterprise.inject.spi.BeanManager;
+import javax.enterprise.inject.spi.CDI;
+
+public final class CDIUtils {
+
+    private CDIUtils() {
+    }
+
+    public static <T> T getInstanceFromCDI(Class<T> clazz) {
+        T t;
+        try {
+            t = findBean(clazz);
+        } catch (ExceptionInInitializerError | NoClassDefFoundError | IllegalStateException ex) {
+            // expected if no CDI implementation is available
+            t = null;
+        } catch (NoSuchElementException ex) {
+            // expected if ClientHeadersFactory is not managed by CDI
+            t = null;
+        }
+        return t;
+    }
+
+    @SuppressWarnings("unchecked")
+    private static <T> T findBean(Class<T> clazz) {
+        BeanManager beanManager = CDI.current().getBeanManager();
+        Bean<?> bean = beanManager.getBeans(clazz).iterator().next();
+        CreationalContext<?> ctx = beanManager.createCreationalContext(bean);
+        T instance = (T) beanManager.getReference(bean, clazz, ctx);
+        return instance;
+    }
+}
\ No newline at end of file
diff --git a/rt/rs/microprofile-client/src/main/java/org/apache/cxf/microprofile/client/proxy/MicroProfileClientProxyImpl.java b/rt/rs/microprofile-client/src/main/java/org/apache/cxf/microprofile/client/proxy/MicroProfileClientProxyImpl.java
index 0fa5145..d8dd35c 100644
--- a/rt/rs/microprofile-client/src/main/java/org/apache/cxf/microprofile/client/proxy/MicroProfileClientProxyImpl.java
+++ b/rt/rs/microprofile-client/src/main/java/org/apache/cxf/microprofile/client/proxy/MicroProfileClientProxyImpl.java
@@ -27,6 +27,7 @@ import java.util.Arrays;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.WeakHashMap;
 import java.util.concurrent.Callable;
 import java.util.concurrent.CompletionStage;
 import java.util.concurrent.ExecutorService;
@@ -52,12 +53,14 @@ import org.apache.cxf.jaxrs.model.ClassResourceInfo;
 import org.apache.cxf.jaxrs.model.OperationResourceInfo;
 import org.apache.cxf.jaxrs.model.Parameter;
 import org.apache.cxf.jaxrs.model.ParameterType;
+import org.apache.cxf.jaxrs.model.ProviderInfo;
 import org.apache.cxf.jaxrs.utils.HttpUtils;
 import org.apache.cxf.jaxrs.utils.InjectionUtils;
 import org.apache.cxf.message.Exchange;
 import org.apache.cxf.message.Message;
 import org.apache.cxf.microprofile.client.MPRestClientCallback;
 import org.apache.cxf.microprofile.client.MicroProfileClientProviderFactory;
+import org.apache.cxf.microprofile.client.cdi.CDIFacade;
 import org.apache.cxf.microprofile.client.cdi.CDIInterceptorWrapper;
 import org.eclipse.microprofile.rest.client.annotation.ClientHeaderParam;
 import org.eclipse.microprofile.rest.client.annotation.RegisterClientHeaders;
@@ -97,6 +100,8 @@ public class MicroProfileClientProxyImpl extends ClientProxyImpl {
 
     private final CDIInterceptorWrapper interceptorWrapper;
     private Object objectInstance;
+    private Map<Class<ClientHeadersFactory>, ProviderInfo<ClientHeadersFactory>> clientHeaderFactories = 
+        new WeakHashMap<>();
 
     //CHECKSTYLE:OFF
     public MicroProfileClientProxyImpl(URI baseURI, ClassLoader loader, ClassResourceInfo cri,
@@ -372,6 +377,7 @@ public class MicroProfileClientProxyImpl extends ClientProxyImpl {
     }
 
     @Override
+    @SuppressWarnings("unchecked")
     protected void handleHeaders(Method m,
                                  Object[] params,
                                  MultivaluedMap<String, String> headers,
@@ -409,25 +415,45 @@ public class MicroProfileClientProxyImpl extends ClientProxyImpl {
                 }
             }
 
-            ClientHeadersFactory headersFactory = null;
-            
             if (headersFactoryAnno != null) {
-                Class<?> headersFactoryClass = headersFactoryAnno.value();
-                headersFactory = (ClientHeadersFactory) headersFactoryClass.newInstance();
-                mergeHeaders(headersFactory, headers);
+                Class<ClientHeadersFactory> headersFactoryClass = (Class<ClientHeadersFactory>)
+                                                                  headersFactoryAnno.value();
+                mergeHeaders(headersFactoryClass, headers);
             }
         } catch (Throwable t) {
             throwException(t);
         }
     }
 
-    private void mergeHeaders(ClientHeadersFactory factory,
-                              MultivaluedMap<String, String> existingHeaders) {
+    private void mergeHeaders(Class<ClientHeadersFactory> factoryCls, MultivaluedMap<String, String> existingHeaders) {
+
+        try {
+            ClientHeadersFactory factory = CDIFacade.getInstanceFromCDI(factoryCls).orElse(factoryCls.newInstance());
 
-        MultivaluedMap<String, String> jaxrsHeaders = getJaxrsHeaders();
-        MultivaluedMap<String, String> updatedHeaders = factory.update(jaxrsHeaders, existingHeaders);
-        existingHeaders.putAll(updatedHeaders);
+            MultivaluedMap<String, String> jaxrsHeaders;
+            if (JAXRS_UTILS_GET_CURRENT_MESSAGE_METHOD != null) {
+                Message m = (Message) JAXRS_UTILS_GET_CURRENT_MESSAGE_METHOD.invoke(null);
+                if (m != null) {
+                    ProviderInfo<ClientHeadersFactory> pi = clientHeaderFactories.computeIfAbsent(factoryCls, k -> {
+                        return new ProviderInfo<ClientHeadersFactory>(factory, m.getExchange().getBus(), true);
+                    });
+                    InjectionUtils.injectContexts(factory, pi, m);
+                }
+                jaxrsHeaders = getJaxrsHeaders(m);
+            } else {
+                jaxrsHeaders = new MultivaluedHashMap<>();
+            }
+
+            MultivaluedMap<String, String> updatedHeaders = factory.update(jaxrsHeaders, existingHeaders);
+            existingHeaders.putAll(updatedHeaders);
+        } catch (Throwable t) {
+            // expected if not running in a JAX-RS server environment.
+            if (LOG.isLoggable(Level.FINEST)) {
+                LOG.log(Level.FINEST, "Caught exception getting JAX-RS incoming headers", t);
+            }
+        }
     }
+
     @Override
     public Object invoke(Object o, Method m, Object[] params) throws Throwable {
         checkClosed();
@@ -474,18 +500,15 @@ public class MicroProfileClientProxyImpl extends ClientProxyImpl {
         throw new RuntimeException(t);
     }
 
-    private static MultivaluedMap<String, String> getJaxrsHeaders() {
+    /**
+     * Returns the incoming request headers from the current JAX-RS request, assuming
+     * that this is invoked inside a JAX-RS request. If not, it will return an empty
+     * map.
+     */
+    private static MultivaluedMap<String, String> getJaxrsHeaders(Message m) {
         MultivaluedMap<String, String> headers = new MultivaluedHashMap<>();
-        try {
-            if (JAXRS_UTILS_GET_CURRENT_MESSAGE_METHOD != null) {
-                Message m = (Message) JAXRS_UTILS_GET_CURRENT_MESSAGE_METHOD.invoke(null);
-                headers.putAll(CastUtils.cast((Map<?, ?>)m.get(Message.PROTOCOL_HEADERS)));
-            }
-        } catch (Throwable t) {
-            // expected if not running in a JAX-RS server environment.
-            if (LOG.isLoggable(Level.FINEST)) {
-                LOG.log(Level.FINEST, "Caught exception getting JAX-RS incoming headers", t);
-            }
+        if (m != null) {
+            headers.putAll(CastUtils.cast((Map<?, ?>) m.get(Message.PROTOCOL_HEADERS)));
         }
         return headers;
     }
diff --git a/systests/microprofile/client/jaxrs/src/test/java/org/apache/cxf/systest/microprofile/rest/client/JaxrsResource.java b/systests/microprofile/client/jaxrs/src/test/java/org/apache/cxf/systest/microprofile/rest/client/InjectClientHeadersFactory.java
similarity index 51%
copy from systests/microprofile/client/jaxrs/src/test/java/org/apache/cxf/systest/microprofile/rest/client/JaxrsResource.java
copy to systests/microprofile/client/jaxrs/src/test/java/org/apache/cxf/systest/microprofile/rest/client/InjectClientHeadersFactory.java
index 455ef80..5dc8823 100644
--- a/systests/microprofile/client/jaxrs/src/test/java/org/apache/cxf/systest/microprofile/rest/client/JaxrsResource.java
+++ b/systests/microprofile/client/jaxrs/src/test/java/org/apache/cxf/systest/microprofile/rest/client/InjectClientHeadersFactory.java
@@ -18,32 +18,24 @@
  */
 package org.apache.cxf.systest.microprofile.rest.client;
 
-import java.net.URI;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.MultivaluedHashMap;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.Request;
 
-import javax.ws.rs.GET;
-import javax.ws.rs.Path;
-import javax.ws.rs.Produces;
-import javax.ws.rs.core.Response;
+import org.eclipse.microprofile.rest.client.ext.ClientHeadersFactory;
 
-import org.eclipse.microprofile.rest.client.RestClientBuilder;
+public class InjectClientHeadersFactory implements ClientHeadersFactory {
 
-@Path("/jaxrs")
-@Produces("text/plain")
-public class JaxrsResource {
+    @Context
+    Request jaxrsRequest;
 
-    @Path("/check")
-    @GET
-    public Response statusCheck() {
-        return Response.ok("up").build();
-    }
+    @Override
+    public MultivaluedMap<String, String> update(MultivaluedMap<String, String> incomingHeaders,
+                                                 MultivaluedMap<String, String> clientOutgoingHeaders) {
 
-    @Path("/propagate")
-    @GET
-    public String propagateHeadersToRestClient() {
-        RestClient client = RestClientBuilder.newBuilder()
-                                             .baseUri(URI.create("http://localhost:8080/ignored"))
-                                             .register(ReturnAllOutboundHeadersFilter.class)
-                                             .build(RestClient.class);
-        return client.getAllHeadersToBeSent();
+        MultivaluedMap<String, String> updatedHeaders = new MultivaluedHashMap<>();
+        updatedHeaders.putSingle("REQUEST_METHOD", jaxrsRequest == null ? "NOT_INJECTED" : jaxrsRequest.getMethod());
+        return updatedHeaders;
     }
-}
+}
\ No newline at end of file
diff --git a/systests/microprofile/client/jaxrs/src/test/java/org/apache/cxf/systest/microprofile/rest/client/JaxrsResource.java b/systests/microprofile/client/jaxrs/src/test/java/org/apache/cxf/systest/microprofile/rest/client/InjectRestClient.java
similarity index 54%
copy from systests/microprofile/client/jaxrs/src/test/java/org/apache/cxf/systest/microprofile/rest/client/JaxrsResource.java
copy to systests/microprofile/client/jaxrs/src/test/java/org/apache/cxf/systest/microprofile/rest/client/InjectRestClient.java
index 455ef80..d2b9618 100644
--- a/systests/microprofile/client/jaxrs/src/test/java/org/apache/cxf/systest/microprofile/rest/client/JaxrsResource.java
+++ b/systests/microprofile/client/jaxrs/src/test/java/org/apache/cxf/systest/microprofile/rest/client/InjectRestClient.java
@@ -18,32 +18,15 @@
  */
 package org.apache.cxf.systest.microprofile.rest.client;
 
-import java.net.URI;
-
 import javax.ws.rs.GET;
 import javax.ws.rs.Path;
-import javax.ws.rs.Produces;
-import javax.ws.rs.core.Response;
-
-import org.eclipse.microprofile.rest.client.RestClientBuilder;
 
-@Path("/jaxrs")
-@Produces("text/plain")
-public class JaxrsResource {
+import org.eclipse.microprofile.rest.client.annotation.RegisterClientHeaders;
 
-    @Path("/check")
-    @GET
-    public Response statusCheck() {
-        return Response.ok("up").build();
-    }
+@Path("/remote")
+@RegisterClientHeaders(InjectClientHeadersFactory.class)
+public interface InjectRestClient {
 
-    @Path("/propagate")
     @GET
-    public String propagateHeadersToRestClient() {
-        RestClient client = RestClientBuilder.newBuilder()
-                                             .baseUri(URI.create("http://localhost:8080/ignored"))
-                                             .register(ReturnAllOutboundHeadersFilter.class)
-                                             .build(RestClient.class);
-        return client.getAllHeadersToBeSent();
-    }
+    String getAllHeadersToBeSent();
 }
diff --git a/systests/microprofile/client/jaxrs/src/test/java/org/apache/cxf/systest/microprofile/rest/client/JaxrsHeaderPropagationTest.java b/systests/microprofile/client/jaxrs/src/test/java/org/apache/cxf/systest/microprofile/rest/client/JaxrsHeaderPropagationTest.java
index 943fa80..9a2c60f 100644
--- a/systests/microprofile/client/jaxrs/src/test/java/org/apache/cxf/systest/microprofile/rest/client/JaxrsHeaderPropagationTest.java
+++ b/systests/microprofile/client/jaxrs/src/test/java/org/apache/cxf/systest/microprofile/rest/client/JaxrsHeaderPropagationTest.java
@@ -80,6 +80,10 @@ public class JaxrsHeaderPropagationTest extends AbstractBusClientServerTestBase
         assertTrue("server did not launch correctly", launchServer(Server.class, true));
         createStaticBus();
         System.out.println("Listening on port " + PORT);
+
+        ConfigProviderResolver.setInstance(
+            new MockConfigProviderResolver(Collections.singletonMap(
+                "org.eclipse.microprofile.rest.client.propagateHeaders", "Header1,MultiHeader")));
     }
 
     @Before
@@ -90,9 +94,6 @@ public class JaxrsHeaderPropagationTest extends AbstractBusClientServerTestBase
 
     @Test
     public void testHeadersArePropagated() throws Exception {
-        ConfigProviderResolver.setInstance(
-            new MockConfigProviderResolver(Collections.singletonMap(
-                "org.eclipse.microprofile.rest.client.propagateHeaders", "Header1,MultiHeader")));
         Logger logger = 
             Logger.getLogger("org.eclipse.microprofile.rest.client.ext.DefaultClientHeadersFactoryImpl"); //NOPMD
         logger.setLevel(Level.ALL);
@@ -110,6 +111,15 @@ public class JaxrsHeaderPropagationTest extends AbstractBusClientServerTestBase
         assertTrue(propagatedHeaderContent.contains("MultiHeader=value1,value2,value3"));
     }
 
+    @Test
+    public void testInjectionOccursInClientHeadersFactory() throws Exception {
+        final Response r = createWebClient("/jaxrs/inject").delete();
+        assertEquals(Status.OK.getStatusCode(), r.getStatus());
+        String returnedHeaderContent = r.readEntity(String.class);
+        System.out.println("returnedHeaderContent: " + returnedHeaderContent);
+        assertTrue(returnedHeaderContent.contains("REQUEST_METHOD=DELETE"));
+    }
+
     private static WebClient createWebClient(final String url) {
         return WebClient
             .create("http://localhost:" + PORT + url)
diff --git a/systests/microprofile/client/jaxrs/src/test/java/org/apache/cxf/systest/microprofile/rest/client/JaxrsResource.java b/systests/microprofile/client/jaxrs/src/test/java/org/apache/cxf/systest/microprofile/rest/client/JaxrsResource.java
index 455ef80..4c05e79 100644
--- a/systests/microprofile/client/jaxrs/src/test/java/org/apache/cxf/systest/microprofile/rest/client/JaxrsResource.java
+++ b/systests/microprofile/client/jaxrs/src/test/java/org/apache/cxf/systest/microprofile/rest/client/JaxrsResource.java
@@ -20,6 +20,7 @@ package org.apache.cxf.systest.microprofile.rest.client;
 
 import java.net.URI;
 
+import javax.ws.rs.DELETE;
 import javax.ws.rs.GET;
 import javax.ws.rs.Path;
 import javax.ws.rs.Produces;
@@ -46,4 +47,14 @@ public class JaxrsResource {
                                              .build(RestClient.class);
         return client.getAllHeadersToBeSent();
     }
+
+    @Path("/inject")
+    @DELETE
+    public String injectContextsIntoClientHeadersFactory() {
+        InjectRestClient client = RestClientBuilder.newBuilder()
+                                                   .baseUri(URI.create("http://localhost:8080/ignored"))
+                                                   .register(ReturnAllOutboundHeadersFilter.class)
+                                                   .build(InjectRestClient.class);
+        return client.getAllHeadersToBeSent();
+    }
 }
diff --git a/systests/microprofile/client/jaxrs/src/test/java/org/apache/cxf/systest/microprofile/rest/client/MockConfigProviderResolver.java b/systests/microprofile/client/jaxrs/src/test/java/org/apache/cxf/systest/microprofile/rest/client/MockConfigProviderResolver.java
index 6a11f26..e0bc64a 100644
--- a/systests/microprofile/client/jaxrs/src/test/java/org/apache/cxf/systest/microprofile/rest/client/MockConfigProviderResolver.java
+++ b/systests/microprofile/client/jaxrs/src/test/java/org/apache/cxf/systest/microprofile/rest/client/MockConfigProviderResolver.java
@@ -36,6 +36,7 @@ public class MockConfigProviderResolver extends ConfigProviderResolver {
         @Override
         public <T> T getValue(String propertyName, Class<T> propertyType) {
             String value = configValues.get(propertyName);
+            System.out.println("getValue(" + propertyName + ") = " + value);
             if (value != null) {
                 if (propertyType == String.class) {
                     return propertyType.cast(value);