grails

  • submit to reddit

Daily Dose: Twitter scores $800 million in record breaking deal

Today, Russian venture firm DST Global invested a record breaking $800 million into Twitter.  According to the release, half of that investment is meant to let Twitter employees and investors cash out their shares, with the other $400 million sold in new...

0 replies - 15010 views - 08/02/11 by Ross Jernigan in Daily Dose

Daily Dose: First Milestone Of Grails 1.4 Released

Grails users will be happy to see that Grails 1.4, the first milestone of the open source framework, was released this week, featuring major changes such as:- Unit test support that can be integrated into any test framework, so there are no more base classes-...

0 replies - 6633 views - 06/08/11 by Jim Moscater in Daily Dose

Daily Dose - Spring Mobile and Spring Android Go Live

SpringSource just announced two new projects to aid Spring users in mobile application development.  The first is Spring Mobile, which provides extensions to Spring MVC to streamline the development of web apps that work across multiple mobile operating...

0 replies - 20816 views - 11/22/10 by Mitchell Pronsc... in Daily Dose

Daily Dose - WebM Available for 80% of YouTube Daily Videos

According to Google's John Luther, over 80% of daily YouTube videos are now available in WebM: a completely free and open source codec pack for HTML5 video.  After it was open sourced at Google I/O in the spring, WebM was quickly adopted by browser-makers...

0 replies - 20032 views - 11/15/10 by Mitchell Pronsc... in Daily Dose

Daily Dose - Juicy Details About Scala 2.9

It seems that the Scala community is perfectly willing to convert their projects to the new 2.8 binaries (Scala 2.8, released last month, was not binary compatible with 2.7).  Over 50% of more than 500 projects have already been converted.  After a bugfix...

11 replies - 20755 views - 08/11/10 by Mitchell Pronsc... in Daily Dose

Daily Dose - Firefox 4 Getting Auto-Updates

Tucked away in a tiny corner of the Firefox discussion forum is a quote from Alex Faaborg, a principal designer on Firefox.  The posting says that Firefox 4 will begin to include automatic updates for minor releases.  Only major updates (e.g. 4, 4.5, or 5)...

0 replies - 17438 views - 08/09/10 by Mitchell Pronsc... in Daily Dose

Refcardz Cheat Sheet - Getting Started with Griffon

Get your free DZone Refcard on Getting Started with Griffon now!

0 replies - 7900 views - 07/19/10 by Lyndsey Clevesy in Announcements

Getting Started with Griffon

By Hamlet DArcy

7,318 Downloads · Refcard 107 of 151 (see them all)

Download
FREE PDF


The Essential Griffon Cheat Sheet

Griffon is a Grails-like application for rich desktop applications and is built on top of Groovy, Java, and Swing. Griffon embraces convention over configuration, automates many common development tasks, and features a large and growing plugin system. Griffon also features property binding for widgets and a broad and extensible event system. These combine to make Griffon an excellent choice for rich Internet applications. This DZone Refcard provides you with the essentials you need to get up and running with Griffon.
HTML Preview
Getting Started with Griffon

Getting Started with Griffon

By Hamlet D'Arcy

WHAT IS GRIFFON?

Griffon is a Grails like application framework for rich desktop applications and is built on top of Groovy, Java, and Swing. Griffon embraces convention over configuration, automates many common development tasks, and features a large and growing plugin system. Griffon also features property binding for widgets and a broad and extensible event system. These combine to make Griffon an excellent choice for rich Internet applications. You can write maintainable and well designed applications quickly without spending time on builds, deployment, or configuration tweaking. You also get a rocksolid, secure, and well-known platform in the JVM, and along with the productivity boost of a modern, dynamic language while retaining and using all your Java expertise.

FROM 0 TO DEPLOYED

Griffon is a full life-cycle framework: it automates not just creation and maintenance of applications, but also build and deployment tasks. We’ll cover Model-View-Controller next, but let’s start with creating, running, packaging, and deploying an app with Java WebStart, going from nothing to deployed in about 5 minutes time. We could deploy as an applet, Jar, or desktop installation as well, but WebStart is the most interesting for RIAs.

Prerequisites - You should have the Java Development Kit (JDK) version 1.5+ (Version 6 recommended).

Installing Griffon - Download the latest release from http://griffon.codehaus.org/. Simply extract the .zip file somewhere on your machine. Next, create an environment variable called GRIFFON_HOME, pointing to the directory you unzipped the package, and add GRIFFON_HOME/bin to your path. The Griffon website contains instructions on how to set environment variables if you need more specific guidance. If you’ve done everything correctly then you should be able to open a command prompt, enter “griffon help”, and see a help message from Griffon.


$ griffon help
Welcome to Griffon 0.3.1 - http://griffon.codehaus.org/
...

Griffon provides many commands to help you create and manage an application, and plugins may add more commands. “griffon help” will display all the available commands for your system.

griffon help Displays all the available commands for the Griffon installation
griffon <target> help Displays help for the specified target

Creating an Application – A full application stack is only a command away. Simply run “griffon create-app” and enter the name for the app when you are prompted.


$ griffon create-app
...
Application name not specified. Please enter:
Starter
...
Created Griffon Application at /home/hdarcy/dev/Starter
$ cd Starter

This step creates an entire project on your disk: standard directory layout, MVC groups, internationalization bundles, build scripts, IDE files, and more. The application is little more than a Hello World app at this point, but you can run it.

griffon create-app Creates a new Griffon application

Running the Application – Griffon apps are desktop applications that a user can install, Applet applications that run in a browser, and WebStart applications that run as Internet apps. Griffon hides the platform differences from you so any Griffon app you write can be deployed in any of these forms. To run the application on your desktop enter “griffon runapp”, and your Hello World style window will pop up shortly after the compile and packaging automatically finishes.

