You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@johnzon.apache.org by rm...@apache.org on 2016/01/30 19:55:22 UTC

incubator-johnzon git commit: better CDI tracking of jsonb instances, can still need improvement for often created ones

Repository: incubator-johnzon
Updated Branches:
  refs/heads/master 093f095d2 -> 7c29e7868


better CDI tracking of jsonb instances, can still need improvement for often created ones


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

Branch: refs/heads/master
Commit: 7c29e78684843f808c785d94458a7a0356c7856e
Parents: 093f095
Author: Romain Manni-Bucau <rm...@gmail.org>
Authored: Sat Jan 30 19:55:05 2016 +0100
Committer: Romain Manni-Bucau <rm...@gmail.org>
Committed: Sat Jan 30 19:55:05 2016 +0100

----------------------------------------------------------------------
 .../apache/johnzon/jsonb/JohnzonBuilder.java    | 90 ++++++++++++++------
 .../java/org/apache/johnzon/jsonb/cdi/CDIs.java | 54 ++++++++++++
 .../johnzon/jsonb/cdi/JohnzonCdiExtension.java  | 75 ++++++++++++++++
 .../javax.enterprise.inject.spi.Extension       |  1 +
 4 files changed, 196 insertions(+), 24 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-johnzon/blob/7c29e786/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/JohnzonBuilder.java
----------------------------------------------------------------------
diff --git a/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/JohnzonBuilder.java b/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/JohnzonBuilder.java
index 587e5e8..c0d9c1f 100644
--- a/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/JohnzonBuilder.java
+++ b/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/JohnzonBuilder.java
@@ -20,11 +20,13 @@ package org.apache.johnzon.jsonb;
 
 import org.apache.johnzon.core.AbstractJsonFactory;
 import org.apache.johnzon.core.JsonGeneratorFactoryImpl;
+import org.apache.johnzon.jsonb.cdi.CDIs;
 import org.apache.johnzon.jsonb.converter.JohnzonJsonbAdapter;
 import org.apache.johnzon.jsonb.factory.SimpleJohnzonAdapterFactory;
 import org.apache.johnzon.jsonb.spi.JohnzonAdapterFactory;
 import org.apache.johnzon.mapper.Adapter;
 import org.apache.johnzon.mapper.Converter;
+import org.apache.johnzon.mapper.Mapper;
 import org.apache.johnzon.mapper.MapperBuilder;
 import org.apache.johnzon.mapper.internal.AdapterKey;
 import org.apache.johnzon.mapper.internal.ConverterAdapter;
