From bc4fbf6d029fa39bbba55d4692f9df62de8a8c75 Mon Sep 17 00:00:00 2001 From: Georgios Andrianakis Date: Fri, 16 Apr 2021 12:32:45 +0300 Subject: [PATCH] Ensure that Jackson writer doesn't negatively affect endpoint score Fixes https://github.com/quarkusio/quarkus/issues/14720#issuecomment-820610879 --- .../JacksonBasicMessageBodyWriter.java | 91 ------------------- .../JacksonMessageBodyWriterUtil.java | 71 +++++++++++++++ .../ResteasyReactiveJacksonProcessor.java | 12 +-- ...va => ServerJacksonMessageBodyReader.java} | 4 +- ...va => ServerJacksonMessageBodyWriter.java} | 28 ++++-- .../RestClientReactiveJacksonProcessor.java | 6 +- .../ClientJacksonMessageBodyWriter.java | 41 +++++++++ 7 files changed, 142 insertions(+), 111 deletions(-) delete mode 100644 extensions/resteasy-reactive/quarkus-resteasy-reactive-jackson-common/runtime/src/main/java/io/quarkus/resteasy/reactive/jackson/runtime/serialisers/JacksonBasicMessageBodyWriter.java create mode 100644 extensions/resteasy-reactive/quarkus-resteasy-reactive-jackson-common/runtime/src/main/java/io/quarkus/resteasy/reactive/jackson/runtime/serialisers/JacksonMessageBodyWriterUtil.java rename extensions/resteasy-reactive/quarkus-resteasy-reactive-jackson/runtime/src/main/java/io/quarkus/resteasy/reactive/jackson/runtime/serialisers/{JacksonMessageBodyReader.java => ServerJacksonMessageBodyReader.java} (92%) rename extensions/resteasy-reactive/quarkus-resteasy-reactive-jackson/runtime/src/main/java/io/quarkus/resteasy/reactive/jackson/runtime/serialisers/{JacksonMessageBodyWriter.java => ServerJacksonMessageBodyWriter.java} (82%) create mode 100644 extensions/resteasy-reactive/rest-client-reactive-jackson/runtime/src/main/java/io/quarkus/rest/client/reactive/jackson/runtime/serialisers/ClientJacksonMessageBodyWriter.java diff --git a/extensions/resteasy-reactive/quarkus-resteasy-reactive-jackson-common/runtime/src/main/java/io/quarkus/resteasy/reactive/jackson/runtime/serialisers/JacksonBasicMessageBodyWriter.java b/extensions/resteasy-reactive/quarkus-resteasy-reactive-jackson-common/runtime/src/main/java/io/quarkus/resteasy/reactive/jackson/runtime/serialisers/JacksonBasicMessageBodyWriter.java deleted file mode 100644 index d3e98a15bcfcb..0000000000000 --- a/extensions/resteasy-reactive/quarkus-resteasy-reactive-jackson-common/runtime/src/main/java/io/quarkus/resteasy/reactive/jackson/runtime/serialisers/JacksonBasicMessageBodyWriter.java +++ /dev/null @@ -1,91 +0,0 @@ -package io.quarkus.resteasy.reactive.jackson.runtime.serialisers; - -import static org.jboss.resteasy.reactive.common.providers.serialisers.JsonMessageBodyWriterUtil.setContentTypeIfNecessary; - -import java.io.IOException; -import java.io.OutputStream; -import java.lang.annotation.Annotation; -import java.lang.reflect.Method; -import java.lang.reflect.Type; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; - -import javax.inject.Inject; -import javax.ws.rs.WebApplicationException; -import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.MultivaluedMap; -import javax.ws.rs.ext.MessageBodyWriter; - -import com.fasterxml.jackson.annotation.JsonView; -import com.fasterxml.jackson.core.JsonFactory; -import com.fasterxml.jackson.core.JsonGenerator.Feature; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.ObjectWriter; - -import io.quarkus.resteasy.reactive.jackson.CustomSerialization; - -public class JacksonBasicMessageBodyWriter implements MessageBodyWriter { - - private static final String JSON_VIEW_NAME = JsonView.class.getName(); - private static final String CUSTOM_SERIALIZATION = CustomSerialization.class.getName(); - - protected final ObjectMapper originalMapper; - protected final ObjectWriter defaultWriter; - protected final ConcurrentMap perMethodWriter = new ConcurrentHashMap<>(); - - @Inject - public JacksonBasicMessageBodyWriter(ObjectMapper mapper) { - this.originalMapper = mapper; - // we don't want the ObjectWriter to close the stream automatically, as we want to handle closing manually at the proper points - JsonFactory jsonFactory = mapper.getFactory(); - if (needsNewFactory(jsonFactory)) { - jsonFactory = jsonFactory.copy(); - setNecessaryJsonFactoryConfig(jsonFactory); - this.defaultWriter = mapper.writer().with(jsonFactory); - } else { - this.defaultWriter = mapper.writer(); - } - } - - private boolean needsNewFactory(JsonFactory jsonFactory) { - return jsonFactory.isEnabled(Feature.AUTO_CLOSE_TARGET) || jsonFactory.isEnabled(Feature.FLUSH_PASSED_TO_STREAM); - } - - protected static void setNecessaryJsonFactoryConfig(JsonFactory jsonFactory) { - jsonFactory.configure(Feature.AUTO_CLOSE_TARGET, false); - jsonFactory.configure(Feature.FLUSH_PASSED_TO_STREAM, false); - } - - @Override - public boolean isWriteable(Class type, Type genericType, Annotation[] annotations, MediaType mediaType) { - return true; - } - - @Override - public void writeTo(Object o, Class type, Type genericType, Annotation[] annotations, MediaType mediaType, - MultivaluedMap httpHeaders, OutputStream entityStream) throws IOException, WebApplicationException { - setContentTypeIfNecessary(httpHeaders); - if (o instanceof String) { // YUK: done in order to avoid adding extra quotes... - entityStream.write(((String) o).getBytes()); - } else { - if (annotations != null) { - for (Annotation annotation : annotations) { - if (JsonView.class.equals(annotation.annotationType())) { - if (handleJsonView(((JsonView) annotation), o, entityStream)) { - return; - } - } - } - } - entityStream.write(defaultWriter.writeValueAsBytes(o)); - } - } - - private boolean handleJsonView(JsonView jsonView, Object o, OutputStream stream) throws IOException { - if ((jsonView != null) && (jsonView.value().length > 0)) { - defaultWriter.withView(jsonView.value()[0]).writeValue(stream, o); - return true; - } - return false; - } -} diff --git a/extensions/resteasy-reactive/quarkus-resteasy-reactive-jackson-common/runtime/src/main/java/io/quarkus/resteasy/reactive/jackson/runtime/serialisers/JacksonMessageBodyWriterUtil.java b/extensions/resteasy-reactive/quarkus-resteasy-reactive-jackson-common/runtime/src/main/java/io/quarkus/resteasy/reactive/jackson/runtime/serialisers/JacksonMessageBodyWriterUtil.java new file mode 100644 index 0000000000000..f990c5905a7b7 --- /dev/null +++ b/extensions/resteasy-reactive/quarkus-resteasy-reactive-jackson-common/runtime/src/main/java/io/quarkus/resteasy/reactive/jackson/runtime/serialisers/JacksonMessageBodyWriterUtil.java @@ -0,0 +1,71 @@ +package io.quarkus.resteasy.reactive.jackson.runtime.serialisers; + +import static org.jboss.resteasy.reactive.common.providers.serialisers.JsonMessageBodyWriterUtil.setContentTypeIfNecessary; + +import java.io.IOException; +import java.io.OutputStream; +import java.lang.annotation.Annotation; + +import javax.ws.rs.core.MultivaluedMap; + +import com.fasterxml.jackson.annotation.JsonView; +import com.fasterxml.jackson.core.JsonFactory; +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.ObjectWriter; + +public final class JacksonMessageBodyWriterUtil { + + private JacksonMessageBodyWriterUtil() { + } + + public static ObjectWriter createDefaultWriter(ObjectMapper mapper) { + // we don't want the ObjectWriter to close the stream automatically, as we want to handle closing manually at the proper points + JsonFactory jsonFactory = mapper.getFactory(); + if (JacksonMessageBodyWriterUtil.needsNewFactory(jsonFactory)) { + jsonFactory = jsonFactory.copy(); + JacksonMessageBodyWriterUtil.setNecessaryJsonFactoryConfig(jsonFactory); + return mapper.writer().with(jsonFactory); + } else { + return mapper.writer(); + } + } + + private static boolean needsNewFactory(JsonFactory jsonFactory) { + return jsonFactory.isEnabled(JsonGenerator.Feature.AUTO_CLOSE_TARGET) + || jsonFactory.isEnabled(JsonGenerator.Feature.FLUSH_PASSED_TO_STREAM); + } + + public static void setNecessaryJsonFactoryConfig(JsonFactory jsonFactory) { + jsonFactory.configure(JsonGenerator.Feature.AUTO_CLOSE_TARGET, false); + jsonFactory.configure(JsonGenerator.Feature.FLUSH_PASSED_TO_STREAM, false); + } + + public static void doLegacyWrite(Object o, Annotation[] annotations, MultivaluedMap httpHeaders, + OutputStream entityStream, ObjectWriter defaultWriter) throws IOException { + setContentTypeIfNecessary(httpHeaders); + if (o instanceof String) { // YUK: done in order to avoid adding extra quotes... + entityStream.write(((String) o).getBytes()); + } else { + if (annotations != null) { + for (Annotation annotation : annotations) { + if (JsonView.class.equals(annotation.annotationType())) { + if (handleJsonView(((JsonView) annotation), o, entityStream, defaultWriter)) { + return; + } + } + } + } + entityStream.write(defaultWriter.writeValueAsBytes(o)); + } + } + + private static boolean handleJsonView(JsonView jsonView, Object o, OutputStream stream, ObjectWriter defaultWriter) + throws IOException { + if ((jsonView != null) && (jsonView.value().length > 0)) { + defaultWriter.withView(jsonView.value()[0]).writeValue(stream, o); + return true; + } + return false; + } +} diff --git a/extensions/resteasy-reactive/quarkus-resteasy-reactive-jackson/deployment/src/main/java/io/quarkus/resteasy/reactive/jackson/deployment/processor/ResteasyReactiveJacksonProcessor.java b/extensions/resteasy-reactive/quarkus-resteasy-reactive-jackson/deployment/src/main/java/io/quarkus/resteasy/reactive/jackson/deployment/processor/ResteasyReactiveJacksonProcessor.java index b31ce52234ca0..b263ccad39e6f 100644 --- a/extensions/resteasy-reactive/quarkus-resteasy-reactive-jackson/deployment/src/main/java/io/quarkus/resteasy/reactive/jackson/deployment/processor/ResteasyReactiveJacksonProcessor.java +++ b/extensions/resteasy-reactive/quarkus-resteasy-reactive-jackson/deployment/src/main/java/io/quarkus/resteasy/reactive/jackson/deployment/processor/ResteasyReactiveJacksonProcessor.java @@ -10,8 +10,8 @@ import io.quarkus.deployment.annotations.BuildStep; import io.quarkus.deployment.builditem.FeatureBuildItem; import io.quarkus.resteasy.reactive.common.deployment.ServerDefaultProducesHandlerBuildItem; -import io.quarkus.resteasy.reactive.jackson.runtime.serialisers.JacksonMessageBodyReader; -import io.quarkus.resteasy.reactive.jackson.runtime.serialisers.JacksonMessageBodyWriter; +import io.quarkus.resteasy.reactive.jackson.runtime.serialisers.ServerJacksonMessageBodyReader; +import io.quarkus.resteasy.reactive.jackson.runtime.serialisers.ServerJacksonMessageBodyWriter; import io.quarkus.resteasy.reactive.jackson.runtime.serialisers.vertx.VertxJsonArrayMessageBodyReader; import io.quarkus.resteasy.reactive.jackson.runtime.serialisers.vertx.VertxJsonArrayMessageBodyWriter; import io.quarkus.resteasy.reactive.jackson.runtime.serialisers.vertx.VertxJsonObjectMessageBodyReader; @@ -44,12 +44,12 @@ void additionalProviders(BuildProducer additionalBean, BuildProducer additionalWriters) { // make these beans to they can get instantiated with the Quarkus CDI configured Jsonb object additionalBean.produce(AdditionalBeanBuildItem.builder() - .addBeanClass(JacksonMessageBodyReader.class.getName()) - .addBeanClass(JacksonMessageBodyWriter.class.getName()) + .addBeanClass(ServerJacksonMessageBodyReader.class.getName()) + .addBeanClass(ServerJacksonMessageBodyWriter.class.getName()) .setUnremovable().build()); additionalReaders - .produce(new MessageBodyReaderBuildItem(JacksonMessageBodyReader.class.getName(), Object.class.getName(), + .produce(new MessageBodyReaderBuildItem(ServerJacksonMessageBodyReader.class.getName(), Object.class.getName(), Collections.singletonList(MediaType.APPLICATION_JSON))); additionalReaders .produce(new MessageBodyReaderBuildItem(VertxJsonArrayMessageBodyReader.class.getName(), @@ -60,7 +60,7 @@ void additionalProviders(BuildProducer additionalBean, JsonObject.class.getName(), Collections.singletonList(MediaType.APPLICATION_JSON))); additionalWriters - .produce(new MessageBodyWriterBuildItem(JacksonMessageBodyWriter.class.getName(), Object.class.getName(), + .produce(new MessageBodyWriterBuildItem(ServerJacksonMessageBodyWriter.class.getName(), Object.class.getName(), Collections.singletonList(MediaType.APPLICATION_JSON))); additionalWriters .produce(new MessageBodyWriterBuildItem(VertxJsonArrayMessageBodyWriter.class.getName(), diff --git a/extensions/resteasy-reactive/quarkus-resteasy-reactive-jackson/runtime/src/main/java/io/quarkus/resteasy/reactive/jackson/runtime/serialisers/JacksonMessageBodyReader.java b/extensions/resteasy-reactive/quarkus-resteasy-reactive-jackson/runtime/src/main/java/io/quarkus/resteasy/reactive/jackson/runtime/serialisers/ServerJacksonMessageBodyReader.java similarity index 92% rename from extensions/resteasy-reactive/quarkus-resteasy-reactive-jackson/runtime/src/main/java/io/quarkus/resteasy/reactive/jackson/runtime/serialisers/JacksonMessageBodyReader.java rename to extensions/resteasy-reactive/quarkus-resteasy-reactive-jackson/runtime/src/main/java/io/quarkus/resteasy/reactive/jackson/runtime/serialisers/ServerJacksonMessageBodyReader.java index a13596a7192cd..78f4c80094113 100644 --- a/extensions/resteasy-reactive/quarkus-resteasy-reactive-jackson/runtime/src/main/java/io/quarkus/resteasy/reactive/jackson/runtime/serialisers/JacksonMessageBodyReader.java +++ b/extensions/resteasy-reactive/quarkus-resteasy-reactive-jackson/runtime/src/main/java/io/quarkus/resteasy/reactive/jackson/runtime/serialisers/ServerJacksonMessageBodyReader.java @@ -19,10 +19,10 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.exc.MismatchedInputException; -public class JacksonMessageBodyReader extends JacksonBasicMessageBodyReader implements ServerMessageBodyReader { +public class ServerJacksonMessageBodyReader extends JacksonBasicMessageBodyReader implements ServerMessageBodyReader { @Inject - public JacksonMessageBodyReader(ObjectMapper mapper) { + public ServerJacksonMessageBodyReader(ObjectMapper mapper) { super(mapper); } diff --git a/extensions/resteasy-reactive/quarkus-resteasy-reactive-jackson/runtime/src/main/java/io/quarkus/resteasy/reactive/jackson/runtime/serialisers/JacksonMessageBodyWriter.java b/extensions/resteasy-reactive/quarkus-resteasy-reactive-jackson/runtime/src/main/java/io/quarkus/resteasy/reactive/jackson/runtime/serialisers/ServerJacksonMessageBodyWriter.java similarity index 82% rename from extensions/resteasy-reactive/quarkus-resteasy-reactive-jackson/runtime/src/main/java/io/quarkus/resteasy/reactive/jackson/runtime/serialisers/JacksonMessageBodyWriter.java rename to extensions/resteasy-reactive/quarkus-resteasy-reactive-jackson/runtime/src/main/java/io/quarkus/resteasy/reactive/jackson/runtime/serialisers/ServerJacksonMessageBodyWriter.java index 57eda43c05c3d..d803428b5115f 100644 --- a/extensions/resteasy-reactive/quarkus-resteasy-reactive-jackson/runtime/src/main/java/io/quarkus/resteasy/reactive/jackson/runtime/serialisers/JacksonMessageBodyWriter.java +++ b/extensions/resteasy-reactive/quarkus-resteasy-reactive-jackson/runtime/src/main/java/io/quarkus/resteasy/reactive/jackson/runtime/serialisers/ServerJacksonMessageBodyWriter.java @@ -1,18 +1,23 @@ package io.quarkus.resteasy.reactive.jackson.runtime.serialisers; +import static io.quarkus.resteasy.reactive.jackson.runtime.serialisers.JacksonMessageBodyWriterUtil.*; import static org.jboss.resteasy.reactive.server.vertx.providers.serialisers.json.JsonMessageServerBodyWriterUtil.setContentTypeIfNecessary; import java.io.IOException; import java.io.OutputStream; +import java.lang.annotation.Annotation; import java.lang.reflect.Method; import java.lang.reflect.Type; import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; import java.util.function.BiFunction; import java.util.function.Function; import javax.inject.Inject; import javax.ws.rs.WebApplicationException; import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.MultivaluedMap; import org.jboss.resteasy.reactive.server.spi.ResteasyReactiveResourceInfo; import org.jboss.resteasy.reactive.server.spi.ServerMessageBodyWriter; @@ -24,14 +29,19 @@ import io.quarkus.resteasy.reactive.jackson.CustomSerialization; -public class JacksonMessageBodyWriter extends JacksonBasicMessageBodyWriter implements ServerMessageBodyWriter {// extends ServerMessageBodyWriter.AllWriteableMessageBodyWriter { +public class ServerJacksonMessageBodyWriter extends ServerMessageBodyWriter.AllWriteableMessageBodyWriter { private static final String JSON_VIEW_NAME = JsonView.class.getName(); private static final String CUSTOM_SERIALIZATION = CustomSerialization.class.getName(); + private final ObjectMapper originalMapper; + private final ObjectWriter defaultWriter; + private final ConcurrentMap perMethodWriter = new ConcurrentHashMap<>(); + @Inject - public JacksonMessageBodyWriter(ObjectMapper mapper) { - super(mapper); + public ServerJacksonMessageBodyWriter(ObjectMapper mapper) { + this.originalMapper = mapper; + this.defaultWriter = createDefaultWriter(mapper); } @Override @@ -65,12 +75,6 @@ public void writeResponse(Object o, Type genericType, ServerRequestContext conte stream.close(); } - @Override - public final boolean isWriteable(Class type, Type genericType, ResteasyReactiveResourceInfo target, - MediaType mediaType) { - return true; - } - // TODO: this can definitely be made faster if necessary by optimizing the use of the map and also by moving the creation of the // biFunction to build time private boolean handleCustomSerialization(Method method, Object o, Type genericType, OutputStream stream) @@ -94,6 +98,12 @@ private boolean handleJsonView(JsonView jsonView, Object o, OutputStream stream) return false; } + @Override + public void writeTo(Object o, Class type, Type genericType, Annotation[] annotations, MediaType mediaType, + MultivaluedMap httpHeaders, OutputStream entityStream) throws IOException, WebApplicationException { + doLegacyWrite(o, annotations, httpHeaders, entityStream, defaultWriter); + } + private static class MethodObjectWriterFunction implements Function { private final Class> clazz; private final Type genericType; diff --git a/extensions/resteasy-reactive/rest-client-reactive-jackson/deployment/src/main/java/io/quarkus/rest/client/reactive/jackson/deployment/RestClientReactiveJacksonProcessor.java b/extensions/resteasy-reactive/rest-client-reactive-jackson/deployment/src/main/java/io/quarkus/rest/client/reactive/jackson/deployment/RestClientReactiveJacksonProcessor.java index c2eae37a9e5bf..dba64a26a340c 100644 --- a/extensions/resteasy-reactive/rest-client-reactive-jackson/deployment/src/main/java/io/quarkus/rest/client/reactive/jackson/deployment/RestClientReactiveJacksonProcessor.java +++ b/extensions/resteasy-reactive/rest-client-reactive-jackson/deployment/src/main/java/io/quarkus/rest/client/reactive/jackson/deployment/RestClientReactiveJacksonProcessor.java @@ -11,9 +11,9 @@ import io.quarkus.deployment.annotations.BuildProducer; import io.quarkus.deployment.annotations.BuildStep; import io.quarkus.deployment.builditem.FeatureBuildItem; +import io.quarkus.rest.client.reactive.jackson.runtime.serialisers.ClientJacksonMessageBodyWriter; import io.quarkus.resteasy.reactive.jackson.deployment.processor.ResteasyReactiveJacksonProviderDefinedBuildItem; import io.quarkus.resteasy.reactive.jackson.runtime.serialisers.JacksonBasicMessageBodyReader; -import io.quarkus.resteasy.reactive.jackson.runtime.serialisers.JacksonBasicMessageBodyWriter; import io.quarkus.resteasy.reactive.jackson.runtime.serialisers.vertx.VertxJsonArrayBasicMessageBodyReader; import io.quarkus.resteasy.reactive.jackson.runtime.serialisers.vertx.VertxJsonArrayBasicMessageBodyWriter; import io.quarkus.resteasy.reactive.jackson.runtime.serialisers.vertx.VertxJsonObjectBasicMessageBodyReader; @@ -42,7 +42,7 @@ void additionalProviders( // make these beans to they can get instantiated with the Quarkus CDI configured Jsonb object additionalBean.produce(AdditionalBeanBuildItem.builder() .addBeanClass(JacksonBasicMessageBodyReader.class.getName()) - .addBeanClass(JacksonBasicMessageBodyWriter.class.getName()) + .addBeanClass(ClientJacksonMessageBodyWriter.class.getName()) .setUnremovable().build()); additionalReaders @@ -57,7 +57,7 @@ void additionalProviders( JsonObject.class.getName(), Collections.singletonList(MediaType.APPLICATION_JSON))); additionalWriters - .produce(new MessageBodyWriterBuildItem(JacksonBasicMessageBodyWriter.class.getName(), Object.class.getName(), + .produce(new MessageBodyWriterBuildItem(ClientJacksonMessageBodyWriter.class.getName(), Object.class.getName(), Collections.singletonList(MediaType.APPLICATION_JSON))); additionalWriters .produce(new MessageBodyWriterBuildItem(VertxJsonArrayBasicMessageBodyWriter.class.getName(), diff --git a/extensions/resteasy-reactive/rest-client-reactive-jackson/runtime/src/main/java/io/quarkus/rest/client/reactive/jackson/runtime/serialisers/ClientJacksonMessageBodyWriter.java b/extensions/resteasy-reactive/rest-client-reactive-jackson/runtime/src/main/java/io/quarkus/rest/client/reactive/jackson/runtime/serialisers/ClientJacksonMessageBodyWriter.java new file mode 100644 index 0000000000000..34a5640bcd55c --- /dev/null +++ b/extensions/resteasy-reactive/rest-client-reactive-jackson/runtime/src/main/java/io/quarkus/rest/client/reactive/jackson/runtime/serialisers/ClientJacksonMessageBodyWriter.java @@ -0,0 +1,41 @@ +package io.quarkus.rest.client.reactive.jackson.runtime.serialisers; + +import static io.quarkus.resteasy.reactive.jackson.runtime.serialisers.JacksonMessageBodyWriterUtil.createDefaultWriter; +import static io.quarkus.resteasy.reactive.jackson.runtime.serialisers.JacksonMessageBodyWriterUtil.doLegacyWrite; + +import java.io.IOException; +import java.io.OutputStream; +import java.lang.annotation.Annotation; +import java.lang.reflect.Type; + +import javax.inject.Inject; +import javax.ws.rs.WebApplicationException; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.MultivaluedMap; +import javax.ws.rs.ext.MessageBodyWriter; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.ObjectWriter; + +public class ClientJacksonMessageBodyWriter implements MessageBodyWriter { + + protected final ObjectMapper originalMapper; + protected final ObjectWriter defaultWriter; + + @Inject + public ClientJacksonMessageBodyWriter(ObjectMapper mapper) { + this.originalMapper = mapper; + this.defaultWriter = createDefaultWriter(mapper); + } + + @Override + public boolean isWriteable(Class type, Type genericType, Annotation[] annotations, MediaType mediaType) { + return true; + } + + @Override + public void writeTo(Object o, Class type, Type genericType, Annotation[] annotations, MediaType mediaType, + MultivaluedMap httpHeaders, OutputStream entityStream) throws IOException, WebApplicationException { + doLegacyWrite(o, annotations, httpHeaders, entityStream, defaultWriter); + } +}