window1

It’s not much to look at yet, but pretty good considering we have written no code. You can also run the application using “griffon run-applet” or “griffon run-webstart”.

griffon run-app Compiles and runs the application as a desktop app
griffon run-applet Compiles and runs the application a browser Applet
griffon run-webstart Compiles and runs the application as a JNLP Webstart project

Signing the Application – The Java platform offers excellent security options, but the in past configuring these options was complex. This is an optional step, you do not need to sign applications, but you should, and Griffon handles all the hard work of managing digital signatures and signing Jar files for you with just two easy steps. First create your digital signature using the JDK’s keytool program (unless your company already has done this). We’ll call ours MyKey.


$ keytool -genkey -alias MyKey

You’ll be prompted to enter a password, as well as your name, company, and location. This creates the required Java key files in your home directory. Now we just need to tell our application about this key file. In a text editor, open the ./griffon-app/conf/Config.groovy configuration file. There are 5 entries that need to be changed in order to properly sign a WebStart application. In the environments.production. signingkey.params properties, add the following settings modified with your home directory and key name:


sigfile = ‘MyKey’
keystore = “/home/hdarcy/.keystore”
alias = ‘MyKey’

Then, under environments.production.griffon turn Jar packing off and specify your Internet deployment location.


jars {
	pack = false
}
webstart {
	codebase = ‘http://www.canoo.com/griffon/starter’
}

Finished. The Jars will all be signed the next time you package the app.

Hot Tip

Groovy property files are an improved version of Java property files. The old .properties file syntax of “key=value” can still be used if you want. However, properties are hierarchical and grouped, and the Groovy syntax makes these groupings more apparent. Plus, you can put any code you want in a property file and have it execute.

Packaging and Deployment – To package your application, run the “griffon package” target. This creates deployable files for Jar, Applet, and WebStart deployments. You’ll be prompted for your keystore password during the signature process. From here, just copy all the contents of your ./dist/webstart folder onto any webserver and your application is ready to launch over the Internet. You can see this sample deployed at http://canoo.com/griffon/starter. There is no need for a Java Servlet container, just copy the files and access the URL.

griffon package Packages the application into deployable bundles

SWING DONE RIGHT

Consistent Project Structure - Griffon projects follow a convention; all Griffon projects are meant to look the same. This consistency eases maintenance costs and promotes application best practices. The following table shows the project layout for a default project, and lists the contents of each folder.

Project Structure

./griffon-app/conf Build and runtime configuration data
./griffon-app/controllers Controller classes, orchestrate views and models
./griffon-app/i18n Message bundles for internationalization
./griffon-app/lifecycle Scripts to run on application events
./griffon-app/models Model classes
./griffon-app/resources Images, properties, and other resources
./griffon-app/views User interface view classes
./lib Jar files and libraries
./scripts Gant scripts, a Groovy wrapper around the Ant build tool
./src/main Other source files, with many JVM languages supported
./test Testing files, at both the integration and unit level

Hot Tip

When configuring version control for your project, do not check in these files: dist, staging, stacktrace. log, and the .iws file. Instead, add them to your VC’s ignore list.

Pervasive MVC – Model-View-Controller (MVC) is an often used design pattern that separates concerns in applications. An MVC pattern contains three essential elements: A View defines how your application looks. Buttons, Frames, and Widgets are all part of the view layer. A Controller defines how your application behaves. Querying the database, managing data, and coordinating user events are all part of the controller layer. The Model holds data and state required by both the controller and view. The state of buttons, the contents of text boxes, and dirty field tracking are all part of the model layer.

Hot Tip

A Griffon model is not a domain model, but an application model. As such, the Griffon model makes it easy for the controller and view to exchange data in a toolkit agnostic way. A domain model describes the conceptual entities in your software system. Consider the difference between an Employee object (a domain model) and an EmployeeTableModel (an application model).

Our starter application contains exactly one MVC triad: the main frame. Larger Griffon applications are made of many MVC triads, which are all defined in ./griffon-app/conf/Application.groovy. An MVC triad can be based around an entire window, a panel, or simply a widget. Beginners often create one MVC triad for each window in their application, but this is a mistake. MVC is a pattern you apply to components or bundles of components. The WeatherWidget sample application from the Griffon distribution illustrates this:

window2

In this window there are two visible MVC triads: The main frame WeatherWidget, which contains four SmallForecast MVC triads (one for each day of the week shown). Creating and reusing MVC triads is a key design and decomposition technique for building Griffon applications. Strive to build many, small, and reusable MVC triads within your application. This Griffon command will help you:

griffon create-mvc Creates a new MVC group: model, view, controller, and test

SIMPLE MVC

Griffon supports many view layer GUI toolkits through plugins: Swing (the default), Eclipse Standard Widget Toolkit (SWT), Pivot, Gtk, and even JavaFX. Using these toolkits is as easy as installing the appropriate plugin. For now, we’ll stay in Swing and start with an example. Following is a modified MVC Group from the first example, we’re adding a button and a simple counter to the screen. The view script adds a button and a label to the form, and the Controller simply updates a counter. The Model is used to communicate between the two:

model

ClickerView.groovy

application(title:’Clicker’) {
	gridLayout(rows: 2, cols: 1)
	label(text:bind {model.message})
	button(text: ‘Click Me’, actionPerformed: controller.&action)
}

ClickerController.groovy

class ClickerController {
	def model
	def counter = 0
	def action = {
	model.message = “Count: ${counter++}”
	}
}

ClickerModel.groovy

class ClickerModel {
	@groovy.beans.Bindable String message
}

The launched application looks like this once we click the button a few times:

