JOHNZON-163 small customizations on Alessandro fix to ensure we don't keep 
recreating jsonb instances and we log when a config is ignored


Project: http://git-wip-us.apache.org/repos/asf/johnzon/repo
Commit: http://git-wip-us.apache.org/repos/asf/johnzon/commit/eb93b91a
Tree: http://git-wip-us.apache.org/repos/asf/johnzon/tree/eb93b91a
Diff: http://git-wip-us.apache.org/repos/asf/johnzon/diff/eb93b91a

Branch: refs/heads/master
Commit: eb93b91a5a0adeb494b2a36ee98a0cb7c2c6a229
Parents: 2e4a6ae
Author: Romain Manni-Bucau <[email protected]>
Authored: Tue Mar 27 15:47:52 2018 +0200
Committer: Romain Manni-Bucau <[email protected]>
Committed: Tue Mar 27 15:47:52 2018 +0200

----------------------------------------------------------------------
 .../jaxrs/jsonb/jaxrs/JsonbJaxrsProvider.java   | 89 ++++++++++++++++----
 1 file changed, 73 insertions(+), 16 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/johnzon/blob/eb93b91a/johnzon-jsonb/src/main/java/org/apache/johnzon/jaxrs/jsonb/jaxrs/JsonbJaxrsProvider.java
----------------------------------------------------------------------
diff --git 
a/johnzon-jsonb/src/main/java/org/apache/johnzon/jaxrs/jsonb/jaxrs/JsonbJaxrsProvider.java
 
b/johnzon-jsonb/src/main/java/org/apache/johnzon/jaxrs/jsonb/jaxrs/JsonbJaxrsProvider.java
index 15e1194..25cf998 100644
--- 
a/johnzon-jsonb/src/main/java/org/apache/johnzon/jaxrs/jsonb/jaxrs/JsonbJaxrsProvider.java
+++ 
b/johnzon-jsonb/src/main/java/org/apache/johnzon/jaxrs/jsonb/jaxrs/JsonbJaxrsProvider.java
@@ -42,8 +42,9 @@ import java.lang.annotation.Annotation;
 import java.lang.reflect.Type;
 import java.util.Collection;
 import java.util.Properties;
-import java.util.concurrent.atomic.AtomicReference;
-import java.util.function.Supplier;
+import java.util.function.Function;
+import java.util.logging.Logger;
+
 import javax.annotation.Priority;
 import javax.ws.rs.core.Context;
 import javax.ws.rs.ext.ContextResolver;
@@ -54,11 +55,12 @@ import javax.ws.rs.ext.Providers;
 @Produces(MediaType.APPLICATION_JSON)
 @Consumes(MediaType.APPLICATION_JSON)
 @Priority(value = 4900)
-public class JsonbJaxrsProvider<T> implements MessageBodyWriter<T>, 
MessageBodyReader<T> {
+public class JsonbJaxrsProvider<T> implements MessageBodyWriter<T>, 
MessageBodyReader<T>, AutoCloseable {
 
     protected final Collection<String> ignores;
-    protected final AtomicReference<Supplier<Jsonb>> delegate = new 
AtomicReference<>();
     protected final JsonbConfig config = new JsonbConfig();
+    protected volatile Function<Class<?>, Jsonb> delegate = null;
+    private boolean customized;
 
     @Context
     private Providers providers;
@@ -70,10 +72,6 @@ public class JsonbJaxrsProvider<T> implements 
MessageBodyWriter<T>, MessageBodyR
     protected JsonbJaxrsProvider(final Collection<String> ignores) {
         this.ignores = ignores;
     }
-    
-    protected Jsonb createJsonb() {
-        return JsonbBuilder.create(config);
-    }
 
     private boolean isIgnored(final Class<?> type) {
         return ignores != null && ignores.contains(type.getName());
@@ -82,6 +80,7 @@ public class JsonbJaxrsProvider<T> implements 
MessageBodyWriter<T>, MessageBodyR
     // config - main containers support the configuration of providers this way
     public void setFailOnUnknownProperties(final boolean active) {
         config.setProperty("johnzon.fail-on-unknown-properties", active);
+        customized = true;
     }
 
     public void setOtherProperties(final String others) {
@@ -93,34 +92,42 @@ public class JsonbJaxrsProvider<T> implements 
MessageBodyWriter<T>, MessageBodyR
             }
         }};
         properties.stringPropertyNames().forEach(k -> config.setProperty(k, 
properties.getProperty(k)));
+        customized = true;
     }
 
     public void setIJson(final boolean active) {
         config.withStrictIJSON(active);
+        customized = true;
     }
 
     public void setEncoding(final String encoding) {
         config.withEncoding(encoding);
+        customized = true;
     }
 
     public void setBinaryDataStrategy(final String binaryDataStrategy) {
         config.withBinaryDataStrategy(binaryDataStrategy);
+        customized = true;
     }
 
     public void setPropertyNamingStrategy(final String propertyNamingStrategy) 
{
         config.withPropertyNamingStrategy(propertyNamingStrategy);
+        customized = true;
     }
 
     public void setPropertyOrderStrategy(final String propertyOrderStrategy) {
         config.withPropertyOrderStrategy(propertyOrderStrategy);
+        customized = true;
     }
 
     public void setNullValues(final boolean nulls) {
         config.withNullValues(nulls);
+        customized = true;
     }
 
     public void setPretty(final boolean pretty) {
         config.withFormatting(pretty);
+        customized = true;
     }
 
     // actual impl
