Accueil > Mongo JEE, MongoDB > Mongo JEE [step3]

Mongo JEE [step3]


In [step2] we have used mongo in a servlet to return the JSON array of the logs collection. In this article we will use Mongo JEE to improve it :

  • use com.mongodb.jee.MongoHolder#connect() to avoid hard coding the mongo URI in the servlet.
  • use com.mongodb.jee.util.JSON to manage JSON streaming when mongo cusor is serialized as JSON and is written in the HTTP response.
  • use com.mongodb.jee.servlet.ServletHelper to simplify the code which set response as JSON and write the JSON stream in the HTTP response.

Download

You can download step3.zip which hosts the Eclipse Project which contains the explained sources in this article. To use it, unzip it and import this project in your Eclipse workspace. As soon as you will do that, your workspace will look like this :

Download JARs with maven

In this article we use :

  1. the Mongo Java Driver. To do that I use this maven dependency :
    <dependency>
    	<groupId>org.mongodb</groupId>
    	<artifactId>mongo-java-driver</artifactId>
    	<version>2.11.1</version>
    </dependency>
    
  2. the Embedded Jetty as server. To do that I use this maven dependency :
    <dependency>
    	<groupId>org.eclipse.jetty</groupId>
    	<artifactId>jetty-webapp</artifactId>
    	<version>8.1.10.v20130312</version>
    	<scope>test</scope>
    </dependency>
    
  3. Mongo JEE. To do that I use this maven dependency :
    <dependency>
    	<groupId>fr.opensagres.mongodb</groupId>
    	<artifactId>mongo-jee</artifactId>
    	<version>1.0.0</version>
    </dependency>
    

The project contains the JARs in the lib, but if you wish to download it with maven , see Download JARs with maven [step1].

MongoHolder#connect()

In [step2]:

  1. the mongo client is created on the init of logs servlet:
    private MongoClient mongo = null;
    
    @Override
    public void init() throws ServletException {
    	super.init();
    
    	// Connect to Mongo DB
    	MongoClientURI mongoURI = new MongoClientURI(
    			"mongodb://localhost:27017");
    	try {
    		mongo = new MongoClient(mongoURI);
    	} catch (UnknownHostException e) {
    		throw new ServletException(e);
    	}
    }
    
  2. the mongo client is closed on the destroy of logs servlet:
    @Override
    public void destroy() {
    	super.destroy();
    	if (mongo != null) {
    		mongo.close();
    	}
    }
    

This code works, but there are some problems :

  • the mongo URI is hard coded. If you wish to change the mongo URI, you must recompile the servlet.
  • if you wish to add a new servlet like logs servlet, it’s not possible to use the mongo pool of the logs servlet. A best design is to delegate the mongo lyfecycle (create and close) in other classes than logs servlet.

Mongo JEE resolves this 2 problems with the MongoHolder. To use it, you must

  1. configure the default mongo URI of the MongoHolder :
    MongoClientURI mongoURI = ...;
    boolean defaultMongo = true;
    MongoHolder.connect(mongoURI, defaultMongo);
    

    You can configure it in your web.xml with the JEE ServletContextListener com.mongodb.jee.servlet.MongoServletContextListener like this :

    <listener>
    	<listener-class>com.mongodb.jee.servlet.MongoServletContextListener</listener-class>
    </listener>
    
    <context-param>
    	<param-name>mongoURI</param-name>
    	<param-value>mongodb://localhost:27017</param-value>
    </context-param>
    
    • on ServletContextListener#contextInitialized, MongoHolder is initialized with default mongoURI declared in the web.xml.
    • on ServletContextListener#contextDestroyed, all instance of Mongo registered in the MongoHolder are closed.
  2. after having configurated the default mongo URI, you can do that :
    Mongo mongo = MongoHolder.connect();
    

web.xml