clicker

View - The view script is Groovy and relies heavily on SwingBuilder, a Groovy convenience class for building Swing based UIs. As you can see, SwingBuilder is a terse and DSL-like script for writing widgets and configuration, which maps closely to the Swing API. In case you are not too familiar with Groovy, here is a quick summary of how this View script relates back to the JDK:

gridLayout(rows: 2,cols: 1) Applies the Java GridLayout to the current container. Parameters are named explicitly and map to the Java constructor or setter methods.
label(text:bind {model.message}) label() is a dynamic method and creates a JLabel in the current container. The text of the label is bound to a model property called message. Any updates to the model.message field will result in the label being updated. All of the event notification and listeners are handled for you.
button(text:’Click Me’, ...) button() is a dynamic method and creates a JButton in the current container. Setters may be invoked as named argument parameters.
actionPerformed: controller&action Creates and adds a Swing ActionListener to the component. This is the Groovy alternative to an anonymous inner class. When the button is clicked the controller is invoked.

Hot Tip

Laying out components in Swing forms is notoriously difficult using the GridBagLayout, which is exactly why MigLayout was created. It’s goal is to make complex layouts easy and normal layouts one-liners, and may of the Griffon team swears by it. Just install the miglayout plugin to get started.

Groovy adds a simplifying layer over the standard GUI toolkits, like Swing; however, GUI toolkits are usually large and complex. It is worthwhile to invest in one of the many Swing books available. Groovy in Action contains a thorough treatment of SwingBuilder, and the Oracle online documentation for Swing is excellent.

Controller – The controller simply updates a counter and tells the model that an update occurred. The model field is automatically injected into controllers by Griffon (as is the view, if you desire). The action field is just a closure (think Runnable) that writes a new message back to the model.

Model – The communication hub holds a simple String field marked @Bindable. This lets Griffon know that objects may bind to the property, and any time the property is updated then the correct PropertyChangeListeners will fire and observers will be notified. Those with a Swing background will understand that this simple annotation removes about 50 lines of boilerplate Swing code!

Advanced Data Binding – Binding widgets to a model is a requirement for modern GUI toolkits. But if you’ve worked with other tools you may be worried about too many events being posted and your application slowing down under a load of bound requests, a situation known as a “Bind Storm”. Griffon offers a flexible API to shelter you from this condition:

bind() Adds automatic event listeners and ties a component to a model
unbind() Removes the automatic listeners from a component
rebind() Reinstates the automatic listeners to a component

You don’t need to understand how binding works to write an application fast, but you may need to in order to write a fast application.

Hot Tip

Many Look & Feels exist to skin Swing apps into something more eye-pleasing. One of the best collections is Substance, available from http://substance.dev.java.net/. To install the Substance Look & Feels, run the following command: griffon install-plugin lookandfeel-substance

SERVICES

Many fields are automatically injected into your components by Griffon: Views receive an application instance, a model, and a controller, and Controllers receive a model and view. You can also create your own helper objects that will automatically be injected into your controllers by using Griffon services. A service is an object with a no-arg constructor, and they are discovered and injected based on naming conventions. To create a service use this Griffon command:

griffon create-service Creates a service class, prompting you to enter a package and a name. Also creates a unit test.

Here is our previous Clicker example refactored to use a service:

CounterService.groovy

class CounterService {
  def counter = 0
  def getNext() {
	 counter++
  }
}

ClickerController.groovy

class ClickerController {
	def model
	def counterService
	def action = {
		model.message = “Count: $counterService.next”
	}
}

Services are a key tool in decomposing large applications into manageable, independent pieces. Strive to move logic out of controllers and into reusable services. If you need more control over construction, then use the Spring or Guice plugins to provide full dependency injection frameworks.

Hot Tip

Mac and Linux users can easily chain commands together using the && operator. For example, to run a clean and package, run the command: “griffon clean && griffon package”. The 2nd command only runs if the 1st succeeds. This also works under Windows with Cygwin.

EVENTS

Custom Event Handing - Griffon has a rich, lightweight event system. For the most part, components in your application communicate via events and message passing rather than direct method calls. This means your controllers stay decoupled from one another but still communicate. Custom events and event handlers are wired together based on naming convention. Here is our controller that posts an event by interacting with the implicit “app” object and handles the event itself.


class ClickerController {
	def model
	def counterService
	def action = {
		app.event(“Click”, [counterService.next])
	}
	def onClick = { value ->
		doLater { model.message = “Count: $value” }
	}
}

Raise events using the GriffonApplication object named “app” and handle them by declaring an “on<EventName>” closure. Simple.

Application Life-Cycle Events - All Griffon applications have the same life-cycle, regardless of whether it is deployed as an applet, application, or webstart. As an application moves through the phases, you have the opportunity to cleanly execute any sort of acquiring or releasing resources you wish. Griffon provides an event system for you to both post and handle the events with custom code. Here’s the basics of the life-cycle:

life cycle

Initialize Application is created and configuration read. Good place to apply a new Look and Feel
Startup All MVC Groups from ./griffon-app/conf/Application.groovy marked as startup groups are instantiated
Ready All pending UI events have been processed and the main frame is about to be displayed
Shutdown The application is about to close
Stop Only available in Applet mode, called when destroy() is invoked by the container

To respond and handle any of the lifecycle events, such as BootstrapEnd, LoadPluginStart, NewInstance, or any of the many others, then add a handler in the file ./griffon-app/conf/Events.groovy. The name of the method should be “on<EventName>”. All of the available events are documented in the Griffon User Guide, and you may add your own custom events as well.

Extensible Build Scripting – The build of Griffon is completely scriptable; there is even a Griffon command to help you write build event extensions:

