Tuesday 10 November 2009

Grails on GAE and persistence

Introduction
In my last post we created very simple Grails project and deployed it on Google Application Engine. Now we will try to extend it to use Google Datastore for persistence.

Configuration
Create a project in the same way as in previous post but ensure you will choose JPA as a persistence provider. Another option is JDO but I simply don't know this technology;)
Next step will be to install gorm-jpa plugin for Grails:
grails install-plugin gorm-jpa

Application goals
We will create very simple one page application to manage list of books. On the top there will be a list of book items. At the bottom there will a form to store new ones.



Implementation
We should create class for our domain object - grails-app\domain\test\Book.groovy:
package test

import javax.persistence.*;

@Entity
class Book implements Serializable {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
Long id

String title

static constraints = {
id visible:false
}
}
We need also web controller that will be responsible for 3 web actions:
  • index - main action listing all books
  • save - adding new book
  • remove - removing book
Add following code to grails-app\controllers\BookController.groovy:
import test.*

class BookController {
def index = {
[books : Book.list( params )]
}

def save = {
Book b=new Book(params)
b.save()
redirect(action : index)
}

def remove = {
Book b=Book.get(params.id)
b.delete()
redirect(action : index)
}
}
Finally add GSP page (grails-app\views\book\index.gsp) that will present data and invoke particular actions of our controller:
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<meta name="layout" content="main" />
<title></title>
</head>
<body>
<h1>Books:</h1>
<table>
<thead>
<tr>
<th>Id</th>
<th>Title</th>
<th></th>
</tr>
</thead>

<g:each in="${books}" status="i" var="book">
<tr>
<td>${book.id}</td>
<td>${book.title}</td>
<td><g:link action="remove" id="${book.id}">remove</g:link> </td>
</tr>
</g:each>
</table>
<h1>New:</h1>
<g:form action="save">
<table>
<tr>
<td>Title</td>
<td><g:textField name="title" /></td>
</tr>
<tr>
<td colspan="2"><input type="submit" /></td>
</tr>
</table>
</g:form>
</body>
</html>
Deploy the application just as we did it in last post. Point the browser to /book resource of your web app. You should see our page running.

Now, you can also browse datastore on GAE account pages:

Saturday 7 November 2009

Deploying Grails application on Google Application Engine

Introduction
Some time ago it was announced that Google Application Engine supports Grails framework. As a great fan of Groovy and Grails I wanted to give it a try. I was also very curious to see how GAE works. In this article I would like to present simple "Hello World" project and its deployment process.

