View Javadoc
1   package org.kuali.common.httplib.inject;
2   
3   import static com.fasterxml.jackson.databind.SerializationFeature.FAIL_ON_EMPTY_BEANS;
4   
5   import javax.inject.Inject;
6   import javax.inject.Provider;
7   
8   import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
9   import com.fasterxml.jackson.databind.ObjectMapper;
10  
11  public final class ObjectMapperProvider implements Provider<ObjectMapper> {
12  
13      @Inject
14      public ObjectMapperProvider(ObjectMapper mapper) {
15          this.mapper = mapper.copy();
16      }
17  
18      private final ObjectMapper mapper;
19  
20      @Override
21      public ObjectMapper get() {
22          mapper.configure(FAIL_ON_EMPTY_BEANS, false); // Some exceptions contain beans with no properties
23          mapper.addMixIn(Throwable.class, ThrowableMixin.class);
24          return mapper.copy();
25      }
26  
27      // Doing this so Jackson doesn't fail on exceptions that aren't json friendly
28      // Jackson ships with the ability to serialize/deserialize all the "normal" elements of any exception
29      // The message and stacktrace always get handled perfectly.
30      // However, some exceptions are odd ducks.
31      // For example: java.io.InterruptedIOException declares a public int called "bytesTransferred" with no getter/setter methods.
32      // Thus we ignore unknown properties so as to prevent ourselves from blowing up when converting from json -> object.
33      // Ignoring unknown properties is lossy, ie "extra" properties of an exception get lost when cycling from object -> json -> object.
34      // However, we won't blow up on funky exceptions containing properties that jackson doesn't know how to handle,
35      // and the stacktrace and message both stay intact
36      // It would be better to take advantage of Jackson's ability to preserve the specific type of
37      // exception using mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
38      // but there is some kind of issue with that and Guava's Optional class.
39      // serializing/deserializing Optional<IOException> doesn't work correctly
40      @JsonIgnoreProperties(ignoreUnknown = true)
41      private static interface ThrowableMixin {}
42  
43  }