griffon create-script Creates a build script in the ./script directory, prompting you to enter a script name

The Griffon build is built on the Gant framework, a Groovy extension to Ant. The content of a build script is an event handler. There are build events for CompileStart, PackagingStart, RunAppEnd, and many more. To add pre or post processing to a build event then simply declare a closure in the script named “event<EventName>”. You can even add new build events if you need to, and the Griffon User Guide contains a complete reference of the built-in build events.

THREADING

The last example contained a method call to something called “doLater” with a closure as a parameter. This hints at one of the major concerns for the Griffon or Swing developer: threading. Swing is a single-threaded GUI toolkit, meaning there is a single thread called the Event Dispatch Thread (EDT) dedicated to refreshing and repainting the UI. If you perform a long computation on the EDT then your application will not repaint properly or may become sluggish. If you update the state of a UI widget from a thread other than the EDT then your widget may not paint or be updated correctly. As a Swing programmer you must remember two rules: all interactions with widgets must occur on the EDT and any other processing should occur off the EDT, and this rule holds true for other GUI toolkits as well. Groovy’s SwingBuilder object gives you three convenience methods to help you with this, and Griffon automatically imports these methods into your MVC groups.

doOutside { ... } Executes a block of code off the EDT.
edt { ... } Executes a block of code on the EDT. Similar to the JDK’s SwingUtilities.invokeAndWait.
doLater { ... } Executes a block of code on the EDT. Similar to the JDK’s SwingUtilities.invokeLater.

It is common for controller actions to start by reading a widget on the EDT, perform work off the EDT, and finally update the UI on the EDT. Here is a properly threaded version of our ClickerController.


class ClickerController {
	def model
	def counterService
	
	def action = {
	   model.busy = true
	   doOutside {
		  try {
		model.message = “Count: $counterService.next”
		} finally {
		  edt { model.busy = false }
		}
	 }
  }
}


The SwingBuilder methods are Swing specific, but Griffon offers a platform agnostic way to invoke them as well. If you are targeting SWT or some other toolkit then use the execOutside, execSync, and execAsync methods instead.

Hot Tip

It is worthwile to invest time understanding how Swing threading works by using the plenty of highquality documentation that exists on the Internet. Oracle’s Java Tutorial contains a section called “Concurrency in Swing” and other articles appear on the Sun Developer Network.

USING PLUGINS

The Griffon Plugin system is a key part of the framework. There are currently over 100 plugins listed in the public plugin repository, ranging from persistence providers like CouchDB and GSQL, rich components like Coverflow and GlazedLists, testing support like easyb and Spock, language support like Clojure and Scala, and many, many more. Plugins strive to make third party library integration a one or two line of code affair, and they are a great way to add features with a minimum of effort. As an example, consider how simple it is to generate Mac, Windows, and Linux installers with the Installer Plugin:


$ griffon install-plugin installer
$ griffon prepare-all-launchers
$ griffon create-all-launchers

Installing the plugin downloads the package from the public repository and installs it. The plugin adds several Griffon targets, and invoking these targets builds the packages. After running these commands you can see a Mac .app application, and Windows .exe installer, and several other formats all sitting in the ./installer folder.

Working effectively with plugins only requires mastering four Griffon targets:

griffon list-plugins Lists all the plugins available to install
griffon plugin-info <plugin name> Lists the documentation of the specified plugin
griffon install-plugin <plugin name> Downloads and installs the specified plugin. Also accepts a file or URL as an argument.
griffon uninstall-plugin <plugin name> Uninstalls the specified plugin.

Hot Tip

If you’d like to publish your own plugin to the repository then send an email to the Griffon mailing list: you’ll quickly be given the version control rights to execute a “griffon release-plugin”. Also, the next version of Griffon allows you to create your own plugin repository so your organization can have a private repo for non-open source plugins.

TESTING

Testing is a first class concern in Griffon. Many of the built in targets create unit test stubs for you and the quality related plugins are particularly rich. The core targets for testing are:

griffon test-app griffon test-app -unit Executes the tests in the project. When the -unit option is present, runs only the unit tests.
griffon create-unit-test Creates a new unit test.
griffon createintegration-test Creates a new integration test, in which the GriffonApplication object is available.

For additional testing options, install the easyb, FEST, and Spock plugins. Easyb is a Jolt award winning Behavior Driven Development library for Groovy, FEST is a UI testing library for Swing, and Spock is a rapidly growing testing tool in the Groovy community. There are many other code quality related plugins as well. The Clover and Cobertura plugins make code coverage statistics available, FindBugs and CodeNarc provide static code analysis, and JDepend and GMetrics offer structural and dependency analysis. Keeping the code clean is only a plugin install away.

Hot Tip

Command completion using the Tab key is available for Bash based command shells, like Linux, Mac, or Windows’ Cygwin. To enable completion, run the command “source $GRIFFON_HOME/bash/griffonauto- scripts”. You might just add this to execute as part of your login scripts.

IDE SUPPORT

Groovy enjoys very good IDE support; IntelliJ IDEA, NetBeans, and Eclipse all offer some level of Groovy support, and Griffon makes tooling easy by generating both Eclipse and IntelliJ IDEA projects files for every application. Currently, IntelliJ IDEA offers the best Groovy and Griffon support. Refactoring, Java-aware find usages, code completion, and many code intentions are supported. As for Griffon specific features, IDEA provides a project builder for new projects, a customized view that knows about MVC layouts, a Griffon target window to replace the need for the command line, support for unit and integration tests, and a UI to manage Griffon Plugins. Plus, you can generate an IDEA project from your Griffon sources in case you generated the project from the command line.

ON THE ROAD TO GRIFFON 1.0

