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/29 14:35:31 UTC
incubator-johnzon git commit: JOHNZON-64 CDI support for @JsonbAdapter
Repository: incubator-johnzon
Updated Branches:
refs/heads/master 6673b73c6 -> d271dec4e
JOHNZON-64 CDI support for @JsonbAdapter
Project: http://git-wip-us.apache.org/repos/asf/incubator-johnzon/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-johnzon/commit/d271dec4
Tree: http://git-wip-us.apache.org/repos/asf/incubator-johnzon/tree/d271dec4
Diff: http://git-wip-us.apache.org/repos/asf/incubator-johnzon/diff/d271dec4
Branch: refs/heads/master
Commit: d271dec4ea6ee7bb75805105291d217f1d2129dd
Parents: 6673b73
Author: Romain Manni-Bucau <rm...@gmail.org>
Authored: Fri Jan 29 14:35:22 2016 +0100
Committer: Romain Manni-Bucau <rm...@gmail.org>
Committed: Fri Jan 29 14:35:22 2016 +0100
----------------------------------------------------------------------
johnzon-jsonb/pom.xml | 24 +++++
.../org/apache/johnzon/jsonb/JohnsonJsonb.java | 7 +-
.../apache/johnzon/jsonb/JohnzonBuilder.java | 50 +++++++--
.../apache/johnzon/jsonb/JsonbAccessMode.java | 25 ++++-
.../jsonb/factory/CdiJohnzonAdapterFactory.java | 71 +++++++++++++
.../factory/SimpleJohnzonAdapterFactory.java | 32 ++++++
.../jsonb/spi/JohnzonAdapterFactory.java | 48 +++++++++
.../apache/johnzon/jsonb/CdiAdapterTest.java | 103 +++++++++++++++++++
.../java/org/apache/johnzon/mapper/Mapper.java | 27 ++++-
.../apache/johnzon/mapper/MapperBuilder.java | 12 ++-
10 files changed, 386 insertions(+), 13 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-johnzon/blob/d271dec4/johnzon-jsonb/pom.xml
----------------------------------------------------------------------
diff --git a/johnzon-jsonb/pom.xml b/johnzon-jsonb/pom.xml
index a9a0c26..df97066 100644
--- a/johnzon-jsonb/pom.xml
+++ b/johnzon-jsonb/pom.xml
@@ -43,6 +43,12 @@
<version>2.0</version>
<scope>provided</scope>
</dependency>
+ <dependency>
+ <groupId>org.apache.geronimo.specs</groupId>
+ <artifactId>geronimo-jcdi_1.1_spec</artifactId>
+ <version>1.0</version>
+ <scope>provided</scope>
+ </dependency>
<dependency>
<groupId>org.apache.johnzon</groupId>
@@ -74,5 +80,23 @@
<version>${cxf.version}</version>
<scope>test</scope>
</dependency>
+ <dependency>
+ <groupId>org.apache.geronimo.specs</groupId>
+ <artifactId>geronimo-interceptor_1.2_spec</artifactId>
+ <version>1.0</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.geronimo.specs</groupId>
+ <artifactId>geronimo-atinject_1.0_spec</artifactId>
+ <version>1.0</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.openwebbeans</groupId>
+ <artifactId>openwebbeans-impl</artifactId>
+ <version>1.6.2</version>
+ <scope>test</scope>
+ </dependency>
</dependencies>
</project>
http://git-wip-us.apache.org/repos/asf/incubator-johnzon/blob/d271dec4/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/JohnsonJsonb.java
----------------------------------------------------------------------
diff --git a/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/JohnsonJsonb.java b/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/JohnsonJsonb.java
index d77c423..7308374 100644
--- a/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/JohnsonJsonb.java
+++ b/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/JohnsonJsonb.java
@@ -39,7 +39,7 @@ import java.util.OptionalInt;
import java.util.OptionalLong;
// TODO: Optional handling for lists (and arrays)?
-public class JohnsonJsonb implements Jsonb {
+public class JohnsonJsonb implements Jsonb, AutoCloseable {
private final Mapper delegate;
public JohnsonJsonb(final Mapper build) {
@@ -360,4 +360,9 @@ public class JohnsonJsonb implements Jsonb {
final Type rawType = ParameterizedType.class.cast(runtimeType).getRawType();
return Class.class.isInstance(rawType) && Collection.class.isAssignableFrom(Class.class.cast(rawType));
}
+
+ @Override
+ public void close() {
+ delegate.close();
+ }
}
http://git-wip-us.apache.org/repos/asf/incubator-johnzon/blob/d271dec4/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 2ccee9f..a43f2cd 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
@@ -22,6 +22,8 @@ import org.apache.johnzon.core.AbstractJsonFactory;
import org.apache.johnzon.core.JsonGeneratorFactoryImpl;
import org.apache.johnzon.jsonb.converter.JsonbConverterFromString;
import org.apache.johnzon.jsonb.converter.JsonbConverterToString;
+import org.apache.johnzon.jsonb.factory.SimpleJohnzonAdapterFactory;
+import org.apache.johnzon.jsonb.spi.JohnzonAdapterFactory;
import org.apache.johnzon.mapper.Converter;
import org.apache.johnzon.mapper.MapperBuilder;
@@ -66,6 +68,7 @@ import java.util.concurrent.ConcurrentMap;
import java.util.stream.Stream;
import static java.util.Collections.emptyMap;
+import static java.util.Optional.ofNullable;
import static javax.json.bind.config.PropertyNamingStrategy.IDENTITY;
import static javax.json.bind.config.PropertyOrderStrategy.LEXICOGRAPHICAL;
@@ -151,11 +154,31 @@ public class JohnzonBuilder implements JsonbBuilder {
final Map<Class<?>, Converter<?>> defaultConverters = createJava8Converters();
defaultConverters.forEach(builder::addConverter);
- builder.setAccessMode(
- new JsonbAccessMode(
- propertyNamingStrategy, orderValue, visibilityStrategy,
- !namingStrategyValue.orElse("").equals(PropertyNamingStrategy.CASE_INSENSITIVE),
- defaultConverters));
+ 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));
+ builder.setAccessMode(accessMode);
// user adapters
@@ -201,7 +224,22 @@ public class JohnzonBuilder implements JsonbBuilder {
}
});
- return new JohnsonJsonb(builder.build());
+ return new JohnsonJsonb(builder.addCloseable(accessMode).build());
+ }
+
+ private JohnzonAdapterFactory findFactory() {
+ 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();
+ }
+ }
+
+ private ClassLoader tccl() {
+ return ofNullable(Thread.currentThread().getContextClassLoader()).orElseGet(ClassLoader::getSystemClassLoader);
}
private static Map<Class<?>, Converter<?>> createJava8Converters() { // TODO: move these converters in converter package
http://git-wip-us.apache.org/repos/asf/incubator-johnzon/blob/d271dec4/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/JsonbAccessMode.java
----------------------------------------------------------------------
diff --git a/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/JsonbAccessMode.java b/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/JsonbAccessMode.java
index f155e35..00ae9b0 100644
--- a/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/JsonbAccessMode.java
+++ b/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/JsonbAccessMode.java
@@ -26,6 +26,7 @@ import org.apache.johnzon.jsonb.converter.JsonbLocalDateTimeConverter;
import org.apache.johnzon.jsonb.converter.JsonbNumberConverter;
import org.apache.johnzon.jsonb.converter.JsonbValueConverter;
import org.apache.johnzon.jsonb.converter.JsonbZonedDateTimeConverter;
+import org.apache.johnzon.jsonb.spi.JohnzonAdapterFactory;
import org.apache.johnzon.mapper.Converter;
import org.apache.johnzon.mapper.access.AccessMode;
import org.apache.johnzon.mapper.access.FieldAccessMode;
@@ -46,6 +47,8 @@ import javax.json.bind.annotation.JsonbValue;
import javax.json.bind.config.PropertyNamingStrategy;
import javax.json.bind.config.PropertyOrderStrategy;
import javax.json.bind.config.PropertyVisibilityStrategy;
+import java.io.Closeable;
+import java.io.IOException;
import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
@@ -58,6 +61,7 @@ import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZonedDateTime;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
@@ -76,23 +80,26 @@ import static java.util.Arrays.asList;
import static java.util.Optional.ofNullable;
import static org.apache.johnzon.mapper.reflection.Converters.matches;
-public class JsonbAccessMode implements AccessMode {
+public class JsonbAccessMode implements AccessMode, Closeable {
private final PropertyNamingStrategy naming;
private final String order;
private final PropertyVisibilityStrategy visibility;
private final FieldAndMethodAccessMode delegate;
private final boolean caseSensitive;
private final Map<Class<?>, Converter<?>> defaultConverters;
+ private final JohnzonAdapterFactory factory;
+ private final Collection<JohnzonAdapterFactory.Instance<?>> toRelease = new ArrayList<>();
public JsonbAccessMode(final PropertyNamingStrategy propertyNamingStrategy, final String orderValue,
final PropertyVisibilityStrategy visibilityStrategy, final boolean caseSensitive,
- final Map<Class<?>, Converter<?>> defaultConverters) {
+ final Map<Class<?>, Converter<?>> defaultConverters, final JohnzonAdapterFactory factory) {
this.naming = propertyNamingStrategy;
this.order = orderValue;
this.visibility = visibilityStrategy;
this.caseSensitive = caseSensitive;
this.delegate = new FieldAndMethodAccessMode(true, true);
this.defaultConverters = defaultConverters;
+ this.factory = factory;
}
@Override
@@ -269,7 +276,9 @@ public class JsonbAccessMode implements AccessMode {
}
final Type[] args = pt.getActualTypeArguments();
final boolean fromString = args[0] == String.class;
- converter = fromString ? new JsonbConverterFromString<>(value.newInstance()) : new JsonbConverterToString<>(value.newInstance());
+ final JohnzonAdapterFactory.Instance<? extends JsonbAdapter> instance = newAdapter(value);
+ toRelease.add(instance);
+ converter = fromString ? new JsonbConverterFromString(instance.getValue()) : new JsonbConverterToString(instance.getValue());
} else if (dateFormat != null) { // TODO: support lists, LocalDate?
if (Date.class == type) {
converter = new JsonbDateConverter(dateFormat);
@@ -290,6 +299,10 @@ public class JsonbAccessMode implements AccessMode {
return converter;
}
+ private JohnzonAdapterFactory.Instance<? extends JsonbAdapter> newAdapter(final Class<? extends JsonbAdapter> value) {
+ return factory.create(value);
+ }
+
@Override
public Map<String, Reader> findReaders(final Class<?> clazz) {
final Map<String, Reader> readers = delegate.findReaders(clazz);
@@ -544,4 +557,10 @@ public class JsonbAccessMode implements AccessMode {
}
return keyComparator;
}
+
+ @Override
+ public void close() throws IOException {
+ toRelease.forEach(JohnzonAdapterFactory.Instance::release);
+ toRelease.clear();
+ }
}
http://git-wip-us.apache.org/repos/asf/incubator-johnzon/blob/d271dec4/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/factory/CdiJohnzonAdapterFactory.java
----------------------------------------------------------------------
diff --git a/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/factory/CdiJohnzonAdapterFactory.java b/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/factory/CdiJohnzonAdapterFactory.java
new file mode 100644
index 0000000..aa2c2b6
--- /dev/null
+++ b/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/factory/CdiJohnzonAdapterFactory.java
@@ -0,0 +1,71 @@
+/*
+ * 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.factory;
+
+import javax.enterprise.context.spi.CreationalContext;
+import javax.enterprise.inject.spi.Bean;
+import javax.enterprise.inject.spi.BeanManager;
+import java.util.Set;
+
+public class CdiJohnzonAdapterFactory extends SimpleJohnzonAdapterFactory {
+ private final BeanManager bm;
+
+ public CdiJohnzonAdapterFactory(final Object bm) {
+ this.bm = BeanManager.class.cast(bm);
+ }
+
+ @Override
+ public <T> Instance<T> create(final Class<T> type) {
+ try {
+ final Set<Bean<?>> beans = bm.getBeans(type);
+ final Bean<?> bean = bm.resolve(beans);
+ if (bean != null) {
+ final CreationalContext<Object> creationalContext = bm.createCreationalContext(null);
+ final T instance = (T) bm.getReference(bean, type, creationalContext);
+ if (bm.isNormalScope(bean.getScope())) {
+ return new ConstantInstance<>((T) bm.getReference(bean, type, creationalContext));
+ }
+ return new CdiInstance<T>(instance, creationalContext);
+ }
+ } catch (final Exception e) {
+ // fallback
+ }
+ return super.create(type);
+ }
+
+ private static class CdiInstance<T> implements Instance<T> {
+ private final T value;
+ private final CreationalContext<Object> context;
+
+ private CdiInstance(final T instance, final CreationalContext<Object> creationalContext) {
+ this.value = instance;
+ this.context = creationalContext;
+ }
+
+ @Override
+ public T getValue() {
+ return value;
+ }
+
+ @Override
+ public void release() {
+ context.release();
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-johnzon/blob/d271dec4/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/factory/SimpleJohnzonAdapterFactory.java
----------------------------------------------------------------------
diff --git a/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/factory/SimpleJohnzonAdapterFactory.java b/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/factory/SimpleJohnzonAdapterFactory.java
new file mode 100644
index 0000000..0f19476
--- /dev/null
+++ b/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/factory/SimpleJohnzonAdapterFactory.java
@@ -0,0 +1,32 @@
+/*
+ * 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.factory;
+
+import org.apache.johnzon.jsonb.spi.JohnzonAdapterFactory;
+
+public class SimpleJohnzonAdapterFactory implements JohnzonAdapterFactory {
+ @Override
+ public <T> Instance<T> create(Class<T> type) {
+ try {
+ return new ConstantInstance<>(type.newInstance());
+ } catch (final InstantiationException | IllegalAccessException e) {
+ throw new IllegalStateException(e);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-johnzon/blob/d271dec4/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/spi/JohnzonAdapterFactory.java
----------------------------------------------------------------------
diff --git a/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/spi/JohnzonAdapterFactory.java b/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/spi/JohnzonAdapterFactory.java
new file mode 100644
index 0000000..57ca6e6
--- /dev/null
+++ b/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/spi/JohnzonAdapterFactory.java
@@ -0,0 +1,48 @@
+/*
+ * 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.spi;
+
+import java.io.Serializable;
+
+public interface JohnzonAdapterFactory {
+ <T> Instance<T> create(final Class<T> type);
+
+ interface Instance<T> extends Serializable {
+ T getValue();
+ void release();
+ }
+
+ class ConstantInstance<T> implements Instance<T> {
+ private final T value;
+
+ public ConstantInstance(final T value) {
+ this.value = value;
+ }
+
+ @Override
+ public T getValue() {
+ return value;
+ }
+
+ @Override
+ public void release() {
+ // no-op
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-johnzon/blob/d271dec4/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/CdiAdapterTest.java
----------------------------------------------------------------------
diff --git a/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/CdiAdapterTest.java b/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/CdiAdapterTest.java
new file mode 100644
index 0000000..e966052
--- /dev/null
+++ b/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/CdiAdapterTest.java
@@ -0,0 +1,103 @@
+/*
+ * 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;
+
+import org.apache.webbeans.config.WebBeansContext;
+import org.apache.webbeans.config.WebBeansFinder;
+import org.apache.webbeans.lifecycle.test.OpenWebBeansTestLifeCycle;
+import org.apache.webbeans.lifecycle.test.OpenWebBeansTestMetaDataDiscoveryService;
+import org.apache.webbeans.proxy.OwbNormalScopeProxy;
+import org.apache.webbeans.util.WebBeansUtil;
+import org.junit.Test;
+
+import javax.enterprise.context.ApplicationScoped;
+import javax.inject.Inject;
+import javax.json.bind.Jsonb;
+import javax.json.bind.JsonbBuilder;
+import javax.json.bind.adapter.JsonbAdapter;
+import javax.json.bind.annotation.JsonbTypeAdapter;
+
+import static java.util.Arrays.asList;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+public class CdiAdapterTest {
+ @Test
+ public void run() {
+ WebBeansFinder.clearInstances(WebBeansUtil.getCurrentClassLoader());
+ final OpenWebBeansTestLifeCycle testLifecycle = new OpenWebBeansTestLifeCycle();
+ final WebBeansContext ctx = WebBeansContext.currentInstance();
+ final OpenWebBeansTestMetaDataDiscoveryService discoveryService = OpenWebBeansTestMetaDataDiscoveryService.class.cast(ctx.getScannerService());
+ discoveryService.deployClasses(asList(Service.class, ModelAdapter.class));
+ testLifecycle.startApplication(null);
+ try {
+ Jsonb jsonb = JsonbBuilder.create();
+ assertEquals("{\"model\":\"5\"}", jsonb.toJson(new Root(new Model(5))));
+ try {
+ AutoCloseable.class.cast(jsonb).close();
+ } catch (final Exception e) {
+ fail(e.getMessage());
+ }
+ } finally {
+ testLifecycle.stopApplication(null);
+ }
+ }
+
+ public static class Root {
+ @JsonbTypeAdapter(ModelAdapter.class)
+ public final Model model;
+
+ public Root(final Model model) {
+ this.model = model;
+ }
+ }
+
+ public static class Model {
+ private final int val;
+
+ public Model(final int i) {
+ val = i;
+ }
+ }
+
+ @ApplicationScoped
+ public static class Service {
+ public String toString(final Model model) {
+ return Integer.toString(model.val);
+ }
+ }
+
+ @ApplicationScoped
+ public static class ModelAdapter implements JsonbAdapter<String, Model> {
+ @Inject
+ private Service service;
+
+ @Override
+ public String adaptTo(final Model obj) throws Exception {
+ assertTrue(OwbNormalScopeProxy.class.isInstance(service)); // additional test
+ return service.toString(obj);
+ }
+
+ @Override
+ public Model adaptFrom(final String obj) throws Exception {
+ throw new UnsupportedOperationException();
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-johnzon/blob/d271dec4/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/Mapper.java
----------------------------------------------------------------------
diff --git a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/Mapper.java b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/Mapper.java
index ea83813..dbeab9a 100644
--- a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/Mapper.java
+++ b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/Mapper.java
@@ -37,6 +37,7 @@ import javax.json.JsonValue.ValueType;
import javax.json.stream.JsonGenerator;
import javax.json.stream.JsonGeneratorFactory;
import javax.xml.bind.DatatypeConverter;
+import java.io.Closeable;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
@@ -80,7 +81,7 @@ import java.util.concurrent.ConcurrentMap;
import static java.util.Arrays.asList;
-public class Mapper {
+public class Mapper implements Closeable {
private static final Converter<Object> FALLBACK_CONVERTER = new FallbackConverter();
private static final JohnzonParameterizedType ANY_LIST = new JohnzonParameterizedType(List.class, Object.class);
@@ -96,12 +97,14 @@ public class Mapper {
protected final boolean treatByteArrayAsBase64URL;
protected final Charset encoding;
protected final ReaderHandler readerHandler;
+ protected final Collection<Closeable> closeables;
// CHECKSTYLE:OFF
public Mapper(final JsonReaderFactory readerFactory, final JsonGeneratorFactory generatorFactory,
final boolean doClose, final Map<Type, Converter<?>> converters,
final int version, final Comparator<String> attributeOrder, final boolean skipNull, final boolean skipEmptyArray,
- final AccessMode accessMode, final boolean treatByteArrayAsBase64, final boolean treatByteArrayAsBase64URL, final Charset encoding) {
+ final AccessMode accessMode, final boolean treatByteArrayAsBase64, final boolean treatByteArrayAsBase64URL, final Charset encoding,
+ final Collection<Closeable> closeables) {
// CHECKSTYLE:ON
this.readerFactory = readerFactory;
this.generatorFactory = generatorFactory;
@@ -115,6 +118,7 @@ public class Mapper {
this.treatByteArrayAsBase64URL = treatByteArrayAsBase64URL;
this.encoding = encoding;
this.readerHandler = ReaderHandler.create(readerFactory);
+ this.closeables = closeables;
}
private static JsonGenerator writePrimitives(final JsonGenerator generator, final Object value) {
@@ -977,6 +981,25 @@ public class Mapper {
return array;
}
+ @Override
+ public synchronized void close() {
+ Collection<Exception> errors = null;
+ for (final Closeable c : closeables) {
+ try {
+ c.close();
+ } catch (final IOException e) {
+ if (errors == null) {
+ errors = new ArrayList<Exception>();
+ }
+ errors.add(e);
+ }
+ }
+ closeables.clear();
+ if (errors != null) {
+ throw new IllegalStateException(errors.toString());
+ }
+ }
+
private static class FallbackConverter implements Converter<Object> {
@Override
public String toString(final Object instance) {
http://git-wip-us.apache.org/repos/asf/incubator-johnzon/blob/d271dec4/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/MapperBuilder.java
----------------------------------------------------------------------
diff --git a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/MapperBuilder.java b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/MapperBuilder.java
index 369c162..64a09ff 100644
--- a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/MapperBuilder.java
+++ b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/MapperBuilder.java
@@ -44,12 +44,15 @@ import javax.json.JsonReaderFactory;
import javax.json.spi.JsonProvider;
import javax.json.stream.JsonGenerator;
import javax.json.stream.JsonGeneratorFactory;
+import java.io.Closeable;
import java.lang.reflect.Type;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.net.URI;
import java.net.URL;
import java.nio.charset.Charset;
+import java.util.ArrayList;
+import java.util.Collection;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
@@ -106,6 +109,7 @@ public class MapperBuilder {
private Charset encoding = Charset.forName(System.getProperty("johnzon.mapper.encoding", "UTF-8"));
private boolean useGetterForCollections;
private String accessModeName;
+ private final Collection<Closeable> closeables = new ArrayList<Closeable>();
public Mapper build() {
if (readerFactory == null || generatorFactory == null) {
@@ -160,7 +164,13 @@ public class MapperBuilder {
skipNull, skipEmptyArray,
accessMode,
treatByteArrayAsBase64, treatByteArrayAsBase64URL,
- encoding);
+ encoding,
+ closeables);
+ }
+
+ public MapperBuilder addCloseable(final Closeable closeable) {
+ closeables.add(closeable);
+ return this;
}
public MapperBuilder setIgnoreFieldsForType(final Class<?> type, final String... fields) {