diff --git a/base/src/main/java/com/fasterxml/jackson/jaxrs/base/ProviderBase.java b/base/src/main/java/com/fasterxml/jackson/jaxrs/base/ProviderBase.java index ee8131d1..74e271a0 100644 --- a/base/src/main/java/com/fasterxml/jackson/jaxrs/base/ProviderBase.java +++ b/base/src/main/java/com/fasterxml/jackson/jaxrs/base/ProviderBase.java @@ -125,20 +125,6 @@ public abstract class ProviderBase< * View to use for writing if none defined for the end point. */ protected Class _defaultWriteView; - - /** - * Object used for handling possible {@link ObjectReader} injection. - * - * @since 2.3 - */ - protected ObjectReaderInjector _readerInjector; - - /** - * Object used for handling possible {@link ObjectWriter} injection. - * - * @since 2.3 - */ - protected ObjectWriterInjector _writerInjector; /* /********************************************************** @@ -190,8 +176,6 @@ public abstract class ProviderBase< protected ProviderBase(MAPPER_CONFIG mconfig) { _mapperConfig = mconfig; - _readerInjector = new ObjectReaderInjector(); - _writerInjector = new ObjectWriterInjector(); } /** @@ -465,15 +449,12 @@ protected boolean hasMatchingMediaTypeForWriting(MediaType mediaType) { protected EP_CONFIG _configForReading(MAPPER mapper, Annotation[] annotations, Class defaultView) { - ObjectReader r = _readerInjector.getAndClear(); - if (r == null) { - if (defaultView != null) { - r = mapper.readerWithView(defaultView); - } else { - r = mapper.reader(); - } +// ObjectReaderModi r = _readerInjector.getAndClear(); + ObjectReader r; + if (defaultView != null) { + r = mapper.readerWithView(defaultView); } else { - r = r.withView(defaultView); + r = mapper.reader(); } return _configForReading(r, annotations); } @@ -481,15 +462,12 @@ protected EP_CONFIG _configForReading(MAPPER mapper, protected EP_CONFIG _configForWriting(MAPPER mapper, Annotation[] annotations, Class defaultView) { - ObjectWriter w = _writerInjector.getAndClear(); - if (w == null) { - if (defaultView != null) { - w = mapper.writerWithView(defaultView); - } else { - w = mapper.writer(); - } +// ObjectWriter w = _writerInjector.getAndClear(); + ObjectWriter w; + if (defaultView != null) { + w = mapper.writerWithView(defaultView); } else { - w = w.withView(defaultView); + w = mapper.writer(); } return _configForWriting(w, annotations); } @@ -634,6 +612,13 @@ public void writeTo(Object value, Class type, Type genericType, Annotation[] writer = writer.withType(rootType); } value = endpoint.modifyBeforeWrite(value); + + // [Issue#32]: allow modification by filter-injectible thing + ObjectWriterModifier mod = ObjectWriterInjector.getAndClear(); + if (mod != null) { + writer = mod.modify(endpoint, value, writer, g); + } + writer.writeValue(g, value); } finally { g.close(); @@ -758,6 +743,7 @@ public Object readFrom(Class type, Type genericType, Annotation[] annota } ObjectReader reader = endpoint.getReader(); JsonParser jp = _createParser(reader, entityStream); + // If null is returned, considered to be empty stream if (jp == null || jp.nextToken() == null) { return null; @@ -766,7 +752,14 @@ public Object readFrom(Class type, Type genericType, Annotation[] annota if (((Class) type) == JsonParser.class) { return jp; } - return reader.withType(genericType).readValue(jp); + final JavaType resolvedType = reader.getTypeFactory().constructType(genericType); + reader = reader.withType(resolvedType); + // [Issue#32]: allow modification by filter-injectible thing + ObjectReaderModifier mod = ObjectReaderInjector.getAndClear(); + if (mod != null) { + reader = mod.modify(endpoint, resolvedType, reader, jp); + } + return reader.readValue(jp); } /** diff --git a/base/src/main/java/com/fasterxml/jackson/jaxrs/cfg/ObjectReaderInjector.java b/base/src/main/java/com/fasterxml/jackson/jaxrs/cfg/ObjectReaderInjector.java index 4bbbb757..8b99f69b 100644 --- a/base/src/main/java/com/fasterxml/jackson/jaxrs/cfg/ObjectReaderInjector.java +++ b/base/src/main/java/com/fasterxml/jackson/jaxrs/cfg/ObjectReaderInjector.java @@ -5,40 +5,41 @@ import com.fasterxml.jackson.databind.*; /** - * Based on ideas from [Issue#32], this class allows "overriding" of {@link ObjectReader} - * that JAX-RS Resource will use; usually this is done from a Servlet or JAX-RS filter + * Based on ideas from [Issue#32], this class allows registering a + * modifier ({@link ObjectReaderModifier}) that can be used to + * reconfigure {@link ObjectReader} + * that JAX-RS Resource will use for reading input into Java Objects. + * Usually this class is accessed from a Servlet or JAX-RS filter * before execution reaches resource. * - * @author apemberton@github, Tatu Saloranta - * * @since 2.3 */ public class ObjectReaderInjector { - protected static final ThreadLocal _threadLocal = new ThreadLocal(); + protected static final ThreadLocal _threadLocal = new ThreadLocal(); /** * Simple marker used to optimize out {@link ThreadLocal} access in cases * where this feature is not being used */ - protected final AtomicBoolean _hasBeenSet = new AtomicBoolean(false); - - public ObjectReaderInjector() { } + protected static final AtomicBoolean _hasBeenSet = new AtomicBoolean(false); + + private ObjectReaderInjector() { } - public void set(ObjectReader r) { + public static void set(ObjectReaderModifier mod) { _hasBeenSet.set(true); - _threadLocal.set(r); + _threadLocal.set(mod); } - public ObjectReader get() { + public static ObjectReaderModifier get() { return _hasBeenSet.get() ? _threadLocal.get() : null; } - public ObjectReader getAndClear() { - ObjectReader r = get(); - if (r != null) { + public static ObjectReaderModifier getAndClear() { + ObjectReaderModifier mod = get(); + if (mod != null) { _threadLocal.remove(); } - return r; + return mod; } } diff --git a/base/src/main/java/com/fasterxml/jackson/jaxrs/cfg/ObjectReaderModifier.java b/base/src/main/java/com/fasterxml/jackson/jaxrs/cfg/ObjectReaderModifier.java new file mode 100644 index 00000000..14bfe98e --- /dev/null +++ b/base/src/main/java/com/fasterxml/jackson/jaxrs/cfg/ObjectReaderModifier.java @@ -0,0 +1,26 @@ +package com.fasterxml.jackson.jaxrs.cfg; + +import java.io.IOException; + +import com.fasterxml.jackson.core.*; + +import com.fasterxml.jackson.databind.*; + +/** + * @since 2.3 + */ +public abstract class ObjectReaderModifier +{ + /** + * Method called to let modifier make any changes it wants to to objects + * used for reading request objects for specified endpoint. + * + * @param endpoint End point for which reader is used + * @param resultType Type that input is to be bound to + * @param r ObjectReader as constructed for endpoint, type to handle + * @param p Parser to use for reading content + */ + public abstract ObjectReader modify(EndpointConfigBase endpoint, + JavaType resultType, ObjectReader r, JsonParser p) + throws IOException; +} diff --git a/base/src/main/java/com/fasterxml/jackson/jaxrs/cfg/ObjectWriterInjector.java b/base/src/main/java/com/fasterxml/jackson/jaxrs/cfg/ObjectWriterInjector.java index 8113aac8..a2a8a1bb 100644 --- a/base/src/main/java/com/fasterxml/jackson/jaxrs/cfg/ObjectWriterInjector.java +++ b/base/src/main/java/com/fasterxml/jackson/jaxrs/cfg/ObjectWriterInjector.java @@ -9,36 +9,34 @@ * that JAX-RS Resource will use; usually this is done from a Servlet or JAX-RS filter * before execution reaches resource. * - * @author apemberton@github, Tatu Saloranta - * * @since 2.3 */ public class ObjectWriterInjector { - protected static final ThreadLocal _threadLocal = new ThreadLocal(); + protected static final ThreadLocal _threadLocal = new ThreadLocal(); /** * Simple marker used to optimize out {@link ThreadLocal} access in cases * where this feature is not being used */ - protected final AtomicBoolean _hasBeenSet = new AtomicBoolean(false); + protected static final AtomicBoolean _hasBeenSet = new AtomicBoolean(false); - public ObjectWriterInjector() { } + private ObjectWriterInjector() { } - public void set(ObjectWriter r) { + public static void set(ObjectWriterModifier mod) { _hasBeenSet.set(true); - _threadLocal.set(r); + _threadLocal.set(mod); } - public ObjectWriter get() { + public static ObjectWriterModifier get() { return _hasBeenSet.get() ? _threadLocal.get() : null; } - public ObjectWriter getAndClear() { - ObjectWriter w = get(); - if (w != null) { + public static ObjectWriterModifier getAndClear() { + ObjectWriterModifier mod = get(); + if (mod != null) { _threadLocal.remove(); } - return w; + return mod; } } diff --git a/base/src/main/java/com/fasterxml/jackson/jaxrs/cfg/ObjectWriterModifier.java b/base/src/main/java/com/fasterxml/jackson/jaxrs/cfg/ObjectWriterModifier.java new file mode 100644 index 00000000..fc93702e --- /dev/null +++ b/base/src/main/java/com/fasterxml/jackson/jaxrs/cfg/ObjectWriterModifier.java @@ -0,0 +1,21 @@ +package com.fasterxml.jackson.jaxrs.cfg; + +import java.io.IOException; + +import com.fasterxml.jackson.core.*; + +import com.fasterxml.jackson.databind.*; + +/** + * @since 2.3 + */ +public abstract class ObjectWriterModifier +{ + /** + * Method called to let modifier make any changes it wants to to objects + * used for writing response for specified endpoint. + */ + public abstract ObjectWriter modify(EndpointConfigBase endpoint, + Object valueToWrite, ObjectWriter r, JsonGenerator g) + throws IOException; +} diff --git a/release-notes/VERSION b/release-notes/VERSION index 80f5ef3d..71d4b3c4 100644 --- a/release-notes/VERSION +++ b/release-notes/VERSION @@ -6,6 +6,7 @@ Sub-modules: Version: 2.3.0 (xx-Oct-2013) #24: Allow defining default view to use for endpoints without View annotation +#33: Provide a way to customize `ObjectReader` / `ObjectWriter` used by end points ------------------------------------------------------------------------ === History: ===