User Tools

Site Tools


at-m42:casestudies:cs05

Adventure Game (Grails)

In this case study, we re-develop part of the adventure game in the Grails web framework. This will demonstrate the productivity gains possible from a good, well-design application development framework, and further emphasizes the power of the Groovy programming language and the so-called lightweight enterprise frameworks. The presentation has been designed as an aide-memoir of the development process that will be demonstrated live in the final lecture of the first week of the module.

The presentation was inspired by case-study presented in Chapter 16 “Seeing the Grails Light” from Groovy in Action and was also influenced by Chapter 11 “Working with Grails” from Groovy Recipes1).

A Short Introduction to Grails

(Reproduced from the Introduction to the Grails user Guide.)

Java web development as it stands today is dramatically more complicated than it needs to be. Most modern web frameworks in the Java space are over complicated and don't embrace the Don't Repeat Yourself (DRY) principals.

Dynamic frameworks like Rails, Django and TurboGears helped pave the way to a more modern way of thinking about web applications. Grails builds on these concepts and dramatically reduces the complexity of building web applications on the Java platform. What makes it different, however, is that it does so by building on already established Java technology like Spring and Hibernate.

Grails is a full stack framework and attempts to solve as many pieces of the web development puzzle through the core technology and it's associated plug-ins. Included out the box are things like:

All of these are made easy to use through the power of the Groovy language and the extensive use of Domain Specific Languages (DSLs).

The Architecture of Grails

Grails is made up of components from the Java Platform, Java Enterprise Edition and “best-of-breed” open source enterprise Java components. It wraps all these up in a Groovy API that makes common activities simple and more complex activities easier than they would be in Java. Furthermore a Grails application can be deployed on any Java Web Container (it comes with Jetty, but a Grails application can be deployed in a web Container such as Tomcat or an Enterprise Application Container such as Glassfish) and against any database that is supported by JDBC and Hibernate (it comes with HSQL).

The Grails Stack

Figure 1: The Grails Stack

This convenience comes at a cost: Grails has fairly fixed ideas about how a web application should be developed (an idea called Convention over Configuration) and you, as a developer, are forced to do things “the Grails way”. The good news is that these conventions are largely based on best practice and it frees you to concentrate on your business logic. After all, concentrating on business logic and having the enterprise integration “just happen” is the holy grail2) of enterprise application development!

The Development Example

We shall take the example that we have developed over the previous four case studies, and re-implement Player and Item administration for an adventure game in Grails.

An index to the source code for all the examples in this case study is available.

Step 2: Create project

The first step in any system development with Grails is the creation of a project. In my case, this will be game project. Change to the development directory then issue the command grails create-app game: <cli prompt='>'> e:\dev\at-m42-2009\Case-Studies\case-study-05>grails create-app game Welcome to Grails 1.1 - http://grails.org/ Licensed under Apache Standard License 2.0 Grails home is set to: d:\java\applications\grails-1.1

