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 }