methanol-jackson-flux¶
Adapters for JSON & Reactive Streams using Jackson & Reactor.
Decoding¶
This adapter converts response bodies into publisher-based sources. Supported types are
Mono
, Flux
, org.reactivestreams.Publisher
and java.util.concurrent.Flow.Publisher
. For all
these types except Mono
, the response body is expected to be a JSON array. The array is tokenized
into its individual elements, each mapped to the publisher's element type.
Note that an HttpResponse
handled with this adapter is completed immediately after the response headers
are received. Body completion is handled by the returned publisher source. Additionally, the decoder
always uses Jackson's non-blocking parser. This makes MoreBodyHandlers::ofDeferredObject
redundant
with this decoder.
Encoding¶
With the exception of Mono
, any subtype of org.reactivestreams.Publisher
or
java.util.concurrent.Flow.Publisher
is encoded to a JSON array containing zero or more elements, each mapped from each published object.
Mono
sources are encoded to a single JSON object (if completed with any).
Installation¶
Gradle¶
implementation 'com.github.mizosoft.methanol:methanol-jackson-flux:1.7.0'
Maven¶
<dependency>
<groupId>com.github.mizosoft.methanol</groupId>
<artifactId>methanol-jackson-flux</artifactId>
<version>1.7.0</version>
</dependency>
The adapters need to be registered as service providers so Methanol knows they're there. The way this is done depends on your project setup.
Module Path¶
Follow these steps if your project uses the Java module system.
-
Add this class to your module:
public class JacksonFluxProviders { private static final ObjectMapper mapper = new ObjectMapper(); public static class EncoderProvider { public static BodyAdapter.Encoder provider() { return JacksonFluxAdapterFactory.createEncoder(mapper); } } public static class DecoderProvider { public static BodyAdapter.Decoder provider() { return JacksonFluxAdapterFactory.createDecoder(mapper); } } }
-
Add the corresponding provider declarations in your
module-info.java
file.requires methanol.adapter.jackson.flux; provides BodyAdapter.Encoder with JacksonFluxProviders.EncoderProvider; provides BodyAdapter.Decoder with JacksonFluxProviders.DecoderProvider;
Classpath¶
Registering adapters from the classpath requires declaring the implementation classes in provider-configuration
files that are bundled with your JAR. You'll first need to implement delegating Encoder
& Decoder
that forward to the instances created by JacksonAdapterFactory
. Extending from ForwardingEncoder
&
ForwardingDecoder
makes this easier.
You can use Google's AutoService to generate the provider-configuration files automatically, so you won't bother writing them.
Using AutoService¶
First, install AutoService.
Gradle¶
implementation "com.google.auto.service:auto-service-annotations:$autoServiceVersion"
annotationProcessor "com.google.auto.service:auto-service:$autoServiceVersion"
Maven¶
<dependency>
<groupId>com.google.auto.service</groupId>
<artifactId>auto-service-annotations</artifactId>
<version>${autoServiceVersion}</version>
</dependency>
Configure the annotation processor with the compiler plugin.
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<annotationProcessorPaths>
<path>
<groupId>com.google.auto.service</groupId>
<artifactId>auto-service</artifactId>
<version>${autoServiceVersion}</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
Next, add this class to your project:
public class JacksonFluxAdapters {
private static final ObjectMapper mapper = new ObjectMapper();
@AutoService(BodyAdapter.Encoder.class)
public static class Encoder extends ForwardingEncoder {
public Encoder() {
super(JacksonFluxAdapterFactory.createEncoder(mapper));
}
}
@AutoService(BodyAdapter.Decoder.class)
public static class Decoder extends ForwardingDecoder {
public Decoder() {
super(JacksonFluxAdapterFactory.createDecoder(mapper));
}
}
}
Manual Configuration¶
You can also write the configuration files manually. First, add this class to your project:
public class JacksonFluxAdapters {
private static final ObjectMapper mapper = new ObjectMapper();
public static class Encoder extends ForwardingEncoder {
public Encoder() {
super(JacksonFluxAdapterFactory.createEncoder(mapper));
}
}
public static class Decoder extends ForwardingDecoder {
public Decoder() {
super(JacksonFluxAdapterFactory.createDecoder(mapper));
}
}
}
Next, create two provider-configuration files in the resource directory: META-INF/services
,
one for the encoder and the other for the decoder. Each file must contain the fully qualified
name of the implementation class.
Let's say the above class is in a package named com.example
. You'll want to have one file for the
encoder named:
META-INF/services/com.github.mizosoft.methanol.BodyAdapter$Encoder
and contains the following line:
com.example.JacksonFluxAdapters$Encoder
Similarly, the decoder's file is named:
META-INF/services/com.github.mizosoft.methanol.BodyAdapter$Decoder
and contains:
com.example.JacksonFluxAdapters$Decoder