You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@cxf.apache.org by GitBox <gi...@apache.org> on 2018/09/23 14:59:27 UTC

[GitHub] deki closed pull request #449: [CXF-7846] jaxrs client instantiator lifecycle and pluggability

deki closed pull request #449: [CXF-7846] jaxrs client instantiator lifecycle and pluggability
URL: https://github.com/apache/cxf/pull/449
 
 
   

This is a PR merged from a forked repository.
As GitHub hides the original diff on merge, it is displayed below for
the sake of provenance:

As this is a foreign pull request (from a fork), the diff is supplied
below (as it won't show otherwise due to GitHub magic):

diff --git a/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/ConfigurableImpl.java b/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/ConfigurableImpl.java
index fe2427a7b7f..6ac7ca6a9e8 100644
--- a/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/ConfigurableImpl.java
+++ b/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/ConfigurableImpl.java
@@ -19,10 +19,14 @@
 
 package org.apache.cxf.jaxrs.impl;
 
+import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collection;
 import java.util.HashSet;
+import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
+import java.util.ServiceLoader;
 import java.util.Set;
 import java.util.logging.Logger;
 import java.util.stream.Collectors;
@@ -41,7 +45,7 @@
 import org.apache.cxf.common.logging.LogUtils;
 import org.apache.cxf.jaxrs.utils.AnnotationUtils;
 
-public class ConfigurableImpl<C extends Configurable<C>> implements Configurable<C> {
+public class ConfigurableImpl<C extends Configurable<C>> implements Configurable<C>, AutoCloseable {
     private static final Logger LOG = LogUtils.getL7dLogger(ConfigurableImpl.class);
     
     private static final Class<?>[] RESTRICTED_CLASSES_IN_SERVER = {ClientRequestFilter.class, 
@@ -51,11 +55,19 @@
     
     private ConfigurationImpl config;
     private final C configurable;
-    
+    private final ClassLoader classLoader;
+
     private final Class<?>[] restrictedContractTypes;
 
+    private final Collection<Object> instantiatorInstances = new ArrayList<>();
+    private volatile Instantiator instantiator;
+
     public interface Instantiator {
         <T> Object create(Class<T> cls);
+
+        default void release(Object instance) {
+            // no-op
+        }
     }
     
     public ConfigurableImpl(C configurable, RuntimeType rt) {
@@ -66,7 +78,8 @@ public ConfigurableImpl(C configurable, Configuration config) {
         this.configurable = configurable;
         this.config = config instanceof ConfigurationImpl
             ? (ConfigurationImpl)config : new ConfigurationImpl(config);
-        restrictedContractTypes = RuntimeType.CLIENT.equals(config.getRuntimeType()) ? RESTRICTED_CLASSES_IN_CLIENT 
+        this.classLoader = Thread.currentThread().getContextClassLoader();
+        restrictedContractTypes = RuntimeType.CLIENT.equals(config.getRuntimeType()) ? RESTRICTED_CLASSES_IN_CLIENT
             : RESTRICTED_CLASSES_IN_SERVER;
     }
 
@@ -110,6 +123,17 @@ protected C getConfigurable() {
         return configurable;
     }
 
+    @Override
+    public void close() {
+        synchronized (instantiatorInstances) {
+            if (instantiatorInstances.isEmpty()) {
+                return;
+            }
+            instantiatorInstances.forEach(instantiator::release);
+            instantiatorInstances.clear();
+        }
+    }
+
     @Override
     public Configuration getConfiguration() {
         return config;
@@ -128,6 +152,12 @@ public C register(Object provider) {
 
     @Override
     public C register(Object provider, int bindingPriority) {
+        if (Instantiator.class.isInstance(provider)) {
+            synchronized (this) {
+                instantiator = Instantiator.class.cast(provider);
+            }
+            return configurable;
+        }
         return doRegister(provider, bindingPriority, getImplementedContracts(provider, restrictedContractTypes));
     }
 
@@ -148,7 +178,7 @@ public C register(Class<?> providerClass) {
 
     @Override
     public C register(Class<?> providerClass, int bindingPriority) {
-        return doRegister(getInstantiator().create(providerClass), bindingPriority, 
+        return doRegister(createProvider(providerClass), bindingPriority,
                           getImplementedContracts(providerClass, restrictedContractTypes));
     }
 
@@ -159,11 +189,25 @@ public C register(Class<?> providerClass, Class<?>... contracts) {
 
     @Override
     public C register(Class<?> providerClass, Map<Class<?>, Integer> contracts) {
-        return register(getInstantiator().create(providerClass), contracts);
+        return register(createProvider(providerClass), contracts);
     }
 
     protected Instantiator getInstantiator() {
-        return ConfigurationImpl::createProvider;
+        if (instantiator != null) {
+            return instantiator;
+        }
+        synchronized (this) {
+            if (instantiator != null) {
+                return instantiator;
+            }
+            final Iterator<Instantiator> instantiators = ServiceLoader.load(Instantiator.class, classLoader).iterator();
+            if (instantiators.hasNext()) {
+                instantiator = instantiators.next();
+            } else {
+                instantiator = ConfigurationImpl::createProvider;
+            }
+        }
+        return instantiator;
     }
 
     private C doRegister(Object provider, int bindingPriority, Class<?>... contracts) {
@@ -217,4 +261,13 @@ private boolean checkConstraints(Object provider) {
         }
         return true;
     }
+
+    private Object createProvider(final Class<?> providerClass) {
+        final Object instance = getInstantiator().create(providerClass);
+        synchronized (instantiatorInstances) {
+            instantiatorInstances.add(instance);
+        }
+        return instance;
+    }
 }
+
diff --git a/rt/rs/client/src/main/java/org/apache/cxf/jaxrs/client/spec/ClientBuilderImpl.java b/rt/rs/client/src/main/java/org/apache/cxf/jaxrs/client/spec/ClientBuilderImpl.java
index 93f8034c2ec..5f6027581d3 100644
--- a/rt/rs/client/src/main/java/org/apache/cxf/jaxrs/client/spec/ClientBuilderImpl.java
+++ b/rt/rs/client/src/main/java/org/apache/cxf/jaxrs/client/spec/ClientBuilderImpl.java
@@ -32,14 +32,13 @@
 import javax.ws.rs.RuntimeType;
 import javax.ws.rs.client.Client;
 import javax.ws.rs.client.ClientBuilder;
-import javax.ws.rs.core.Configurable;
 import javax.ws.rs.core.Configuration;
 
 import org.apache.cxf.jaxrs.client.AbstractClient;
 
 public class ClientBuilderImpl extends ClientBuilder {
 
-    private Configurable<ClientBuilder> configImpl;
+    private ClientConfigurableImpl<ClientBuilder> configImpl;
     private TLSConfiguration secConfig = new TLSConfiguration();
 
     public ClientBuilderImpl() {
@@ -98,7 +97,13 @@ public ClientBuilder register(Object object, Map<Class<?>, Integer> map) {
 
     @Override
     public Client build() {
-        return new ClientImpl(configImpl.getConfiguration(), secConfig);
+        return new ClientImpl(configImpl.getConfiguration(), secConfig) {
+            @Override
+            public void close() {
+                super.close();
+                configImpl.close();
+            }
+        };
     }
 
     @Override
@@ -181,3 +186,4 @@ private void validateTimeout(long timeout) {
         }
     }
 }
+
diff --git a/rt/rs/client/src/test/java/org/apache/cxf/jaxrs/client/spec/ClientBuilderImplTest.java b/rt/rs/client/src/test/java/org/apache/cxf/jaxrs/client/spec/ClientBuilderImplTest.java
new file mode 100644
index 00000000000..da45a0eb2b8
--- /dev/null
+++ b/rt/rs/client/src/test/java/org/apache/cxf/jaxrs/client/spec/ClientBuilderImplTest.java
@@ -0,0 +1,62 @@
+/**
+ * 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.spec;
+
+import java.util.concurrent.atomic.AtomicInteger;
+
+import javax.ws.rs.client.Client;
+
+import org.apache.cxf.jaxrs.impl.ConfigurableImpl;
+import org.apache.cxf.jaxrs.provider.PrimitiveTextProvider;
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+public class ClientBuilderImplTest {
+    @Test
+    public void withCustomInstantiator() {
+        final AtomicInteger create = new AtomicInteger();
+        final AtomicInteger close = new AtomicInteger();
+        final Client build = new ClientBuilderImpl().register(new ConfigurableImpl.Instantiator() {
+            @Override
+            public <T> Object create(final Class<T> cls) {
+                try {
+                    create.incrementAndGet();
+                    return cls.newInstance();
+                } catch (final InstantiationException | IllegalAccessException e) {
+                    fail(e.getMessage());
+                }
+                return null;
+            }
+
+            @Override
+            public void release(final Object instance) {
+                close.incrementAndGet();
+            }
+        }).register(PrimitiveTextProvider.class).build();
+        assertEquals(1, create.get());
+        assertEquals(0, close.get());
+        build.close();
+        assertEquals(1, create.get());
+        assertEquals(1, close.get());
+    }
+}
+


 

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services