9 Tips to Planning and Building Maintainable Grails UIs

How can we build user interfaces using GSP that are manageable and easy to update? Many of the books on Grails focus on the technology available in Grails, but very few give rules and techniques to make GSPs manageable.

Grails templates and the out-of-the-box functionality is great. But once you start trying to integrate layouts and designs for real world websites, you’ll find that bad coding practices can quickly lead to a chaotic and unmaintainable mess of spaghetti code.

In this post, I want to share some tips, lessons and ideas I have learned from projects worked in the last year and a half of Grails UI development.

Planning Your UI

1. Build a Skeleton with Layouts, Taglibs, Codecs and Templates.

For one of our projects, we made the mistake of giving a PSD template to an HTML/CSS contractor. He started putting things together in the way that a traditional HTML developer would, worrying more about positioning and squeezing the right graphics in place. Big chunks of code were copied and pasted into other areas so that it looked right and he would get paid. We then spent the next three weeks retrofitting his HTML mess into our GSP files and had to throw a lot of his code away.

If you’re starting a new project and are not very familiar with Grails, spend a bit of time learning and educating your team about how to properly use Sitemesh layouts, codecs, tag libraries and templates.

Once you have learned them, build a Skeleton for your site. Based on wire frames or other design artifacts, create templates and views that simply render out a string. Use layouts to organize these simple templates and views and map them to your URLMapping. Try navigating your site. This will help you identify missing functionality and better organize your project’s UI structures before changing much of your code.

2. Figure Out The Plugins You Need Early.

One of the big hurdles that get in the way of creating and maintaining Grails projects is trying to insert a plugin after some of the code and page functionality has been scripted. Different plugins will lead to different tags and UI strategies. Ask yourself the following questions:

  • Are you going to use Ajax?
  • Which JavaScript libraries or UI frameworks are you going to use?
  • Which kind of template engine are you going to use? Sitemesh (default) or FreeMaker?
  • Does your site need security and authentication?
  • Do you need a blog, shopping cart solution or third party payment gateway
  • Are you going to use the UI Performance Plugin?
  • Are you going to use rich client technology like Flex, GWT or OpenLaszlo?
  • Are you going to provide alternative views for mobile devices such as the iPhone via the iWebKit plugin?

3. Have a Strategy for Updating Semi-static Content.

There are certain parts of your website that will be updated only once in a while. These might include corporate information, about pages, contact information, etc. This content might be different than the main functionality of your website but might need frequent updates.

Depending on the complexity of your project, you might want to consider building a content management system and admin interface that is separate from your main application. This will allow you to easily maintain this type of data without having to restart or redeploy your application.

Consider hooking up to a Content Management interface like Weceem or the Grails CMS plugin. Or you might want to design your application so you’re editing this content with established platforms with beautiful editing interfaces like WordPress, and then pulling in this data via the WordPress Plugin.

When thinking about static content, also think about where and how you are going to host and update images and other media on your Grails application. Are you going to host them externally in a separate server? Would you need a plugin like static resources? Are you going to deploy a content delivery network for videos? Thinking out and planning these steps will simplify your UI development process and will prevent you from having to make changes later.

Coding Your UI

4. Build Top-Level Templates That Map To Domain Objects

Let’s assume you have a complex book listing GSP file:

structure of the pateBecause this all renders into one page, you might start by adding each of the areas, perhaps separating each section with html markup. You’ll end up with a gsp page that looks like this:

full page gsp

This GSP can get very hard to manage after a while. Worst yet, it is not immediately evident when you come to the page which section actually belongs to which domain classes. You’ll end up spending a lot of time tracking each bit and section.

A better solution might be to break down the larger HTML into templates that map to the domain classes they represent. This allows you to create views used for navigation ( usually homepages and top level category pages ) and those used to display data. This helps keep views simple, allows for re-use and makes updating future pages more manageable.

separated files

So for this example, we might break down the sidebar into further smaller gsp templates, while for things that are fairly atomic like the booklist, just render the template.

( In the example above, you would probably have also separated header, footer and sidebars into a layout. )

5. Generate As Much Code As Possible.