@@ -164,15 +171,65 @@ public class JsonbJaxrsProvider<T> implements 
MessageBodyWriter<T>, MessageBodyR
         getJsonb(type).toJson(t, entityStream);
     }
 
-    protected Jsonb getJsonb(Class<?> type) {
-        if (delegate.get() == null){
-            ContextResolver<Jsonb> contextResolver = 
providers.getContextResolver(Jsonb.class, MediaType.APPLICATION_JSON_TYPE);
-            if (contextResolver != null) {
-                delegate.compareAndSet(null, ()-> 
contextResolver.getContext(type));
-            } else {
-                delegate.compareAndSet(null, ()-> createJsonb());
+    protected Jsonb createJsonb() {
+        return JsonbBuilder.create(config);
+    }
+
+    protected Jsonb getJsonb(final Class<?> type) {
+        if (delegate == null){
+            synchronized (this) {
+                if (delegate == null) {
+                    final ContextResolver<Jsonb> contextResolver = 
providers.getContextResolver(Jsonb.class, MediaType.APPLICATION_JSON_TYPE);
+                    if (contextResolver != null) {
+                        if (customized) {
+                            
Logger.getLogger(JsonbJaxrsProvider.class.getName())
+                                  .warning("Customizations done on the Jsonb 
instance will be ignored because a ContextResolver<Jsonb> was found");
+                        }
+                        delegate = new DynamicInstance(contextResolver); // 
faster than contextResolver::getContext
+                    } else {
+                        delegate = new ProvidedInstance(createJsonb()); // 
don't recreate it
+                    }
+                }
             }
         }
-        return delegate.get().get();
+        return delegate.apply(type);
+    }
+
+    @Override
+    public synchronized void close() throws Exception {
+        if (AutoCloseable.class.isInstance(delegate)) {
+            AutoCloseable.class.cast(delegate).close();
+        }
+    }
+
+    private static final class DynamicInstance implements Function<Class<?>, 
Jsonb> {
+        private final ContextResolver<Jsonb> contextResolver;
+
+        private DynamicInstance(final ContextResolver<Jsonb> resolver) {
+            this.contextResolver = resolver;
+        }
+
+        @Override
+        public Jsonb apply(final Class<?> type) {
+            return contextResolver.getContext(type);
+        }
+    }
+
+    private static final class ProvidedInstance implements Function<Class<?>, 
Jsonb>, AutoCloseable {
+        private final Jsonb instance;
+
+        private ProvidedInstance(final Jsonb instance) {
+            this.instance = instance;
+        }
+
+        @Override
+        public Jsonb apply(final Class<?> aClass) {
+            return instance;
+        }
+
+        @Override
+        public void close() throws Exception {
+            instance.close();
+        }
     }
 }

Reply via email to