Spring MVC and Google App engine

We will look to see how we can bundle google app engine with Spring MVC. The scope of this is just to explain how to integrate Spring MVC and app engine. URL for accessing the application is http:\contactsathishjayapal.appspot.comhome. Spring MVC is a nifty native framework for web application development. It is very powerful and versatile framework that supports clean seperation of concerns in MVC architecture. More information about Spring MVC and its power is explained here. Google app engine is a cloud based service from google for hosting and deploying Java and Python based application. Again this is a very powerful and flexible cloud infrastructure. More information on google cloud can be found here. Assumption over here is reader knows something about spring MVC and google cloud. We are using IntelliJ IDE for the development process.

IntelliJ has a useful plugin to integrate with Google App engine. IDE saves a lot of time for developers. IntelliJ allows users to deploy apps directly into the cloud and it has a local sandbox that developers can use to test code base locally. Here are some screens that can help to showcase IntelliJ's support for GAE development.


Once you create a fresh project, resulting screen will be something like this

Note the css, images folders we say under the web directory are project specific. We will discuss more about these folders soon. Now that we have the bare bone project setup, let us move to the next logical step. We have to start integrating the MVC servlet engine to project setup.









From Sathish Blog


To hook up spring MVC system has to integrate with DispatchServlet and we are using the contextloaderlistener to bootstrap Spring WebApplicationContext. The applicationContext.xml is the file that we are using for app core logic specific bean definitions. The other spring context file that will be used in the project is dispatchServlet.xml file. We will discuss each and every line in the dispatchservlet.xml file. Lot of color coding, but am sure we can discuss this to make things much clearer.










From Sathish Blog











From Sathish Blog


Here is the break-up of our color coded stuff. As always if you have to get hold of the base code you can always email me.
Let us first get through the header section:

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
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
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">
Let us examine this name-space convention.
xmlns:context="http://www.springframework.org/schema/context" ==>The namespace over here is keeping spring container posted that we are going to use the Annotation API's for some of our code base. We will get more into it in a bit.
xmlns:mvc="http://www.springframework.org/schema/mvc" ==> Namespace is telling the container that we are going to use the Spring MVC API's.
xmlns="http://www.springframework.org/schema/beans"==> Finally; we know the usual suspect. Spring Beans information.
Before we breakup further of the context.xml file, a brief run down how spring MVC handles its request.

Step 1) User sends a request to application
Step 2) Dispatch servlet - controller intercepts the request
Step 3) Dispatch servlet hands the request to Handling mappings.
Step 4) Handler mapping takes the request and identifies the correct controller with the help of the adapter to invoke based on URL that is being used for request.
Step 5) The controllers do the magic for connecting to a service or do required business logics
Step 6) Once controllers are back they hand over items to views.
Step 7) The view resolver then takes control and pushes the view data to respective templates/JSP's to display

Now that we have back-bone, let us c our dispatch servlet is handling its requests.

As you can see in the above flowchart, first thing the MVC container does is to get the request from dispatch servlet and looks into the annotation handler. The corresponding definition for annotation handler in our xml file is

From Sathish Blog



Above two statements are asking container to look into the package using AnnotationHandlerMapping. We will see the classes defined in these packages later in post. Once the handler is identifying appropriate controller, control is sent to the controller.
Further if for some reason controller is not defined then container switches to search controller using simpleUrlHandler.

From Sathish Blog


As you can see for the simple url handler we have only one name/value pair defined. All error pages are following simple url handler.

The definition of error page is followed by this definition

From Sathish Blog


Now since we are done with controller identification process, next logical step would be to look at the role of adapters in invoking controllers. All spring MVC contollers are handled by default by SimpleHandlerAdapter. We are also doing a validation of data in the back-end. So to fulfill both these we are defining these following items:

From Sathish Blog


By default SimpleControllerHandlerAdapter initializes the webBindingInitializer, where as AnnotationMethod Handler requires an exclusive definition of bindinit. Talking about this is not in scope for this post. We can come back to it at a later point if I see enough searches or questions :) But note the definition is mandatory for validators to work. GAE throws an ugly exception if this is not done properly.
One other advantage of using annotations is, application can externalize its static content with a simple definition of this

