<img height="1" width="1" style="display:none" src="https://www.facebook.com/tr?id=1194005000700189&amp;ev=PageView&amp;noscript=1">
VizuriBlogHero.jpg

From Vizuri's Experts

Java & Mongo Object-Document Mappers with Morphia

Morphia - A Java-based Object Document Mapper (ODM) Framework for MongoDB

Morphia is a lighter weight framework for mapping Java objects from / to MongoDB. Unlike Spring Data and Hibernate OGM, Morphia only works with Mongo.

Recently there have been a lot of presentations around the use of Morphia to manage POJOs with MongoDB. Some good presentations by 10Gen to take a look at are:

MongoDB on the JVM
Simplifying Persistence for Java and MongoDB

Features

From the Morphia project site, the main goals are to:

  • Type-safe/preserving: we deal with POJOs -- java classes and fields

  • Annotation based configuration (less code)

  • Easy to use Query interface (intuitive)

  • Flexibility in your domain objects (reduce the need for DTO/DMOs)

  • Fast enough never to give up on the items above to change your programming style

In addition, Morphia aligns with our focus to implement the Data MapperUnit of WorkIdentity MapForeign Key Mapping patterns that we identified earlier.

Morphia in Action

NOTE: For most of the code examples, we will only show relevant snippets. The complete project is available via the Vizuri Mongo-ODM Github repository.

Prerequisites

The standard set of tools used as part of our evaluation are as follows:
Apache Maven
Eclipse (or your favorite I D E)
MongoDB - Setup Instructions are available here

Dependencies

To get the started, lets create a Maven project and add in the Mongo drivers and Morphia libraries.

As a Maven best practice, we've defined the versions in the properties section. This simplifies incrementing versions across projects. The relevant properties we have set here are:

<properties>  
    <mongodb.driver.version>2.7.2</mongodb.driver.version>  
    <morphia.version>0.98</morphia.version>
</properties>

And the libraries that we'll add to the dependencies section are:

<!-- MongoDB Java Driver -->
    <dependency>
    <groupId>org.mongodb</groupId>
    <artifactId>mongo-java-driver</artifactId>
    <version>${mongodb.driver.version}</version>
    <type>jar</type>
    <scope>compile</scope>
</dependency>

<!-- Morphia - ODM for MongoDB -->
<dependency>
    <groupId>com.google.code.morphia</groupId>
    <artifactId>morphia</artifactId>
    <version>${morphia.version}</version>
    </dependency>    
Domain Model

Rather than pollute all of the objects in our Domain Model with code to manage the Identity Map ID for our field, we're going to create a 'BaseEntity' to use globally.

The entire class is in the copy at GitHub, but essentially its an abstract class that defines the ID and Version properties that out other entities will inherit.

If you're familiar with JPA, the @ID annotation is the key for the object. The @Property annotation is equivalent to the @Column in JPA.

package com.vizuri.mongo.odm.morphia.model;

import java.io.Serializable;
...

public abstract class BaseEntity implements Serializable {

... 

   @Id
   @Property("id")     //NOTE:  The id field must map to the _id field in MongoDB.  This property is added to illustrate the mapping, but is unnecessary.  Only @Id is needed.
   protected ObjectId id;

   public ObjectId getId() {
       return id;
   }

   public void setId(ObjectId id) {
      this.id = id;
   }
...

}

To let Morphia know that we manage the object, we mark our class with the @Entity annotation:

@Entity
public class Quote extends BaseEntity {

... 

}
DAO Pattern

The BasicDAO object from Morphia is what will allow us to implement the Data Mapper pattern. It contains the typical data access methods such as find, delete, save that we can extend to manage the retrieval of our objects.

For managing the Quote objects, we created a QuoteRepository that extends the BasicDAO. We added a specific method to find by one of the attributes of the Quote object. The QuoteRepositoryTest Unit test in our GitHub project has examples on how to initialize MongoDB data store and insert and retrieve a Quote from the collection.

public class QuoteRepository extends BasicDAO<Quote, ObjectId> {
    public QuoteRepository(Mongo mongo, Morphia morphia, String dbName) {
        super(mongo,morphia,dbName);
    }

    public Iterator<Quote> findByQuoteNumber(String quoteNumber) {
        Pattern regExp = Pattern.compile(quoteNumber + ".*", Pattern.CASE_INSENSITIVE);
        return ds.find(entityClazz).filter("quoteNumber", regExp).iterator();   
    }
}

There is certainly more to look at with the Query object and other BasicDaO methods. However this is a good enough to get an understanding of how to map a Java POJO to the data store collection.

Conclusions

Strengths

In general, morphia seems to be a mature and widely used library. Morphia does have an active community in the Morphia Google Group. The latest version in the Maven Central Repository is 0.99. This is from the Google Code site, and while being behind the github fork, is helpful for those project teams that use Ivy, Maven, and/or Gradle to help manage their project dependencies. The big concerns here are:

  • are there any major differences between the mophia framework and current mongodb java driver?
  • how long will it take to resolve those differences.

Morphia certainly makes it easy to map our POJOs to collections in the mongo datastore. The BasicDAO object for Morphia gives us a way to implement the standard DAO pattern that is part of the JPA implementations we are familiar with. Integrating morphia into our projects is easy as we only need to add in the mongo java driver and morphia libraries.

Weaknesses

The future of morphia is a little unclear. One area of concern for Morphia is that the last release was over a year ago. This is problematic as Mongo continues to improve and add new features.

Fortunately, there's a new fork over at GitHub that has revived the project. These releases haven't made it over to the Maven Central repositories yet, but there has been a lot of activity recently.

There have also been some rumors that the Morphia driver would eventually be absorbed into the MongoDB Java Driver, but while some of the committers for Morphia are happily employed by 10Gen, it hasn't shown up on the roadmap yet.

Isaac Christoffersen

Isaac Christoffersen has over 15 years of experience in system integration and software solutions development for non-profit, commercial, and government clients. He is a technology innovator and community-leader with a unique blend of business acumen and technology skills.