How correctly and thread safe reuse Jackson ObjectReader? - java

Jackson have ObjectReader and documentation says that you need to use it for thread safety. But I can't understand how to do it correctly
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectReader;
import java.io.IOException;
import java.util.Map;
public class JsonParser {
private ObjectMapper OBJECT_MAPPER = new ObjectMapper();
private ObjectReader OBJECT_READER = new ObjectMapper().readerFor(Map.class);
public Map<String, String> parseJson1(String json) throws IOException {
ObjectReader objectReader = OBJECT_MAPPER.readerFor(Map.class);
return objectReader.readValue(json);
}
public Map<String, String> parseJson2(String json) throws IOException {
return OBJECT_READER.readValue(json);
}
}
I wrote two samples
parseJson1() - creates ObjectReader from ObjectMapper on each parsing
parseJson2() - reuses single instance on ObjectReader
Which of them is right?

Documentation said it's "fully thread-safe" it means you can use parseJson2 safely without worring about invoking this method in concurrent threads.
https://fasterxml.github.io/jackson-databind/javadoc/2.5/com/fasterxml/jackson/databind/ObjectReader.html
Uses "fluent" (or, kind of, builder) pattern so that instances are immutable (and thus fully thread-safe with no external synchronization); new instances are constructed for different configurations. Instances are initially constructed by ObjectMapper and can be reused, shared, cached; both because of thread-safety and because instances are relatively light-weight.

Related

Does com.fasterxml.jackson.databind.ObjectMapper has internal synchronization? [duplicate]