My example uses:
  • Grails 1.1.1 (http://www.grails.org)
  • GAE SDK 1.2.6 for Java (http://code.google.com/intl/pl/appengine/downloads.html#Google_App_Engine_SDK_for_Java)
  • Java 1.6
Configuration
As a first step please download required software and install it. To configure it properly you need to set up:
  • variable GRAILS_HOME to directory where you installed Grails
  • variable APPENGINE_HOME to directory where you installed GAE SDK
  • add GRAILS_HOME\bin directory to PATH variable
Creating GAE account
Go to GAE website (http://appengine.google.com) and create an account. Log in and add new application to your account. Specify application name - I will use "gae-grails-maciek-test".

Creating simple project
Go the your workspace directory and type: grails create-app GoogleGrailsTest
Script should create your project subdirectory - GoogleGrailsTest. You can import your project to Eclipse or another IDE.



Please modify GoogleGrailsTest\grails-app\conf\Config.groovy and add following line:
google.appengine.application="gae-grails-maciek-test"

Of course you should use your GAE application name. Go to project directory and install grails GAE plugin:
grails install-plugin app-engine

You will be asked if you want to use JPA or JDO for persistence. It is not important at all for our case.

To run you project locally on your computer type: grails app-engine run
You should be able to access it at http://localhost:8080



I must confess I noticed a strange stack trace in log files, but application was still running properly...

Deployment
Type:
grails set-version 1
grails app-engine package

First deployment should be done with:
$APPENGINE_HOME/bin/appcfg.cmd update ./target/war

Later when you just update application on GAE sever you can just type:
grails app-engine deploy

During deployment process you will be asked about your google account email and password. I noticed strange bug during authentication process. When script asks you for email just push Enter and go to the next line and enter it there. Password can be entered normally. Without this trick I was not able to authenticate properly.

Now you should be able to access your application at http://your-app-name.appspot.com - in my case on http://gae-grails-maciek-test.appspot.com/

Application can be monitored on GAE pages after logging in to your account:




Sunday 6 September 2009

Partial rendering with Spring MVC and Spring Javascript

Introduction
Almost all modern web pages uses many AJAX techniques. One of them is partial rendering - it allows user to rerender only part of a page instead of its full contents.

Main benefits are:
  • less response size sent via network
  • less time needed to show new page contents
  • less application server load
  • better user experience
Recently I was using partial rendering in JSF application with Ajax4JSF framework. To have wider perspecitve I was going to try another out of the box solution from lightweight stack like Spring MVC, Spring Javascript and Apache Tiles.

Application goals
Test application has a page layout configured with Tiles. Pages consist of menu on the left side and main contents on the right. Navigation links in menu are used to choose page contents for right side - it will be rerendered (Ajax) after each click on menu item.

Main page (rendering time is just to show ajax behaviour):


Page after ajax rerendering triggered by click in menu:


To prepare my sample application I used:
  • Maven 2.0.9
  • Java 1.6.0_12
  • Spring 2.5.6
  • Spring Javascript 2.0.5
  • Apache Tiles 2.1.0
Project structure
I used typical maven structure for the project:


























All project dependencies are configured in maven's pom.xml:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.maciekm</groupId>
<artifactId>spring-js-demo</artifactId>
<packaging>war</packaging>
<version>1.0-SNAPSHOT</version>
<name>spring-js-demo Maven Webapp</name>
<url>http://maven.apache.org</url>
<dependencies>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.4</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>2.5.6</version>
</dependency>
<dependency>
<groupId>org.springframework.webflow</groupId>
<artifactId>org.springframework.js</artifactId>
<version>2.0.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.apache.tiles</groupId>
<artifactId>tiles-core</artifactId>
<version>2.1.0</version>
</dependency>
<dependency>
<groupId>org.apache.tiles</groupId>
<artifactId>tiles-jsp</artifactId>
<version>2.1.0</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>taglibs</groupId>
<artifactId>standard</artifactId>
<version>1.0</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<finalName>spring-js-demo</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.mortbay.jetty</groupId>
<artifactId>maven-jetty-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
Web application configuration
At first we need to configure our web app in web.xml:
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app>
<display-name>Archetype Created Web Application</display-name>
<filter>
<filter-name>characterEncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<servlet>
<servlet-name>springjsdemo</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet>
<servlet-name>Resource Servlet</servlet-name>
<servlet-class>org.springframework.js.resource.ResourceServlet</servlet-class>
<init-param>
<param-name>allowedResourcePaths</param-name>
<param-value>/**/*.css,/**/*.gif,/**/*.ico,/**/*.jpeg,/**/*.jpg,/**/*.js,/**/*.png,META-INF/**/*.css,META-INF/**/*.gif,META-INF/**/*.ico,META-INF/**/*.jpeg,META-INF/**/*.jpg,META-INF/**/*.js,META-INF/**/*.png,META-INF/**/dojo/resources/blank.html,/dojo/resources/blank.html</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>springjsdemo</servlet-name>
<url-pattern>*.htm</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>Resource Servlet</servlet-name>
<url-pattern>/resources/*</url-pattern>
</servlet-mapping>
</web-app>
Springjsdemo servlet is used to start spring web application context and as a front controller in our application. Resources Servlet is necessary for Spring Javascript. characterEncodingFilter is important when you want to use national characters on pages fragments rerendered by Ajax.

We also have to setup application context - springjsdemo-servlet.xml:
<?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-2.5.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd">

<context:component-scan base-package="org.maciekm.springjsdemo"/>
<bean id="tilesConfigurer" class="org.springframework.web.servlet.view.tiles2.TilesConfigurer">
<property name="definitions">
<list>
<value>/WEB-INF/tiles/pages.xml</value>
</list>
</property>
</bean>
<bean id="tilesViewResolver" class="org.springframework.js.ajax.AjaxUrlBasedViewResolver">
<property name="viewClass" value="org.springframework.js.ajax.tiles2.AjaxTilesView"/>
</bean>
</beans>
We configured Spring MVC to work with Apache Tiles. Spring MVC controller will be found and initialized by component scanning.

Pages layout
Tiles layouts are configured in pages.xml:
<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE tiles-definitions PUBLIC
"-//Apache Software Foundation//DTD Tiles Configuration 2.1//EN"
"http://tiles.apache.org/dtds/tiles-config_2_1.dtd">
<tiles-definitions>
<definition name="welcome" template="/WEB-INF/jsp/template.jsp">
<put-attribute name="menu" value="/WEB-INF/jsp/menu.jsp"/>
<put-attribute name="body" value="/WEB-INF/jsp/welcome.jsp"/>
</definition>
<definition name="page1" extends="welcome">
<put-attribute name="body" value="/WEB-INF/jsp/page1.jsp"/>
</definition>
<definition name="page2" extends="welcome">
<put-attribute name="body" value="/WEB-INF/jsp/page2.jsp"/>
</definition>
</tiles-definitions>
Idea of using Tiles is not just to define page layouts. It helps us to define logical structure of pages so we will be able to rerender its parts.

Our layout template is in template.jsp and we configured 3 views based on it: welcome, page1 and page2. Each view consist of menu and body attributes.

Here we have template.jsp source:
<%@ page pageEncoding="UTF-8" %>
<%@ include file="include.jsp" %>
<html>
<head>
<title>Spring JS Demo</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" >
<META HTTP-EQUIV="Pragma" CONTENT="no-cache">
<META HTTP-EQUIV="Expires" CONTENT="-1">
<meta http-equiv="Content-Language" content="pl">
<meta http-equiv="Cache-Control" content="no-store, no-cache, must-revalidate, Post-Check=0, Pre-Check=0">
<script type="text/javascript" src="<c:url value="/resources/dojo/dojo.js" />"> </script>
<script type="text/javascript" src="<c:url value="/resources/spring/Spring.js" />"> </script>
<script type="text/javascript" src="<c:url value="/resources/spring/Spring-Dojo.js" />"> </script>
</head>
<body>
<table cellpadding="5" cellspacing="5" border="1" width="100%">
<tr>
<td id="left" width="150px"><tiles:insertAttribute name="menu" /></td>
<td id="right"><tiles:insertAttribute name="body" /></td>
</tr>
</table>
</body>
</html>
JS files needed for Spring Javascript have been included.

Web pages
The core point of our application is menu. It contains links that will allow you to choose body of the web page and rerender it using Ajax.
<%@ page pageEncoding="UTF-8" %>
<%@ include file="include.jsp" %>
&nbsp;&nbsp;&nbsp;&nbsp;Menu:
<br/>
<br/>
<ul>
<li>
<form action="<c:url value='/page1.htm'/>" method="POST" id="page1Form" style="padding: 0px;margin: 0px;"></form>
<a id="page1" href="#">Page 1</a>
</li>
<li>
<form action="<c:url value='/page2.htm'/>" method="POST" id="page2Form" style="padding: 0px;margin: 0px;"></form>
<a id="page2" href="#">Page 2</a>
</li>
</ul>
<script type="text/javascript">
Spring.addDecoration(new Spring.AjaxEventDecoration({
elementId: "page1",
formId: "page1Form",
event: "onclick",
params: {fragments: "body"}
}));
Spring.addDecoration(new Spring.AjaxEventDecoration({
elementId: "page2",
formId: "page2Form",
event: "onclick",
params: {fragments: "body"}
}));
</script>
<br/><br/>
Rendering time:<br/><%=new java.util.Date()%>
Each link is "decorated" with special Spring Javascript code. AjaxEventDecoration will make Ajax request to server to ask for the page configured in form definition. However, it will ask only for specified page fragment - body.
Name of this fragment must be the same as name of Tiles attribute in layout of requested page.
On both current page as well as loaded fragment we need to have a div element with ID same as fragment name - body. Spring Javascript will be able to replace its old contents with new that just has been loaded from server.

Note: I used POST forms to define links becouse I had some problems with GET requests and cacheing in IE8. However it is not a recommended solution in a serious project. You should consider using GET with random parameters added just to avoid caching problem.

Default page body is defined in welcome.jsp as a part of welcome tiles view:
<%@ page pageEncoding="UTF-8" %>
<%@ include file="include.jsp" %>
<div id="body">
Main area
</div>
As I said, it contains body div as an container for ajax rerendering with its initial value.
Below we have alternative pages that can be selected from menu.

page1.jsp:
<%@ page pageEncoding="UTF-8" %>
<%@ include file="include.jsp" %>
<div id="body">
This is page 1. Rendering time: <%=new java.util.Date()%>
</div>
And page2.jsp:
<%@ page pageEncoding="UTF-8" %>
<%@ include file="include.jsp" %>
<div id="body">
This is page 2. Rendering time: <%=new java.util.Date()%>
</div>
We need also some less important jsp pages to make our application running.
We use include.jsp just to include some TLDs:
<%@ page pageEncoding="UTF-8" %>
<%@ taglib uri="http://tiles.apache.org/tags-tiles" prefix="tiles" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jstl/core" %>
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
index.jsp is used only to redirect us from root view to our welcome page:
<%@ include file="/WEB-INF/jsp/include.jsp" %>
<c:redirect url="welcome.htm"/>
Spring MVC controller
Of course we need MVC controller to map our views to urls. It our simple case it does not contain any business logic.

We map:
  • /welcome.htm -> welcome view
  • /page1.htm -> page1 view
  • /page2.html -> page2 view
Source code:
package org.maciekm.springjsdemo.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class MainController {

@RequestMapping("/welcome.htm")
public String welcomePage() {
return "welcome";
}

@RequestMapping("/page1.htm")
public String page1() {
return "page1";
}

@RequestMapping("/page2.htm")
public String page2() {
return "page2";
}
}
Running and testing
To run application type mvn jetty:run from console in main project directory. It should start Jetty server and deploy our webapp to http://localhost:8080/spring-js-demo. Point your browser to this url and test links in menu.

Hopefully our Ajax partial rendering works:)