Base Directory: E:\dev\at-m42-2009\Case-Studies\case-study-05 Running script d:\java\applications\grails-1.1\scripts\CreateApp_.groovy Environment set to development

  [mkdir] Created dir: E:\dev\at-m42-2009\Case-Studies\case-study-05\game\src
  [mkdir] Created dir: E:\dev\at-m42-2009\Case-Studies\case-study-05\game\src\java
  [mkdir] Created dir: E:\dev\at-m42-2009\Case-Studies\case-study-05\game\src\groovy
  [mkdir] Created dir: E:\dev\at-m42-2009\Case-Studies\case-study-05\game\grails-app
  [mkdir] Created dir: E:\dev\at-m42-2009\Case-Studies\case-study-05\game\grails-app\controllers
  [mkdir] Created dir: E:\dev\at-m42-2009\Case-Studies\case-study-05\game\grails-app\services
  [mkdir] Created dir: E:\dev\at-m42-2009\Case-Studies\case-study-05\game\grails-app\domain
  [mkdir] Created dir: E:\dev\at-m42-2009\Case-Studies\case-study-05\game\grails-app\taglib
  [mkdir] Created dir: E:\dev\at-m42-2009\Case-Studies\case-study-05\game\grails-app\utils
  [mkdir] Created dir: E:\dev\at-m42-2009\Case-Studies\case-study-05\game\grails-app\views
  [mkdir] Created dir: E:\dev\at-m42-2009\Case-Studies\case-study-05\game\grails-app\views\layouts
  [mkdir] Created dir: E:\dev\at-m42-2009\Case-Studies\case-study-05\game\grails-app\i18n
  [mkdir] Created dir: E:\dev\at-m42-2009\Case-Studies\case-study-05\game\grails-app\conf
  [mkdir] Created dir: E:\dev\at-m42-2009\Case-Studies\case-study-05\game\test
  [mkdir] Created dir: E:\dev\at-m42-2009\Case-Studies\case-study-05\game\test\unit
  [mkdir] Created dir: E:\dev\at-m42-2009\Case-Studies\case-study-05\game\test\integration
  [mkdir] Created dir: E:\dev\at-m42-2009\Case-Studies\case-study-05\game\scripts
  [mkdir] Created dir: E:\dev\at-m42-2009\Case-Studies\case-study-05\game\web-app
  [mkdir] Created dir: E:\dev\at-m42-2009\Case-Studies\case-study-05\game\web-app\js
  [mkdir] Created dir: E:\dev\at-m42-2009\Case-Studies\case-study-05\game\web-app\css
  [mkdir] Created dir: E:\dev\at-m42-2009\Case-Studies\case-study-05\game\web-app\images
  [mkdir] Created dir: E:\dev\at-m42-2009\Case-Studies\case-study-05\game\web-app\META-INF
  [mkdir] Created dir: E:\dev\at-m42-2009\Case-Studies\case-study-05\game\lib
  [mkdir] Created dir: E:\dev\at-m42-2009\Case-Studies\case-study-05\game\grails-app\conf\spring
  [mkdir] Created dir: E:\dev\at-m42-2009\Case-Studies\case-study-05\game\grails-app\conf\hibernate

[propertyfile] Creating new property file: E:\dev\at-m42-2009\Case-Studies\case-study-05\game\application.properties

   [copy] Copying 1 resource to E:\dev\at-m42-2009\Case-Studies\case-study-05\game
  [unjar] Expanding: E:\dev\at-m42-2009\Case-Studies\case-study-05\game\grails-shared-files.jar into E:\dev\at-m42-2009\Case-Studies\case-study-05\game
 [delete] Deleting: E:\dev\at-m42-2009\Case-Studies\case-study-05\game\grails-shared-files.jar
   [copy] Copying 1 resource to E:\dev\at-m42-2009\Case-Studies\case-study-05\game
  [unjar] Expanding: E:\dev\at-m42-2009\Case-Studies\case-study-05\game\grails-app-files.jar into E:\dev\at-m42-2009\Case-Studies\case-study-05\game
 [delete] Deleting: E:\dev\at-m42-2009\Case-Studies\case-study-05\game\grails-app-files.jar
   [move] Moving 1 file to E:\dev\at-m42-2009\Case-Studies\case-study-05\game
   [move] Moving 1 file to E:\dev\at-m42-2009\Case-Studies\case-study-05\game
   [move] Moving 1 file to E:\dev\at-m42-2009\Case-Studies\case-study-05\game
   [copy] Copying 1 file to e:\home\cpjobling\.grails\1.1\plugins

Installing plug-in hibernate-1.1

  [mkdir] Created dir: e:\home\cpjobling\.grails\1.1\projects\game\plugins\hibernate-1.1
  [unzip] Expanding: e:\home\cpjobling\.grails\1.1\plugins\grails-hibernate-1.1.zip into e:\home\cpjobling\.grails\1.1\projects\game\plugins\hibernate-1.1

