ZK With MongoDB Part 3 - Using Spring Data
Ashish Dasnurkar, Engineer, Potix Corporation
January 25, 2012
ZK 5
Introduction
For Spring application developers, Spring Data project has support for MongoDB that allows mapping Java objects to/from mongoDB documents. In this article I will rewrite the same TODO application sample code described in Part 1 and Part 2 of this series using Spring data for mongoDB.
Spring Data for MongoDB
Spring Data
To include Spring Data for mongodb, add Spring milestone repository in pom.xml like illustrated below as we will use its latest 1.0.0.M5 milestone release
<repository>
<id>spring-milestone</id>
<name>Spring Maven MILESTONE Repository</name>
<url>http://maven.springframework.org/milestone</url>
</repository>
Then add Spring data mongoDB dependency in pom.xml as shown below;
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongo-java-driver</artifactId>
<version>2.6.5</version>
<type>jar</type>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-mongodb</artifactId>
<version>1.0.0.M5</version>
</dependency>
View
View part remains the same as described in earlier articles. Only change here is that the controller applied to the window is now managed by Spring so we use ZK’s spring variable resolver to resolve controller instance
<?variable-resolver class="org.zkoss.zkplus.spring.DelegatingVariableResolver"?>
<zk>
<window title="Simple Todo application with Spring data support for mongodb " width="640px" border="normal" apply="${todoCtrl}">
…
</window>
</zk>
Model
There are two ways in which Spring data for mongodb can support mapping of model/domain objects. One is without using annotations and other is with annotations. Here for the sake of keeping our example code simple I will NOT use annotations so our Task model class simply consists of few fields with corresponding getter/setter methods.
public class Task {
private String id;
private String name;
private Integer priority;
private Date executionDate;
… // constructor and getter/setter methods
Now I need some supporting service that will handle CRUD of Task instances. First I need to create com.mongodb.Mongo
instance and register it with Spring IoC container. Here I will use XML based bean metadata using mongo schema in a separate mongo-config.xml
file to achieve this.
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:mongo="http://www.springframework.org/schema/data/mongo"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/data/mongo
http://www.springframework.org/schema/data/mongo/spring-mongo-1.0.xsd">
<!-- Default bean name is 'mongo' -->
<mongo:mongo host="localhost" port="27017"/>
…
As you can see from above, default connection settings for com.mongodb.Mongo
instance is used. Next, MongoTemplate
is the central class in Spring data for mongoDB that provides rich set of features to interact with mongoDB database. I will use XML bean meatadata to register MongoTemplate
so I can auto-wire it to use within task service class to perform CRUD operations on task mongoDB documents. Add the following XML fragment into mongo-config.xml.
<!-- Offers convenience methods and automatic mapping between MongoDB JSON documents and your domain classes. -->
<bean id="mongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate">
<constructor-arg ref="mongo"/>
<constructor-arg name="databaseName" value="simpletasks"/>
</bean>
I pass com.mongodb.Mongo
bean to MongoTamplate
and the database name. Note that MongoTemplate
is thread-safe and can be reused in multiple instances.
Now let’s define our TaskService
class to work with Model Task instances mapping to/from Task documents in mongoDB.
@Service("taskService")
@Transactional
public class TaskService {
@Resource(name="mongoTemplate")
private MongoTemplate mongoTemplate;
…
I inject MongoTempalte
instance in TaskService
class using the @Resource
annotation. Now I can use MongoTemplate
instance and use its convenient APIs to access mongodb database. Let’s use it to get the list of all previously created tasks in the database.
public List<Task> findAll() {
Query query = new Query(where("id").exists(true));
List<Task> tasks = mongoTemplate.find(query, Task.class);
return tasks;
}
In the above findAll()
method, I used where static factory method to create a Criteria instance which in turn is used to create a Query instance. I then pass this Query instance to MongoTamplate find(Query, Class)
API. Note that I also pass Task.class
to find()
API so that MongoTamplate
can perform the mapping of Task documents in mongodDBto our Task model class.
Similarly, I implement methods to add, delete and update task documents in simpltasks mongoDB database as shown below;
public void add(Task task) {
try {
mongoTemplate.insert(task);
} catch(Exception e) {}
}
Adding new document is simple. Just create a new Task instance and pass it to insert(Object)
API of MongoTemplate
.
public void update(Task task) {
Query query = new Query(where("id").is(task.getId()));
try {
Update update = new Update();
update.set("name", task.getName());
update.set("priority", task.getPriority());
update.set("executionDate", task.getExecutionDate());
mongoTemplate.updateMulti(query, update, Task.class);
} catch(Exception e) {}
}
Updating existing mongoDB document is simple as well. First of all, create a Query to identify which document(s) you want to update and create an Update instance which is a map and set the document properties as key and their new value in the form of Key-Value pair. Finally, pass this Query and Update object and model class to updateMulti() API of MongoTemplate so MongoTemplate can map all the document properties accordingly. Note that you can also use updaeFirst() if you only want to update only the first result that matches given query.
public void delete(Task task) {
try {
Query query = new Query(where("id").is(task.getId()));
// Run the query and delete the entry
mongoTemplate.remove(query, Task.class);
} catch(Exception e) {}
}
For deleting, again, create a Query using where factory static method and pass it to remove()
API of MongoTemplate
.
Controller
@org.springframework.stereotype.Component("todoCtrl")
@Scope("prototype")
public class SpringTODOController extends GenericForwardComposer {
@Resource(name="taskService")
private TaskService taskService;
Once TaskService
is ready I inject it into todoCtrl
bean which is a controller class that is applied to todo application window. Now rest of the application behavior can be easily implemented by defining add,update and delete button event handlers and using above defined TaskSerivce
CRUD methods. Please check the SpringTODOController.java source code for reference.
Summary
In this article I demonstrated how Spring application developers can use Spring data for mongoDB support to interact with mongoDB database. There are lot of advanced features in Spring data for mongoDB and it is recommended to refer its documentation.
Download Sample Code
You can download/clone the complete source code for this Part 1 application from its github repository here.
Comments
Copyright © Potix Corporation. This article is licensed under GNU Free Documentation License. |