Modify the web.xml to declare com.mongodb.jee.servlet.MongoServletContextListener and the default mongo URI like this :

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
	id="WebApp_ID" version="2.5">
	<display-name>Mongo JEE</display-name>

	<servlet>
		<servlet-name>LogsServlet</servlet-name>
		<servlet-class>org.samples.mongodb.servlet.LogsServlet</servlet-class>
	</servlet>

	<servlet-mapping>
		<servlet-name>LogsServlet</servlet-name>
		<url-pattern>/servlet/logs/*</url-pattern>
	</servlet-mapping>

	<listener>
		<listener-class>com.mongodb.jee.servlet.MongoServletContextListener</listener-class>
	</listener>

	<context-param>
		<param-name>mongoURI</param-name>
		<param-value>mongodb://localhost:27017</param-value>
	</context-param>

</web-app>

LogsServlet – MongoHolder

Modify org.samples.mongodb.servlet.LogsServlet to use MongoHolder#connect() like this :

package org.samples.mongodb.servlet;

import java.io.IOException;
import java.io.Writer;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.mongodb.DB;
import com.mongodb.DBCollection;
import com.mongodb.DBCursor;
import com.mongodb.Mongo;
import com.mongodb.jee.MongoHolder;
import com.mongodb.util.JSON;

public class LogsServlet extends HttpServlet {

	@Override
	protected void doGet(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {

		Mongo mongo = MongoHolder.connect();
		// Get DB collection
		DB db = mongo.getDB("websites");
		DBCollection coll = db.getCollection("logs");

		DBCursor cursor = coll.find();

		// HTTP response is JSON
		response.setCharacterEncoding("UTF-8");
		response.setContentType("application/json");

		// Loop for DB cursor and write each DB document in the HTTP writer
		Writer writer = response.getWriter();

		StringBuilder buf = new StringBuilder();
		JSON.serialize(cursor, buf);
		writer.write(buf.toString());

		writer.flush();

	}

}

Restart the server to check the servlet logs works again.

com.mongodb.jee.util.JSON

In [step2] the mongo cursor is serialized (by using StringBuilder) as JSON in the HTTP response like this:

Writer writer = response.getWriter();

StringBuilder buf = new StringBuilder();
com.mongodb.util.JSON.serialize(cursor, buf);
writer.write(buf.toString());

Problem with this code is that you must create a StringBuilder instance before writing in the HTTP response. To avoid this problem, you can use Mongo JEE which provides the same JSON helper but with Writer as parameter. So you can do that :

Writer writer = response.getWriter();

com.mongodb.jee.util.JSON.serialize(cursor, writer);

LogsServlet – JSON

Modify org.samples.mongodb.servlet.LogsServlet to use com.mongodb.jee.util.JSON like this :

package org.samples.mongodb.servlet;

import java.io.IOException;
import java.io.Writer;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.mongodb.DB;
import com.mongodb.DBCollection;
import com.mongodb.DBCursor;
import com.mongodb.Mongo;
import com.mongodb.jee.MongoHolder;
import com.mongodb.util.JSON;

public class LogsServlet extends HttpServlet {

	@Override
	protected void doGet(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {

		Mongo mongo = MongoHolder.connect();
		// Get DB collection
		DB db = mongo.getDB("websites");
		DBCollection coll = db.getCollection("logs");

		DBCursor cursor = coll.find();

		// HTTP response is JSON
		response.setCharacterEncoding("UTF-8");
		response.setContentType("application/json");

		// Loop for DB cursor and write each DB document in the HTTP writer
		Writer writer = response.getWriter();

		//StringBuilder buf = new StringBuilder();
		com.mongodb.jee.util.JSON.serialize(cursor, writer);
		//writer.write(buf.toString());

		writer.flush();
	}

}

Restart the server to check the servlet logs works again.

ServletHelper

You can notice that the code :

// HTTP response is JSON
response.setCharacterEncoding("UTF-8");
response.setContentType("application/json");

// Loop for DB cursor and write each DB document in the HTTP writer
Writer writer = response.getWriter();

//StringBuilder buf = new StringBuilder();
com.mongodb.jee.util.JSON.serialize(cursor, writer);
//writer.write(buf.toString());

writer.flush();

is generic. You can do the same thing with the Mongo JEE com.mongodb.jee.servlet.ServletHelper :

// Write in the HHTP response the JSON array of the cursor.
ServletHelper.writeJson(cursor, response);

LogsServlet – ServletHelper

Modify org.samples.mongodb.servlet.LogsServlet to use com.mongodb.jee.servlet.ServletHelper like this :

package org.samples.mongodb.servlet;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.mongodb.DB;
import com.mongodb.DBCollection;
import com.mongodb.DBCursor;
import com.mongodb.Mongo;
import com.mongodb.jee.MongoHolder;
import com.mongodb.jee.servlet.ServletHelper;

public class LogsServlet extends HttpServlet {

	@Override
	protected void doGet(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {

		Mongo mongo = MongoHolder.connect();
		// Get DB collection
		DB db = mongo.getDB("websites");
		DBCollection coll = db.getCollection("logs");

		DBCursor cursor = coll.find();

		// Write in the HHTP response the JSON array of the cursor.
		ServletHelper.writeJson(cursor, response);
	}

}

Restart the server to check the servlet logs works again.

Conclusion

In this article we have seen how to Mongo JEE can improve code with servlet which uses Mongo. In the next article [step4], we will replace our logs servlet with a JAX-RS logs service by using javax.ws.rs.core.StreamingOutput.

Catégories :Mongo JEE, MongoDB
  1. Aucun commentaire pour l’instant.
  1. Mai 12, 2013 à 11:22
  2. Mai 14, 2013 à 1:16

Laisser un commentaire