Executing hibernate-1.1 plugin post-install script … Plugin hibernate-1.1 installed Created Grails Application at E:\dev\at-m42-2009\Case-Studies\case-study-05/game

e:\dev\at-m42-2009\Case-Studies\case-study-05> </cli>

As you can see, grails creates a large number of directories and files in the folder game which will also be the name of the project: game will be the name of the application in the web-application URL, the name of the generated WAR file (generated for deployment in Tomcat or some other application container), and a number of other things. It can be overriden in the the game\application.properties file that is generated along with the rest of the standard directory structure. As you can see in Listing 1 and in Figure 2, convention over configuration comes into play before you write a single line of code.

1: application.properties (at-m42/Case-Studies/case-study-05/game/application.properties)
extern> http://www.cpjobling.org.uk/~eechris/at-m42/Case-Studies/case-study-05/game/application.properties

The files generated by grails create-app

Figure 2: The files generated by grails create-app

An explanation of what all these files are is shown in Table 1.

*Table 2*: Directory structure of the game project (reproduced from Groovy in Action, Table 16.1 )

Directory Content
grails-app The grails-specific part of the web application
<html>&ndash;&ndash;</html>conf Configuration data sources and bootstrapping
<html>&ndash;&ndash;</html>controllers All Grails controllers; initially empty
<html>&ndash;&ndash;</html>domain All Grails domain classes (models); initially empty
<html>&ndash;&ndash;</html>i18n Message bundles for internationalization
<html>&ndash;&ndash;</html>services All Grails service classes; initially empty
<html>&ndash;&ndash;</html>taglib All Grails tag libraries
<html>&ndash;&ndash;</html>views All Grails views (GSP or JSP); initially empty
<html>&ndash;&ndash;&ndash;&ndash;</html>layouts All sitemesh layouts
grails-tests All Grails unit tests; initially empty
hibernate Optional Hibernate configuration and mapping files
lib Additional libraries as jar files
spring Spring configuration file(s)
src
<html>&ndash;&ndash;</html>groovy Additional Groovy sources; initially empty
<html>&ndash;&ndash;</html>java Additional Java sources; initially empty
web-app Web application document root directory
<html>&ndash;&ndash;</html>css Resource directory for Cascading Style Sheets
<html>&ndash;&ndash;</html>images Resource directory for images
<html>&ndash;&ndash;</html>js Resource directory for JavaScript files
<html>&ndash;&ndash;</html>WEB-INF J2EE meta information (web.xml, and so on)
<html>&ndash;&ndash;&ndash;&ndash;</html>classes Target for compiled classes; initially empty
<html>&ndash;&ndash;&ndash;&ndash;</html>tld Resource directory for compiled tag libraries

Step 3: Run Application

<cli prompt=“>”> e:\dev\at-m42-2009\Case-Studies\case-study-05\game>grails run-app Welcome to Grails 1.1 - http://grails.org/ Licensed under Apache Standard License 2.0 Grails home is set to: d:\java\applications\grails-1.1

Base Directory: E:\dev\at-m42-2009\Case-Studies\case-study-05\game Running script d:\java\applications\grails-1.1\scripts\RunApp.groovy Environment set to development

  [mkdir] Created dir: e:\home\cpjobling\.grails\1.1\projects\game\classes
[groovyc] Compiling 6 source files to e:\home\cpjobling\.grails\1.1\projects\game\classes
  [mkdir] Created dir: e:\home\cpjobling\.grails\1.1\projects\game\resources\grails-app\i18n

[native2ascii] Converting 11 files from E:\dev\at-m42-2009\Case-Studies\case-study-05\game\grails-app\i18n to e:\home\cpjobling\.grails\1.1\projects\game\resources\grails-app\i18n

   [copy] Copying 1 file to e:\home\cpjobling\.grails\1.1\projects\game\classes
   [copy] Copied 2 empty directories to 2 empty directories under e:\home\cpjobling\.grails\1.1\projects\game\resources

Running Grails application.. Server running. Browse to http://localhost:8080/game </cli>

Now connect to http://localhost:8080/game.

