1

I'm using below code from this link to add custom de-serializer for one of my data model class (JSON to JAXB models conversion).

I would like to use com.fasterxml.jackson.jaxrs.json.JacksonJaxbJsonProvider for my JSON serialization/de-serialization for other data models.

The default implementation of JacksonJaxbJsonProvider works perfectly for my JAXB models with super class as abstract class. But once I have provided my own custom ObjectMapper (as shown below), the default implementation of JacksonJaxbJsonProvider is not used. i.e the JAXB annotations and fields declared for my abstract class are not converted properly by Custom ObjectMapper as it cannot find the fields declared in abstract class.

So I would like to use the custom ObjectMapper and the default implementation of JacksonJaxbJsonProvider at the same time depending on the JAXB model in question.

40  package org.glassfish.jersey.examples.jackson;
41  
42  import javax.ws.rs.ext.ContextResolver;
43  import javax.ws.rs.ext.Provider;
44  
45  import com.fasterxml.jackson.databind.AnnotationIntrospector;
46  import com.fasterxml.jackson.databind.DeserializationFeature;
47  import com.fasterxml.jackson.databind.ObjectMapper;
48  import com.fasterxml.jackson.databind.SerializationFeature;
49  import com.fasterxml.jackson.databind.introspect.JacksonAnnotationIntrospector;
50  import com.fasterxml.jackson.databind.type.TypeFactory;
51  import com.fasterxml.jackson.module.jaxb.JaxbAnnotationIntrospector;
52  
53  /**
54   * TODO javadoc.
55   *
56   * @author Jakub Podlesak (jakub.podlesak at oracle.com)
57   */
58  @Provider
59  public class MyObjectMapperProvider implements ContextResolver<ObjectMapper> {
60  
61      final ObjectMapper defaultObjectMapper;
62      final ObjectMapper combinedObjectMapper;
63  
64      public MyObjectMapperProvider() {
65          defaultObjectMapper = createDefaultMapper();
66          combinedObjectMapper = createCombinedObjectMapper();
67      }
68  
69      @Override
70      public ObjectMapper getContext(final Class<?> type) {
71  
72          if (type == CombinedAnnotationBean.class) {
73              return combinedObjectMapper;
74          } else {
75              return defaultObjectMapper;
76          }
77      }
78  
79      private static ObjectMapper createCombinedObjectMapper() {
80          return new ObjectMapper()
81                  .configure(SerializationFeature.WRAP_ROOT_VALUE, true)
82                  .configure(DeserializationFeature.UNWRAP_ROOT_VALUE, true)
83                  .setAnnotationIntrospector(createJaxbJacksonAnnotationIntrospector());
84      }
85  
86      private static ObjectMapper createDefaultMapper() {
87          final ObjectMapper result = new ObjectMapper();
88          result.enable(SerializationFeature.INDENT_OUTPUT);
89  
90          return result;
91      }
92  
93      private static AnnotationIntrospector createJaxbJacksonAnnotationIntrospector() {
94  
95          final AnnotationIntrospector jaxbIntrospector = new JaxbAnnotationIntrospector(TypeFactory.defaultInstance());
96          final AnnotationIntrospector jacksonIntrospector = new JacksonAnnotationIntrospector();
97  
98          return AnnotationIntrospector.pair(jacksonIntrospector, jaxbIntrospector);
99      }
100 }
ulab
  • 1,079
  • 3
  • 15
  • 45
  • 1
    You have the process confused. The ObjectMapper does not use the Provider. The Provider uses the mapper. That being said, your question doesn't completely make sense. Maybe the grammar is confusing me. Can you try and rephrase the question. Pretty much try to clean up the third paragraph. It is a little unclear exactly what you are trying to accomplish, and why the code you provided will not work for you – Paul Samsotha Apr 12 '16 at 06:09
  • @Meiko You linked to this same question – Paul Samsotha Apr 12 '16 at 06:10
  • @peeskillet :-D oh yes... was too late yesterday... this one: http://stackoverflow.com/questions/18872931/custom-objectmapper-with-jersey-2-2-and-jackson-2-1 – Meiko Rachimow Apr 12 '16 at 07:07
  • @peeskillet sorry I edited it. Can you tell me if this is ok ? I can explain in that case. – ulab Apr 12 '16 at 07:49
  • And the example you provided (or something similar) does not work for you? – Paul Samsotha Apr 12 '16 at 07:52
  • yes it is similar. When the JSON is read using `response.readEntity()` as part of testcase, looks like default implementation is not called. – ulab Apr 12 '16 at 08:19
  • 1
    Is the `getContext` method even being called? If not, you might need to register the resolver with the client – Paul Samsotha Apr 12 '16 at 08:23
  • yes you are right. It is not called. But I have registered the provider packages with property `jersey.config.server.provider.packages` Is there something else ? – ulab Apr 12 '16 at 08:28
  • additional info : If I remove custom resolver in client side, then default implementation kicks in and it resolved the entity perfectly. `jersey.config.server.provider.classnames` property with `com.fasterxml.jackson.jaxrs.json.JacksonJaxbJsonProvider`. But with both properties, I dont see the getContext getting called and it fails with unknown property available in abstract class – ulab Apr 12 '16 at 08:41
  • You need to register the resolver for the server also. You can use the same `...classnames` property. You can have more than one class in the value. Just split them with a comma – Paul Samsotha Apr 12 '16 at 08:44
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/108897/discussion-between-peeskillet-and-ulab). – Paul Samsotha Apr 12 '16 at 08:45

1 Answers1

2

This call

.setAnnotationIntrospector(createJaxbJacksonAnnotationIntrospector());

is what adds the JAXB support for the combinedObjectMapper. So if you want the JAXB support for the defaultObjectMapper, just add the same call.

final ObjectMapper result = new ObjectMapper();
result.setAnnotationIntrospector(createJaxbJacksonAnnotationIntrospector());
Paul Samsotha
  • 205,037
  • 37
  • 486
  • 720