A little background information
Most of you have probably have heard the term NoSQL before. The term is used in situations where you do not have a traditional relation database for storing information. There are many different sorts of NoSQL databases. To make a small summary these are probably the most well-known:
- Wide Column Stores: Hadoop and Cassandra
- Document Stores: CouchDB and MongoDB
- Key Value Store: Redis
- Eventually Consistent Key Value Store: Voldemort
- Graph Databases: Neo4J
The above types cover most of the differences, but for each type there are a lot of different implementations. For a better overview you might want to take a look at the NOSQL database website.
For my own experiment I chose to use MongoDB, since I had read a lot about it and it seemed quite easy to get started with.
MongoDB is as they describe it on their website:
A scalable, high-performance, open source, document-oriented database.The document-oriented aspect was one of the reasons why I chose MongoDB to start with. It allows you to store rich content with data structures inside your datastore.
Getting started with MongoDB

To begin with, I looked at the Quick start page for Mac OS X and I recommend you to do that too (unless you use a different OS). It will get you going and within a couple of minutes you'll have MongoDB up and running on your local machine.
MongoDB stores it's data by default in a certain location. Of course you can configure that, so I started MongoDB with the --dbpath parameter. This parameter will allow you to specificy your own storage location. It will look something like this:
$ ./mongodb-xxxxxxx/bin/mongod --dbpath=/Users/jreijn/Development/temp/mongodb/
If you do that you eventually will get a message saying:
Mon Jul 18 22:19:58 [initandlisten] waiting for connections on port 27017
Mon Jul 18 22:19:58 [websvr] web admin interface listening on port 28017
At this point MongoDB is running and we can proceed to the next step: using Spring Data to interact with MongoDB.
Getting started with Spring Data
The primary goal of the Spring Data project is to make it easier for developers to work with (No)SQL databases. The Spring Data project already has support for a number of the above mentioned NoSQL type of databases.Since we're now using MongoDB, there is a specific sub project that handles MongoDB interaction. To be able to use this in our project we first need to add a Maven dependency to our pom.xml.
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-mongodb</artifactId>
<version>${spring.data.mongo.version}</version>
</dependency>
Looks easy right? Just one single Maven dependency. Of course in the end the spring-data-mongodb artifact depends on other artifacts which it will bring into your project. In this post I used version 1.0.2.RELEASE. Now on to some Java code!
For my first experiment I used a simple Person domain object that I'm going to query and persist inside the database. The Person class is quite simple and looks as follows.
package com.jeroenreijn.mongodb.example.domain;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;
/**
* A simple POJO representing a Person
*
*/
@Document
public class Person {
@Id
private String personId;
private String name;
private String homeTown;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getPersonId() {
return personId;
}
public void setPersonId(final String personId) {
this.personId = personId;
}
public String getName() {
return name;
}
public void setName(final String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(final int age) {
this.age = age;
}
public String getHomeTown() {
return homeTown;
}
public void setHomeTown(final String homeTown) {
this.homeTown = homeTown;
}
@Override
public String toString() {
return "Person [id=" + personId + ", name=" + name + ", age=" + age + ", home town=" + homeTown + "]";
}
}
Now if you look at the class more closely you will see some Spring Data specific annotations like @Id and @Document . The @Document annotation identifies a domain object that is going to be persisted to MongoDB. Now that we have a persistable domain object we can move on to the real interaction.
For easy connectivity with MongoDB we can make use of Spring Data's MongoTemplate class. Here is a simple PersonRepository object that handles all 'Person' related interaction with MongoDB by means of the MongoTemplate.
package com.jeroenreijn.mongodb.example;
import java.util.Iterator;
import java.util.List;
import com.jeroenreijn.mongodb.example.domain.Person;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.stereotype.Repository;
/**
* Repository for {@link Person}s
*
*/
@Repository
public class PersonRepository {
static final Logger logger = LoggerFactory.getLogger(PersonRepository.class);
@Autowired
MongoTemplate mongoTemplate;
public void logAllPersons() {
List<Person> results = mongoTemplate.findAll(Person.class);
logger.info("Total amount of persons: {}", results.size());
logger.info("Results: {}", results);
}
public void insertPersonWithNameJohnAndRandomAge() {
//get random age between 1 and 100
double age = Math.ceil(Math.random() * 100);
Person p = new Person("John", (int) age);
mongoTemplate.insert(p);
}
/**
* Create a {@link Person} collection if the collection does not already exists
*/
public void createPersonCollection() {
if (!mongoTemplate.collectionExists(Person.class)) {
mongoTemplate.createCollection(Person.class);
}
}
/**
* Drops the {@link Person} collection if the collection does already exists
*/
public void dropPersonCollection() {
if (mongoTemplate.collectionExists(Person.class)) {
mongoTemplate.dropCollection(Person.class);
}
}
}
If you look at the above code you will see the MongoTemplate in action. There is quite a long list of method calls which you can use for inserting, querying and so on. The MongoTemplate in this case is @Autowired from the Spring configuration, so let's have a look at the configuration.
<?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:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<!-- Activate annotation configured components -->
<context:annotation-config/>
<!-- Scan components for annotations within the configured package -->
<context:component-scan base-package="com.jeroenreijn.mongodb.example">
<context:exclude-filter type="annotation" expression="org.springframework.context.annotation.Configuration"/>
</context:component-scan>
<!-- Define the MongoTemplate which handles connectivity with MongoDB -->
<bean id="mongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate">
<constructor-arg name="mongo" ref="mongo"/>
<constructor-arg name="databaseName" value="demo"/>
</bean>
<!-- Factory bean that creates the Mongo instance -->
<bean id="mongo" class="org.springframework.data.mongodb.core.MongoFactoryBean">
<property name="host" value="localhost"/>
</bean>
<!-- Use this post processor to translate any MongoExceptions thrown in @Repository annotated classes -->
<bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor"/>
</beans>
The MongoTemplate is configured with a reference to a MongoDBFactoryBean (which handles the actual database connectivity) and is setup with a database name used for this example.
Now that we have all components in place, let's get something in and out of MongoDB.
package com.jeroenreijn.mongodb.example;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* Small MongoDB application that uses spring data to interact with MongoDB.
*
*/
public class MongoDBApp {
static final Logger logger = LoggerFactory.getLogger(MongoDBApp.class);
public static void main( String[] args ) {
logger.info("Bootstrapping MongoDemo application");
ConfigurableApplicationContext context = new ClassPathXmlApplicationContext("META-INF/spring/applicationContext.xml");
PersonRepository personRepository = context.getBean(PersonRepository.class);
// cleanup person collection before insertion
personRepository.dropPersonCollection();
//create person collection
personRepository.createPersonCollection();
for(int i=0; i<20; i++) {
personRepository.insertPersonWithNameJohnAndRandomAge();
}
personRepository.logAllPersons();
logger.info("Finished MongoDemo application");
}
}
All this application does for now is setup a connection with MongoDB, insert 20 persons (documents), fetch them all and write the information to the log. As a first experiment this was quite fun to do.
I was just about to try this very same thing, so thanks!
ReplyDeleteAwesome! I think both technologies are really interesting. I hope this post gave you a quick starter.
ReplyDeleteHow to skip the value in domain objects without changing the domain object class or using @Transient..
ReplyDelete@Rameez:
ReplyDeleteI do not fully understand what you want to achieve? If you have a domain object you want to skip the value only once of all the time?
what if i want to connect with a mongo db with auth mode? I mean with user and pass.
ReplyDelete@KCOtzen: You can provide an extra constructor argument to the MongoTemplate that contains the user credentials. See http://support.cloudfoundry.com/entries/20018322-alert-mongo-bindings-have-changed for a small example at the bottom of the topic.
ReplyDeletewill try this.. mongo db looks impressive..
ReplyDeleteHello,
ReplyDeleteFirst I would like to thank Jeroen for publishing this. I found it helpful.
For future readers, I noticed the packages have changed around a bit. Classes in package org.springframework.data.document.mongodb have moved to org.springframework.data.mongodb.core.
-john
Hi John,
DeleteThank you for the feedback! I had already updated the sample on Github some time ago. I've now also updated the article!
Jeroen
this was really helpful.. i am able to use your code as 'seed' code to get all the integration going...!! this is simply great..!!
ReplyDeleteThanks again..
Hi Jeroen,
ReplyDeleteI had a question. In the spring mongodb documentation, (http://static.springsource.org/spring-data/data-mongo/docs/current/reference/html/)- section 6, they are referring to Repository as an interface in which we can define custom query methods and use the @Query annotation.
In the spring definitions, we need to use
However, In your sample code, you are having it as a class.
I would prefer to use the approach mentioned in the spring data docs, but it seems like it wont work directly with how you have structured the code. Do you have any insight into this from your experience with spring mongodb data?
I appreciate your help on this.
Thanks
Using your 'seed' project, i was able to get things going:
ReplyDeleteI was following up more on how to create Repository Interfaces mentioned in ,
http://static.springsource.org/spring-data/data-mongo/docs/current/reference/html/, section 6, as it looks like I want to delegate the work of creating query methods to spring and only define my custom query methods with @Query annotations in the Repository interface. This way, i can delegate the responsibility of creating methods for custom queries to spring.
In your example, you have used Repository class and annotated it with @Repository and left it up to spring's auto-scanning to identify the repo objects.
Have you used the way mentioned in the link that i have shared ? What do you think will be the best way to proceed?
I appreciate your help on this.
Thanks
Sarthak
Do we have to use maven? I just want to create console application and I want to send some data to MongoDB.
ReplyDeleteCan you do configuration not only xml but also annotations.
Regards
Can you add source codes of this example?
ReplyDeleteThe sources can be found here: https://github.com/jreijn/spring-mongo-demo
DeleteThis sample is really very help full for me, so thanks!!!!!!
ReplyDelete