When Mashape pivoted, we needed to create a brand new data access object (DAO) implementation. There were two main constraints: flexibility and development speed.
Flexibility meant a schema-free solution, to keep pushing features even if they required major changes in the database structure. Speed meant a library or a framework that could easily help us during the implementation. Previously, we were using MySQL + Hibernate. We were not able to iterate fast enough on the database as we were stuck with all those tables, columns and migration issues. Hibernate is a good product, but it’s a whole new world – we didn’t need too much complexity, and hence it was not really the best couple on which to bet again.
At that time I was playing with mongoDB, but never really used it in production. I decided to give it a serious try. Mashape is built in Java, and before making the final decision, I spent some time looking for a library that could have helped me to build the whole thing. I found morphia: a neat Java library for mapping objects with mongoDB, with a basic abstract DAO implementation. I downloaded the artifact from the Maven repository, and after some local testing I started to write the new implementation.
There were two main needs:
- Don’t lose flexibility in case we needed to add a new DAO implementation in the future.
- The development couldn’t be stopped while I was hacking on my new games, so we needed a mock DAO implementation too in the meanwhile.
Implementing the DAO switch
We decided to program two interfaces, to create multiple implementations of our entites. Every interface extends a base Entity interface that declares methods for getting/setting the common properties like the id (a String object) and the creationDate.
public interface User extends Entity
The DAOs were interfaces that extended a BaseDAO interface, declaring the common methods that every DAO would had. You’ll notice the examples below use Generics:
public interface UserDAO extends BaseDAO
After building the “quick and dirty” Mock implementation, it was time for mongoDB and morphia. The latter offers DAO support in a BasicDAO class, so I just used it to build another abstract class to be extended by all the mongo DAOs. Before that, I’ve created a BaseMongoEntity class to implement the Entity interface. The @Id annotation is provided by morphia to set the ID field, that is an ObjectId object – so I’m doing some ObjectId/String conversion operations.
Then, I created a mongo implementation for the User entity. Persisting objects in mongoDB using morphia it’s extremely easy. Value properties are automatically persisted. If you need more customization (custom fields name, embedded objects, lazy loading, references, etc), just use its annotations.
Finally, I created the mongo DAO class for the User entity that is initialized with the MongoUser implementation. By calling the save method declared in BasicDAO, the MongoUser object will be persisted in a “users” collection. The BasicDAO constructor requires a morphia object that you can initialize in a singleton factory, and where you will map all the classes you want to persist in mongoDB.
What’s missing here is an abstract DAOFactory class that it’s extended by the other specific DAO factories (MockDAOFactory and MongoDAOFactory, in my case).
The DAOFactory class is a singleton that could be configured at runtime with a *.properties file that stores the class paths to the MockDAOFactory and MongoDAOFactory, and then creates new instances of them. With this pluggable design, any kind of DAO can be added (yes, also MySQL and Hibernate).
morphia is well supported and it is getting better, while mongoDB is a valid alternative to relational databases. I never had problems of any kind. Sharding and replication is easy to enable, and it is reliable and super fast overall.
It took me a couple of days to implement all the DAOs – with just some small fixes during the following months.
Hope this helps