80

I am happy with how the ObjectMapper works and general use within my application. What I would like to understand is the best way to implement the ObjectMapper to ensure it is re-used and I'm not creating unnecessary instances within my application?

My thoughts are that I can declare the ObjectMapper in a Utils class as follows:

public class Utils {

    public final static ObjectMapper mapper = new ObjectMapper();

}

I could then reference this from the various places I need to using code such as:

JsonSimple jsonSimple = Utils.mapper.readValue(jsonString, JsonSimple.class);

I came across this other question (Should I declare Jackson's ObjectMapper as a static field?) that prompted my approach. I think maybe the key difference is that I want to share my ObjectMapper instance across many different classes, not just within a single class.

Does this approach sound appropriate or am I missing something?

Thanks

Community
  • 1
  • 1
nickebbitt
  • 1,711
  • 1
  • 13
  • 13
  • http://wiki.fasterxml.com/JacksonBestPracticesPerformance "thread-safe provided that configuration is done before any use (and from a single thread)" – Christophe Roussy Jul 24 '17 at 08:22

4 Answers4

62

It's fine to use a single instance per application provided you don't call any configuration methods after it's been made visible i.e. you should do all your initialization inside a static block.

RokL
  • 2,663
  • 3
  • 22
  • 26
  • 1
    thanks for your reply - in my use case at the moment I don't require any configuration to be performed. Would it be appropriate to have a standard ObjectMapper for most cases, and in the future, if scenarios arise requiring additional configuration, declare a new instance for that purpose? – nickebbitt Sep 04 '13 at 14:42
  • 5
    Yes. Also note that with Jackson 2.x, you can use `ObjectMapper` as sort of factory for light-weight and 100% thread-safe (immutable) `ObjectReader` and `ObjectWriter` objects -- these are cheap to create, and always thread-safe, no matter how they are used. – StaxMan Sep 06 '13 at 05:57
  • 2
    Ah right, I reckon ObjectReader will suit my case better then. Cheers all – nickebbitt Sep 06 '13 at 08:47
17

As posted in other answers, the ObjectMapper is indeed Thread safe. But reusing the same object can decrease the performance of your application, since all - 1 threads can be locked at a given time waiting for the owner of the lock to complete the serialization/deserialization of JSON.

This is especially critical on web servers such as Jetty or Tomcat: the overall performance of the entire server can be compromised, for instance, if you use the singleton ObjectMapper as entry/exit point of REST services - depending, of course, on your access load.

So, my suggestion is to use a pool of ObjectMappers, to allow multiple Threads to use it, and in a way you don't have to recreate the mappers every time you need them. The number to ObjectMappers in the pool should be the same number of worker Threads of your application.

More about: http://jackson-users.ning.com/forum/topics/pooling-objectmapper-for-performance

-- EDIT --

Ok, some users are really passionate about the Jackson lib to the point that they downvote this answer without even looking at the linked website. Anyway, this answer is based on my experience with the lib without any modifications (just using ObjectMapper, no extra classes, no custom serializer, no custom JSONFactory, nothing) at the time of the answer (2013). I don't use it anymore on my projects so I don't know about newer versions - but I guess it should be solved by now.

As developer, if you're going to use Jackson or any other JSON reader/writer on your project, directly or indirectly, consider running a profiling tool on your server to see how the threads behave on high load. It's a simple step that doesn't harm.

Gilberto Torrezan
  • 5,113
  • 4
  • 31
  • 50
  • I'll definitely consider this if I experience the problems that you describe - thanks – nickebbitt Sep 05 '13 at 13:08
  • 14
    No, description does not make any sense -- what lock? Where? Added by whom? `ObjectMapper` does NOT have global locks that would have this effect and original question did not suggest such locking. So the idea of pooling would be adding complexity for no benefit that I can see. – StaxMan Sep 06 '13 at 05:52
  • 4
    @StaxMan Please see the related link. I tested myself an application with thousands of requests per second using REST with Jackson as serializer/deserializer, and profiling the code I found the Jackson lib was locking the threads (ensuring the Thread safety) internally. I think developers should be aware of this kind of issue when scaling their applications. I just don't understand why you down voted all the answers here - **that** doesn't make sense. – Gilberto Torrezan Sep 09 '13 at 15:32
  • 7
    I have read the linked to answer and it seems to be you that does not understand it -- this problem is (a) NOT due to `ObjectMapper` (it'd be `JsonFactory`) and (b) ALWAYS been shown (so far) to be due to OTHER problem, such as developer not closing `JsonParser`s used. It is completely orthogonal to your claims; and this is why I have voted down 2 of existing answers; they are basically FUD. – StaxMan Sep 10 '13 at 00:33
  • Aside from above points, please do report your findings -- I do not recall seeing your data points on mailing list. As I said, so far all profiling wrt String canonicalization have been shown to be caused by other sub-optimal usage. And I do not recall other places where measurable thread contention would be found; neither directly by my own usage nor by anyone from large user community. I do not vote down answers that show actual data, reproduction but your answer is vague and does not give any concrete details; and link is mostly irrelevant as well. – StaxMan Sep 10 '13 at 00:36
  • @StaxMan That's a matter of using the right tool for the right job: since I was in need of performance (thousands of requests per second), I dropped all the REST and Jackson in favour of protocol buffers. Problem solved for my case. By the way this conversation is highly off-topic, but I won't remove the answer since I still think it's valuable to developers to think about thread contention when using singleton serializers/deserializers. – Gilberto Torrezan Sep 10 '13 at 14:18
  • @GilbertoTorrezan FWIW, yes, thinking about contention is useful. As to protobuf vs Jackson/JSON: you are doing it again -- based on YOUR ASSUMPTIONS you CLAIM you "need" protobuf. Jackson/JSON can absolutely handle tens of thousands of encoding/decoding requests per second; as per `jvm-serializers` project. As can protobuf, thrift, and many other codecs listed there; all doing above 100k/sec. You do not "need" to change to PB for that. I doubt it makes much different at all for most services; possibly including yours. But I guess that's all there's to say about this subject. – StaxMan Sep 10 '13 at 17:39
  • 3
    I had the same problem as @GilbertoTorrezan. When using Jetty 8 and Tomcat there were severe problems (several over 100 miliseconds events of threads waiting locks showed by JProfiler inside calls to ObjectMapper) when several threads where trying to serialize. My solution was to switch to Thrift and if you analyse it's generated / library code there isint any Syncronized block, and voila! problem solved! – Thiago Born Sep 10 '13 at 20:48
  • 2
    Does this still hold true, because I see it does not require any synchronization. http://fasterxml.github.io/jackson-databind/javadoc/2.1.0/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."_ – kisna Aug 20 '15 at 20:05
  • Your concern is valid. There is a concern about ObjectMapper internal synchronization. Yes, it is thread-safe, however accessive internal synchronization is harmful to resource and performance perspectives. This risk most probably won't be captured by the unit test. – Awan Biru Feb 19 '21 at 17:49
8

Use the latest version of Jackson and use ObjectReader and ObjectWriter instead of ObjectMapper

talebisia
  • 91
  • 1
  • 4
3

The plain static singleton you proposed in your question is correct. An alternative approach would be to use the singleton pattern (the use of singleton pattern been discussed at length in answer comments to a similar question). Here's a simple example:

public enum Mapper {
  INSTANCE;
  private final ObjectMapper mapper = new ObjectMapper();

  private Mapper(){
    // Perform any configuration on the ObjectMapper here.
  }

  public ObjectMapper getObjectMapper() {
    return mapper;
  }
}

Then you can use (and reuse) the ObjectMapper singleton as follows:

ObjectMapper mapper = Mapper.INSTANCE.getObjectMapper();
JsonSimple jsonSimple = mapper.readValue(jsonString, JsonSimple.class);

This is safe as ObjectMapper is thread-safe after configuration.

Caveat: As @StaxMan points out in the answer comments, this does NOT guarantee against further (re)configuration on the returned singleton.

Community
  • 1
  • 1
lorcan
  • 3,280
  • 3
  • 24
  • 31
  • thanks for your answer, it definitely provides me with an implementation option...unfortunately I can't up-vote it but I would if I could. – nickebbitt Sep 05 '13 at 13:08
  • 4
    I do not see why this would be an improvement over using plain static singleton -- please note that this does NOT guarantee against further (re)configuration; caller can still call config methods. To protect against that, wrapper would need to define its own methods and NOT expose underlying `ObjectMapper`. So what is the actual point here? – StaxMan Sep 10 '13 at 00:38
  • Thanks for the comment @StaxMan. Your point on the singleton's exposure of config methods is important. – lorcan Sep 10 '13 at 08:06