Correct design to construct an object - java

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);

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);

How correctly and thread safe reuse Jackson ObjectReader?

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.

Use #JacksonInject with #JsonCreator on a top level map

With Jackson json library, it is possible to deserialize object through the use of the #JsonCreator, and be given the "top level" map representing the input json, as follows:
class MyClass {
final int field;
#JsonCreator
public MyClass(Map<String, Object> map) {
this.field = (int) map.get("theInt");
}
}
or even on a static factory method:
class MyClass {
final int field;
public MyClass(int theInt) {
this.field = theInt;
}
#JsonCreator
static MyClass create(Map<String, Object> map) {
return new MyClass((int) map.get("theInt"));
}
}
The previous examples can process the following kind of json input:
{
"key1":"value1",
"key2":"value2",
"key3":"value3"
}
This is particularly useful in my case because I would like to deserialize a json which structure I don't know. Being given access to what I call the "top level map" makes things simple.
I would like to deserialize my objects this way as it also allows to create immutable objects, instead of using #JsonAnySetter which doesn't permit this, and #JsonProperty which I can't use as I don't know the properties name in advance as I mentioned earlier.
Then to go further, I would like to inject some configuration in my factory method, and Jackson allows this through the use of #JacksonInject and a call to withInjectableValues(InjectableValues) on the ObjectMapper.
This is eventually the kind of code I would like to use:
class MyClass {
final MyField[] myFields;
public MyClass(MyField... myFields) {
this.myFields = myFields;
}
#JsonCreator
static MyClass create(#JacksonInject("conf") Conf conf, Map<String, Object> map) {
MyFields[] myFields;
// initialize myFields (or any other object) based on the content of map
// and also make use of the inject conf
return new MyClass(myFields);
}
}
Unfortunately, Jackson throws the following kind of exceptions:
when trying the trick on the constructor
JsonMappingException: Argument #1 of constructor [constructor for MyClass, annotations: {JsonCreator=#JsonCreator()}] has no property name annotation; must have name when multiple-paramater constructor annotated as Creator
when trying the trick on the factory method
JsonMappingException: Argument #1 of factory method [method create, annotations: {JsonCreator=#JsonCreator()}] has no property name annotation; must have when multiple-paramater static method annotated as Creator
Does anyone know how I could solve the problem?
To sum up the requirements, I need:
access to the top level map (don't know the json property names in advance)
to create an immutable object (so can't use #JsonAnySetter)
to inject some conf to the #JsonCreator decorated constructor or factory method
I cannot change the json input format, which looks like this:
{
"key1":"value1",
"key2":"value2",
"key3":"value3"
}
[EDIT]
This is a known issue: http://jira.codehaus.org/browse/JACKSON-711 (not fixed yet)
Right, you would like to both use "delegating" creator (single argument, into which JSON input is first bound) -- different from "property-based" creator where set of named parameters are passed -- and injectable value(s). This should ideally work, but I think it might not work currently.
I think there is a Jira entered for this, so you can check it (http://jira.codehaus.org/browse/JACKSON) out.
Just to make sure: are you using version 1.9.2? There have been some fixes in this are since 1.9.0; which at least would give better error message.

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