@@ -75,9 +77,13 @@ import static javax.json.bind.config.PropertyNamingStrategy.IDENTITY;
 import static javax.json.bind.config.PropertyOrderStrategy.LEXICOGRAPHICAL;
 
 public class JohnzonBuilder implements JsonbBuilder {
+    private static final Object NO_BM = new Object();
+
     private final MapperBuilder builder = new MapperBuilder();
     private JsonProvider jsonp;
     private JsonbConfig config;
+    private Object beanManager;
+    private CDIs cdiIntegration;
 
     @Override
     public JsonbBuilder withConfig(final JsonbConfig config) {
@@ -155,30 +161,31 @@ public class JohnzonBuilder implements JsonbBuilder {
 
         final Map<AdapterKey, Adapter<?, ?>> defaultConverters = createJava8Converters(builder);
 
+        final JohnzonAdapterFactory factory = config.getProperty("johnzon.factory").map(val -> {
+            if (JohnzonAdapterFactory.class.isInstance(val)) {
+                return JohnzonAdapterFactory.class.cast(val);
+            }
+            if (String.class.isInstance(val)) {
+                try {
+                    return JohnzonAdapterFactory.class.cast(tccl().loadClass(val.toString()).newInstance());
+                } catch (final InstantiationException | ClassNotFoundException | IllegalAccessException e) {
+                    throw new IllegalArgumentException(e);
+                }
+            }
+            if (Class.class.isInstance(val)) {
+                try {
+                    return JohnzonAdapterFactory.class.cast(Class.class.cast(val).newInstance());
+                } catch (final InstantiationException | IllegalAccessException e) {
+                    throw new IllegalArgumentException(e);
+                }
+            }
+            throw new IllegalArgumentException("Unsupported factory: " + val);
+        }).orElseGet(this::findFactory);
         final JsonbAccessMode accessMode = new JsonbAccessMode(
             propertyNamingStrategy, orderValue, visibilityStrategy,
             !namingStrategyValue.orElse("").equals(PropertyNamingStrategy.CASE_INSENSITIVE),
             defaultConverters,
-            config.getProperty("johnzon.factory").map(val -> {
-                if (JohnzonAdapterFactory.class.isInstance(val)) {
-                    return JohnzonAdapterFactory.class.cast(val);
-                }
-                if (String.class.isInstance(val)) {
-                    try {
-                        return JohnzonAdapterFactory.class.cast(tccl().loadClass(val.toString()).newInstance());
-                    } catch (final InstantiationException | ClassNotFoundException | IllegalAccessException e) {
-                        throw new IllegalArgumentException(e);
-                    }
-                }
-                if (Class.class.isInstance(val)) {
-                    try {
-                        return JohnzonAdapterFactory.class.cast(Class.class.cast(val).newInstance());
-                    } catch (final InstantiationException | IllegalAccessException e) {
-                        throw new IllegalArgumentException(e);
-                    }
-                }
-                throw new IllegalArgumentException("Unsupported factory: " + val);
-            }).orElseGet(this::findFactory));
+            factory);
         builder.setAccessMode(accessMode);
 
 
@@ -224,14 +231,49 @@ public class JohnzonBuilder implements JsonbBuilder {
             }
         });
 
