MongoDB, Play and AWS – Developing java application for the cloud

Summary: In this post I share my experience how easy it is to build a simple application using Play Framework and MongoDB. We will deploy it into PaaS – Amazon’s Elastic Beanstalk for instant scalability and availability.
Technology stack:

  1. NoSQL Datastore – MongoDB for persistent layer
  2. Play Framework
  3. Amazon Elastic Beanstalk – cloud PaaS
  4. Java

The step we will take a following:

  1. Create a free MongoDB instance in the cloud using MongoLab service
  2. Develop simple Web application with Play framework
  3. Deploy application into Amazon Beanstalk for plug and play deployment and scalability

Data storage:

NoSQL database are vastly different from RDBMS in that they don’t store data in fixed schemas with tables and row. Some of them, like Reddis, store data in key/value pair. another, like MongoDB or CouchDB, store data as documents.
MongoDB stores documents as JSON and provide API as a mixture of JSON objects and JavaScript functions. Developers interact with MongoDB via the shell program, which permits command-line arguments, or by using a language driver to access datastore instances. This is very convenient for developers, much more flexible to work with and much more easy to work with. No more joins to create, flexible documents design – each document may have different set of keys.

Instead of installing mongoDB locally, I decided to get an instance from MongoLab. This is cloud based service, based on Amazon EC2, and provide a plethora of additional conveniences compare to plain MongoDB local instance. Top notch user interface, “kick-ass” admin tools, search interface – and more important, instant scalability and availability of your data. You can get free account for up to 240Mb of data – and in MongoDB this is a big amount to play with.

Modeling some real life object with mongoDB is very easy and natural. For example, I want to model object of art for museum catalog. All of them have title, some of them have creators, some have date of creation. Plus it could be different types of objects – paintings, sculpture e.t.c. In relation model we end up with manu fields with null values, type field, or several tables for each type of art.
In MongoDB this concept is easy – just one document for each individual item.
For example, one record – document describing work of art in MongoDB:

{
    "_id": {
        "$oid": "4de1a0ff0aa918683d000001"
    },
    "image_id": "GRINART_90710175179",
  
    "metadata": {
        "ID Number": "1986.0623",
        "Title": "The Pantheon (Church of Sainte-Genevieve), plan",
        "imageUrl": "art/1986_0623.jpg",
        "Material": "Architecture",
        "Creator": "Soufflot, Jacques-Germain",
        "Location": "France, Paris",
        "Style Period": "Neoclassic",
        "Date": "1757-90",
        
    }
}

Because data stored as JSON, it is very convenient to create REST API for any Ajax application. Much easier than to serialize object to JSON in java code.
So let say we have thousand of those documents and we wanted to create a small web based application to display the data. We will create application using server side view processing for SEO puproses, so Google boot will have an easy job to index our documents. Another option would be to create a one page application and feed data on UI event using AJAX call. While it is cool with the users, Google engine will not be able to execute java script on the page to index our documents. So we will stick with simpler model for now.

Application:
There are a lot of great frameworks out there for Java web development, but Play Framework combines productivity, easy of use with great power and flexibility. Stateless, pure java or scala, small and powerful. You can download and read more about this open source project : Play Framework

After you successfully install play framework, you can create a domain class that will map our MongoDB document to a java object. Because we don’t know up front what key/value pairs or fields our document will contain, I will map it to simple java HashMap.
In order to communicate with MongoDB we need a driver. MongoDB’s Java language driver is intended to abstract much of the JSON and JavaScript code you can see when working with mongoDB so that you are left with a straightforward Java API. I use Morphia – MongoDB Integration [morphia] module for Play framework.

Now let’s create our model class:

package models;

import java.util.Map;

import org.bson.types.ObjectId;

import play.modules.morphia.Model;

import com.google.code.morphia.annotations.Entity;
import com.google.code.morphia.annotations.Id;

@Entity("images")
public class ArtObject extends Model {
	@Id ObjectId id; // auto-generated, if not set (see ObjectId)
	public String image_id;
	public String collection;
	public Map<String, String> metadata;
}

Metadata entry in MongoDB document will be mapped directly to our Map metadata field in our Java object.
Next step is to write controller. In my simplest case, I just get first record, and prepare data for previous/next pagination:

import java.util.List;

import models.ArtObject;
import play.mvc.Controller;

public class Application extends Controller {

