Spring MVC Web with Google NoSQL Datastore on GAE Cloud

The article represents key aspects of integrating your Spring MVC web application with Google NoSQL Datastore while working on Google App Engine cloud computing platform. Additionally, it presents code samples for you to get started in a quick manner.

You may access the sample application talked about in this article on this page, Welcome to GAE World!

Following has been discussed:

  • High-level architecture & design
  • Setup
  • NoSQL Data Model (NoSQL data entity vis-a-vis Google Datastore)
  • Implementation including code samples such as following:
    • Controller (HelloController)
    • JSP (hello.jsp)
    • DAOs (GoogleDSCommentDAO)


High-level Architecture & Design

Following are key technologies used for the implementation discussed in this article:

  • Spring MVC
  • Google Datastore (NoSQL Database)
  • Jetty (Web Server)
  • Bootstrap (UI) for rapid good looking UI widgets
  • Google App Engine as cloud computing platform

The web application is based on MVC architecture pattern and is developed using Spring component model. You would see key concepts of Spring (Annotations based dependency injection) being used in the code samples listed below.

Setup

For you to be able to get up and running with using Google Datastore with Spring MVC, we recommend you to go through our previous articles such as following:

Google NoSQL Datastore & Related Implementation

The key to implementing Google NoSQL datastore is understanding of concepts around Google NoSQL such as Entity, Key, Kind, Attribute etc. Some of these concepts are described below in light of sample implementation shown in this article:

NoSQL Data Entity (Comment)

Take a look at following pages to get an overview on Google Datastore and related key concepts.

“Comment” is created as an entity in NoSQL Datastore. It has attributes (analogous to columns in RDBMS) such as email, text and date which is stored in Google NoSQL datastore.

CommentDAO.java

Pay attention to the fact that interface does not consist of Google DS specific objects (such as Key, Entity etc) in the method signature. This is just to make sure that interface definitions are implementation agnostic and could be used for both RDBMS and NoSQL database. For this very reason, “Comment” domain object is conceptualized such that it could be passed in between controller and model objects.

public interface CommentDAO {

	long save( Comment comment );

	List getAll( int count );
}

GoogleDSCommentDAO.java

This class implements following two methods of the interface, CommentDAO.

  • save( Comment comment) : Saves the comment entity in the Google NoSQL datastore
  • getAll( int count): Get “count” number of comments entities from the datastore
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.springframework.stereotype.Component;

import com.google.appengine.api.datastore.DatastoreService;
import com.google.appengine.api.datastore.DatastoreServiceFactory;
import com.google.appengine.api.datastore.Entity;
import com.google.appengine.api.datastore.FetchOptions;
import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.datastore.KeyFactory;
import com.google.appengine.api.datastore.Query;

@Component
public class GoogleDSCommentDAO implements CommentDAO {

	public static final String EntityKind =	"TestComments";

	@Override
	public long save(Comment comment) {
	    Key commentKey = KeyFactory.createKey( EntityKind, comment.getEmail());	    	    
	    Entity commentEntity = new Entity("Comment", commentKey);
	    commentEntity.setProperty("email", comment.getEmail());
	    commentEntity.setProperty("date", comment.getDate());
	    commentEntity.setProperty("text", comment.getText());

	    DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
	    Key key = datastore.put(commentEntity);

	    return key.getId();
	}

	public List getAll( int count ) {
		DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();	    
	    Query query = new Query("Comment").addSort("date", Query.SortDirection.DESCENDING);
	    List entities = datastore.prepare(query).asList(FetchOptions.Builder.withLimit( count ));
	    List comments = new ArrayList();
	    if( entities != null && entities.size() > 0 ) {
	    	for( Entity entity: entities ) {
	    		comments.add( createCommentFromEntity( entity ) );
	    	}
	    }
	    return comments;
	}

	private Comment createCommentFromEntity( Entity entity ) {

		Comment comment = new Comment();
		comment.setEmail( (String)entity.getProperty("email") );
		comment.setText( (String)entity.getProperty("text") );
		comment.setDate( (Date)entity.getProperty("date") );

		return comment;
	}

}

Implementation & Code Samples

Following is listed code samples for controller and view.

HelloController.java (Controller)

Method: newComment( ModelMap model )

//Display all the comments along with fields to create new entry in hello.jsp
@RequestMapping(value = "/springmvc/helloworld", method = RequestMethod.GET)
public ModelAndView newComment( ModelMap model ) {		
	List comments = commentsImpl.getAll( 10 );
	return new ModelAndView("hello", "comments", comments );
}

Method: createComment( @RequestParam(“email”) String email, @RequestParam(“comment”) String text )

//Create new entry upon the submission of the form in page, hello.jsp
@RequestMapping(value = "/springmvc/createcomments", method = RequestMethod.POST)
public ModelAndView createComment( @RequestParam("email") String email, @RequestParam("comment") String text ) {

	Comment comment = new Comment();
	comment.setEmail(email);
	comment.setText( text );
	comment.setDate( new Date() );

	Long id = commentsImpl.save( comment );
	String message = null;
    if( id > 0  ) {
	message = "Data saved in the datastore!";
    } else {
	message = "Data failed to get saved in the datastore!";	    	
    }
    List comments = commentsImpl.getAll( 10 );

	ModelAndView model = new ModelAndView("hello");						
	model.addObject("message", message );
	model.addObject("comments", comments );

	return model;
}

hello.jsp (View)

Following snippets display the key code blocks to display the comments.

<div>
<%
List<Comment> comments = (List<Comment>) request.getAttribute( "comments" );
if (comments.isEmpty()) {
%>
<div style="padding:0px 0px 0px 25px">
No comments are found to be entered.
</div>
<%
} else {
for (Comment comment : comments) {
pageContext.setAttribute("comment", comment.getText());
pageContext.setAttribute("email", comment.getEmail());
pageContext.setAttribute("date", comment.getDate());
%>
<div style="padding:0px 0px 0px 25px">
<div>
${comment}
</div>
<div style="padding-top:10px;font-size:11px">
Posted by: ${email}, Date: ${date}
</div>
</div>
<hr/>
<%
}
}
%>
</div>

 

 

Recommended Books

 

Download

If you would like to get access to entire code for quick coding, download from this page.



Ajitesh Kumar

Ajitesh Kumar

I have been recently working in the area of Data analytics including Data Science and Machine Learning / Deep Learning. I am also passionate about different technologies including programming languages such as Java/JEE, Javascript, Python, R, Julia, etc, and technologies such as Blockchain, mobile computing, cloud-native technologies, application security, cloud computing platforms, big data, etc. I would love to connect with you on Linkedin. Check out my latest book titled as First Principles Thinking: Building winning products using first principles thinking.
Posted in Cloud, Java. Tagged with , .