jQuery Mobile, Grails, GAE, Oh My!
I recently decided to sit down and play with jQuery Mobile and absolutely fell in love with it. I’ve been designing web applications for years, but the pure simplicity in jQuery Mobile is absolutely amazing. The one part I’ve never been good at is graphics with respect to web design. jQuery Mobile removes that requirement and allows me to focus purely on semantics, which is what the web is all about anyways. The end result is jQuery Mobile themes the semantics according to the end platform. Further, the work of ensuring the site renders appropriately in various end devices is automatically accounted for. jQuery Mobile scales from iPhone to iPad to Blackberry to Android and back again. My hat goes off to the work put forth by the jQuery Mobile team. But enough of the praise…let’s get to what and how I did with a step by step guide…click to read more.
First of all, I decided to also play with Google App Engine for the first time since it is a free server for Java hosting. Also, since I’m a huge proponent of Grails, I used Grails for the templating and server side. This article will explain all three cases. The actual project I built was a Budget analysis tool, so I will use parts of that in explaining everything.
Step 1: Setup Grails Project
The first step is to create and setup a Grails project. This assumes you have already downloaded Grails and setup your environment variables accordingly. Open up a console/terminal:
# grails create-app budget |
This will create a new directory and populate it with a default Grails web application. If you want to verify it works, just change to the new budget directory and enter grails run-app. This will start the embedded web server to which you can point your browser to localhost:8080 and see the default web application. Amazing how easy it is to get up and going with Grails as well.
Step 2: Create Domain Classes
Now that we have a running application, let’s do something useful with it. Since I am creating a budget-type application, let’s create a transaction domain class to house our various budgets and transactions.
# grails create-domain-class com.znet.budget.Transaction |
This will create an empty domain class an relevant test cases. Since the class is empty, we need to add some properties to it. In simplistic Groovy fashion, that just means adding the fields and letting Groovy automatically add the getters, setters, etc.
class Transaction { static constraints = { // database constraints for grails (GORM) } Integer id; String type; String name; String description; Double amount; } |
Want to test and verify this all works? Simply generate a controller and associated views and you are up and running with a persistable model.
# grails generate-all com.znet.budget.Transaction |
Now run the app (grails run-app) and you will have default views with the ability to create, edit, delete, and view…all with just a few commands and lines of code.
Step 3: Setup Layout via jQuery Mobile
Now that we have the database and default code out of the way, let’s create the base layout and utilize jQuery Mobile. Grails uses Sitemesh under the covers to handle the layouts. If you open up the generated list.gsp view (ie: grails-app/views/transaction/list.gsp), you will notice there is a meta tag in the head section specifying the layout as ‘main’. This tells Grails to wrap the body in that layout template (grails-app/views/layouts/main.gsp). Open up the layout template and update the head section to add a few key meta tags and links to jQuery Mobile:
<!-- base title of the application [overridable from each view template] -->
<title><g:layoutTitle default="Budget" /></title>
<!-- shortcut icon to use in standard browsers -->
<link rel="shortcut icon" href="/favicon.png" />
<!-- iOS tip to allow the application to be installed on the home screen -->
<meta content="yes" name="apple-mobile-web-app-capable" />
<!-- iOS tip to specify sizing and constraints -->
<meta content="minimum-scale=1.0, width=device-width, maximum-scale=0.6667, user-scalable=no" name="viewport" />
<!-- iOS tip to specify the home screen icon for web app and the splash screen -->
<!-- NOTE: splash screen MUST be 320x460 and PNG format -->
<link rel="apple-touch-icon" href="/touch.png"/>
<link rel="apple-touch-startup-image" href="/splash.png" />
<!-- stylesheet for jQuery Mobile -->
<link rel="stylesheet" href="http://code.jquery.com/mobile/1.0a4.1/jquery.mobile-1.0a4.1.min.css" />
<!-- javascript for jQuery Mobile -->
<script src="http://code.jquery.com/jquery-1.5.2.min.js"></script>
<script src="http://code.jquery.com/mobile/1.0a4.1/jquery.mobile-1.0a4.1.min.js"></script>
<!-- overridable properties from view -->
<g:layoutHead /> |
The main part to be concerned with are the links to jQuery and jQuery Mobile. Note that we are linking to 1.0alpha4 as of this blog entry (newer versions are prolly available that you should link to instead). Also of interest is the optimizations for iOS as a pure web application. iOS allows web pages to be installed on the Home Screen and then launched without the Safari wrapper (navigation, headers, etc). It also allows custom splash screen while the web application is loading. Note that the splash screen, icons, etc must be in specific formats to properly work.
With jQuery Mobile and the head section in place, we can now define the base semantic layout. Semantics are important to the web as it allows better accessibility, meaning, SEO optimizations, styling, etc. jQuery Mobile heavily stresses this by using semantics in ways they were meant to be used. jQuery Mobile uses ‘data’ attributes to demark various sections with specific meanings. For example, you use the data attributes to demark the page, the header, footer, content, widgets, etc. The following is an example layout using a single header and tabbed navigation bar. This content should be placed in the body section of the layout template.
<div data-role="page">
<!-- Define Header Bar -->
<div data-role="header" data-position="fixed">
<h1><g:layoutTitle default="Budget" /></h1>
<!-- Allow Specific View to Provide Buttons on the Header (back, edit, save, etc) -->
<g:pageProperty name="page.buttons" />
</div>
<!-- Define Content Section -->
<div data-role="content">
<!-- Load Content from Actual View -->
<g:pageProperty name="page.content" />
</div>
<!-- Define Navigation Bar in Footer -->
<div data-role="footer" data-id="nav" data-position="fixed">
<div data-role="navbar">
<ul>
<!-- Define Each Tab as List Item Links -->
<li>
<g:link controller="transaction" action="list" params="[type:'bill']" data-transition="fade">Bills</g:link>
</li>
<li>
<g:link controller="transaction" action="list" params="[type:'budget']" data-transition="fade">Budget</g:link>
</li>
<li>
<g:link controller="transaction" action="list" params="[type:'deposit']" data-transition="fade">Deposits</g:link>
</li>
</ul>
</div>
</div>
</div> |
We utilize Sitemesh sections to allow views to inject specific content in specific portions of the layout. For example, a view could specify the buttons section to add buttons to the header (more on this in a bit). We use standard links in the navigation bar to link to specific pages. Note that we use ‘data-transition’ attributes to specify how the subsequent page should load. By default, jQuery Mobile uses Ajax to load each page and once the page has been loaded, it transitions according to a given animation if provided. This adds not only flair to the web application, but also shows the user that something is occurring and that the page has changed.
With this base layout in place, we can again run the application and see the formatting done by jQuery Mobile. Try it on a mobile device for example. The best part is that we did not write a single line of CSS or Javascript, yet we have a scalable UI for a variety of devices with a good base theme. Again, there is so much power in simplicity allowing developers to focus on features, not design and architecture.
Step 4: Setup Routes for Transaction Types
You may have noticed that we were using the same controller and action in the navigation bar links but with different parameters. By default, Grails will append the type parameter as a query param. However, with SEO in mind and RESTful practices in mind, I prefer to use actual URIs. To allow the type parameter to exist in the URI, we must update the grails-app/conf/UrlMappings.groovy mappings file. This tells Grails how to route various URIs to which controllers and views. Via convention over configuration, Grails routes most controllers automatically. For our case, we must tell Grails about the type parameter. After that, Grails will automatically insert the proper links into the templates accordingly. Note that this is not an often discussed feature of Grails, but it is a really powerful feature. For example, simply update the mappings file and every link updates without having to explicitly update each link in each template which is highly error prone.
class UrlMappings { static mappings = { // allow the 'type' parameter to be listed and route to the transaction controller "/transaction/$type/$action?/$id?"{ controller = 'transaction'; } } } |
Step 4: Setup List View
We now have a layout in jQuery Mobile and proper routes. Now we must setup the controller to utilize that type parameter to load the proper items. To do so, we use GORM and dynamic finders. Dynamic finders in Grails is prolly the coolest feature I have seen in a long time as it allows data to be loaded via dynamic APIs without writing a single line of SQL. The examples below are just the tip of the iceberg…it gets much more powerful and dynamic.
class TransactionController { def list = { def transactions = Transaction.findAllByType(params.type ?: 'bills'); [transactions:transactions, type:params.type]; } } |
Wow…two lines of code and we have loaded a domain class, accessed a backend repository (ie: SQL), generated the APIs/SQL to access the backend data store, and converted the data into our custom domain class. Now that is power on the backend. But let’s get back to the powerful frontend now. Let’s update our list.gsp template to utilize our new data model as well as jQuery Mobile to show a nice list.
<html>
<head>
<meta name="layout" content="main" />
<title>${type}</title>
</head>
<body data-id="${type}" data-nobackbtn="true">
<!-- Specify Buttons for Header Section -->
<content tag="buttons">
<g:link action="create" params="[type:type]" class="ui-btn-right"
data-icon="plus" data-transition="slideup">
Add
</g:link>
</content>
<!-- Specify Content Section -->
<content tag="content">
<!-- Specify List with Dividers -->
<ul data-role="listview" data-dividertheme="b">
<!-- Specify a header in the list for the total -->
<li data-theme="e">
<h4>Total</h4>
<h4 class="ui-li-aside">
<g:formatNumber number="${transactions*.amount.sum() ?: 0.0}" type="currency" currencyCode="USD" />
</h4>
</li>
<!-- Loop Through Remaining Transactions -->
<g:each in="${transactions}" status="i" var="transaction">
<li>
<g:link controller="transaction" action="show"
params="[type:type]" id="${transaction.id}"
class="ui-btn-right" data-transition="slide">
<h4>${transaction.name}</h4>
<p>${transaction.description}</p>
<h4 class="ui-li-aside">
<g:formatNumber number="${transaction.amount}" type="currency" currencyCode="USD" />
</h4>
</g:link>
</li>
</g:each>
</ul>
</content>
</body>
</html> |
The things to note here are first that we use standard ul/li tags within jQuery Mobile and then use the data attributes to inform jQuery Mobile that the list should be styled as a list view. There are also various themes you can select for the dividers and actual list items to add consistency and style. Within each list item, you define the title via standard h4 tags, and optional body via a p tag, and an optional value to be displayed to the right of the items. jQuery Mobile will take the content and style as necessary.
Step 5: Remaining Views
I will not go into specifics of the remaining views (show, edit, etc), but rather hit some focus points of those views. jQuery Mobile supports forms in standard ways with custom styling to match particular devices so they fit and show up best. All you need to do is use standard input and labels. Further, you can use forms in standard list views to create a clean separation.
<ul data-role="listview">
<!-- Specify List Item as Containing Form/Field Data -->
<li id="name-container" data-role="fieldcontain">
<label for="name"><g:message code="transaction.name.label" default="Name" /></label>
<span class="${hasErrors(bean: transaction, field: 'name', 'errors')}">
<g:textField name="name" value="${fieldValue(bean: transaction, field: 'name')}" />
</span>
</li>
...
</ul> |
Finally, jQuery Mobile supports the notion of dialogs where you can cause a button, link, etc to show a given piece of content in an inline dialog rather than actual page. I am not a big fan of dialogs within mobile devices, so in my particular cases, I preferred to use complete views for edit pages. Just make sure that you specify the data animation attributes. Also, if you are going from an edit page back to a show or list page, make sure to give the same data animation attribute but provide the data-direction="reverse" attribute to tell jQuery Mobile to go the opposite direction. For example, if you used data-transition="slideup" to view the edit page to cause the content to slide up into place, then specify slideup in the edit view going back to the show view using reverse so that jQuery slides down the content. This keeps everything consistent and familar to the end user.
Step 6: Google App Engine
The final piece of this puzzle was uploading to Google App Engine. I will not elaborate on this heavily as there are several good blog articles out there on getting Grails to work with Google App Engine. The key essentials are installing the app-engine plugin in Grails, uninstalling the tomcat/jetty plugin, and setting up a few key configurations. GAE supports using JPA within AppEngine to access the data store. As such, most (not all) features within GORM will automatically work with Google’s data store. However, I did have some issues in getting dynamic finders to work properly.
Final Thoughts
Grails, as a backend framework, is amazing. Simple and highly effective. It allows applications to be quickly built without having to build entire frameworks to do things. In my full fledged application above, most of the code was auto-generated through scaffolding and only the views were really modified.
jQuery Mobile, as a frontend framework, is equally amazing. When I started this project, I did not want to have to create the entire design to look good on a mobile device and deal with all those nuances. I discovered jQuery Mobile and was instantly sold. Just add semantic HTML and some data attributes and let jQuery Mobile take care of the rest.
Kudos go out to both teams. At this point, I cannot think of two better frameworks together for mobile web applications within HTML5 than Grails and jQuery Mobile.

Hi, great tutorial, but as a NewBe to grails and JQuery, I find it hard to implement..