The Jackson library's ObjectMapper class seems to be thread safe.
Does this mean that I should declare my ObjectMapper as a static field like this
class Me {
private static final ObjectMapper mapper = new ObjectMapper();
}
instead of as an instance-level field like this?
class Me {
private final ObjectMapper mapper = new ObjectMapper();
}
Yes, that is safe and recommended.
The only caveat from the page you referred is that you can't be modifying configuration of the mapper once it is shared; but you are not changing configuration so that is fine. If you did need to change configuration, you would do that from the static block and it would be fine as well.
EDIT: (2013/10)
With 2.0 and above, above can be augmented by noting that there is an even better way: use ObjectWriter and ObjectReader objects, which can be constructed by ObjectMapper.
They are fully immutable, thread-safe, meaning that it is not even theoretically possible to cause thread-safety issues (which can occur with ObjectMapper if code tries to re-configure instance).
Although ObjectMapper is thread safe, I would strongly discourage from declaring it as a static variable, especially in multithreaded application.
Not even because it is a bad practice, but because you are running a heavy risk of deadlocking. I am telling it from my own experience. I created an application with 4 identical threads that were getting and processing JSON data from web services.
My application was frequently stalling on the following command, according to the thread dump:
Map aPage = mapper.readValue(reader, Map.class);
Beside that, performance was not good.
When I replaced static variable with the instance based variable, stalling disappeared and performance quadrupled. I.e. 2.4 millions JSON documents were processed in 40min.56sec., instead of 2.5 hours previously.
A trick I learned from this PR if you don't want to define it as a static final variable but want to save a bit of overhead and guarantee thread safe.
private static final ThreadLocal<ObjectMapper> om = new ThreadLocal<ObjectMapper>() {
#Override
protected ObjectMapper initialValue() {
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
return objectMapper;
}
};
public static ObjectMapper getObjectMapper() {
return om.get();
}
credit to the author.
Although it is safe to declare a static ObjectMapper in terms of thread safety, you should be aware that constructing static Object variables in Java is considered bad practice. For more details, see Why are static variables considered evil? (and if you'd like, my answer)
In short, statics should be avoided because the make it difficult to write concise unit tests. For example, with a static final ObjectMapper, you can't swap out the JSON serialization for dummy code or a no-op.
In addition, a static final prevents you from ever reconfiguring ObjectMapper at runtime. You might not envision a reason for that now, but if you lock yourself into a static final pattern, nothing short of tearing down the classloader will let you re-initialize it.
In the case of ObjectMapper its fine, but in general it is bad practice and there is no advantage over using a singleton pattern or inversion-of-control to manage your long-lived objects.
com.fasterxml.jackson.databind.type.TypeFactory._hashMapSuperInterfaceChain(HierarchicType)
com.fasterxml.jackson.databind.type.TypeFactory._findSuperInterfaceChain(Type, Class)
com.fasterxml.jackson.databind.type.TypeFactory._findSuperTypeChain(Class, Class)
com.fasterxml.jackson.databind.type.TypeFactory.findTypeParameters(Class, Class, TypeBindings)
com.fasterxml.jackson.databind.type.TypeFactory.findTypeParameters(JavaType, Class)
com.fasterxml.jackson.databind.type.TypeFactory._fromParamType(ParameterizedType, TypeBindings)
com.fasterxml.jackson.databind.type.TypeFactory._constructType(Type, TypeBindings)
com.fasterxml.jackson.databind.type.TypeFactory.constructType(TypeReference)
com.fasterxml.jackson.databind.ObjectMapper.convertValue(Object, TypeReference)
The method _hashMapSuperInterfaceChain in class com.fasterxml.jackson.databind.type.TypeFactory is synchronized.
Am seeing contention on the same at high loads.
May be another reason to avoid a static ObjectMapper
This question may be old, but here's what I do.
Hold the ObjectMapper instance in a thread-safe singleton:
public final class JacksonObjectMapperHolder {
private static volatile JacksonObjectMapperHolder INSTANCE;
private static final Object MUTEX = new Object();
public static JacksonObjectMapperHolder getInstance() {
JacksonObjectMapperHolder instance = INSTANCE;
if(instance == null) {
synchronized(MUTEX) {
instance = INSTANCE;
if(instance == null) {
INSTANCE = instance = new JacksonObjectMapperHolder();
}
}
}
return instance;
}
private final ObjectMapper objectMapper = new ObjectMapper();
private JacksonObjectMapperHolder() {
super();
}
public final ObjectMapper getObjectMapper() {
return objectMapper;
}
}

Infinite recursion when deserializing with Jackson and Mockito

I am trying to generically print any object with mapper.writeValueAsString but I am facing a infinite recursion when deserializing objects with Mockito and Jackson. The objects I am trying to deserialize perform underlying Hibernate calls to DBs etc and I have no control over the classes themselves.
Currently I am using the following versions of Mockito and Jackson but the same is happening for older 1.X versions of Jackson.
Mockito: org.mockito:mockito-all:jar:1.9.5:compile
Jackson: com.fasterxml.jackson.core:jackson-databind:jar:2.9.7:compile
As specified, I cannot modify the underlying classes with annotation such as #JsonIgnore because they are outside dependencies not under my control. I also cannot create mixins for my user case because I am trying to generically print the contents of any object that is sent in.
I have tried adding the DeserializationConfig FAIL_ON_UNKNOWN_PROPERTIES to false in older Jackson version and I have tried setting the DeserializationFeature FAIL_ON_MISSING_CREATOR_PROPERTIES to false.
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
public static PrintUtil {
public static String printJSON(Object obj) {
String printstring = "printfailed";
try {
ObjectMapper mapper = new ObjectMapper();
LOG.debug("formatted JSON String ");
printstring = mapper.writeValueAsString(obj);
} catch (JsonProcessingException e) {
e.printStackTrace();
}
return printstring;
}
}
The infinite recursion terminal output is seen when running Mockito tests for methods that contain Log4j statements which in turn call the PrintUtil function. The statement e.printStackTrace() begins printing while running the tests.
Most of the object that are being sent to this utility method are JAXB XML Service Response Objects.
Without being able to modify the classes themselves, I see two possible solutions.
1) Wrap the objects into objects you own as suggested by #TheHeadRush and annotate it appropriately. I would suggest using #JsonIdentityInfo so the objects serialize to their ID, rather than being ignored completely with #JsonIgnore.
2) Use a custom deserializer for the object which is causing the recursion. Here is an example:
public class CustomDeserializer extends StdDeserializer<MyObject>{
// Add constructors as necessary.
#Override
public List<Item> deserialize(
JsonParser jsonparser,
DeserializationContext context)
throws IOException, JsonProcessingException {
return null; // Return something that won't recurse here.
}
}
Then register the deserializer with the ObjectMapper you are using:
// Register the deserializer:
SimpleModule module = new SimpleModule()
.addDeserializer(MyObject.class, new CustomDeserializer());
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.registerModule(module);

Correct design to construct an object

