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 }