Hello Grails page.

Figure 3: Welcome to Grails.

Step 4: Create First Domain Class

Run command grails creat-domain-class Item <cli prompt=“>”> e:\dev\at-m42-2009\Case-Studies\case-study-05\game>grails create-domain-class Item Welcome to Grails 1.1 - http://grails.org/ Licensed under Apache Standard License 2.0 Grails home is set to: d:\java\applications\grails-1.1

Base Directory: E:\dev\at-m42-2009\Case-Studies\case-study-05\game Running script d:\java\applications\grails-1.1\scripts\CreateDomainClass.groovy Environment set to development Created DomainClass for Item Created Tests for Item e:\dev\at-m42-2009\Case-Studies\case-study-05\game> </cli>

Creates a domain class Item.groovy:

1|Listing 2: Domain class Item.groovy (at-m42/Case-Studies/case-study-05/game/grails-app/domain/Item.groovy)
class Item {
 
    static constraints = {
    }
}

It also creates a GroovyTestCase class:

1|Listing 3: Test class for domain class Item.groovy (at-m42/Case-Studies/case-study-05/game/test/unit/ItemTests.groovy)
import grails.test.*
 
class ItemTests extends GrailsUnitTestCase {
    protected void setUp() {
        super.setUp()
    }
 
    protected void tearDown() {
        super.tearDown()
    }
 
    void testSomething() {
 
    }
}

Unit test and integration tests can be run automatically from the command line using grails test-app. This will run unit tests and integration tests and report the results, formatted in HTML, in game/test/reports/html/index.html. With such great support, it'd be a crime not to write unit tests!

Step 4: Add some properties and a Controller

Each domain class is simply a Plain-Old-Groovy-Object with one major difference. If we add some properties, these will be automatically persisted to a database.

1|Listing 4: Item class with properties (at-m42/Case-Studies/case-study-05/game/grails-app/domain/Item.groovy)
class Item {
 
    static constraints = {
    }
 
    String name
    String description
    Integer weight
 
    String toString() { return "${name}" }
}

If we now add a controller, we will be able to create some objects via the web interface. <cli prompt=“>”> e:\dev\at-m42-2009\Case-Studies\case-study-05\game>grails create-controller Item

Welcome to Grails 1.1 - http://grails.org/ Licensed under Apache Standard License 2.0 Grails home is set to: d:\java\applications\grails-1.1

Base Directory: E:\dev\at-m42-2009\Case-Studies\case-study-05\game Running script d:\java\applications\grails-1.1\scripts\CreateController.groovy Environment set to development Created Controller for Item

  [mkdir] Created dir: E:\dev\at-m42-2009\Case-Studies\case-study-05\game\grails-app\views\item

Created Tests for Item e:\dev\at-m42-2009\Case-Studies\case-study-05\game> </cli>

As you can see this creates a new controller

1|Listing 5: ItemController class (at-m42/Case-Studies/case-study-05/game/grails-app/controllers/ItemController.groovy)
class ItemController {
 
    def index = { }
}

It also creates another GroovyTestCase, ItemControllerTests, for testing the ItemController, and an empty folder for Item views (game/grails-app/views/item).

Before we use this, we'll make Grails generate the necessary views “on-the-fly” by replacing def index = {} with def scaffold = Item:

1|Listing 6: ItemController class with dynamic scaffolding (at-m42/Case-Studies/case-study-05/game/grails-app/controllers/ItemController.groovy)
class ItemController {
 
    def scaffold = Item
}

I found that at this step, I had to stop the running grails application, run grails clean then restart the server!

After this runs, you will be able to browse to http://localhost:8080/game/item/list and start adding, editing and deleting items. All the necessary view code is generated automatically for you by Grails at run-time.


Home | Lectures | Previous Case Study | Case Studies

1)
See Recommended Reading for full bibliographic details
2)
pun intended
at-m42/casestudies/cs05.txt · Last modified: 2011/01/14 12:59 by 127.0.0.1