One of the very powerful things about Grails is the ability to generate code based on domain objects. However, this mechanism is also one that is rarely used outside of the typical CRUD templates. In past projects, what I ended up doing was to edit the resulting gsp file, losing the ability to regenerate my views when I needed to change domains.

If you follow the last tip, you will see that your data views become fairly individualized, atomic containers for data. You can then use a plugin like the xTemplate plugin to define more views than the default CRUD views provided by Grails. I find that you usually want a read-only list browser, a read-only individual item browser.

This is also an excellent way to extend plugins and other functionality.

Let’s say you want to provide AJAX functionality to your domain objects and connect this into the Grails-UI plugin. Once you have built one that works, you can take this functionality and extract it so that you can use this functionality to generate more views. At the end of the day, you will be able to update individual views via the generate-views command whenever your domain object changes, and not to worry about doing this manually. Less manual labour = less mistakes.

6. Build Helper Libraries.

A trick that has served me well is to build taglibs for links and images that you are going to put on your gsp pages with a custom tag that wraps the default Grails tags. I’ve found that many websites have succint SEO and tracking requirements. By keeping an utility library that generates your links, you don’t have to worry about forgetting to add analytics or title/alt tags.

For code that you find yourself writing across projects, consider wrapping these into utility plugins that you can then share across your projects ( and contribute to the community! ).

For example, if you find yourself embedding a lot of flash files in your projects, you might want to create a tag that also writes out the alternative content and noscript tags and put it into a plugin. If your script library updates, you simply need to update your plugin instead of updating all your codebases by hand.

7. Preserve Names Across Technologies.

This one is pretty simple. Let’s assume you have a bunch of gsp files that also call css and javaScript files. Come up with a common convention to associate them. For example, you might have a set of css files for Book called book.css, book_ie6.css and book_ie7.css, and a set of JavaScripts called book.js.

If the layouts of your pages change often, consider also having css and javascript files called book_external.css and book_external.js that are served from an external source and override the files deployed with your web application. This will let you change your site without having to re-deploy, assuming that this is what is dictated by your semi-static content strategy.

If you have complex views, consider writing a helper service that has the same name as the views. For a read-only bookList, for example, build a method called getBookList() in your BookService. This prevents you from repeating this code across many controllers, and helps you keep this code maintainable. ( Also think about putting as a code template in src/templates, so you can generate helper services easily without affecting your controller ).

8. Keep Your Technologies Uncoupled.

With scriptlets and the g:if tag, it becomes very tempting to resort to all sorts of inline code generation madness to customize css and javascript views. The problem comes when you need to replace or refactor this code later on. Let’s say that you wrote a css that calculates widths according to the a value in your domain objects like this:

.book{ width: ${ book.narrow ? 40 : 120 } px }

What happens when you suddenly find out that you need to use this component somewhere else with a different margin? You would need to rewrite this section and find all the places where your code has been inlined. Instead, keep your code and style separate by strictly forcing domain objects to generate id tags in Divs, then style these divs according to your UI specifications:

<div id=" ${ book.narrow ? 'narrowBook' : 'wideBook' } " />


This way, you can simply overwrite the css file for the new page.

Similarly, it’s easy to try to insert values directly into inline JavaScript files. Just don’t. Instead, what I’ve found works is to declare variables in your GSP files,

<g:javascript>
	var bookCount = ${ Book.count() }; 
</g:javascript>


Then use them in your javascript code.
The reason for this is twofold.

First, you can look at the variables you’re using and passing back and forth right away, allowing you to catch if a variable has been missed or is returning the wrong value.

Second, you can then keep the bulk of your javascript inside a separate js file. This allows you to quickly replace it with another library or test it out with fake data during development. It removes the dependency to your backend. It also enables this to be compressed via utilities like ui-performance.

9. Write Tests.

Test, we all know we should write them, but it’s easiest to forget about them when you’re working with the UI layer. After all, you’ve already written all your controller and unit tests. Why bother spending time testing out things that can be caught by a website run-through?

You will find that writing at least a minimal set of tests will enable you to keep sane once a whole whack of UI code has been written. There are a lot of plugins that can help you with catching accidental 404s and 500 errors, specially when it comes to complex HTML websites.

The list of plugins keep growing, but currently you can choose between:

