title: Custom Jackson ObjectMapper in Jersey 2 with Spring
body: <p>I'm having some issues migrating Jersey from 1.x to 2.x. My application uses Jersey to provide REST web services, with data served in JSON via Jackson and Spring 4 to handle the dependency injection.</p>
  
  <p>In Jersey 1.x i used to write JsonDeserializer as components managed by Spring, so i could access my services to load from the persistance layer my domain object during the deserialization, but in 2.x i'm having issues getting the injection of services in the deserializers to work. The approach i follewd was inspired by this blog post: <a href="http://www.runningasroot.com/blog/2012/05/02/autowiring-jackson-deserializers-in-spring/" rel="noreferrer">http://www.runningasroot.com/blog/2012/05/02/autowiring-jackson-deserializers-in-spring/</a></p>
  
  <p>This is dependency section of my <strong>pom.xml</strong>:</p>
  
  <pre><code>&lt;dependencies&gt;
      &lt;!-- Spring --&gt;
      &lt;dependency&gt;
          &lt;groupId&gt;org.springframework&lt;/groupId&gt;
          &lt;artifactId&gt;spring-core&lt;/artifactId&gt;
          &lt;version&gt;${spring.version}&lt;/version&gt;
      &lt;/dependency&gt;
      &lt;dependency&gt;
          &lt;groupId&gt;org.springframework&lt;/groupId&gt;
          &lt;artifactId&gt;spring-context&lt;/artifactId&gt;
          &lt;version&gt;${spring.version}&lt;/version&gt;
      &lt;/dependency&gt;
      &lt;dependency&gt;
          &lt;groupId&gt;org.springframework&lt;/groupId&gt;
          &lt;artifactId&gt;spring-web&lt;/artifactId&gt;
          &lt;version&gt;${spring.version}&lt;/version&gt;
      &lt;/dependency&gt;
      &lt;!-- Jersey --&gt;
      &lt;dependency&gt;
          &lt;groupId&gt;org.glassfish.jersey.containers&lt;/groupId&gt;
          &lt;artifactId&gt;jersey-container-servlet&lt;/artifactId&gt;
          &lt;version&gt;${jersey.version}&lt;/version&gt;
      &lt;/dependency&gt;
      &lt;dependency&gt;
          &lt;groupId&gt;org.glassfish.jersey.ext&lt;/groupId&gt;
          &lt;artifactId&gt;jersey-spring3&lt;/artifactId&gt;
          &lt;version&gt;${jersey.version}&lt;/version&gt;
      &lt;/dependency&gt;
      &lt;dependency&gt;
          &lt;groupId&gt;org.glassfish.jersey.media&lt;/groupId&gt;
          &lt;artifactId&gt;jersey-media-multipart&lt;/artifactId&gt;
          &lt;version&gt;${jersey.version}&lt;/version&gt;
      &lt;/dependency&gt;
      &lt;dependency&gt;
          &lt;groupId&gt;org.glassfish.jersey.media&lt;/groupId&gt;
          &lt;artifactId&gt;jersey-media-json-jackson&lt;/artifactId&gt;
          &lt;version&gt;${jersey.version}&lt;/version&gt;
      &lt;/dependency&gt;
      &lt;!-- Commons Codec --&gt;
      &lt;dependency&gt;
          &lt;groupId&gt;commons-codec&lt;/groupId&gt;
          &lt;artifactId&gt;commons-codec&lt;/artifactId&gt;
          &lt;version&gt;${commons-codec.version}&lt;/version&gt;
      &lt;/dependency&gt;
  
      &lt;!-- cut --&gt;
  
  &lt;dependencies&gt;
  </code></pre>
  
  <p>Jersey version is 2.7, Spring 4.0.2.RELEASE.</p>
  
  <p>This is my <strong>web.xml</strong>:</p>
  
  <pre><code>&lt;?xml version="1.0" encoding="UTF-8"?&gt;
  &lt;web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"&gt;
  
      &lt;module-name&gt;myApp/module-name&gt;
  
      &lt;listener&gt;
          &lt;listener-class&gt;org.springframework.web.context.ContextLoaderListener&lt;/listener-class&gt;
      &lt;/listener&gt;
  
      &lt;context-param&gt;
          &lt;param-name&gt;contextClass&lt;/param-name&gt;
          &lt;param-value&gt;
              org.springframework.web.context.support.AnnotationConfigWebApplicationContext
          &lt;/param-value&gt;
      &lt;/context-param&gt;
  
      &lt;context-param&gt;
          &lt;param-name&gt;contextConfigLocation&lt;/param-name&gt;
          &lt;param-value&gt;it.mgt.myApp.config.ApplicationConfig&lt;/param-value&gt;
      &lt;/context-param&gt;
  
      &lt;servlet&gt;
          &lt;servlet-name&gt;jersey-serlvet&lt;/servlet-name&gt;
          &lt;servlet-class&gt;org.glassfish.jersey.servlet.ServletContainer&lt;/servlet-class&gt;
          &lt;init-param&gt;
              &lt;param-name&gt;javax.ws.rs.Application&lt;/param-name&gt;
              &lt;param-value&gt;it.mgt.myApp.config.JerseyConfig&lt;/param-value&gt;
          &lt;/init-param&gt;
          &lt;load-on-startup&gt;1&lt;/load-on-startup&gt;
      &lt;/servlet&gt;
      &lt;servlet-mapping&gt;
          &lt;servlet-name&gt;jersey-serlvet&lt;/servlet-name&gt;
          &lt;url-pattern&gt;/api/*&lt;/url-pattern&gt;
      &lt;/servlet-mapping&gt;
  
  &lt;/web-app&gt;
  </code></pre>
  
  <p>This is my <strong>Spring configuration</strong> class:</p>
  
  <pre><code>@Configuration
  @ComponentScan({"it.mgt.myApp"})
  @PropertySource("classpath:myApp.properties")
  public class ApplicationConfig {
  
      // Cut
  
  }
  </code></pre>
  
  <p>This is my <strong>Jersey Resource config</strong> class:</p>
  
  <pre><code>public class JerseyConfig extends ResourceConfig {
  
      public JerseyConfig() {
          packages("it.mgt.myApp");
  
          register(MultiPartFeature.class);
  
          register(RequestContextFilter.class);
  
          register(ObjectMapperContextResolver.class);
          register(JacksonFeature.class);
  
          register(CorsRequestFilter.class);
          register(SignatureProcessingFilter.class);
          register(AuthorizationFeature.class);
          register(CorsResponseFilter.class);
          register(new UserBinder());
      }
  }
  </code></pre>
  
  <p>This is my <strong>ObjectMapperContextResolver</strong> class:</p>
  
  <pre><code>@Component
  @Provider
  public class ObjectMapperContextResolver implements ContextResolver&lt;ObjectMapper&gt; {
  
      @Autowired
      private SpringObjectMapper objectMapper;
  
      public ObjectMapperContextResolver() {
          super();
      }
  
      @Override
      public ObjectMapper getContext(Class&lt;?&gt; type) {
          return objectMapper;
      }
  
  }
  </code></pre>
  
  <p>I think @Provider annotation is redundant with the registrationg in the resource config class.</p>
  
  <p>This is my <strong>SpringObjectMapper</strong> class:</p>
  
  <pre><code>@Component
  public class SpringObjectMapper extends ObjectMapper {
  
      private static final long serialVersionUID = 1413033425692174337L;
  
      @Autowired
      ApplicationContext applicationContext;
  
      public SpringObjectMapper() {
          this.setSerializationInclusion(JsonSerialize.Inclusion.NON_NULL);
          this.configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, true);
      }
  
      @Override
      @Autowired
      public void setHandlerInstantiator(HandlerInstantiator hi) {
          super.setHandlerInstantiator(hi);
      }
  
  }
  </code></pre>
  
  <p>This is my <strong>SpringBeanHandlerInstantiator</strong> class:</p>
  
  <pre><code>@Component
  public class SpringBeanHandlerInstantiator extends HandlerInstantiator {
  
      private ApplicationContext applicationContext;
  
      @Autowired
      public SpringBeanHandlerInstantiator(ApplicationContext applicationContext) {
          this.applicationContext = applicationContext;
      }
  
      @Override
      public JsonDeserializer&lt;?&gt; deserializerInstance(DeserializationConfig dc, Annotated antd, Class&lt;? extends JsonDeserializer&lt;?&gt;&gt; type) {
          try {
              return (JsonDeserializer&lt;?&gt;) applicationContext.getBean(type);
          } catch (Exception e) {
          }
  
          return null;
      }
  
      @Override
      public KeyDeserializer keyDeserializerInstance(DeserializationConfig dc, Annotated antd, Class&lt;? extends KeyDeserializer&gt; type) {
          try {
              return (KeyDeserializer) applicationContext.getBean(type);
          } catch (Exception e) {
          }
  
          return null;
      }
  
      @Override
      public JsonSerializer&lt;?&gt; serializerInstance(SerializationConfig sc, Annotated antd, Class&lt;? extends JsonSerializer&lt;?&gt;&gt; type) {
          try {
              return (JsonSerializer&lt;?&gt;) applicationContext.getBean(type);
          } catch (Exception e) {
          }
  
          return null;
      }
  
      @Override
      public TypeResolverBuilder&lt;?&gt; typeResolverBuilderInstance(MapperConfig&lt;?&gt; mc, Annotated antd, Class&lt;? extends TypeResolverBuilder&lt;?&gt;&gt; type) {
          try {
              return (TypeResolverBuilder&lt;?&gt;) applicationContext.getBean(type);
          } catch (Exception e) {
          }
  
          return null;
      }
  
      @Override
      public TypeIdResolver typeIdResolverInstance(MapperConfig&lt;?&gt; mc, Annotated antd, Class&lt;? extends TypeIdResolver&gt; type) {
          try {
              return (TypeIdResolver) applicationContext.getBean(type);
          } catch (Exception e) {
          }
  
          return null;
      }
  
  }
  </code></pre>
  
  <p>This is my <strong>domain entity class</strong>, serializers and deserializers are static inner classes:</p>
  
  <pre><code>@JsonSerialize(using = User.Serializer.class)
  @JsonDeserialize(using = User.Deserializer.class)
  public class User {
  
      @Component
      public static class Serializer extends JsonSerializer&lt;User&gt; {
  
          @Override
          public void serialize(User obj, JsonGenerator jg, SerializerProvider sp) throws IOException, JsonProcessingException {
              // Cut
          }
  
      }
  
      @Component
      public static class Deserializer extends JsonDeserializer&lt;User&gt; {
  
          @Autowired
          SomeService someService;
  
          @Override
          public User deserialize(JsonParser jp, DeserializationContext dc) throws IOException, JsonProcessingException {
              User user = new User();
  
              // Cut
              // Use someService here
          }
  
      }
  
      // Cut
  
  }
  </code></pre>
  
  <p>I tried to put a brakpoint in ObjectMapperContextResolver.getContext(Class type) but it never get hit, i suspect that's the root of the problem, but after two days of attempts and studying jersey docs i'm running out of ideas.</p>
  
  <p>Anybody can point me out on how to achive this properly?</p>