You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cxf.apache.org by re...@apache.org on 2021/09/17 00:05:28 UTC
[cxf] branch master updated: CXF-7543: JAX-RS Features not used in
proxies or WebClients (#849)
This is an automated email from the ASF dual-hosted git repository.
reta pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/cxf.git
The following commit(s) were added to refs/heads/master by this push:
new bf25a93 CXF-7543: JAX-RS Features not used in proxies or WebClients (#849)
bf25a93 is described below
commit bf25a931a96a6eb6cac47651bef1f2ff4fb442bc
Author: Andriy Redko <dr...@gmail.com>
AuthorDate: Thu Sep 16 20:05:21 2021 -0400
CXF-7543: JAX-RS Features not used in proxies or WebClients (#849)
---
.../cxf/jaxrs/client/JAXRSClientFactoryBean.java | 41 ++++++++++
.../JAXRSClientFactoryBeanDefinitionParser.java | 59 ++++++++++++++
.../cxf/jaxrs/client/cache/ClientCacheTest.java | 23 ++++++
.../client/spring/JAXRSClientFactoryBeanTest.java | 34 ++++++++
.../client/spring/SpringParameterHandler.java | 58 +++++++++++++
.../org/apache/cxf/jaxrs/client/spring/clients.xml | 6 ++
.../client/MicroProfileClientFactoryBean.java | 14 +++-
.../client/CxfTypeSafeClientBuilderTest.java | 42 ++++++++++
.../client/MicroProfileClientFactoryBeanTest.java | 94 ++++++++++++++++++++++
9 files changed, 368 insertions(+), 3 deletions(-)
diff --git a/rt/rs/client/src/main/java/org/apache/cxf/jaxrs/client/JAXRSClientFactoryBean.java b/rt/rs/client/src/main/java/org/apache/cxf/jaxrs/client/JAXRSClientFactoryBean.java
index 13d3c28..ccf547c 100644
--- a/rt/rs/client/src/main/java/org/apache/cxf/jaxrs/client/JAXRSClientFactoryBean.java
+++ b/rt/rs/client/src/main/java/org/apache/cxf/jaxrs/client/JAXRSClientFactoryBean.java
@@ -24,12 +24,19 @@ import java.lang.reflect.Type;
import java.net.URI;
import java.security.AccessController;
import java.security.PrivilegedAction;
+import java.util.Arrays;
+import java.util.HashSet;
import java.util.List;
import java.util.Map;
+import java.util.Set;
import java.util.logging.Logger;
import javax.ws.rs.CookieParam;
import javax.ws.rs.HeaderParam;
+import javax.ws.rs.RuntimeType;
+import javax.ws.rs.core.Configurable;
+import javax.ws.rs.core.Configuration;
+import javax.ws.rs.core.Feature;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.ext.ParamConverter;
import javax.ws.rs.ext.ParamConverterProvider;
@@ -45,6 +52,8 @@ import org.apache.cxf.endpoint.UpfrontConduitSelector;
import org.apache.cxf.jaxrs.AbstractJAXRSFactoryBean;
import org.apache.cxf.jaxrs.JAXRSServiceFactoryBean;
import org.apache.cxf.jaxrs.JAXRSServiceImpl;
+import org.apache.cxf.jaxrs.impl.ConfigurableImpl;
+import org.apache.cxf.jaxrs.impl.FeatureContextImpl;
import org.apache.cxf.jaxrs.impl.MetadataMap;
import org.apache.cxf.jaxrs.model.ClassResourceInfo;
import org.apache.cxf.jaxrs.utils.AnnotationUtils;
@@ -403,6 +412,10 @@ public class JAXRSClientFactoryBean extends AbstractJAXRSFactoryBean {
});
}
}
+
+ protected <C extends Configurable<C>> Configurable<?> getConfigurableFor(C context) {
+ return new ConfigurableImpl<>(context, RuntimeType.CLIENT);
+ }
protected void applyFeatures(AbstractClient client) {
if (getFeatures() != null) {
@@ -410,6 +423,34 @@ public class JAXRSClientFactoryBean extends AbstractJAXRSFactoryBean {
feature.initialize(client.getConfiguration(), getBus());
});
}
+
+ // Process JAX-RS features which are passed through as providers
+ final Set<Object> providers = new HashSet<>();
+ for (final Object provider: getProviders()) {
+ if (provider instanceof Feature) {
+ final Feature feature = (Feature)provider;
+ final FeatureContextImpl context = new FeatureContextImpl();
+ final Configurable<?> configurable = getConfigurableFor(context);
+ final Configuration configuration = configurable.getConfiguration();
+ final Set<Object> registered = configuration.getInstances();
+
+ if (!configuration.isRegistered(feature)) {
+ configurable.register(feature);
+
+ // Disregarding if the feature is enabled or disabled, register only newly added providers,
+ // excluding pre-existing ones and the feature instance itself.
+ final Set<Object> added = new HashSet<Object>(configuration.getInstances());
+ added.remove(feature);
+ added.removeAll(registered);
+
+ providers.addAll(added);
+ }
+ }
+ }
+
+ if (!providers.isEmpty()) {
+ setProviders(Arrays.asList(providers));
+ }
}
/**
diff --git a/rt/rs/client/src/main/java/org/apache/cxf/jaxrs/client/spring/JAXRSClientFactoryBeanDefinitionParser.java b/rt/rs/client/src/main/java/org/apache/cxf/jaxrs/client/spring/JAXRSClientFactoryBeanDefinitionParser.java
index 6543ddc..5c6989d 100644
--- a/rt/rs/client/src/main/java/org/apache/cxf/jaxrs/client/spring/JAXRSClientFactoryBeanDefinitionParser.java
+++ b/rt/rs/client/src/main/java/org/apache/cxf/jaxrs/client/spring/JAXRSClientFactoryBeanDefinitionParser.java
@@ -20,12 +20,14 @@ package org.apache.cxf.jaxrs.client.spring;
import java.io.IOException;
import java.lang.annotation.Annotation;
+import java.lang.reflect.Constructor;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import javax.ws.rs.Path;
+import javax.ws.rs.core.Configurable;
import javax.ws.rs.ext.Provider;
import javax.xml.namespace.QName;
@@ -35,6 +37,7 @@ import org.apache.cxf.bus.spring.BusWiringBeanFactoryPostProcessor;
import org.apache.cxf.common.util.ClasspathScanner;
import org.apache.cxf.configuration.spring.AbstractFactoryBeanDefinitionParser;
import org.apache.cxf.jaxrs.client.JAXRSClientFactoryBean;
+import org.apache.cxf.jaxrs.impl.ConfigurableImpl;
import org.apache.cxf.jaxrs.model.UserResource;
import org.apache.cxf.jaxrs.utils.ResourceUtils;
import org.springframework.beans.BeansException;
@@ -109,11 +112,50 @@ public class JAXRSClientFactoryBeanDefinitionParser extends AbstractFactoryBeanD
setFirstChildAsProperty(el, ctx, bean, name);
}
}
+
+ /**
+ * Instantiate newly registered provider instances using {@link AutowireCapableBeanFactory}
+ */
+ private static class SpringInstantiator implements ConfigurableImpl.Instantiator {
+ private final AutowireCapableBeanFactory beanFactory;
+
+ SpringInstantiator(final AutowireCapableBeanFactory beanFactory) {
+ this.beanFactory = beanFactory;
+ }
+
+ @Override
+ public <T> Object create(Class<T> cls) {
+ return beanFactory.createBean(cls, resolveAutowireMode(cls), true);
+ }
+
+ @Override
+ public void release(Object instance) {
+ beanFactory.destroyBean(instance);
+ }
+
+ /**
+ * Return the resolved autowire mode (AUTOWIRE_CONSTRUCTOR or AUTOWIRE_BY_TYPE).
+ */
+ private <T> int resolveAutowireMode(Class<T> cls) {
+ final Constructor<?>[] constructors = cls.getConstructors();
+
+ for (Constructor<?> constructor: constructors) {
+ // If there is a default constructor, we are good to go with
+ // autowiring by type, otherwise we need construction injection.
+ if (constructor.getParameterCount() == 0) {
+ return AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE;
+ }
+ }
+
+ return AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR;
+ }
+ }
public static class JAXRSSpringClientFactoryBean extends JAXRSClientFactoryBean
implements ApplicationContextAware {
private List<String> basePackages;
+ private SpringInstantiator instantiator;
public JAXRSSpringClientFactoryBean() {
super();
@@ -125,6 +167,10 @@ public class JAXRSClientFactoryBeanDefinitionParser extends AbstractFactoryBeanD
public void setApplicationContext(ApplicationContext ctx) throws BeansException {
try {
+ if (instantiator == null) {
+ instantiator = new SpringInstantiator(ctx.getAutowireCapableBeanFactory());
+ }
+
if (basePackages != null) {
final Map< Class< ? extends Annotation >, Collection< Class< ? > > > classes =
ClasspathScanner.findClasses(basePackages, Path.class, Provider.class);
@@ -159,6 +205,17 @@ public class JAXRSClientFactoryBeanDefinitionParser extends AbstractFactoryBeanD
setBus(BusWiringBeanFactoryPostProcessor.addDefaultBus(ctx));
}
}
+
+ @Override
+ protected <C extends Configurable<C>> Configurable<?> getConfigurableFor(C context) {
+ final Configurable<?> configurable = super.getConfigurableFor(context);
+
+ if (instantiator != null) {
+ configurable.register(instantiator);
+ }
+
+ return configurable;
+ }
}
static Class<?> getServiceClass(Collection<Class<?>> rootClasses) {
@@ -184,4 +241,6 @@ public class JAXRSClientFactoryBeanDefinitionParser extends AbstractFactoryBeanD
}
return providers;
}
+
+
}
diff --git a/rt/rs/client/src/test/java/org/apache/cxf/jaxrs/client/cache/ClientCacheTest.java b/rt/rs/client/src/test/java/org/apache/cxf/jaxrs/client/cache/ClientCacheTest.java
index f784f5d..5fc4be6 100644
--- a/rt/rs/client/src/test/java/org/apache/cxf/jaxrs/client/cache/ClientCacheTest.java
+++ b/rt/rs/client/src/test/java/org/apache/cxf/jaxrs/client/cache/ClientCacheTest.java
@@ -89,6 +89,29 @@ public class ClientCacheTest {
}
@Test
+ public void testGetTimeStringUsingClientFactory() {
+ CacheControlFeature feature = new CacheControlFeature();
+ try {
+ JAXRSClientFactoryBean bean = new JAXRSClientFactoryBean();
+ bean.setAddress(ADDRESS);
+ bean.setProviders(Collections.singletonList(feature));
+ bean.setTransportId(LocalTransportFactory.TRANSPORT_ID);
+
+ final WebClient cached = bean.createWebClient()
+ .accept("text/plain")
+ .header(HttpHeaders.CACHE_CONTROL, "public");
+
+ final Response r = cached.get();
+ assertEquals(Response.Status.OK.getStatusCode(), r.getStatus());
+ final String r1 = r.readEntity(String.class);
+ waitABit();
+ assertEquals(r1, cached.get().readEntity(String.class));
+ } finally {
+ feature.close();
+ }
+ }
+
+ @Test
public void testGetTimeStringAsInputStream() throws Exception {
CacheControlFeature feature = new CacheControlFeature();
try {
diff --git a/rt/rs/client/src/test/java/org/apache/cxf/jaxrs/client/spring/JAXRSClientFactoryBeanTest.java b/rt/rs/client/src/test/java/org/apache/cxf/jaxrs/client/spring/JAXRSClientFactoryBeanTest.java
index ecfff4c..f34d037 100644
--- a/rt/rs/client/src/test/java/org/apache/cxf/jaxrs/client/spring/JAXRSClientFactoryBeanTest.java
+++ b/rt/rs/client/src/test/java/org/apache/cxf/jaxrs/client/spring/JAXRSClientFactoryBeanTest.java
@@ -18,22 +18,30 @@
*/
package org.apache.cxf.jaxrs.client.spring;
+import java.util.List;
+
+import javax.ws.rs.core.Feature;
+import javax.ws.rs.core.FeatureContext;
import javax.xml.namespace.QName;
import org.apache.cxf.BusFactory;
import org.apache.cxf.jaxrs.client.Client;
import org.apache.cxf.jaxrs.client.JAXRSClientFactoryBean;
+import org.apache.cxf.jaxrs.client.cache.CacheControlClientReaderInterceptor;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.junit.After;
import org.junit.Test;
import static org.hamcrest.CoreMatchers.endsWith;
+import static org.hamcrest.CoreMatchers.hasItem;
+import static org.hamcrest.CoreMatchers.instanceOf;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertThat;
+
public class JAXRSClientFactoryBeanTest {
@After
@@ -110,4 +118,30 @@ public class JAXRSClientFactoryBeanTest {
endsWith("?list=1&list=2"));
}
}
+
+ @Test
+ public void testClientWithFeatures() throws Exception {
+ try (ClassPathXmlApplicationContext ctx =
+ new ClassPathXmlApplicationContext(new String[] {"/org/apache/cxf/jaxrs/client/spring/clients.xml"})) {
+ final Client bean = (Client) ctx.getBean("client4");
+ assertNotNull(bean);
+
+ final JAXRSClientFactoryBean cfb = (JAXRSClientFactoryBean)ctx.getBean("client4.proxyFactory");
+ assertNotNull(bean);
+
+ assertThat((List<Object>)cfb.getProviders(),
+ hasItem(instanceOf(CacheControlClientReaderInterceptor.class)));
+
+ assertThat((List<Object>)cfb.getProviders(),
+ hasItem(instanceOf(SpringParameterHandler.class)));
+ }
+ }
+
+ public static class SomeFeature implements Feature {
+ @Override
+ public boolean configure(FeatureContext context) {
+ context.register(SpringParameterHandler.class);
+ return true;
+ }
+ }
}
\ No newline at end of file
diff --git a/rt/rs/client/src/test/java/org/apache/cxf/jaxrs/client/spring/SpringParameterHandler.java b/rt/rs/client/src/test/java/org/apache/cxf/jaxrs/client/spring/SpringParameterHandler.java
new file mode 100644
index 0000000..10745a5
--- /dev/null
+++ b/rt/rs/client/src/test/java/org/apache/cxf/jaxrs/client/spring/SpringParameterHandler.java
@@ -0,0 +1,58 @@
+/**
+ * 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.jaxrs.client.spring;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+import java.util.Objects;
+
+import javax.ws.rs.ext.ParamConverter;
+import javax.ws.rs.ext.ParamConverterProvider;
+
+import org.apache.cxf.jaxrs.client.Customer;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.ApplicationContext;
+
+public class SpringParameterHandler implements ParamConverterProvider, ParamConverter<Customer> {
+ @Autowired
+ public SpringParameterHandler(ApplicationContext context) {
+ Objects.requireNonNull(context);
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public <T> ParamConverter<T> getConverter(Class<T> cls, Type arg1, Annotation[] arg2) {
+ if (Customer.class == cls) {
+ return (ParamConverter<T>)this;
+ }
+ return null;
+ }
+
+ public Customer fromString(String s) throws IllegalArgumentException {
+ Customer c = new Customer();
+ c.setName(s);
+ return c;
+ }
+
+ @Override
+ public String toString(Customer arg0) throws IllegalArgumentException {
+ return null;
+ }
+}
diff --git a/rt/rs/client/src/test/java/org/apache/cxf/jaxrs/client/spring/clients.xml b/rt/rs/client/src/test/java/org/apache/cxf/jaxrs/client/spring/clients.xml
index 320de2e..7f33450 100644
--- a/rt/rs/client/src/test/java/org/apache/cxf/jaxrs/client/spring/clients.xml
+++ b/rt/rs/client/src/test/java/org/apache/cxf/jaxrs/client/spring/clients.xml
@@ -59,4 +59,10 @@
<entry key="expand.query.value.as.collection" value="true" />
</jaxrs:properties>
</jaxrs:client>
+ <jaxrs:client id="client4" serviceClass="org.apache.cxf.jaxrs.resources.BookStore" address="http://localhost:9000/foo" threadSafe="true">
+ <jaxrs:providers>
+ <bean class="org.apache.cxf.jaxrs.client.cache.CacheControlFeature"/>
+ <bean class="org.apache.cxf.jaxrs.client.spring.JAXRSClientFactoryBeanTest.SomeFeature"/>
+ </jaxrs:providers>
+ </jaxrs:client>
</beans>
\ No newline at end of file
diff --git a/rt/rs/microprofile-client/src/main/java/org/apache/cxf/microprofile/client/MicroProfileClientFactoryBean.java b/rt/rs/microprofile-client/src/main/java/org/apache/cxf/microprofile/client/MicroProfileClientFactoryBean.java
index 389c4fa..0f10811 100644
--- a/rt/rs/microprofile-client/src/main/java/org/apache/cxf/microprofile/client/MicroProfileClientFactoryBean.java
+++ b/rt/rs/microprofile-client/src/main/java/org/apache/cxf/microprofile/client/MicroProfileClientFactoryBean.java
@@ -28,6 +28,7 @@ import java.util.concurrent.ExecutorService;
import javax.ws.rs.client.ClientRequestFilter;
import javax.ws.rs.client.ClientResponseFilter;
+import javax.ws.rs.core.Configurable;
import javax.ws.rs.core.Configuration;
import org.apache.cxf.common.util.ClassHelper;
@@ -51,17 +52,19 @@ import org.eclipse.microprofile.rest.client.RestClientBuilder;
public class MicroProfileClientFactoryBean extends JAXRSClientFactoryBean {
private final Comparator<ProviderInfo<?>> comparator;
private final List<Object> registeredProviders;
+ private final Configurable<RestClientBuilder> configurable;
private final Configuration configuration;
private ClassLoader proxyLoader;
private boolean inheritHeaders;
private ExecutorService executorService;
private TLSConfiguration secConfig;
- public MicroProfileClientFactoryBean(MicroProfileClientConfigurableImpl<RestClientBuilder> configuration,
+ public MicroProfileClientFactoryBean(MicroProfileClientConfigurableImpl<RestClientBuilder> configurable,
String baseUri, Class<?> aClass, ExecutorService executorService,
TLSConfiguration secConfig) {
super(new MicroProfileServiceFactoryBean());
- this.configuration = configuration.getConfiguration();
+ this.configurable = configurable;
+ this.configuration = configurable.getConfiguration();
this.comparator = MicroProfileClientProviderFactory.createComparator(this);
this.executorService = (executorService == null) ? Utils.defaultExecutorService() : executorService;
this.secConfig = secConfig;
@@ -71,7 +74,7 @@ public class MicroProfileClientFactoryBean extends JAXRSClientFactoryBean {
super.setProperties(this.configuration.getProperties());
registeredProviders = new ArrayList<>();
registeredProviders.addAll(processProviders());
- if (!configuration.isDefaultExceptionMapperDisabled()) {
+ if (!configurable.isDefaultExceptionMapperDisabled()) {
registeredProviders.add(new ProviderInfo<>(new DefaultResponseExceptionMapper(), getBus(), false));
}
registeredProviders.add(new ProviderInfo<>(new JsrJsonpProvider(), getBus(), false));
@@ -134,6 +137,11 @@ public class MicroProfileClientFactoryBean extends JAXRSClientFactoryBean {
inheritHeaders, executorService, configuration, interceptorWrapper, secConfig, varValues);
}
}
+
+ @Override
+ protected <C extends Configurable<C>> Configurable<?> getConfigurableFor(C context) {
+ return configurable;
+ }
Configuration getConfiguration() {
return configuration;
diff --git a/rt/rs/microprofile-client/src/test/java/org/apache/cxf/microprofile/client/CxfTypeSafeClientBuilderTest.java b/rt/rs/microprofile-client/src/test/java/org/apache/cxf/microprofile/client/CxfTypeSafeClientBuilderTest.java
index c9d09a6..8ca5f4b 100644
--- a/rt/rs/microprofile-client/src/test/java/org/apache/cxf/microprofile/client/CxfTypeSafeClientBuilderTest.java
+++ b/rt/rs/microprofile-client/src/test/java/org/apache/cxf/microprofile/client/CxfTypeSafeClientBuilderTest.java
@@ -24,6 +24,8 @@ import java.net.URL;
import javax.ws.rs.PathParam;
import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.Feature;
+import javax.ws.rs.core.FeatureContext;
import javax.ws.rs.core.Response;
import org.apache.cxf.jaxrs.client.WebClientUtil;
@@ -116,6 +118,30 @@ public class CxfTypeSafeClientBuilderTest {
// TODO: add a test for writer interceptors - possibly in systests
//assertEquals(TestWriterInterceptor.getAndResetValue(), 1);
}
+
+ @Test
+ public void testInvokesPostOperationWithRegisteredFeature() throws Exception {
+ String inputBody = "input body will be removed";
+ String expectedResponseBody = TestMessageBodyReader.REPLACED_BODY;
+
+ InterfaceWithoutProvidersDefined api = new CxfTypeSafeClientBuilder()
+ .register(SomeFeature.class)
+ .property("microprofile.rest.client.disable.default.mapper", true)
+ .baseUrl(new URL("http://localhost/null"))
+ .build(InterfaceWithoutProvidersDefined.class);
+
+ Response response = api.executePost(inputBody);
+
+ String body = response.readEntity(String.class);
+
+ response.close();
+
+ assertEquals(expectedResponseBody, body);
+
+ assertEquals(TestClientResponseFilter.getAndResetValue(), 1);
+ assertEquals(TestClientRequestFilter.getAndResetValue(), 1);
+ assertEquals(TestReaderInterceptor.getAndResetValue(), 1);
+ }
@Test(expected = NoSuchEntityException.class)
public void testResponseExceptionMapper() throws Exception {
@@ -223,4 +249,20 @@ public class CxfTypeSafeClientBuilderTest {
public void testProxyAddressNullHost() {
RestClientBuilder.newBuilder().proxyAddress(null, 8080);
}
+
+ public static class SomeFeature implements Feature {
+ @Override
+ public boolean configure(FeatureContext context) {
+ context
+ .register(TestClientRequestFilter.class)
+ .register(TestClientResponseFilter.class)
+ .register(TestMessageBodyReader.class, 4999)
+ .register(TestMessageBodyWriter.class)
+ .register(TestParamConverterProvider.class)
+ .register(TestReaderInterceptor.class)
+ .register(TestWriterInterceptor.class)
+ .register(EchoClientReqFilter.class);
+ return true;
+ }
+ }
}
diff --git a/rt/rs/microprofile-client/src/test/java/org/apache/cxf/microprofile/client/MicroProfileClientFactoryBeanTest.java b/rt/rs/microprofile-client/src/test/java/org/apache/cxf/microprofile/client/MicroProfileClientFactoryBeanTest.java
new file mode 100644
index 0000000..9951f82
--- /dev/null
+++ b/rt/rs/microprofile-client/src/test/java/org/apache/cxf/microprofile/client/MicroProfileClientFactoryBeanTest.java
@@ -0,0 +1,94 @@
+/**
+ * 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;
+
+import java.util.List;
+
+import javax.ws.rs.core.Feature;
+import javax.ws.rs.core.FeatureContext;
+
+import org.apache.cxf.jaxrs.client.spec.TLSConfiguration;
+import org.apache.cxf.microprofile.client.mock.MyClient;
+import org.eclipse.microprofile.rest.client.RestClientBuilder;
+import org.eclipse.microprofile.rest.client.tck.providers.TestClientRequestFilter;
+
+import org.junit.Test;
+
+import static org.hamcrest.CoreMatchers.hasItem;
+import static org.hamcrest.CoreMatchers.instanceOf;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+
+public class MicroProfileClientFactoryBeanTest {
+ @Test
+ @SuppressWarnings("unchecked")
+ public void testCreateClientEnabledFeature() throws Exception {
+ final MicroProfileClientConfigurableImpl<RestClientBuilder> configurable =
+ new MicroProfileClientConfigurableImpl<>(RestClientBuilder.newBuilder());
+
+ final MicroProfileClientFactoryBean bean = new MicroProfileClientFactoryBean(configurable,
+ "http://bar", MyClient.class, null, new TLSConfiguration());
+
+ final SomeFeature feature = new SomeFeature(true);
+ bean.setProvider(feature);
+
+ assertTrue(bean.create() instanceof MyClient);
+ assertTrue(configurable.getConfiguration().isRegistered(SomeFeature.class));
+ assertTrue(configurable.getConfiguration().isRegistered(TestClientRequestFilter.class));
+ assertTrue(configurable.getConfiguration().isEnabled(SomeFeature.class));
+
+ assertThat((List<Object>)bean.getProviders(), hasItem(instanceOf(TestClientRequestFilter.class)));
+ }
+
+ @Test
+ @SuppressWarnings("unchecked")
+ public void testCreateClientDisabledFeature() throws Exception {
+ final MicroProfileClientConfigurableImpl<RestClientBuilder> configurable =
+ new MicroProfileClientConfigurableImpl<>(RestClientBuilder.newBuilder());
+
+ final MicroProfileClientFactoryBean bean = new MicroProfileClientFactoryBean(configurable,
+ "http://bar", MyClient.class, null, new TLSConfiguration());
+
+ final SomeFeature feature = new SomeFeature(false);
+ bean.setProvider(feature);
+
+ assertTrue(bean.create() instanceof MyClient);
+ assertTrue(configurable.getConfiguration().isRegistered(SomeFeature.class));
+ assertTrue(configurable.getConfiguration().isRegistered(TestClientRequestFilter.class));
+ assertFalse(configurable.getConfiguration().isEnabled(SomeFeature.class));
+
+ assertThat((List<Object>)bean.getProviders(), hasItem(instanceOf(TestClientRequestFilter.class)));
+ }
+
+ public static class SomeFeature implements Feature {
+ private final boolean enabled;
+
+ public SomeFeature(boolean enabled) {
+ this.enabled = enabled;
+ }
+
+ @Override
+ public boolean configure(FeatureContext context) {
+ context.register(TestClientRequestFilter.class);
+ return enabled;
+ }
+ }
+}