I have a major design concern about my specific use-case in object construction.
I am constructing an object MyMessage based on the value of the com.fasterxml.jackson.databind.JsonNode object. For that purpose, of course, the ObjectMapper is used, so the actual construction snippet would look something like following:
JsonNode json = JsonLoader.fromResource("msg.json");
MyMessage m = jsonMapper.treeToValue(json, MyMessage.class);
Here the jsonMapper variable is of the type ObjectMapper.
Now, I would like MyMessage to only be able to construct from a static factory method, and keep the actual constructor private (as it has way too many fields). So the preferred construction would like this:
MyMessage m = MyMessage.createFromJson(json);
Here a json variable is of type JsonNode.
And that is where the problem begins. Obviously, ObjectMapper instance is needed to construct the object from JSON, and I would try to avoid it being passed-in by the client code.
Now, making ObjectMapper as a private (static) field of MyMessage comes to mind, and have something like this:
private static final ObjectMapper jsonMapper = new ObjectMapper();
private MyMessage(/* many fields */){/* ctor code */}
public MyMessage createFromJson(JsonNode json) {
return jsonMapper.treeToValue(json, MyMessage.class)
}
But here the problem is that I want the ObjectMapper object to be singleton for my entire application, and used not only for constructing MyMessage object, but also different kind of Message objects such as YourMessage, SomeOtherMessage, etc.
The problem with having many (static) instances of ObjectMapper is that I will have very large number of different Message classes, and many instances per class. So this would be very memory inefficient.
The Question
What is the closest I can get to have both a singleton ObjectMapper and a static factory method? Or maybe you could suggest some other design idea (I don't know if a builder pattern could help somehow) that would suit my use-case?
I'd suggest you move away from the static factory method restriction, and have a Factory that creates your messages, and make that class have a reference to your singleton ObjectMapper:
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
final class MessagesFactory {
private final ObjectMapper objectMapper;
// This constructor is a great candidate for DI
MessagesFactory(final ObjectMapper objectMapper) {
this.objectMapper = objectMapper;
}
<T extends Message> T createFromJson(
final JsonNode json, final Class<T> messageClass
) throws JsonProcessingException {
return objectMapper.treeToValue(json, clazz);
}
}
Then, wherever you need it, you can do:
MyMessage m1 = messagesFactory.createFromJson(json, MyMessage.class);
MyMessage2 m2 = messagesFactory.createFromJson(otherJson, MyMessage2.class);

IllegalStateException occurs when using Jackson #JsonDeserialize annotation

I'm trying to use a custom deserializer in Jackson to deserialize some json objects. However, when I try to have the ObjectMapper read the json, the following exception occurs:
java.lang.IllegalStateException: AnnotationIntrospector returned Class com.Geometry.GeometryDeserializer; expected Class<JsonDeserializer>
I'm somewhat at a loss of what to do here, since it seems like the AnnotationIntrospector is complaining that my GeometryDeserializer is not a subclass of JsonDeserializer, when it clearly is.
Here's where I create the Object Mapper:
public void deserializeJson(String json) {
ObjectMapper mapper = new ObjectMapper();
mapper.addMixInAnnotations(Feature.class, MixIn.class);
Feature feature = mapper.readValue(json, Feature.class);
}
...my Mix In class:
abstract class MixIn {
#JsonDeserialize(using=GeometryDeserializer.class)
abstract void setGeometry(Geometry geometry);
}
...and my deserializer:
public class GeometryDeserializer extends JsonDeserializer<Geometry> {
#Override
public Geometry deserialize(JsonParser jp, DeserializationContext dc) throws IOException, JsonProcessingException {
//stuff happens
}
}
Any feedback/assistance would be greatly appriciated.
Thanks.
Wild guess: you are accidentally mixing up Jackson 1.x and Jackson 2.x types? Class names are mostly the same, but live in different packages -- things work when using one set of classes, but IDEs may cause accidental mix-ups.

Should I declare Jackson's ObjectMapper as a static field?

The Jackson library's ObjectMapper class seems to be thread safe.
Does this mean that I should declare my ObjectMapper as a static field like this
class Me {
private static final ObjectMapper mapper = new ObjectMapper();
}
instead of as an instance-level field like this?
class Me {
private final ObjectMapper mapper = new ObjectMapper();
}
Yes, that is safe and recommended.
The only caveat from the page you referred is that you can't be modifying configuration of the mapper once it is shared; but you are not changing configuration so that is fine. If you did need to change configuration, you would do that from the static block and it would be fine as well.
EDIT: (2013/10)
With 2.0 and above, above can be augmented by noting that there is an even better way: use ObjectWriter and ObjectReader objects, which can be constructed by ObjectMapper.
They are fully immutable, thread-safe, meaning that it is not even theoretically possible to cause thread-safety issues (which can occur with ObjectMapper if code tries to re-configure instance).
Although ObjectMapper is thread safe, I would strongly discourage from declaring it as a static variable, especially in multithreaded application.
Not even because it is a bad practice, but because you are running a heavy risk of deadlocking. I am telling it from my own experience. I created an application with 4 identical threads that were getting and processing JSON data from web services.
My application was frequently stalling on the following command, according to the thread dump:
Map aPage = mapper.readValue(reader, Map.class);
Beside that, performance was not good.
When I replaced static variable with the instance based variable, stalling disappeared and performance quadrupled. I.e. 2.4 millions JSON documents were processed in 40min.56sec., instead of 2.5 hours previously.
A trick I learned from this PR if you don't want to define it as a static final variable but want to save a bit of overhead and guarantee thread safe.
private static final ThreadLocal<ObjectMapper> om = new ThreadLocal<ObjectMapper>() {
#Override
protected ObjectMapper initialValue() {
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
return objectMapper;
}
};
public static ObjectMapper getObjectMapper() {
return om.get();
}
credit to the author.
Although it is safe to declare a static ObjectMapper in terms of thread safety, you should be aware that constructing static Object variables in Java is considered bad practice. For more details, see Why are static variables considered evil? (and if you'd like, my answer)
In short, statics should be avoided because the make it difficult to write concise unit tests. For example, with a static final ObjectMapper, you can't swap out the JSON serialization for dummy code or a no-op.
In addition, a static final prevents you from ever reconfiguring ObjectMapper at runtime. You might not envision a reason for that now, but if you lock yourself into a static final pattern, nothing short of tearing down the classloader will let you re-initialize it.
In the case of ObjectMapper its fine, but in general it is bad practice and there is no advantage over using a singleton pattern or inversion-of-control to manage your long-lived objects.
com.fasterxml.jackson.databind.type.TypeFactory._hashMapSuperInterfaceChain(HierarchicType)
com.fasterxml.jackson.databind.type.TypeFactory._findSuperInterfaceChain(Type, Class)
com.fasterxml.jackson.databind.type.TypeFactory._findSuperTypeChain(Class, Class)
com.fasterxml.jackson.databind.type.TypeFactory.findTypeParameters(Class, Class, TypeBindings)
com.fasterxml.jackson.databind.type.TypeFactory.findTypeParameters(JavaType, Class)
com.fasterxml.jackson.databind.type.TypeFactory._fromParamType(ParameterizedType, TypeBindings)
com.fasterxml.jackson.databind.type.TypeFactory._constructType(Type, TypeBindings)
com.fasterxml.jackson.databind.type.TypeFactory.constructType(TypeReference)
com.fasterxml.jackson.databind.ObjectMapper.convertValue(Object, TypeReference)
The method _hashMapSuperInterfaceChain in class com.fasterxml.jackson.databind.type.TypeFactory is synchronized.
Am seeing contention on the same at high loads.
May be another reason to avoid a static ObjectMapper
This question may be old, but here's what I do.
Hold the ObjectMapper instance in a thread-safe singleton:
public final class JacksonObjectMapperHolder {
private static volatile JacksonObjectMapperHolder INSTANCE;
private static final Object MUTEX = new Object();
public static JacksonObjectMapperHolder getInstance() {
JacksonObjectMapperHolder instance = INSTANCE;
if(instance == null) {
synchronized(MUTEX) {
instance = INSTANCE;
if(instance == null) {
INSTANCE = instance = new JacksonObjectMapperHolder();
}
}
}
return instance;
}
private final ObjectMapper objectMapper = new ObjectMapper();
private JacksonObjectMapperHolder() {
super();
}
public final ObjectMapper getObjectMapper() {
return objectMapper;
}
}

Categories

Resources