ZK With MongoDB Part 2 - Using Morphia"

From Documentation
m (Created page with "{{Template:Smalltalk_Author| |author=Ashish Dasnurkar, Engineer, Potix Corporation |date=January 18, 2011 |version=ZK 5 }} {{Template:UnderConstruction}} =Introduction= [http:...")
 
m
Line 79: Line 79:
 
<br /> <br />  
 
<br /> <br />  
  
Now, as in Part 1 we need a DAO to make persistence calls to MongoDB as it is a good practice to encapsulate persistence calls within DAO so that calling code (controller in this case) can use it without knowing the underlying details. Morphia has a built-in support for DAO interface in the form of BasicDAO implementation of it. This abstract class implements all the basic CRUD methods on model objects. I can just extend from this BasicDAO and since it uses generics to define a parameter class I wouldn't even need to cast the results returned from this DAO methods. Below is my TaskDAO implementation
+
Now, as in Part 1 we need a DAO to make persistence calls to MongoDB as it is a good practice to encapsulate persistence calls within DAO so that calling code (controller in this case) can use it without knowing the underlying details. Morphia has a built-in support for DAO interface in the form of BasicDAO implementation of it. This abstract class implements all the basic CRUD methods on model objects. I can just extend from this BasicDAO and since it uses generics to define a parameter class I wouldn't even need to cast the results returned from this DAO methods. Below is my TaskDAO implementation;
 +
 
 +
<source lang="java">
 +
public class TaskDAO extends BasicDAO<Task, ObjectId> {
 +
 
 +
public TaskDAO(Mongo mongo, Morphia morphia) {
 +
super(mongo, morphia, "todo");
 +
}
 +
}
 +
</source>
 +
 
 +
As you can see, all it takes is an instance of Morphia and an instance of Mango. Similar to Part 1 we can reuse mango instance by defining a singleton object to contain it. Morphia instance is also recommended to create once and reuse. So I have defined a MangoDBManager singleton class that has 2 static methods to maintain single instance of Mango as well as Morphia as shown below;
 +
 
 +
<source lang="java">
 +
 
 +
public class MongoDBManager {
 +
 
 +
private static Mongo mongo = null;
 +
private static Morphia morphia = null;
 +
private MongoDBManager() {};
 +
 +
public static synchronized DB getDB() throws Exception {
 +
if(mongo == null) {
 +
mongo = new Mongo();
 +
}
 +
return mongo.getDB("test");
 +
}
 +
public static synchronized Mongo getMongo() throws Exception {
 +
if(mongo == null) {
 +
mongo = new Mongo();
 +
}
 +
return mongo;
 +
}
 +
public static synchronized Morphia getMorphia() throws Exception {
 +
if(morphia == null) {
 +
mongo = getMongo();
 +
morphia = new Morphia();
 +
morphia.mapPackage("org.zkoss.mongodb.model");
 +
}
 +
 +
return morphia;
 +
}
 +
}
 +
 
 +
</source>
 +
 
 +
The only other thing notable here is the call to <tt>Morphia#mapPackage(String)</tt> which tells morphia from which Java package model classes are to be mapped to MongoDB.

Revision as of 07:47, 12 January 2012

DocumentationSmall Talks2012JanuaryZK With MongoDB Part 2 - Using Morphia
ZK With MongoDB Part 2 - Using Morphia

Author
Ashish Dasnurkar, Engineer, Potix Corporation
Date
January 18, 2011
Version
ZK 5

WarningTriangle-32x32.png This page is under construction, so we cannot guarantee the accuracy of the content!

Introduction

Part 1 introduced you how to write a non-relation database driven ZK application. In particular, I used mongoDB and its Java driver low level APIs. The problem with that approach was I had to manually convert results returned from Java driver APIs to model Javabean instances. Wouldn't it be better if we could just talk to database in terms on POJOs? Morphia, a type-safe Java library does exactly that. It allows mapping Javabean objects to/from mongoDB. Let see how we can use it in our TODO sample application

