ZK With MongoDB Part 3 - Using Spring Data

From Documentation
DocumentationSmall Talks2012JanuaryZK With MongoDB Part 3 - Using Spring Data
ZK With MongoDB Part 3 - Using Spring Data

Author
Ashish Dasnurkar, Engineer, Potix Corporation
Date
January 25, 2012
Version
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>
  • Note that it requires mongoDB Java driver.

    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.