	// display index page
	public static void index(String id) {
		// read counter as a parameter
		// String id = params.get("page");
		if (id == null) {
			id = "1";

		}
		int current = Integer.parseInt(id);
		List<ArtObject> list = ArtObject.find().offset(current).fetch(1);
		ArtObject artObject = (ArtObject) list.get(0);
		String url = artObject.metadata.get("imageUrl");
		String newUrl = url.replace("size0", "size2");

		// System.out.print(url);

		render(artObject, newUrl);

	}

	public static void image(String id) {

		// read counter as a parameter
		// String id = params.get("page");
		if (id == null) {
			id = "1";

		}
		int current = Integer.parseInt(id);
		List<ArtObject> list = ArtObject.find().offset(current).fetch(1);
		ArtObject artObject = (ArtObject) list.get(0);
		String url = artObject.metadata.get("imageUrl");
		String newUrl = url.replace("size0", "size2");

		
		int next = Integer.parseInt(id) + 1;
		int prev = Integer.parseInt(id) - 1;
		render(artObject, newUrl, next, prev);

	}
}

Now we need a view to display our data. Play framework uses groovy based view template engine. In simplest form we have following code to iterate over each key-value pair in our database and display metadata with image.

#{extends 'main.html' /}
#{set title:'Home' /}
<link rel="stylesheet" type="text/css" media="screen" 
     href="@{'/public/stylesheets/play-pagination.css'}">
#{if artObject}
    <div class="post">
        <h2 class="post-title">
            <img src="/public/images/g-artstor-logo.gif"/>
            <h2>From ${artObject.metadata.Collection}</h2>
        </h2>
        <div class="post-metadata">
            <img src="http://myserver/${newUrl}"/><br>
            <h2>${artObject.metadata.Title}</h2>
           
            <span class="metadata">
            <table>
            #{list items:artObject.metadata, as:'oldPost'}
            <tr>
            <td class="odd">
            ${oldPost.key}
            </td>
            <td class="even">
            ${oldPost.value}
            </td>
            </tr>
             #{/list}
             </table>
            </span>
            
         
           
        </div>
        <div class="pagination">
        
          <a href="${prev}"</h1>Previous</a>
         <a href="${next}"</h1>next</a>
        </div>
    </div>
   
    
#{/if}

Database connections are stored inside application.conf file. Dependency are in dependencies.yml file. You can learn about Play framework by browsing documentation online.

After writing simple test cases and running our apps locally for manual testing, let deploy it to Amazon Elastic Beanstalk.
Presuming you’ve signed up for Beanstalk, you start by logging in to your AWS Management Console. From there, select the Elastic Beanstalk tab, then click the Upload your own application option, followed by the Launch Application button. This will result in a dialog requesting a few pieces of information:

In this dialog, you have to provide a name, which will also be the URL of your application. You also need to provide a war file. Once you’ve hit the Continue button, you’ll be taken back to the AWS Management Console, while the application fires up. This could take a while — for instance, I saw times of up to 10 minutes.
Once your application is fully deployed and everything has been configured on Amazon’s end, you should see a nice green box next to your application’s name. The green light means the application is good to go.

Now we have completely cloud based running application – both MongoDB instance and Application are on amazon cloud. By clicking the green button our application displayed in browser.

Elastic Beanstalk provide some vital statistics about our application, like latency, CPU utilization, number of requests – all in cool looking interface.

You start to see the real power of Beanstalk when you click the Edit Configuration link in the Environmental Details section on the bottom right of the Beanstalk Management Console. Clicking this link brings up a dialog with a host of options, including some really neat possibilities.
amazon elastic beanstalk- scaling

Conclusion: Using modern NoSQL database, rapid development framework, good old fashioned java and most important, cloud services – developers can be much more productive and deploy application into scalable, performant environment. No more time spend on server provisioning, middleware installations, load balancers and network configurations.
This is a great option for developers and some companies who don’t want to maintain datacenters and application infrastructure.

2 Comments

  1. Nice post, thanks for sharing :)

    So, how is morphia holding up? Last time I checked there were too few commits going on, too many issues reported on github… I ended up looking for another ODM/ORM alternatives.

    Another question: did you consider building a REST API instead of direct rendering? What path would you take in that case?

    Reply
    • I don’t know about morphia, I ended up using Spring Data for MongoDB as ODM solution. So far very pleased with architecture and capabilities of the project. They have book published and resources on gitHub.
      I did build REST API using Spring framework. If you not in spring lang, then I would recommend checking out Dropwizard http://dropwizard.codahale.com/.
      My application provide interface to MongoDB via Rest API as a service, so I had to build it anyway.

      Reply

Submit a Comment

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>