Using Morphia

Follow the dependencies documentation to include Morphia in your project. I use maven so I simply included following dependency in my pom.xml

 

<dependency>
	<groupId>com.google.code.morphia</groupId>
	<artifactId>morphia</artifactId>
	<version>0.99</version>
</dependency>

View

View part remains the same as in Part 1. Only change is I have a new controller to use morphia for managing task CRUD operations.

 
<window title="To do list" width="640px" border="normal" apply="org.zkoss.mongodb.controller.MongoDBMorphiaDemoCtrl">
	<listbox id="tasks" multiple="true" rows="10">
		<listhead>
			<listheader label="Item" />
			<listheader label="Priority" width="50px" />
			<listheader label="Date" width="90px" />
		</listhead>
	</listbox>
	<groupbox>
		<caption label="Event" />
		Item: <textbox id="name" constraint="no empty" cols="25" />
		Priority: <intbox id="priority" cols="1" constraint="no empty"/>
		Date: <datebox id="date" cols="8" constraint="no empty"/>
		<button id="add" label="Add" />
		<button id="update" label="Update" />
		<button id="delete" label="Delete" />
	</groupbox>
</window>

Model

Like Hibernate, Morphia uses annotations for defining mapping between POJO and MongoDB document templates. Below I annotate Task Javabean properties with Morphia annotations

 

@Entity("tasks")
public class Task {
	@Id
	private ObjectId id;
	
	@Indexed(value = IndexDirection.ASC, name = "taskName", unique = true)
	private String name;
	
	@Indexed(value = IndexDirection.ASC, name = "taskPriority")
	private int priority;
	
	@Indexed(value = IndexDirection.ASC, name = "executionDate")
	private Date executionDate;

	// getters and setters
}

Here Entity annotation defines mongoDB collection in which Task Javabean will be stored. Id annotation marks a field in an @Entity to be the id field in mongoDB. MongoDB will auto assign a unique id into it. Indexed annotation defines Javabean property is to be indexed. More on Morphia annotations, refer to here.



Now, as in Part 1 we need a DAO to make persistence calls to MongoDB as it is a good practice to encapsulate persistence calls within DAO so that calling code (controller in this case) can use it without knowing the underlying details. Morphia has a built-in support for DAO interface in the form of BasicDAO implementation of it. This abstract class implements all the basic CRUD methods on model objects. I can just extend from this BasicDAO and since it uses generics to define a parameter class I wouldn't even need to cast the results returned from this DAO methods. Below is my TaskDAO implementation;

 
public class TaskDAO extends BasicDAO<Task, ObjectId> {

	public TaskDAO(Mongo mongo, Morphia morphia) {
		super(mongo, morphia, "todo");
	}
}

As you can see, all it takes is an instance of Morphia and an instance of Mango. Similar to Part 1 we can reuse mango instance by defining a singleton object to contain it. Morphia instance is also recommended to create once and reuse. So I have defined a MangoDBManager singleton class that has 2 static methods to maintain single instance of Mango as well as Morphia as shown below;

 

public class MongoDBManager {

	private static Mongo mongo = null;
	private static Morphia morphia = null;
	private MongoDBManager() {};
	
	public static synchronized DB getDB() throws Exception {
		if(mongo == null) {
			mongo = new Mongo();
		} 
		return mongo.getDB("test");
	}
	public static synchronized Mongo getMongo() throws Exception {
		if(mongo == null) {
			mongo = new Mongo();
		}
		return mongo;
	}
	public static synchronized Morphia getMorphia() throws Exception {
		if(morphia == null) {
			mongo = getMongo();
			morphia = new Morphia();
			morphia.mapPackage("org.zkoss.mongodb.model");
		}
		
		return morphia;
	}
}

The only other thing notable here is the call to Morphia#mapPackage(String) which tells morphia from which Java package model classes are to be mapped to MongoDB.