-        return new JohnsonJsonb(builder.addCloseable(accessMode).build());
+        getBeanManager(); // force detection
+
+        final boolean useCdi = cdiIntegration != null && cdiIntegration.isCanWrite();
+        final Mapper mapper = builder.addCloseable(accessMode).build();
+
+        return useCdi ? new JohnsonJsonb(mapper) {
+            {
+                cdiIntegration.track(this);
+            }
+
+            @Override
+            public void close() {
+                try {
+                    super.close();
+                } finally {
+                    if (cdiIntegration.isCanWrite()) {
+                        cdiIntegration.untrack(this);
+                    }
+                }
+            }
+        } : new JohnsonJsonb(mapper);
+    }
+
+    private Object getBeanManager() {
+        if (beanManager == null) {
+            try { // don't trigger CDI is not there
+                final Class<?> cdi = tccl().loadClass("javax.enterprise.inject.spi.CDI");
+                final Object cdiInstance = cdi.getMethod("current").invoke(null);
+                beanManager = cdi.getMethod("getBeanManager").invoke(cdiInstance);
+                cdiIntegration = new CDIs(beanManager);
+            } catch (final NoClassDefFoundError | Exception e) {
+                beanManager = NO_BM;
+            }
+        }
+        return beanManager;
     }
 
     private JohnzonAdapterFactory findFactory() {
+        if (getBeanManager() == NO_BM || config.getProperty("johnzon.skip-cdi")
+                .map(s -> "true".equalsIgnoreCase(String.valueOf(s))).orElse(false)) {
+            return new SimpleJohnzonAdapterFactory();
+        }
         try { // don't trigger CDI is not there
-            final Class<?> cdi = tccl().loadClass("javax.enterprise.inject.spi.CDI");
-            final Object cdiInstance = cdi.getMethod("current").invoke(null);
-            final Object beanManager = cdi.getMethod("getBeanManager").invoke(cdiInstance);
             return new org.apache.johnzon.jsonb.factory.CdiJohnzonAdapterFactory(beanManager);
         } catch (final NoClassDefFoundError | Exception e) {
             return new SimpleJohnzonAdapterFactory();

http://git-wip-us.apache.org/repos/asf/incubator-johnzon/blob/7c29e786/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/cdi/CDIs.java
----------------------------------------------------------------------
diff --git a/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/cdi/CDIs.java b/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/cdi/CDIs.java
new file mode 100644
index 0000000..50e2d5f
--- /dev/null
+++ b/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/cdi/CDIs.java
@@ -0,0 +1,54 @@
+/*
+ * 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.johnzon.jsonb.cdi;
+
+import org.apache.johnzon.jsonb.JohnsonJsonb;
+
+// helper class to lazy trigger CDI deps
+public final class CDIs {
+    private final JohnzonCdiExtension tracker;
+
+    public CDIs(final Object beanManager) {
+        this.tracker = Lazy.load(beanManager);
+    }
+
+    public void track(final JohnsonJsonb johnsonJsonb) {
+        tracker.track(johnsonJsonb);
+    }
+
+    public void untrack(final JohnsonJsonb johnsonJsonb) {
+        tracker.untrack(johnsonJsonb);
+    }
+
+    public boolean isCanWrite() {
+        return tracker.isCanWrite();
+    }
+
+    private static class Lazy {
+        private Lazy() {
+            // no-op
+        }
+
+        private static JohnzonCdiExtension load(final Object beanManager) {
+            final javax.enterprise.inject.spi.BeanManager bm = javax.enterprise.inject.spi.BeanManager.class.cast(beanManager);
+            return JohnzonCdiExtension.class.cast(
+                bm.getReference(bm.resolve(bm.getBeans(JohnzonCdiExtension.class)), JohnzonCdiExtension.class, null));
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-johnzon/blob/7c29e786/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/cdi/JohnzonCdiExtension.java
----------------------------------------------------------------------
diff --git a/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/cdi/JohnzonCdiExtension.java b/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/cdi/JohnzonCdiExtension.java
new file mode 100644
index 0000000..d925659
--- /dev/null
+++ b/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/cdi/JohnzonCdiExtension.java
@@ -0,0 +1,75 @@
+/*
+ * 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.johnzon.jsonb.cdi;
+
+import org.apache.johnzon.jsonb.JohnsonJsonb;
+
+import javax.enterprise.event.Observes;
+import javax.enterprise.inject.spi.BeforeBeanDiscovery;
+import javax.enterprise.inject.spi.BeforeShutdown;
+import javax.enterprise.inject.spi.Extension;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.concurrent.locks.ReentrantLock;
+
+public class JohnzonCdiExtension implements Extension {
+    private final Collection<JohnsonJsonb> jsonbs = new ArrayList<>();
+    private final ReentrantLock lock = new ReentrantLock();
+    private volatile boolean canWrite = false;
+
+    public boolean isCanWrite() {
+        return canWrite;
+    }
+
+    public void track(final JohnsonJsonb jsonb) {
+        if (!canWrite) {
+            throw new IllegalStateException("CDI context already shutdown");
+        }
+        lock.lock();
+        try {
+            jsonbs.add(jsonb);
+        } finally {
+            lock.unlock();
+        }
+    }
+
+    public void untrack(final JohnsonJsonb jsonb) {
+        synchronized (this) {
+            lock.lock();
+            try {
+                if (!jsonbs.remove(jsonb)) {
+                    return;
+                }
+            } finally {
+                lock.unlock();
+            }
+        }
+        jsonb.close();
+    }
+
+    void started(@Observes final BeforeBeanDiscovery beforeBeanDiscovery) {
+        canWrite = true;
+    }
+
+    void cleanUp(@Observes final BeforeShutdown beforeShutdown) {
+        canWrite = false;
+        jsonbs.forEach(this::untrack);
+        jsonbs.clear();
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-johnzon/blob/7c29e786/johnzon-jsonb/src/main/resources/META-INF/services/javax.enterprise.inject.spi.Extension
----------------------------------------------------------------------
diff --git a/johnzon-jsonb/src/main/resources/META-INF/services/javax.enterprise.inject.spi.Extension b/johnzon-jsonb/src/main/resources/META-INF/services/javax.enterprise.inject.spi.Extension
new file mode 100644
index 0000000..89497eb
--- /dev/null
+++ b/johnzon-jsonb/src/main/resources/META-INF/services/javax.enterprise.inject.spi.Extension
@@ -0,0 +1 @@
+org.apache.johnzon.jsonb.cdi.JohnzonCdiExtension