The next version of Griffon will be 0.9, an API stable release on the road to 1.0. However, Griffon handles upgrades automatically and upgrades have always been painless. If you install version 0.3 and later upgrade to 0.9, then Griffon prompts you to run the upgrade scripts and convert the project. Upgrading should be seamless, any required changes are handled by the scripts supplied by the Griffon team or the plugin authors. If you’ve written your own plugins, take a look at the user mailing list to see if there are any required upgrade steps you need to provide to your users for a new release.

Hot Tip

In version 0.9, Griffon supports camelCase for targets. This means typing “griffon cApp” matches “create-app” and executes that target. If the camelCase input is ambiguous then Griffon will prompt you to select the intended target from a list.

MORE INFO

The best documentation for Griffon is the Griffon in Action book, currently available in early access form from the publisher’s website, if it hasn’t already been published. It extensively covers the material here, but also takes in depth looks at writing your own plugins, installing new look and feels, and managing the development versus production environments. Otherwise, the Griffon User Guide and mailing list are free to use, and the mailing list in particular is quite responsive. For more info on rich clients in Swing, I recommend the book Filthy Rich Swing Clients.

For learning by example, the Griffon download package contains several examples, and the code for all examples in this Refcard are available at: http://github.com/HamletDRC/ GriffonRefcard. Lastly, you can follow all the latest Griffon news by following @theaviary on Twitter. Happy Developing!

About The Authors

Photo of author Hamlet D'Arcy

Hamlet D'Arcy

Hamlet D'Arcy has been writing software for over a decade, and has spent considerable time coding in Groovy, Java, and C++. He's passionate about learning new languages and different ways to think about problems, and recently he's been discovering the joys of both F# and Scheme. He's a committer on several open source projects including Groovy and JConch, and is a contributor on a few others (including Griffon and the IDEA Groovy Plugin). He blogs regularly at http://hamletdarcy.blogspot.com, tweets as HamletDRC, and can be contacted at hamletdrc@gmail.com.

Recommended Book

Griffon in Action

Griffon in Action is a comprehensive tutorial written for Java developers who want a more productive approach to UI development. In this book, readers will immediately dive into Griffon. After a Griffon orientation and a quick Groovy tutorial, they'll start building examples that explore Griffon's high productivity approach to Swing development. The book covers declarative view development, like the one provided by JavaFX Script, as well as the structure, architecture and life cycle of Java application development.


Share this Refcard with
your friends & followers...

DZone greatly appreciates your support.


Your download should begin immediately.
If it doesn't, click here.

Daily Dose - Solaris 10 License Change

At some point during the Oracle-Sun integration, Solaris 10 had a change in its usage terms which has caused some confusion on tech news sites and blogs.  The change is described in this quote from the licensing terms: "Once you have completed the...

4 replies - 17569 views - 03/29/10 by Mitchell Pronsc... in Daily Dose

Daily Dose - Google Buzz: What's the Big Deal?

Google Buzz: What's the Big Deal?   

3 replies - 15661 views - 02/11/10 by Mitchell Pronsc... in Daily Dose

DZone Daily Dose - 12/24

Grails Still Holy   

0 replies - 13068 views - 12/24/09 by Mitchell Pronsc... in Daily Dose

Download Your Free Grails Cheat Sheet Now!

New to Grails? Click here to download DZone's latest Refcard: Getting Started with Grails.

1 replies - 7427 views - 06/29/09 by Lyndsey Clevesy in Announcements

Getting Started with Grails

By Dave Klein

16,024 Downloads · Refcard 60 of 151 (see them all)

Download
FREE PDF


The Essential Grails Cheat Sheet

Grails is a full-stack web application framework built on top of popular open source frameworks such as Spring, Hibernate, Ant, and JUnit. This DZone Refcard takes you through a brief introduction of Grails, and helps you to set up your first Grails application in minutes. It serves as a handy reference manual for working with Grails Controllers, Services, Views and GSP taglibs. You also may enjoy these other DZone Refcardz on related topics: Spring Configuration and JUnit and EasyMock.
HTML Preview
Getting Started with Grails

Getting started with grails

By Dave Klein

Getting started with grails

Grails is a full-stack web application framework built on top of such tried and true open source frameworks as Spring, Hibernate, Ant, JUnit and more. By applying principles such as Convention over Configuration and Don't Repeat Yourself, and taking advantage of the dynamic Groovy programming language, Grails makes it incredibly easy to use these powerful tools. Grails doesn't reinvent the wheel; Grails makes a wheel that inflates itself and rolls where you want it to!

In case you are new to Grails, we'll start with a brief introduction, which should be enough to get you hooked and turn you into a Grails developer. That's when this Refcard will come in handy; it is a cheat sheet for Grails developers, a quick source for those things you keep having to go back to the docs to look up. Controllers, Services and Views with a detailed GSP taglib reference.

Installing Grails

Download the Grails archive from http://grails.org/download and extract it to a local directory. Set a GRAILS_HOME environment variable to that directory and add GRAILS_ HOME/bin to your path. (You also need a valid JAVA_HOME environment variable.) Now you're ready to go!

A Web App in the Blink of an Eye

To create a new Grails application, type:


$ grails create-app AutoMart

Now change to the AutoMart directory and create a domain class:


$ grails create-domain-class Car

Open AutoMart/grails-app/domain/Car.groovy and edit it, like so:


class Car {
	String make
	String model
	Integer year
}

Save this file, and run:


$ grails generate-all Car

Create-app and create-domain-class are Grails scripts. To see what other scripts are provided by Grails, run grails help from the command line.

You now have a complete working web application, with pages for creating, displaying, editing and listing Car instances. You can launch it with:


$ grails run-app

Grails runs on port 8080 by default. You can easily run on a different port like this:


$ grails -Dserver.port=9090 run-app

Grails

Figure 1: Create Car

Navigate to http:// localhost:8080/AutoMart and look around. Figure 1 and Figure 2 show a couple of the views Grails gives us 'out of the box.' You can also leave it running while you continue to develop. Just save your changes and refresh your browser. This rapid feedback is one of the strengths of Grails.

Grails_2

Figure 2: Car List

Grails Conventions

In our example the Car.groovy file that Grails created for us was placed in a directory called grails-app/domain. This is one of the many conventions in Grails. Placing source files in certain directories and naming them in certain ways can make magical things happen in a Grails application.

Domain Classes

Placing a Groovy class file in the grails-app/domain directory will turn it into a persistent domain class. Several properties and methods will be added to the class dynamically, and Grails will create a table based on the name of the class, with fields for each property.

Refcards_subscribe

Hot Tip

Be careful about adding methods beginning with 'get' to a domain class. Grails will consider that a property and try to persist it. You can avoid this by not giving the method a return type (ie. def getSomething(){...} )

Controllers

Grails controllers are simple Groovy classes with names ending in 'Controller' and residing in the grails-app/controllers directory. Controllers also receive several methods and properties dynamically. Any closure defined as a property in a Controller will become an action reachable by a URL in the following form: application/controller/action.

Views

For each controller in your application there will be a directory under grails-app/views/ named after the controller class (ie. grails-app/views/car). This directory is where your views (.gsp files) go. When a controller action is completed it will automatically attempt to render a view with the name of the action. So, when you call http://localhost:8080/AutoMart/car/list the list action will execute and render the list.gsp page. You can, of course render specific pages but convention can be a huge time-saver.

Services

A Groovy class with a name ending in 'Service' and residing in the grails-app/services directory becomes a Grails service and has built-in transaction handling and more.

TagLibs

Creating custom tags in Grails is so easy it should be illegal. Just create a Groovy class ending with 'TagLib' and place it in the grails-app/TagLib directory. Then define a closure property and write to the OutputStream called 'out' that is already given to you. You can also use the tag's attributes and body by simply declaring them.


class YourTagLib{
def saySomething = {attrs, body ->
  if (attrs.tone == 'loud')
	out << body().toUpperCase()
  elseif (attrs.tone == 'quiet')
	out << body().toLowerCase()
  else
	out << body()
}
You can use this tag in a .gsp like this:
<g:saySomething tone='loud'>
  I'm shouting now!
</g:saySomething>

You can use this tag in a .gsp like this:


<g:saySomething tone='loud'>
   I'm shouting now!
</g:saySomething>


I'M SHOUTING NOW!

There are no extra classes to create, no interfaces to implement, no TLDs to create. You could probably take up a new hobby with the time you'll save!

Testing

Unit Tests

Grails encourages unit testing by automatically creating stubbed out unit tests when creating artifacts (domain classes, controllers, services, and taglibs), and by including a powerful testing framework based on JUnit.

In Grails 1.1 (and earlier via a plugin), there are several classes inheriting from JUnit's TestCase class. Figure 1 shows these classes.

Grails Test Classes

Figure 3: Grails Test Classes

Here are some of the methods that are available to us in the Grails testing framework.

mockDomain(class, list)- Mocks the domain class and stores instances in the list. Provides the dynamic GORM methods to class.
mockFor(class, loose) '" Returns a mock of the class. loose determines whether mock has loose expectations or strict.
mockForConstraintsTest(class, list) '" Similar to mockDomain but works for domains or command objects and adds a validate method to test constraints.
mockController(controllerClass) '" Mocks a controller, adding the usual dynamic properties and methods.
mockTagLib(tagLibClass) '" Mocks a TagLib, adding the usual dynamic properties and methods.
mockLogging(class, enableDebug) '" Adds a mock logger to the class.

Do main Class Magic

Dynamic methods

Grails adds several methods to our domain classes at runtime. Here are some of the most commonly used domain class methods:

Method Description
get(id) Retrieves an instance by id
getAll([id,id,id...]) Retrieves multiple instances by ids
list() Retrieves all instances
listOrderBy*() Retrieves list of instances sorted by expression
findBy*() Returns first instance matching expression
findAllBy*() Returns all instances matching expression
count() Returns total number of instances
countBy*() Returns count of instances matching expression
save() Attempts to persist instance
validate() Validates an instance based on constraints
delete() Attempts to permanently remove instance
withTransaction Executes a closure within a transaction
withCriteria Executes a hibernate criteria using the CriteriaBuilder
hasErrors Returns true if instance has validation errors

Methods such as countBy*() and findBy*() are synthesized methods, made up of the root method name and a combination of domain class properties and the following comparators:

  • Equal (Implied default comparator)
  • NotEqual
  • LessThan
  • LessThanEquals
  • GreaterThan
  • GreaterThanEquals
  • Like
  • like (case insensitive Like)
  • InList
  • Between
  • IsNull
  • IsNotNull

Up to two properties with optional comparators can be combined with a logical operator for example:


Car.countByMakeAndAgeLessThan('Dodge', 4)
Car.findAllByMakeAndModelInList('Ford', ['Mustang', 'Explorer'])


Pagination and Sorting Parameters

The domain method list() takes four parameters which are used for sorting and pagination. These same parameters can be passed in a Map as the last parameter to the findAllBy* methods.

Parameter Description
max The maximum number of instances to return
offset The position to begin retrieving from
sort Domain property to sort by
order Whether to sort asceding or decending

Example: Car.list(max:10, sort:'year', order:'desc')

Constraint Validation

Either the save() or validate() methods shown above will trigger Grails' powerful data validation. Grails provides 17 built-in constraints plus the validation constraint for custom validation.

Many of these constraints also influence database schema generation; those are in shown in bold.

blank (true/false) allow an empty string value
nullable (true/false) allow nulls
max Maximum value of any type that implements java.lang.Comparable
min Minimum value of any type that implements java.lang.Comparable
size Uses a range to determine the upper and lower limits of a collection or a String
maxSize The maximum size of a collection or String
minSize The minimum size of a collection or String
range Uses a range to determine the limits of a numeric value
scale Rounds value to specified number of decimal places - Does not generate an Error
notEqual No comment
inList Value must be contained in supplied list
Matches Value must match supplied regular expression
Unique (true/false) Verifies uniqueness in database
url (true/false) Must be valid URL
email (true/false) Must be valid email address
creditCard (true/false) Must be valid credit card number
password (true/false) Must be valid password
Validator Takes a closure for custom validation. First parameter is value, second (if supplied) is the instance being validated

Here's an example of how constraints are declared in a domain class:


static constraints = {
   make()
   model()
   year()
   desription()
}

If validation fails during a call to save(), no exception is thrown. The failure is quietly recorded and stored in the instances errors property. To see if a domain class instance has validation errors, use the hasErrors() method in conjuction with the errors property, like so:


if (carInsance.hasErrors()){
   carInstance.errors.allErrors.each{ println it }
}

Relationships

GORM also makes relationships between different domain classes easier. Here we'll show how to implement the basic domain relationships.

One-to-one

one-to-one-figure

Unidirectional one-to-one is the simplest type of relationship. One class has a Reference to another. This is declared by a property of the type of another domain class:


class Car {
   Engine engine
}

A bi-directional one-to-one is the same thing but with each class in the relationship having a reference to the other.


class Driver {
    Car car
}
class Car {
    Driver driver
}

Usually in a situation like this you want to show ownership and have cascading updates based on that ownership. With Grails that just takes single line of code:


class Car{
   Driver driver
   static belongsTo = Driver
}

Now a Car belongs to a Driver and when the Driver is saved the Car will be saved too. If the Driver is deleted then the Car goes with him. Makes sense. belongsTo also works with unidirectional relationships.

One-to-many

one-to-one-figure

Figure 5: One-to-many

To declare a uni-directional one-to-many relationship just include a static hasMany property in the owning class.


class Driver {
   static hasMany = [cars : Car]
}

Now a Driver will have a Collection of Car instances called cars.

To make this bi-directional add a belongsTo property to the many class.


class Car{
Driver driver
   static belongsTo = Driver
}

Many-to-many

many-to-many-figure

Figure 6: Many-to-many

A many-to-many relationship can be declared by adding a hasMany to both classes involved and a belongsTo property to one of them.


class Driver {
   static hasMany = [cars : Car]
}
class Car {
   static hasMany = [drivers : Driver]
   static belongsTo = Driver
}

The three r's of co ntrollers

There are three possible conclusions to a controller action in Grails. You can return map of data or nothing and Grails will attempt to display the .gsp view with the same name as the action. You can also redirect to another url or action. The third way is to render something. This can be a view, a template, JSON, XML or just about anything that can be written to the response.

Redirect Method Parameters
controller Controller to redirect to. If action is not present the default action of the controller will be used.
action Action to redirect to. If controller is not present current controller will be used.
id Id to be passed, as params.id, to the redirect.
url URL to redirect to ('http://grails.org').
uri URI to redirect to ('/car/edit/1').
params A map of parameters to be passed to the redirect.
Render Method Parameters
text Text to rendered to the resonse
view A GSP view. Can include pat
template A template (partial GSP view). Often used with AJAX actions.
model A map containing data to be used by the view or template.
bean A single bean to used as the model for the view or template.
collection A collection of objects to be used as the model for the view or template.
builder Builder object to be used to render markup.
contentType Sets the content type of the response.
encoding Sets the encoding of the response

Services

Grails service classes are powerful and easy to use. Here's a few important things to remember when using services.

Transactions

Grails service classes are transactional by default. If you don't want that behavior, for example, if you are going to handle transactions with the dynamic domain class method withTransaction, you can turn it off with a single line:


class CarService {
   static transactional = false
}

Service Injection

Services can be injected into controllers, domain classes, or other services simply by declaring a property with the same name as the service class type but with the first letter lowercase:


class CarController{
def carService
}

You can also inject Services into plain old groovy objects, but it takes a couple more lines of code. First declare the service in your POGO.


class MyPogo {
  def carService
}

Then when you create an instance of your POGO do this:


import org.codehaus.groovy.grails.commons.ApplicationHolder
def myPogo = new MyPogo()
def ctx = ApplicationHolder.application.mainContext
ctx.autowireCapableBeanFactory.autowireBeanProperties(
   myPogo,
   AutowireCapableBeanFactory.AUTOWIRE_BY_NAME,
   false)


This will tell Spring to inject any Spring beans that are declared in the MyPogo class into the myPogo instance. Since Grails service classes are Spring beans, the carService will be injected.

Services and Scope

Grails services are singletons by default. To change that you just need to declare a static scope variable.


static scope = 'request'

Here are the possible values for scope:

Scope Description
request A new instance is created for each request
session One instance is created for an entire session
flash An instance is created that will exist for this request and the next request
prototype A new instance is created for each objec that it's injected into
flow instance exists for the life of a flow (webflow only)
conversation Instance exists for the life of a flow and all sub-flows (webflow only)

GSP

Along with the ability to easily create custom GSP tags, Grails provides over 50 built-in tags. So many that it can be easy to miss one that could be just what you need. The following table shows some of the tags you don't want to miss:

Logical Tags

if- Conditionaly render GSP portions

Attribute Description
test* Expression to evaluate
env* Name of a Grails environment

<g:if env='development' test='${car.year > 2008}'>
   <p>This car is new.</p>
</g:if>

Else- The logical else tag


Else- The logical else tag
No Attributes


<g:if test='car.make == 'Honda''>
...
</g:if>
<g:else>
   <p>Sir, this car is not a Honda.</p>
</g:else>

Looping Tags

each- iterate over each element of the specified object

Attribute Description
in The object to iterate over
status Variable to stor the iteration index in
var The name of the item

<g:each var='car' in='${cars}'>
   <p>Make: ${car.make}</p>
   <p>Year: ${car.year}</p>
</g:each>

findAll- condtionally iterate over objects in a collection

Attribute Description
in The collection to iterate over
expr A Gpath expression

<h1>2003 Vehicles</h1>
<ul>
<g:findAll in='${cars}' expr='it.year == '2003''>
   <li>${it.make} ${it.model}</li>
</g:findAll>
</ul>

Form Tags

form- HTML Form with an action attribute based on controller/action/id

Attribute Description
action* Action to use in the Form Action
controller* Controller to use in the Form Action
id* ID to use in the Form Action
url* A map containing the action/controller/id

<g:form name='myForm' action='show' id='1'>
...
</g:form>
<g:form name='myOtherForm' url='[action:'list',controller:'car']'>
...
</g:form>


*if not specified, the current controller/action will be used

datePicker- Creates HTML selects for day/month/year/hour/second

Attribute Description
name Name of the date picker field set
value Current value of the date picker
default Default date. if '=none', the default is blank
Precision Date granularity: year, month, day, hour, minute
noSelection Map detailing the key and value to use for the 'no selection made' choice in the selected box
Years List/range of displayed years, in specific order

<g:datePicker name='myDate' value='${new Date()}'
noSelection='['':'-Choose-']'/>
<g:datePicker name='myDate' value='${new Date()}' precision='day'
years='${1930..1970}'/>

checkBox- Creates an HTML checkbox form field

Attribute Description
name Name of the checkBox
value Expression; if evaluates to true, 'checked = true'

<g:checkBox name='Used' value='${true}' />

radio- Creates an HTML radio button

Attribute Description
value value represented by radio button. Displayed as label
name Name of radio button
checked Boolean true/false for checked status

<g:radio name='myGroup' value='2' />

Select- Creates an HTML select

from a list or range to select from
value the current value of the property
optionKey property of the bean to use as the key
optionValue property of the bean to use as the value
noSelection single-entry Map with a default key to return and a default value to display.
valueMessage-Prefix Will be prepended to the option value with a '.' to create a key to lookup the value in the i18n message bundle.

<g:select name='car.year' from='${1903..2009}' value='${year}'
noSelection='['':'-Choose car year-']'/>



hiddenField-

Creates an HTML input of type 'hidden'

name the name of the input field
value the value of the text field

<g:hiddenField name='year' value='${carInstance.year}'/>

actionSubmit- Creates a submit button with the specified value

name Required; the title of the button. if 'action' is not specified, this will be the default action.
action the action to execute

<g:actionSubmit value='Button Label' action='Update'/>

Link Tags

link- Creates an HTML anchor tag based on parameters

action name of action to link to - if not specified, the default action will be used
controller name of the controller to link to '" if not specified, the current controller will be used
id the id to use in the link
params a Map containing request parameters
url a Map containing the controller, action, etc. to use in the link

<g:link controller='car' action='list'>List of Cars</g:link>

createLink- Creates a URL which can be used in anchor tags, etc.

action the action to be used in the link- if not specified the default action will be used
controller the controller to be used in the link '" if not specified the current controller will be used
id the id to be used in the link
url a Map containing the controller, action, id, etc.

<g:createLink controller='car' action='show' id='1'/>
will create
AutoMart/car/show/1
As a method call in a GSP:
<a href='${g.createLink(controller:car, action:show, id:1)}'>View
Car #1</a>
will create
<a href='/AutoMart/car/show/1'>View Car #1</a>

createLinkTo- Creates a link to a static resource

dir the directory in the application to link to
file the name of the file in the application to link to

<g:createLinkTo dir='css' file='main.css' />
creates a link to
/shop/css/main.css

Ajax Tags


In order for the Ajax tags to work properly, you need
to include the javascript tag, specifying the library to
use, in the <head> section of your page. For example:
<head>
   <javascript library='yui' />
</head>

javascript- For inclusion of JavaScript libraries and scripts; also a shorthand for inline JavaScript

library the library to include
src the name of the JavaScript file to import - will look for a file in /web-app/js/
base the full URL to prepend to the library name

<g:javascript src='/sites/all/modules/dzone/assets/refcardz/060/thisisascript.js' />
will import
/web-app/js/thisisascript.js
<g:javascript library='scriptaculous' />
will import necessary JavaScript for the Scriptaculous library
Inline JavaScript:
<g:javascript>alert('hello')</g:javascript>


About The Author

Photo of author Dave Klein

Dave Klein

Dave Klein is a developer with Contegix, a company specializing in delivering managed internet infrastructure based upon Linux, Mac OS X, JEE, and Grails. Dave has worked as a developer, architect, project manager, mentor, and trainer for the past 15 years, and has presented at user groups and national conferences. Dave's Groovy and Grails-related thoughts can be found at http://dave-klein.blogspot.com.

Recommended Book

WPF book

In Grails: A Quick-Start Guide,you'll see how to use Grails by iteratively building an unique,working application. By the time we're done, you'll have built and deployed a real,functioning website.

Share this Refcard with
your friends & followers...

DZone greatly appreciates your support.


Your download should begin immediately.
If it doesn't, click here.