An Introduction to Groovy and Grails

by Harshad Oak
10/25/2006

Create Custom View

When I created the controller, Grails also created a new display directory in the grails-app\views directory and added the following mapping in my web.xml file.

<servlet-mapping>
 <servlet-name>grails</servlet-name>
 <url-pattern>/display/*</url-pattern>
</servlet-mapping>

Grails currently has a generate-views command that is capable of generating a view based on a domain class, however there's no create-view command that could auto-generate a view for you. See Figure 3 for an example.

Figure 3: A default view showing Trousers

Figure 3: A default view showing Trousers

As I wish to create a view independent of a domain class, let's manually create the view file. Within the directory grails-app\views\display\, create a file named list.gsp, as shown in Listing 6.

Listing 6: list.gsp

<html>
 <head>
  <meta http-equiv="Content-Type" CONTENT="text/html;charset=utf-8"/>
  <title>Display Shirt And Trouser List</title>
  <link rel="stylesheet" href="${createLinkTo(dir:'css',file:'main.css')}"></link>
 </head>
 <body>
   <div class="nav">
      <span class="menuButton"><a href="${createLinkTo(dir:'')}">Home</a></span>
  </div>
  <div class="body">
     <h1>Shirt List</h1>
      <table>
        <tr>
         <th>Id</th><th>Cabinet</th> <th>Color</th><th>Name</th>
        </tr>
        <g:each in="${shirtList}">
         <tr>
          <td>${it.id}</td> <td>${it.cabinet.name}</td>
          <td>${it.color}</td> <td>${it.name}</td>
         </tr>
        </g:each>
        </table>
        <h1>Trouser List</h1>
        <table>
         <tr>
           <th>Id</th> <th>Cabinet</th>
           <th>Color</th> <th>Name</th>
         </tr>
         <g:each in="${trouserList}">
           <tr>
             <td>${it.id}</td> <td>${it.cabinet.name}</td>
             <td>${it.color}</td> <td>${it.name}</td>
           </tr>
         </g:each>               
        </table>           
        </div>
    </body>
</html>

In similar fashion to what I did earlier, you can now either run the application using the run-app command, or create a war file and deploy it on Tomcat. You should see the new view at http://localhost:8080/ClothesMgt/display/, as shown in Figure 4.

Figure 4: Our newly created view listing shirts and trousers

Figure 4: The newly created view listing shirts and trousers

Let's now have a quick look at Grails services.

Services

If you are wondering how you would separate your business logic and where you would put it, the answer lies in Grails Services. Services are named in the format SomeNameService.groovy and placed in the directory /grails-app/services/. Services can make use of dependency injection features, and you can easily call these services from within controllers.

Let's look at an example of how you can use a service. First, you will create your new service using the create-service command. Run the command and name the service Order. Grails will create two files, grails-app/services/OrderService.groovy and grails-tests/OrderTests.groovy.

Now edit OrderService.groovy, as shown in Listing 7. The serviceMethod() is auto-generated while you have introduced a new orderGoods() method.

Listing 7: OrderService.groovy

class OrderService {
  boolean transactional = true
  def serviceMethod() {
    // TODO
  }
  def orderGoods() {
    return "Order Placed - New shirts and trousers \
                              will be sent shortly."
  }
}

Now edit DisplayController, as shown in Listing 8. You introduce the reorder closure that uses the OrderService. Note that the service will be injected by Groovy.

Listing 8: DisplayController.groovy

class DisplayController {
  OrderService orderService    
    
  def index = {redirect(action:list,params:params)}
    
  def list = {
        params['max'] = 10
        return [ shirtList: Shirt.list( params ) 
            , trouserList: Trouser.list( params )]
  }    
  
  def reorder = {
         render(orderService.orderGoods())
  }
    
}

Now when you access the URL http://localhost:8080/ClothesMgt/display/reorder, the reorder closure will call the OrderService, and the response will be sent back to the browser. You can similarly move all your business logic into services, and then use them quite easily using the injection capabilities of Grails.

Dynamic Methods and Properties

As noted earlier, the domain classes don't have any methods like find(), findAll(), or save() that would fetch data from the database or update/delete existing data. In the controllers you have not written methods like redirect() or render() either. But the domain classes and controllers serve their intended purpose and enable all required actions. The reason for this is the presence of dynamic methods and properties in Grails. Dynamic methods are added to classes dynamically as if the functionality is compiled in the program.

These are the methods and properties that are available but you do not need to write. These dynamic methods cover most of the common scenarios that you would come cross in Web application development. For domain classes, there are dynamic methods like find(), findAll(), list(), executeQuery(), save(), and delete(). Controllers have dynamic properties like session, request, and response, and dynamic methods like chain(), render(), and redirect(). To truly leverage the power of Grails, you need to be aware of the capabilities of all these dynamic methods and properties.

In Passing: Auto Reload and @Property

An important feature of Grails is its ability to auto-reload files as you make changes during development. So just edit and save a gsp file, and the new file will get auto-reloaded. Transactional services like the OrderService created here, however, don't get reloaded. You will see the following message on the server console "[groovy] Cannot reload class [class OrderService] reloading of transactional service classes is not currently possible. Set class to non-transactional first. " .

The auto-reload capability of Grails should save you a lot of time that would otherwise be wasted on server restarts. I have come across some cases, like renaming a jsp file to gsp, where Grails was unable to auto-reload. However, this capability of Grails can be expected to further improve in future versions.

Prior to the Groovy JSR 06 version, you had to use @Property to define any new property in Groovy. So you will see a number of old Groovy examples online that make use of @Property. Please note, however, that @Property has been removed from Groovy JSR 06 and will also not be required in Grails 0.2 and later versions.

Summary

In this article I introduced the basic features of the Grails framework and created an application using Grails. The best thing about Groovy and Grails is that everything runs on good old Java and Java EE—so you can develop applications quickly using the RAD features of Groovy and Grails, and then deploy applications on a reliable Java EE server. Considering the noise and hype around Ruby and Rails, there sure was a need for a Java alternative. Groovy and Grails look well-equipped to fill that space.

Download

Download code from this article:

References

Harshad Oak is the creator of the Java J2EE portal IndicThreads.com. He wrote Pro Jakarta Commons and Oracle JDeveloper 10g: Empowering J2EE Development as well as coauthored Java 2 Enterprise Edition 1.4 Bible. He is also the founder of Rightrix Solutions