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 2021/04/22 08:08:21 UTC
[johnzon] branch master updated: [JOHNZON-340] add JSON-B support
in websocket module
This is an automated email from the ASF dual-hosted git repository.
rmannibucau pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/johnzon.git
The following commit(s) were added to refs/heads/master by this push:
new 73eb0fb [JOHNZON-340] add JSON-B support in websocket module
73eb0fb is described below
commit 73eb0fbaac15d837432ca6f6531c5e811ef918b1
Author: Romain Manni-Bucau <rm...@gmail.com>
AuthorDate: Thu Apr 22 10:08:15 2021 +0200
[JOHNZON-340] add JSON-B support in websocket module
---
johnzon-websocket/pom.xml | 14 ++++
.../TypeAwareDecoder.java} | 43 ++---------
.../lazy/LazySupplier.java} | 38 +++++-----
.../websocket/internal/mapper/MapperLocator.java | 42 ++---------
.../internal/mapper/MapperLocatorDelegate.java | 86 ++++++++++++++++++++++
.../servlet/IgnoreIfMissing.java} | 37 +++++-----
.../JsonbLocator.java} | 31 ++------
.../websocket/jsonb/JsonbLocatorDelegate.java | 83 +++++++++++++++++++++
.../johnzon/websocket/jsonb/JsonbTextDecoder.java | 70 ++++++++++++++++++
.../JsonbTextEncoder.java} | 24 +++---
.../websocket/mapper/JohnzonTextDecoder.java | 10 +--
.../websocket/mapper/JohnzonTextEncoder.java | 6 +-
.../apache/johnzon/websocket/MapperCodecTest.java | 4 +-
src/site/markdown/index.md | 17 +++++
14 files changed, 354 insertions(+), 151 deletions(-)
diff --git a/johnzon-websocket/pom.xml b/johnzon-websocket/pom.xml
index c73c2f1..7568633 100644
--- a/johnzon-websocket/pom.xml
+++ b/johnzon-websocket/pom.xml
@@ -49,9 +49,23 @@
</dependency>
<dependency>
+ <groupId>org.apache.geronimo.specs</groupId>
+ <artifactId>geronimo-jsonb_1.0_spec</artifactId>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
<groupId>org.apache.johnzon</groupId>
<artifactId>johnzon-mapper</artifactId>
<version>${project.version}</version>
+ <scope>provided</scope>
+ <optional>true</optional>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.johnzon</groupId>
+ <artifactId>johnzon-jsonb</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
</dependency>
<dependency>
diff --git a/johnzon-websocket/src/main/java/org/apache/johnzon/websocket/mapper/JohnzonTextDecoder.java b/johnzon-websocket/src/main/java/org/apache/johnzon/websocket/internal/TypeAwareDecoder.java
similarity index 74%
copy from johnzon-websocket/src/main/java/org/apache/johnzon/websocket/mapper/JohnzonTextDecoder.java
copy to johnzon-websocket/src/main/java/org/apache/johnzon/websocket/internal/TypeAwareDecoder.java
index 4530966..0e92215 100644
--- a/johnzon-websocket/src/main/java/org/apache/johnzon/websocket/mapper/JohnzonTextDecoder.java
+++ b/johnzon-websocket/src/main/java/org/apache/johnzon/websocket/internal/TypeAwareDecoder.java
@@ -16,51 +16,29 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.johnzon.websocket.mapper;
+package org.apache.johnzon.websocket.internal;
-import org.apache.johnzon.mapper.Mapper;
-import org.apache.johnzon.websocket.internal.mapper.MapperLocator;
-
-import java.io.Reader;
-import java.lang.annotation.Annotation;
-import java.lang.reflect.Method;
-import java.lang.reflect.Type;
-import javax.websocket.DecodeException;
-import javax.websocket.Decoder;
import javax.websocket.EndpointConfig;
import javax.websocket.OnMessage;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpointConfig;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Method;
+import java.lang.reflect.Type;
-public class JohnzonTextDecoder implements Decoder.TextStream<Object> {
- protected Mapper mapper;
+public abstract class TypeAwareDecoder {
protected Type type;
- public JohnzonTextDecoder() {
+ public TypeAwareDecoder() {
// no-op
}
- // for client side no way to guess the type so let the user provide it easily
- public JohnzonTextDecoder(final Type type) {
- this(null, type);
- }
-
- public JohnzonTextDecoder(final Mapper mapper, final Type type) {
- this.mapper = mapper;
+ public TypeAwareDecoder(final Type type) {
this.type = type;
}
- @Override
- public Object decode(final Reader stream) throws DecodeException {
- return mapper.readObject(stream, type);
- }
-
- @Override
- public void init(final EndpointConfig endpointConfig) {
- if (mapper == null) {
- mapper = MapperLocator.locate();
- }
+ protected void init(final EndpointConfig endpointConfig) {
if (type != null) {
return;
}
@@ -102,9 +80,4 @@ public class JohnzonTextDecoder implements Decoder.TextStream<Object> {
}
}
}
-
- @Override
- public void destroy() {
- // no-op
- }
}
diff --git a/johnzon-websocket/src/main/java/org/apache/johnzon/websocket/mapper/JohnzonTextEncoder.java b/johnzon-websocket/src/main/java/org/apache/johnzon/websocket/internal/lazy/LazySupplier.java
similarity index 53%
copy from johnzon-websocket/src/main/java/org/apache/johnzon/websocket/mapper/JohnzonTextEncoder.java
copy to johnzon-websocket/src/main/java/org/apache/johnzon/websocket/internal/lazy/LazySupplier.java
index 964c3b5..e8c95e7 100644
--- a/johnzon-websocket/src/main/java/org/apache/johnzon/websocket/mapper/JohnzonTextEncoder.java
+++ b/johnzon-websocket/src/main/java/org/apache/johnzon/websocket/internal/lazy/LazySupplier.java
@@ -16,32 +16,32 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.johnzon.websocket.mapper;
+package org.apache.johnzon.websocket.internal.lazy;
-import org.apache.johnzon.mapper.Mapper;
-import org.apache.johnzon.websocket.internal.mapper.MapperLocator;
+import java.util.function.Supplier;
-import java.io.IOException;
-import java.io.Writer;
-import javax.websocket.EncodeException;
-import javax.websocket.Encoder;
-import javax.websocket.EndpointConfig;
+public class LazySupplier<T> implements Supplier<T> {
+ private Supplier<T> delegate;
+ private volatile T instance;
-public class JohnzonTextEncoder implements Encoder.TextStream<Object> {
- private Mapper mapper;
-
- @Override
- public void init(final EndpointConfig endpointConfig) {
- mapper = MapperLocator.locate();
+ public LazySupplier(final Supplier<T> provider) {
+ this.delegate = provider;
}
@Override
- public void destroy() {
- // no-op
+ public T get() {
+ if (instance == null) {
+ synchronized (this) {
+ if (instance == null) {
+ instance = delegate.get();
+ delegate = null;
+ }
+ }
+ }
+ return instance;
}
- @Override
- public void encode(final Object object, final Writer writer) throws EncodeException, IOException {
- mapper.writeObject(object, writer);
+ public T getInstance() {
+ return instance;
}
}
diff --git a/johnzon-websocket/src/main/java/org/apache/johnzon/websocket/internal/mapper/MapperLocator.java b/johnzon-websocket/src/main/java/org/apache/johnzon/websocket/internal/mapper/MapperLocator.java
index 9145694..6596437 100644
--- a/johnzon-websocket/src/main/java/org/apache/johnzon/websocket/internal/mapper/MapperLocator.java
+++ b/johnzon-websocket/src/main/java/org/apache/johnzon/websocket/internal/mapper/MapperLocator.java
@@ -18,45 +18,17 @@
*/
package org.apache.johnzon.websocket.internal.mapper;
-import org.apache.johnzon.mapper.Mapper;
-import org.apache.johnzon.mapper.MapperBuilder;
+import org.apache.johnzon.websocket.internal.servlet.IgnoreIfMissing;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-import javax.servlet.ServletContextEvent;
-import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;
-@WebListener
-public class MapperLocator implements ServletContextListener {
- private static final Map<ClassLoader, Mapper> MAPPER_BY_LOADER = new ConcurrentHashMap<ClassLoader, Mapper>();
- private static final String ATTRIBUTE = MapperLocator.class.getName() + ".mapper";
-
- @Override
- public void contextInitialized(final ServletContextEvent servletContextEvent) {
- final Mapper build = newMapper();
- MAPPER_BY_LOADER.put(servletContextEvent.getServletContext().getClassLoader(), build);
- servletContextEvent.getServletContext().setAttribute(ATTRIBUTE, build);
- }
-
- @Override
- public void contextDestroyed(final ServletContextEvent servletContextEvent) {
- MAPPER_BY_LOADER.remove(servletContextEvent.getServletContext().getClassLoader());
- }
-
- public static Mapper locate() {
- ClassLoader loader = Thread.currentThread().getContextClassLoader();
- if (loader == null) {
- loader = MapperLocator.class.getClassLoader();
- }
- final Mapper mapper = MAPPER_BY_LOADER.get(loader);
- if (mapper == null) {
- return newMapper();
- }
- return mapper;
+@WebListener // since people move to json-b we make this init lazy
+public class MapperLocator extends IgnoreIfMissing {
+ public MapperLocator() {
+ super(() -> new MapperLocatorDelegate());
}
- private static Mapper newMapper() {
- return new MapperBuilder().build();
+ public static Object locate() {
+ return MapperLocatorDelegate.locate();
}
}
diff --git a/johnzon-websocket/src/main/java/org/apache/johnzon/websocket/internal/mapper/MapperLocatorDelegate.java b/johnzon-websocket/src/main/java/org/apache/johnzon/websocket/internal/mapper/MapperLocatorDelegate.java
new file mode 100644
index 0000000..48fc30d
--- /dev/null
+++ b/johnzon-websocket/src/main/java/org/apache/johnzon/websocket/internal/mapper/MapperLocatorDelegate.java
@@ -0,0 +1,86 @@
+/*
+ * 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.websocket.internal.mapper;
+
+import org.apache.johnzon.mapper.Mapper;
+import org.apache.johnzon.mapper.MapperBuilder;
+import org.apache.johnzon.websocket.internal.lazy.LazySupplier;
+
+import javax.servlet.ServletContext;
+import javax.servlet.ServletContextEvent;
+import javax.servlet.ServletContextListener;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.function.Supplier;
+
+import static java.util.Optional.ofNullable;
+
+public class MapperLocatorDelegate implements ServletContextListener {
+ private static final Map<ClassLoader, Supplier<Mapper>> MAPPER_BY_LOADER = new ConcurrentHashMap<ClassLoader, Supplier<Mapper>>();
+ private static final String ATTRIBUTE = MapperLocator.class.getName() + ".mapper";
+
+ @Override
+ public void contextInitialized(final ServletContextEvent servletContextEvent) {
+ final ServletContext servletContext = servletContextEvent.getServletContext();
+ final Supplier<Mapper> supplier = ofNullable(servletContext.getAttribute(ATTRIBUTE))
+ .map(it -> (Supplier<Mapper>) it)
+ .orElseGet(() -> {
+ final LazySupplier<Mapper> lazySupplier = new LazySupplier<>(MapperLocatorDelegate::newMapper);
+ servletContext.setAttribute(ATTRIBUTE, lazySupplier);
+ return lazySupplier;
+ });
+ MAPPER_BY_LOADER.put(servletContext.getClassLoader(), supplier);
+ }
+
+ @Override
+ public void contextDestroyed(final ServletContextEvent servletContextEvent) {
+ final Supplier<Mapper> supplier = MAPPER_BY_LOADER.remove(servletContextEvent.getServletContext().getClassLoader());
+ if (LazySupplier.class.isInstance(supplier)) {
+ final Object mapper = LazySupplier.class.cast(supplier).getInstance();
+ if (mapper != null) {
+ Mapper.class.cast(mapper).close();
+ }
+ }
+ }
+
+ public static Mapper locate() {
+ ClassLoader loader = Thread.currentThread().getContextClassLoader();
+ if (loader == null) {
+ loader = MapperLocatorDelegate.class.getClassLoader();
+ }
+ Supplier<Mapper> mapper = MAPPER_BY_LOADER.get(loader);
+ if (mapper == null) {
+ synchronized (MAPPER_BY_LOADER) {
+ mapper = MAPPER_BY_LOADER.get(loader);
+ if (mapper != null) {
+ return mapper.get();
+ }
+ final Mapper instance = newMapper();
+ mapper = () -> instance;
+ MAPPER_BY_LOADER.put(loader, mapper);
+ return mapper.get();
+ }
+ }
+ return mapper.get();
+ }
+
+ private static Mapper newMapper() {
+ return new MapperBuilder().build();
+ }
+}
diff --git a/johnzon-websocket/src/main/java/org/apache/johnzon/websocket/mapper/JohnzonTextEncoder.java b/johnzon-websocket/src/main/java/org/apache/johnzon/websocket/internal/servlet/IgnoreIfMissing.java
similarity index 51%
copy from johnzon-websocket/src/main/java/org/apache/johnzon/websocket/mapper/JohnzonTextEncoder.java
copy to johnzon-websocket/src/main/java/org/apache/johnzon/websocket/internal/servlet/IgnoreIfMissing.java
index 964c3b5..f91344e 100644
--- a/johnzon-websocket/src/main/java/org/apache/johnzon/websocket/mapper/JohnzonTextEncoder.java
+++ b/johnzon-websocket/src/main/java/org/apache/johnzon/websocket/internal/servlet/IgnoreIfMissing.java
@@ -16,32 +16,33 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.johnzon.websocket.mapper;
+package org.apache.johnzon.websocket.internal.servlet;
-import org.apache.johnzon.mapper.Mapper;
-import org.apache.johnzon.websocket.internal.mapper.MapperLocator;
+import javax.servlet.ServletContextEvent;
+import javax.servlet.ServletContextListener;
+import java.util.function.Supplier;
-import java.io.IOException;
-import java.io.Writer;
-import javax.websocket.EncodeException;
-import javax.websocket.Encoder;
-import javax.websocket.EndpointConfig;
+public class IgnoreIfMissing implements ServletContextListener {
+ private final Supplier<ServletContextListener> delegate;
+ private boolean skipped;
-public class JohnzonTextEncoder implements Encoder.TextStream<Object> {
- private Mapper mapper;
-
- @Override
- public void init(final EndpointConfig endpointConfig) {
- mapper = MapperLocator.locate();
+ public IgnoreIfMissing(final Supplier<ServletContextListener> delegate) {
+ this.delegate = delegate;
}
@Override
- public void destroy() {
- // no-op
+ public void contextInitialized(final ServletContextEvent sce) {
+ try {
+ delegate.get().contextInitialized(sce);
+ } catch (final Error | RuntimeException re) {
+ skipped = true;
+ }
}
@Override
- public void encode(final Object object, final Writer writer) throws EncodeException, IOException {
- mapper.writeObject(object, writer);
+ public void contextDestroyed(final ServletContextEvent sce) {
+ if (!skipped) {
+ delegate.get().contextDestroyed(sce);
+ }
}
}
diff --git a/johnzon-websocket/src/main/java/org/apache/johnzon/websocket/mapper/JohnzonTextEncoder.java b/johnzon-websocket/src/main/java/org/apache/johnzon/websocket/jsonb/JsonbLocator.java
similarity index 51%
copy from johnzon-websocket/src/main/java/org/apache/johnzon/websocket/mapper/JohnzonTextEncoder.java
copy to johnzon-websocket/src/main/java/org/apache/johnzon/websocket/jsonb/JsonbLocator.java
index 964c3b5..d84490d 100644
--- a/johnzon-websocket/src/main/java/org/apache/johnzon/websocket/mapper/JohnzonTextEncoder.java
+++ b/johnzon-websocket/src/main/java/org/apache/johnzon/websocket/jsonb/JsonbLocator.java
@@ -16,32 +16,15 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.johnzon.websocket.mapper;
+package org.apache.johnzon.websocket.jsonb;
-import org.apache.johnzon.mapper.Mapper;
-import org.apache.johnzon.websocket.internal.mapper.MapperLocator;
+import org.apache.johnzon.websocket.internal.servlet.IgnoreIfMissing;
-import java.io.IOException;
-import java.io.Writer;
-import javax.websocket.EncodeException;
-import javax.websocket.Encoder;
-import javax.websocket.EndpointConfig;
+import javax.servlet.annotation.WebListener;
-public class JohnzonTextEncoder implements Encoder.TextStream<Object> {
- private Mapper mapper;
-
- @Override
- public void init(final EndpointConfig endpointConfig) {
- mapper = MapperLocator.locate();
- }
-
- @Override
- public void destroy() {
- // no-op
- }
-
- @Override
- public void encode(final Object object, final Writer writer) throws EncodeException, IOException {
- mapper.writeObject(object, writer);
+@WebListener
+public class JsonbLocator extends IgnoreIfMissing {
+ public JsonbLocator() {
+ super(() -> new JsonbLocatorDelegate());
}
}
diff --git a/johnzon-websocket/src/main/java/org/apache/johnzon/websocket/jsonb/JsonbLocatorDelegate.java b/johnzon-websocket/src/main/java/org/apache/johnzon/websocket/jsonb/JsonbLocatorDelegate.java
new file mode 100644
index 0000000..3e1032a
--- /dev/null
+++ b/johnzon-websocket/src/main/java/org/apache/johnzon/websocket/jsonb/JsonbLocatorDelegate.java
@@ -0,0 +1,83 @@
+/*
+ * 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.websocket.jsonb;
+
+import javax.json.bind.Jsonb;
+import javax.json.bind.JsonbBuilder;
+import javax.servlet.ServletContext;
+import javax.servlet.ServletContextEvent;
+import javax.servlet.ServletContextListener;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+import static java.util.Optional.ofNullable;
+
+public class JsonbLocatorDelegate implements ServletContextListener {
+ private static final Map<ClassLoader, Jsonb> BY_LOADER = new ConcurrentHashMap<>();
+ private static final String ATTRIBUTE = JsonbLocator.class.getName() + ".jsonb";
+
+ @Override
+ public void contextInitialized(final ServletContextEvent servletContextEvent) {
+ final ServletContext servletContext = servletContextEvent.getServletContext();
+ final Jsonb instance = ofNullable(servletContext.getAttribute(ATTRIBUTE))
+ .map(Jsonb.class::cast)
+ .orElseGet(() -> {
+ final Jsonb jsonb = newInstance();
+ servletContext.setAttribute(ATTRIBUTE, jsonb);
+ return jsonb;
+ });
+ BY_LOADER.put(servletContext.getClassLoader(), instance);
+ }
+
+ @Override
+ public void contextDestroyed(final ServletContextEvent servletContextEvent) {
+ final Jsonb instance = BY_LOADER.remove(servletContextEvent.getServletContext().getClassLoader());
+ if (instance != null) {
+ try {
+ instance.close();
+ } catch (final Exception e) {
+ throw new IllegalStateException(e.getMessage(), e);
+ }
+ }
+ }
+
+ public static Jsonb locate() {
+ ClassLoader loader = Thread.currentThread().getContextClassLoader();
+ if (loader == null) {
+ loader = JsonbLocatorDelegate.class.getClassLoader();
+ }
+ Jsonb jsonb = BY_LOADER.get(loader);
+ if (jsonb == null) {
+ synchronized (BY_LOADER) {
+ jsonb = BY_LOADER.get(loader);
+ if (jsonb != null) {
+ return jsonb;
+ }
+ jsonb = newInstance();
+ BY_LOADER.put(loader, jsonb);
+ return jsonb;
+ }
+ }
+ return jsonb;
+ }
+
+ private static Jsonb newInstance() {
+ return JsonbBuilder.create();
+ }
+}
diff --git a/johnzon-websocket/src/main/java/org/apache/johnzon/websocket/jsonb/JsonbTextDecoder.java b/johnzon-websocket/src/main/java/org/apache/johnzon/websocket/jsonb/JsonbTextDecoder.java
new file mode 100644
index 0000000..c010e89
--- /dev/null
+++ b/johnzon-websocket/src/main/java/org/apache/johnzon/websocket/jsonb/JsonbTextDecoder.java
@@ -0,0 +1,70 @@
+/*
+ * 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.websocket.jsonb;
+
+import org.apache.johnzon.websocket.internal.TypeAwareDecoder;
+
+import javax.json.bind.Jsonb;
+import javax.json.bind.JsonbException;
+import javax.websocket.DecodeException;
+import javax.websocket.Decoder;
+import javax.websocket.EndpointConfig;
+import java.io.Reader;
+import java.lang.reflect.Type;
+
+public class JsonbTextDecoder extends TypeAwareDecoder implements Decoder.TextStream<Object> {
+ protected Jsonb mapper;
+ protected Type type;
+
+ public JsonbTextDecoder() {
+ // no-op
+ }
+
+ // for client side no way to guess the type so let the user provide it easily
+ public JsonbTextDecoder(final Type type) {
+ this(null, type);
+ }
+
+ public JsonbTextDecoder(final Jsonb jsonb, final Type type) {
+ super(type);
+ this.mapper = jsonb;
+ }
+
+ @Override
+ public Object decode(final Reader stream) throws DecodeException {
+ try {
+ return mapper.fromJson(stream, type);
+ } catch (final JsonbException je) {
+ throw new DecodeException("", je.getMessage(), je);
+ }
+ }
+
+ @Override
+ public void init(final EndpointConfig endpointConfig) {
+ if (mapper == null) {
+ mapper = JsonbLocatorDelegate.locate();
+ }
+ super.init(endpointConfig);
+ }
+
+ @Override
+ public void destroy() {
+ // no-op
+ }
+}
diff --git a/johnzon-websocket/src/main/java/org/apache/johnzon/websocket/mapper/JohnzonTextEncoder.java b/johnzon-websocket/src/main/java/org/apache/johnzon/websocket/jsonb/JsonbTextEncoder.java
similarity index 71%
copy from johnzon-websocket/src/main/java/org/apache/johnzon/websocket/mapper/JohnzonTextEncoder.java
copy to johnzon-websocket/src/main/java/org/apache/johnzon/websocket/jsonb/JsonbTextEncoder.java
index 964c3b5..bf1873c 100644
--- a/johnzon-websocket/src/main/java/org/apache/johnzon/websocket/mapper/JohnzonTextEncoder.java
+++ b/johnzon-websocket/src/main/java/org/apache/johnzon/websocket/jsonb/JsonbTextEncoder.java
@@ -16,23 +16,21 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.johnzon.websocket.mapper;
+package org.apache.johnzon.websocket.jsonb;
-import org.apache.johnzon.mapper.Mapper;
-import org.apache.johnzon.websocket.internal.mapper.MapperLocator;
-
-import java.io.IOException;
-import java.io.Writer;
+import javax.json.bind.Jsonb;
+import javax.json.bind.JsonbException;
import javax.websocket.EncodeException;
import javax.websocket.Encoder;
import javax.websocket.EndpointConfig;
+import java.io.Writer;
-public class JohnzonTextEncoder implements Encoder.TextStream<Object> {
- private Mapper mapper;
+public class JsonbTextEncoder implements Encoder.TextStream<Object> {
+ private Jsonb jsonb;
@Override
public void init(final EndpointConfig endpointConfig) {
- mapper = MapperLocator.locate();
+ jsonb = JsonbLocatorDelegate.locate();
}
@Override
@@ -41,7 +39,11 @@ public class JohnzonTextEncoder implements Encoder.TextStream<Object> {
}
@Override
- public void encode(final Object object, final Writer writer) throws EncodeException, IOException {
- mapper.writeObject(object, writer);
+ public void encode(final Object object, final Writer writer) throws EncodeException {
+ try {
+ jsonb.toJson(object, writer);
+ } catch (final JsonbException je) {
+ throw new EncodeException(object, je.getMessage(), je);
+ }
}
}
diff --git a/johnzon-websocket/src/main/java/org/apache/johnzon/websocket/mapper/JohnzonTextDecoder.java b/johnzon-websocket/src/main/java/org/apache/johnzon/websocket/mapper/JohnzonTextDecoder.java
index 4530966..60c27fa 100644
--- a/johnzon-websocket/src/main/java/org/apache/johnzon/websocket/mapper/JohnzonTextDecoder.java
+++ b/johnzon-websocket/src/main/java/org/apache/johnzon/websocket/mapper/JohnzonTextDecoder.java
@@ -21,10 +21,6 @@ package org.apache.johnzon.websocket.mapper;
import org.apache.johnzon.mapper.Mapper;
import org.apache.johnzon.websocket.internal.mapper.MapperLocator;
-import java.io.Reader;
-import java.lang.annotation.Annotation;
-import java.lang.reflect.Method;
-import java.lang.reflect.Type;
import javax.websocket.DecodeException;
import javax.websocket.Decoder;
import javax.websocket.EndpointConfig;
@@ -32,6 +28,10 @@ import javax.websocket.OnMessage;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpointConfig;
+import java.io.Reader;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Method;
+import java.lang.reflect.Type;
public class JohnzonTextDecoder implements Decoder.TextStream<Object> {
protected Mapper mapper;
@@ -59,7 +59,7 @@ public class JohnzonTextDecoder implements Decoder.TextStream<Object> {
@Override
public void init(final EndpointConfig endpointConfig) {
if (mapper == null) {
- mapper = MapperLocator.locate();
+ mapper = Mapper.class.cast(MapperLocator.locate());
}
if (type != null) {
return;
diff --git a/johnzon-websocket/src/main/java/org/apache/johnzon/websocket/mapper/JohnzonTextEncoder.java b/johnzon-websocket/src/main/java/org/apache/johnzon/websocket/mapper/JohnzonTextEncoder.java
index 964c3b5..015daa9 100644
--- a/johnzon-websocket/src/main/java/org/apache/johnzon/websocket/mapper/JohnzonTextEncoder.java
+++ b/johnzon-websocket/src/main/java/org/apache/johnzon/websocket/mapper/JohnzonTextEncoder.java
@@ -21,18 +21,18 @@ package org.apache.johnzon.websocket.mapper;
import org.apache.johnzon.mapper.Mapper;
import org.apache.johnzon.websocket.internal.mapper.MapperLocator;
-import java.io.IOException;
-import java.io.Writer;
import javax.websocket.EncodeException;
import javax.websocket.Encoder;
import javax.websocket.EndpointConfig;
+import java.io.IOException;
+import java.io.Writer;
public class JohnzonTextEncoder implements Encoder.TextStream<Object> {
private Mapper mapper;
@Override
public void init(final EndpointConfig endpointConfig) {
- mapper = MapperLocator.locate();
+ mapper = Mapper.class.cast(MapperLocator.locate());
}
@Override
diff --git a/johnzon-websocket/src/test/java/org/apache/johnzon/websocket/MapperCodecTest.java b/johnzon-websocket/src/test/java/org/apache/johnzon/websocket/MapperCodecTest.java
index 9b2770c..2dcc209 100644
--- a/johnzon-websocket/src/test/java/org/apache/johnzon/websocket/MapperCodecTest.java
+++ b/johnzon-websocket/src/test/java/org/apache/johnzon/websocket/MapperCodecTest.java
@@ -26,6 +26,8 @@ import org.apache.johnzon.websocket.endpoint.Message;
import org.apache.johnzon.websocket.endpoint.ServerEndpointImpl;
import org.apache.johnzon.websocket.endpoint.ServerReport;
import org.apache.johnzon.websocket.internal.mapper.MapperLocator;
+import org.apache.johnzon.websocket.internal.mapper.MapperLocatorDelegate;
+import org.apache.johnzon.websocket.internal.servlet.IgnoreIfMissing;
import org.apache.johnzon.websocket.mapper.JohnzonTextDecoder;
import org.apache.johnzon.websocket.mapper.JohnzonTextEncoder;
import org.apache.openejb.arquillian.common.IO;
@@ -58,7 +60,7 @@ public class MapperCodecTest {
.addClasses(ServerEndpointImpl.class, ServerReport.class, Message.class)
.addAsLibrary(
ShrinkWrap.create(JavaArchive.class, "johnzon-websocket.jar")
- .addClasses(MapperLocator.class, JohnzonTextDecoder.class, JohnzonTextEncoder.class)
+ .addClasses(MapperLocator.class, MapperLocatorDelegate.class, IgnoreIfMissing.class, JohnzonTextDecoder.class, JohnzonTextEncoder.class)
.addPackages(true, JsonProviderImpl.class.getPackage())
.addPackages(true, Mapper.class.getPackage()))
.addAsLibrary(jarLocation(Json.class));
diff --git a/src/site/markdown/index.md b/src/site/markdown/index.md
index 867cec7..f97517b 100644
--- a/src/site/markdown/index.md
+++ b/src/site/markdown/index.md
@@ -391,6 +391,13 @@ Integration is at codec level (encoder/decoder). There are two families of codec
* The ones based on JSON-P (JsonObject, JsonArray, JsonStructure)
* The ones based on Johnzon Mapper
+Note that if you want to control the Mapper or JSON-B instance used by decoders you can set up the associated servlet listeners:
+
+* org.apache.johnzon.websocket.internal.mapper.MapperLocator for johnzon-mapper
+* org.apache.johnzon.websocket.jsonb.JsonbLocator for JSON-B
+
+if you write in the servlet context an attribute named `org.apache.johnzon.websocket.internal.mapper.MapperLocator.mapper` (it is a `Supplier<Mapper>`) or `org.apache.johnzon.websocket.jsonb.JsonbLocator.jsonb` (depending the implementation you use) it will be used instead of the default instance.
+
#### JSON-P integration
Encoders:
@@ -415,6 +422,16 @@ Decoder:
* `org.apache.johnzon.websocket.mapper.JohnzonTextDecoder`
+#### JSON-B integration
+
+Encoder:
+
+* `org.apache.johnzon.websocket.jsonb.JsonbTextEncoder`
+
+Decoder:
+
+* `org.apache.johnzon.websocket.jsonb.JsonbTextDecoder`
+
#### Sample
##### JSON-P Samples