I have a backend server running on JAX-RS (RestEasy flavour).
Some of the endpoint responses contain dates, which I want to be formatted as ISO strings.
@Value // Lombok annotation
public class MyResponse {
String someDateAsString;
}
Because I don't want the conversion to be "improvised" by each developer in each Response, I standardize it like this :
@Value
public class MyResponse {
LocalDateTime someDate;
}
And I make the conversion happen automatically by using the corresponding setting of Jackson :
@Provider
@Produces(MediaType.APPLICATION_JSON)
public class JacksonDatatypeProducer implements ContextResolver<ObjectMapper> {
private final ObjectMapper mObjectMapper;
public JacksonDatatypeProducer() {
this.mObjectMapper = new ObjectMapper()
.findAndRegisterModules()
.configure(WRITE_DATES_AS_TIMESTAMPS, false); // <-- where the magic happens
}
@Override
public ObjectMapper getContext(final Class<?> objectType) {
return mObjectMapper;
}
}
This works great, I get my dates as ISO strings in the frontend.
PROBLEM:
My backend is also the consumer of many third-party services.
They are called through various instances of javax.ws.rs.client.Client
.
The framework knows how to inject them automatically, because this kind of class is present:
public class HttpClientProducer {
private final ResteasyClient mClient;
@Inject
HttpClientProducer(final Logger logger) {
mClient = ((ResteasyClientBuilder) ClientBuilder.newBuilder().register(new JacksonDatatypeProducer()))
.build();
}
@Produces
@ApplicationScoped
public Client getClient() {
return mClient;
}
}
I want my backend (as a server) to have its own configuration for Jackson. I do not want it to share the same settings as all those 3rd party clients (especially not the WRITE_DATES_AS_TIMESTAMPS
setting).
I cannot wrap my head around the proper way of telling the server (and only the server) explicitly which Jackson settings to use. I.e. there's too much magic wiring, I don't know where to act in the instantiation flow -- whether be explicit or implicit locations.
I've been looking for a class similar to this HttpClientProducer
, but meant to instantiate the backend as a server instead. There doesn't seem to be one.
MY ATTEMPTS:
First of all I wonder why the JacksonDatatypeProducer
is instantiated manually in HttpClientProducer
.
Is that a "mistake" in the legacy code? I.e. why wouldn't they use dependency injection if it's to instantiate the same JacksonDatatypeProducer
anyways?
You should be able to use the jakarta.ws.rs.ConstrainedTo
annotation (or javax.ws.rs.ConstrainedTo
if you're using older versions of Jakarta REST and RESTEasy).
You'd annotate your ContextResolver
for the client with @ConstrainedTo(RuntimeType.CLIENT)
and your server with @ConstrainedTo(RuntimeType.SERVER)
.