From Sathish Blog


We are ready for the view resolver. We are asking the container to look for all the JSP's using the internalview resolver.

From Sathish Blog


Final note on this xml file: GAE is not very helpful when it displays an error page. So I turned to Spring MVC for help. This following XML definition turns the error page/exceptions to a good user friendly screen.

From Sathish Blog


Now that we have covered the major part of this whole blog, we will now look at the controller that we have for this effort, we have two controllers, home controller and Thankyou controller.

Code base for home controller is here.

@RequestMapping(value = "/home", method = RequestMethod.GET)
public String homeMember(Model model) {
LOGGER.log(Level.WARNING, "Home Controller called");
ContactFormData contactFormData = new ContactFormData();
contactFormData.setAppName("SpringSecurity");
model.addAttribute("contactFormData", contactFormData);
LOGGER.log(Level.SEVERE, "Home Controller call ended");
return "home";
}


From the above definition, basically we are creating an empty form object for the view called home to start working. The JSP file for home is here
The form for this JSP is defined as

From Sathish Blog


GAE allows JSTL and spring form tags to work in its container. We are defining them in our header file section.

Here is an usage of the form errors and other items. 

From Sathish Blog



Here is the validator code to make sure all fields in the form are checked for "required" validity.,

From Sathish Blog


@Component
public class ContactFormValidator implements Validator{
@Override
public boolean supports(Class clazz) {
return ContactFormData.class.isAssignableFrom(clazz);
}
@Override
public void validate(Object target, Errors errors) {
ValidationUtils.rejectIfEmpty(errors,"appName","required.appName");
ValidationUtils.rejectIfEmpty(errors,"compliantNature","required.compliantNature");
ValidationUtils.rejectIfEmpty(errors,"state","required.state");
ValidationUtils.rejectIfEmpty(errors,"subject","required.subject");
ValidationUtils.rejectIfEmpty(errors,"message","required.message");
ValidationUtils.rejectIfEmpty(errors,"emailid","required.emailid");
}
}

Now that we have the hang of front-end coding for GAE, let us move to the database/persistence layer of the application. GAE supports database if you use the JPA/JDO framework. I did not find both frameworks as interesting the hibrenate framework am used to. But there is an excellent API called objectify that masks JPA framework to work in GAE. More information on this framework here. Using this API's I was able to do a simple database insert and listing. Here is the code for DAO object.

/**

Actual Facade Class

**/
public class ContactFormFacade implements DaoFacade, ApplicationEventPublisherAware {
static final Log logger = LogFactory.getLog(ContactFormFacade.class);
public ObjectifyFactory getObjectifyFactory() {
return objectifyFactory;
}
public void setObjectifyFactory(ObjectifyFactory objectifyFactory) {
this.objectifyFactory = objectifyFactory;
}
private ObjectifyFactory objectifyFactory;
public void merge(ContactData contactData) {
Objectify obj = objectifyFactory.begin();
obj.put(contactData);
EmailEvent emailEvent = new EmailEvent(this, ((ContactFormData) contactData).getMessage(),
((ContactFormData) contactData).getEmailid());
appEventPub.publishEvent(emailEvent);
}
public Object listAll() {
Objectify obj = objectifyFactory.begin();
Object lst = obj.query(ContactFormData.class).list();
logger.debug("Listing all data");
return lst;
}
ApplicationEventPublisher appEventPub;
@Override
public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
appEventPub = applicationEventPublisher;
}
}

/**

Actual DAO class

**/

public class JpaContactFormDao implements ContactBaseDao{
@PersistenceContext
private EntityManager entityManager;
@Override
@Transactional
public void store(ContactData data) {
entityManager.merge(data);
}

@Override
public void delete(ContactData data) {

}

@Override
public List listAll() {
return null;
}
}


So in this post we saw the GAE integration with spring MVC, we went in detail about spring MVC integration and then we ended up with a simple example of a DAO object.

The entire source code is viewable in google code here.