Configure Morphia to work without a default constructor

In my current project we’re migrating our existing entity model to MongoDB and have turned to Morphia for mapping our Java objects to and from its MongoDB representation. Our Java entities are immutable and preferably we’d like to keep it that way. Morphia, like most other mapping frameworks, require us to have a default constructor but it doesn’t require it to be public. So a work-around would be to have a private constructor that’s used only by Morphia:

It’s quite unfortunate that we have to clutter all our entity models with a private constructor that we really don’t want so what are our options? On the bright side Morphia allows us to configure a lot of things and one of these is the ability to specify a new ObjectFactory. The ObjectFactory is responsible for instantiating Java objects in Morphia. If you don’t want to implement all methods in the interface yourself it’s possible to extend the DefaultCreator and override the createInstance method. Next we’re going to make use of a trick in the JVM that allows us to instantiate an object without invoking any constructor:

ReflectionFactory is located in the sun.reflect package so it’s not guaranteed to work in other JVM’s than SUN/Oracle but other vendors does implement this class as well. If you want to be on the safe side you should use the Objenesis framework that deals solely with this issue.

Now since the constructor is not invoked the state inside the object is left uninitialized (all fields are null). For the entities themselves this is no problem since Morphia will set the internal state using reflection after the constructor is invoked but the problem is that the state itself is also constructed using the same ObjectFactory. In the example above it means that the List called something will not be initialized properly. What we can do to solve this is to simply check if the class has a default constructor and if so, use it! We can implement this check in a method like this:

Putting it all together and we have our own custom ObjectFactory:

There’s only one thing missing, how do we tell Morphia to use our ObjectFactory? Here’s one way:

That’s it! Now you can remove the redundant default constructor from all your entities.

This Post Has 6 Comments

  1. Thanks Johan. Exactly what I was looking for.

  2. Great post, great to get rid of redundant code only needed for third party frameworks!

  3. Great post, thanks a lot, works like a charm.
    That’s exactly what I needed.

    Thanks Johan.

  4. Great job. I had a similar situation, so you just save me a lot of time :)

  5. You saved me! I was considering using Jackson for serialization to a Map and then convert it to a Document, but it necessitate a default constructor too.

    1. Thanks for your kind words

Leave a Reply

Close Menu