How can I get the Jackson object mapper link in jersey2 / hk2 app

I have a jersey2 application configured to support JSON through Jackson by adding

<dependency> <groupId>org.glassfish.jersey.media</groupId> <artifactId>jersey-media-json-jackson</artifactId> <version>${jersey.version}</version> </dependency> 

in the POM file and

 public MyApplication() { ... register(JacksonFeature.class) ... } 

in my application. Everything works, my resources get deserialized POJOs as arguments

 @POST @Consumes(MediaType.APPLICATION_JSON) public void blah(MyPojo p) { ... } 

Now one of the thoese resources needs a link to Jackson ObjectMapper to do some deserialization on its own. I tried to do something like

 @Inject public MyResource(@Context ObjectMapper mapper) { ... } 

or

 @GET public String foo(@Context ObjectMapper mapper) { ... } 

but in both cases the reference to mapper is zero. How can I enter a link to ObjectMapper in my resources?

+7
java json dependency-injection hk2
source share
2 answers

Initially, the default ObjectMapper used by the Jackson provider is not used. It does not use ObjectMapper at all. It uses other Jackson APIs to handle serialization (de).

If you want to use / insert one instance of ObjectMapper , then you just need to create a Factory for it

 public class ObjectMapperFactory implements Factory<ObjectMapper> { final ObjectMapper mapper = new ObjectMapper(); @Override public ObjectMapper provide() { return mapper; } @Override public void dispose(ObjectMapper t) {} } 

Then tie it

 register(new AbstractBinder(){ @Override public void configure() { bindFactory(ObjectMapperFactory.class) .to(ObjectMapper.class).in(Singleton.class); } }); 

It should be noted that any configuration of ObjectMapper not thread protected . Therefore, say that you tried to configure it from your resource method, these operations are not thread safe.

Another thing that should be noted with the Jackson provider is that if we provide a ContextResolver , such as the @Laurentiu L mentioned , the Jackson provider will switch to using our ObjectMapper . In this case, if you want to use the same ObjectMapper , you can find it in Factory . for example

 public class ObjectMapperFactory implements Factory<ObjectMapper> { private final Providers providers; final ObjectMapper mapper = new ObjectMapper(); public ObjectMapperFactory(@Context Providers providers) { this.providers = providers; } @Override public ObjectMapper provide() { ContextResolver<ObjectMapper> resolver = providers.getContextResolver( ObjectMapper.class, MediaType.APPLICATION_JSON); if (resolver == null) { return mapper; } return resolver.getContext(null); } @Override public void dispose(ObjectMapper t) {} } 

In order for the above to work (use one ObjectMapper ), you need to make sure that you are using ContextResolver<ObjectMapper> , and make sure that the ContextResolver annotation matches the corresponding @Produces and @Consumes .

+5
source share

In addition to JacksonFeature, you need to register a ContextResolver for ObjectMapper.

A simple example from Documentation in 9.1.4.2. Set up and register

 @Provider public class MyObjectMapperProvider implements ContextResolver<ObjectMapper> { final ObjectMapper defaultObjectMapper; public MyObjectMapperProvider() { defaultObjectMapper = createDefaultMapper(); } @Override public ObjectMapper getContext(Class<?> type) { return defaultObjectMapper; } private static ObjectMapper createDefaultMapper() { final ObjectMapper result = new ObjectMapper(); result.configure(Feature.INDENT_OUTPUT, true); return result; } // ... } 

Full code sample available on Github

You also need to register it

  .register(MyObjectMapperProvider.class) 
+3
source share

All Articles