Additionally, you can use external tools like JMeter, VisualVM or Perf4J to track your page performance and memory usage. Don’t forget about tools like YSlow and Google Page Speed.

At the minimum, write a set of tests that map to your URL mappings to check for 404s and 500 errors. Check your links and use a plugin like build-test-data to see that your components are working the way they are supposed to.

Anyway, these are the lessons I have learned from Grails UI development. I hope they are useful to you. What are yours?

14 thoughts on “9 Tips to Planning and Building Maintainable Grails UIs

  1. Ted Naleid

    Those are solid tips Tomas.

    Kind of building on your #6, I like to create a “domain” plugin for most mid/large projects I work on. That plugin holds all of my domain classes as well as any shared services.

    I can then install that plugin in client apps that all talk to the same database schema easily.

    On my current app, we’ve got 3 different applications all using the same domain plugin (admin, consumer portal, batch/quartz). This separation makes things a lot cleaner and gives us more deployment options.

    You can use the BuildConfig.groovy config file to specify the location of a local plugin so that you don’t need to manually install the domain plugin every time you make a change. It’s pretty much just like having the domain objects right in your app.

    Reply
  2. Marc Palmer

    Nice one Tomas. Some other patterns I’ve hit on are:

    Use a JS object to pass in data from the Grails model to JS code, rather than global vars – especially for example passing in links to ajax actions that are subject to url mappings:

    var myAppGlobalData = {
    newItemPostURL: ‘${createLink(controller:”test”, action:”save”).encodeAsJavaScript()}’
    updateItemPostURL: ‘${createLink(controller:”test”, action:”update”).encodeAsJavaScript()}’
    }

    Then you include the rest of your page’s JS as an external .js file to preserve sanity

    Another is to use taglibs for all your common UI elements eg:

    …and so on. This way you don’t need to know how to get an icon to render – which might use jquery ui styles, or custom sliding doors etc

    We also find that during prototype/wireframing and perhaps final site deploy, using something like blueprintcss.org framework helps us get there MUCH quicker without a designer at all, so the designer can play with the app and get a real feel for what they can do with it.

    Finally, I get designers to download and install grails using an OS X shell script I wrote, so that they can run the app locally🙂

    Reply
  3. Jakob

    Hey Tomás,
    nice writeup. Those tips bring some painful memories alive.😉

    Here’s something that I find very useful when you use lots of custom written JavaScript:

    I usually create a JavaScript function getBaseUrl() in the top level layout. All it returns is a ${resource(dir:’/’)} or in pre 1.1 versions ${createLinkTo(dir:’/’)}. This makes writing JavaScript cleaner, you don’t have put JavaScript on top of every GSP page – instead you can separate your JavaScript nicely out into separate files.

    In the same manner I add a getLocale() function that returns the current locale. Allows easy access to this kind of information.

    My last advice is to use uiperformance or similar plugins. It’s more of a procedure thing, but the benefits are significant, especially when a lot of JavaScript is in place.

    Cheers,
    Jakob

    Reply
    1. Tomas Lin Post author

      Thanks for the correction Stephan. And thanks for all the hard work you, Marc, Glen, July, Sergei and the crew are putting in to make this a reality…

      Reply
  4. Konstantin Gurnov

    Hello Tomas,

    Very solid writup, especially 5th tip. I have solid Flex & PureMVC background and could say that generation of AS Proxies from domain objects saved lots of time and bugs. In spite of many existing projects, I preferred to create own lightweigt AS generator from java domain object.

    I’m new in Grails and will be happy to find the way of reusing its built in generation abilities for this purpose.

    Reply
  5. Jennifer

    Hi Tomas,
    Nice write up!
    I have a question. I’m working on a system in Groovy/Grails that build user interfaces using GSP just like what you wrote. But I wish to use flex interface, so I was wondering, is there a way to use flex interface components in my system Grails UI? Or I do have to abandon my UI and change to Flex mxml files? And how to do that?
    Thanks.
    If you prefer, here´s my email address: jenniangel@gmail.com

    Reply
  6. Pingback: Blog bookmarks 08/27/2010 « My Diigo bookmarks

  7. Pingback: 用闭包增强注解 – grails开发平台

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s