0

I use Jersey 2.9 and Jackson 2.5.1 to generate JSON responses on a RESTful API.

In order to provide a custom ObjectMapper, I implement a ContextResolver like so:

@Provider
public class ObjectMapperProvider implements ContextResolver<ObjectMapper> {

    @Context UriInfo uriInfo;

    private final ObjectMapper objectMapper;

    public ObjectMapperProvider() {
    objectMapper = new ObjectMapper();

    objectMapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
    objectMapper.enable(SerializationFeature.INDENT_OUTPUT);
    objectMapper.enable(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS);
    }

    @Override
    public ObjectMapper getContext(Class<?> type) {

        // TODO: configure custom object mapper depending on query string params

        return objectMapper;
    }

}

It works great the first time I access the endpoint: the getContext method is invoked and I perform custom configurations on the objectmapper (possibly returning a new one) depending on the query string provided by the user.

However, once the endpoint has been accessed once, Jersey seems to cache that object mapper and never ask for it again invoking getContext. I need to disable or prevent this behavior since the query string might have changed and I might need to return a different object mapper for that request.

Is this possible??

Thank you!!

Edy Bourne
  • 5,679
  • 13
  • 53
  • 101

1 Answers1

0

Note that the object mapper is relatively expensive to create. It is thread safe and designed to be reused. So instead of creating your own context you can consider customizing the Jackson JAX-RS provider per request without creating a new mapper instance.

There are couple ways you can achieve that.

You can annotate your resource method with the Jackson specific annotations. Example:

@JacksonFeatures(serializationEnable 
        = { SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS })
public void foo() {}

But that doesn't allow to pass the request parameters to the object mapper.

Another option is to create an instance of ObjectWriterModifier/ObjectReaderModifier and register it via thread local injection via ObjectWriterInjector/ObjectReaderInjector. See example.

You can also try to combine a per-request scope context provider and the thread local modification.

Community
  • 1
  • 1
Alexey Gavrilov
  • 10,593
  • 2
  • 38
  • 48
  • The ObjectWriterMoifier didn't work for me unfortunately, Jersey seems to fail before it is invoked and the returned value is not used when serializing the object. I ended up accomplishing this using a custom `BeanSerializer`, then having it do the job by registering an module with `objectMapper.registerModule`. Thanks anyways though! – Edy Bourne Jun 30 '14 at 22:01