Grails Gathers Steam, Heads for 1.0

, May 1st, 2007

In the past few years, web frameworks have increasingly been focused on productivity. Ruby on Rails is seen by many as the poster-child for rapid web development, which has put a lot of pressure on traditional frameworks. In the Java marketplace, a number of frameworks are responding to that call by aiming for increased productivity, rapid development, and support for scripting languages. From Grails to Stripes, RIFE to Trails, Tapestry 5.X and Phobos, there are a lot of people looking for new ways to make Java web development a productive, rapid environment for building web applications that scale.

Grails, a Rails-style web framework using Groovy on the Java platform, has been getting a lot of attention lately, with a rapidly growing community and increasing production use for major corporations including Tropicana and Pepsico. Grails is often compared to Ruby on Rails, which is both an opportunity and a challenge, as people are attracted to the power of a Rails-like framework on a familiar platform, but may move on to Rails itself. A recent set of comparisons imply that Grails has the edge on performance for now, but that new releases of Ruby promise better performance across the board, and that may change.

Although there has been some discussion about support for Ruby within Grails, it doesn’t currently seem likely. If, instead of integrating Ruby with Grails, you’d like to integrate parts of Grails with your other applications, it is apparently possible to use the Grails object/relational mapper, GORM, outside of a Grails context, such as in a Java desktop application. All of the major IDEs are showing signs of increased support for Groovy and Grails. There’s been some discussion of IDE support in Netbeans, as well as discussion of improvements for GroovyJ in IDEA. Eclipse has the beginnings of a Grails plugin and new releases of the Groovy/Eclipse plugin and Edward Povazan working on improved code completion support with Big Sky Technology.

Grails recently released version 0.5, with improved performance, custom URLs, enhancements to GORM and more. Next on the roadmap is 0.6, with a 1.0 release late in the year. InfoQ spoke with Graeme Rocher, a co-founder and the project lead for Grails about its current success and the future.

When asked about the recent surge in attention for Grails, Graeme responded:

Well, Java developers all over are being made aware that configuration is no longer a necessary activity and Grails is one of the frameworks leading this surge. However, in comparison to other frameworks, Grails has a really strong message around re-using your existing Java knowledge, infrastructure, and code. Grails is as elegant as Rails, but as flexible as Spring MVC or Seam. It really does provide the best of both worlds. As to the uptake, that has really been lead by our community and world of mouth. We spent over a year putting together a 0.1 release; if it had been mediocre no one would have paid any attention. As it is, we have many happy users who are spreading the word and increasing Grails’ mindshare.

When comparing Grails to other frameworks for building web applications in Java:

Well, it really embraces DRY and convention-over-configuration. You really have pretty much zero configuration when developing a Grails application. However, you get all of this AND tight Java integration with existing APIs, libraries and frameworks like the Java Enterprise stack, Spring, Hibernate & SiteMesh.

In addition it has a number of key selling points. Including an extensible plug-in system, a domain-driven ORM layer built on Hibernate, and a powerful view technology with Groovy Server Pages (GSP).

On convincing someone to try Grails for the first time:

Developers don’t really need a lot of convincing, it is more management that is the struggle. However, if I do want to convince people to use Grails, I just do a quick 5 minute demo and they’re sold.

As to where Grails goes next, for v1.0 and therafter, Graeme Rocher said:

We’re really focusing on improving the developer experience and getting out 1.0 by autumn time. We have only a few “big” jobs left and then it is just incremental improvements to reach the finishing line. Some things that we have left to do are for example JSP tag library support in GSP, possible support for JPA as a plug-in, and improvements to our unit testing infrastructure.

Overall though we are mainly focused on getting 1.0 out the door after that we’ll look at leveraging the infrastructure we have in place and writing many plug-ins for Grails to continue to improve the developer experience. For example I really want to get round to writing a Groovy compiler for GWT that hooks into Grails as a plug-in, which should be fun.

If you’d like to learn more about Grails, you can continue to read about Grails at InfoQ, or take a look at Grails website, read Getting Started with Grails or the Definitive Guide to Grails.

Geoffrey Wiseman, InfoQ

Tags: ,

Java Web Frameworks Increase Support for Auto-Reload

, April 25th, 2007

In building software, the speed of the compile-build-test cycle has a significant impact on the productivity of the developer. If a developer must recompile and rebuild the application, redeploy it, and potentially restart the server, this takes time that can slow down the development process.

Some platforms for building web applications, particularly those using dynamic and scripting languages, allow developers to make modifications to the application (code, templates and configuration) and see the results of those changes immediately.

This feature is called different things, such as auto-reload and incremental hot-deployment, and the extent to which platforms and frameworks support something of this nature has an impact on how rapidly developers can develop and maintain a web application.

Auto-Reload in Java

Most Java web frameworks have had some level of support for an auto-reload capability, often starting at the level of a page templating language. For instance, it has long been possible to modify a JSP file within a web application and have the application server detect the change and restart.

As web applications grow in size, the time required to restart the server often increases, and this form of auto-reload may require too much time and have too many limitations, particularly when compared to the competition, such as Ruby on Rails.

With several Java web frameworks having recently announced increased support for auto-reload, InfoQ took the opportunity to catch up with some of the more popular Java web frameworks and compile the results.

Grails
Grails supports auto-reloading with some limintations:

All Grails artifacts (controllers, tag libs, services etc.) are reloadable in Grails, however there are some quirks:

  • Services can currently only be reloaded if the ‘transactional’ property is set to false
  • Domain Classes are re-mapped to the database at runtime. If the data source is configured to auto-generate the database via the ‘update’ setting of the ‘dbCreate’ property it will do its best effort to update the database. This process doesn’t always go smoothly however and changing domain classes occasionally require an application restart

Seam
Seam 1.2.1 has just introduced what they’re calling “incremental hot-deployment“:

Only Seam JavaBean components are supported - it doesn’t work for entities, and it doesn’t (yet) work for EJB3 components. We do plan to support this feature for EJB3 components, but it looks like we won’t have time to work on that until after JavaOne.

Spring MVC & Web Flow
Spring 2.0.4 allows a Spring MVC dispatcher to be reloaded. Spring’s support for dynamic languages allows controllers and validators to be written in Beanshell and Groovy, and refreshed without restarting the application.

Spring Web Flow, which can be used with Spring MVC, Struts 1 and 2 and JSF, can be used to take responsibility for the navigation and state management of a web application, allowing the flow to be rebuilt without restarting the server.

Keith Donald adds this, about Spring IDE 2.0’s support for Spring Web Flow:

You can now use Spring IDE 2.0 to make a change to your navigation logic graphically (by drag-n- drop) and just see those changes take affect, again with no container restart. You don’t even have to save your flow definition (the tool does it for you).

Struts 2
Struts 2 allows actions to be reloaded if they have changed. Patrick Lightbody cautions:

Ultimately the problem is that the chain of objects (ie: stateful action -> stateless spring services) gets so complicated that it becomes difficult to know what can successfully reload and what can’t.

Tapestry 5
Although Tapestry 4 supported reloading of the HTML templates and page properties in a development mode, Tapestry 5 is adding extensive support for live class and template reloading.

As with the other frameworks, there are limitations:

  • Auto-reload is not currently supported for resources in JAR files.
  • Since the reloading uses classloaders, this can result in ClassCastExceptions when communicating with classes that haven’t been reloaded.
  • The potential for memory leaks if you retain references to classes that have been reloaded.

Geoffrey Wiseman, InfoQ

Tags: ,

Grails + EJB Domain Models Step-by-Step

, , August 22nd, 2006

Ruby on Rails continues to turn many heads in the software engineering world, but enterprise shops remain relatively unconvinced. Why? We wonder, “How is some framework built on a scripting language going to fit into my enterprise application?!” In the case of Ruby on Rails, the typical argument concerns the lack of support for enterprise services (e.g., distributed transactions, messaging, etc.). To many businesses, a platform without those services simply isn’t an option.

 

Grails aims to address those concerns and legitimize rapid application development (RAD) for the enterprise. Built on Groovy, Grails offers seamless integration with Java. It provides direct access to those enterprise services that your business depends on, and at the same time adds powerful dynamic language constructs to your toolkit.

As one impressive example of its enterprise integration abilities, Grails let’s you quickly and easily build a web application backed by your existing EJB3 entity beans. But, it doesn’t stop there. Grails gives your entity beans a hearty shot of steroids, but does so completely dynamically, without altering your EJB source code in any way. Grails Object Relational Mapping (GORM) is built on Hibernate 3 (but will eventually offer support for the Java Persistence API) and uses Groovy’s Meta Object Protocol (MOP) to add all sorts of handy dynamic methods to your otherwise-static entity beans. And those methods are not only accessible from Grails and Groovy; your Java code can invoke those methods as well! We suddenly have all the enterprise-level capabilities of JEE/EJB3 and the benefits of RAD web application development!

So, let’s see what it takes to build a Grails application backed by EJB3 entity beans. In the steps below, we’ll create a new Grails application, import entity beans into the application, generate the scaffolding to quickly build a default web interface for the entity beans, and then explore a few of the handy dynamic methods Grails adds to the entity beans.

First we need an EJB3 application to start with. (Well, Grails doesn’t require that you have an EJB3 application as your starting point. However, the general assumption of this article is that you’re interested in incorporating RAD web development into your EJB3 project.) Let’s assume we have some EJB3 entity beans that model the employees (EmployeeBean) in a company and the computers (ComputerBean) assigned to those employees. (Be sure to see the Resources section if you run into any issues along the way. There you’ll find the complete source code for the Grails application, a sample JEE application that uses these entity beans, and other useful artifacts.)

The following two tables support our entity beans. (We’ll use MySQL 5.0 for this example. You can use this script to create a new database named ejb3example populated with these tables.)

And let’s have a quick look at our company’s motley lineup of worker bees and their hardware.

How long should it take to build a web user interface that interacts with this data and that integrates with our existing code base? Well, it shouldn’t take us long, but we’ve sure come to accept that this process requires significant effort. With Grails, it doesn’t have to be that way.

Step 1 - Install Grails

Since EJB3 is dependent upon JDK 5, you’ll want to make sure that you have JDK 5 installed and that your JAVA_HOME environment variable points to your JDK 5 installation.

Follow these quick steps to install Grails on your system. (This article uses Grails 0.2.1 - the current stable release as of this writing.) (Also, if you’re using a *nix system, you may need to check out this thread if you encounter installation issues.)

Step 2 - “Hello, Grails!”

  1. From a command prompt, navigate to the directory where you want to create your Grails application. Then, enter grails create-app. When asked for an application name, enter ejb3_grails.
    jMac:~/dev jason$ grails create-app
    ...
    create-app:
        [input] Enter application name:
    ejb3_grails
    ...
    BUILD SUCCESSFUL
    Total time: 4 seconds
  2. Just to make sure all is well with our environment, let’s start our application. Move into the new directory created for our application, and then enter grails run-app to start the application.
    jMac:~/dev jason$ cd ejb3_grails
    jMac:~/dev/ejb3_grails jason$ grails run-app
    …
    run-app:watch-context:
  3. The application is now waiting for our requests. Open your browser to http://localhost:8080/ejb3_grails/, and you should see this friendly message welcoming you to Grails.

Step 3 - Import the Entity Beans

  1. Grails comes pre-packaged with HSQLDB, but since we’re using MySQL, we have a few quick steps to tell Grails how to talk to our database. First, download the Java MySQL driver from http://www.mysql.com/products/connector/j/. I opted for the current production-ready version which, as of this writing, is 3.1.13.
  2. Open the zip file and extract the mysql-connector-java-3.1.13-bin.jar file into the lib directory of your Grails application - in our case, that’s ejb3_grails/lib. (Please note that the exact name of the JAR file may differ based on the version of the driver you downloaded.)
  3. Now we’re ready to tell Grails where to find our database. Open ApplicationDataSource.groovy in your editor of choice, and modify it to match the settings below. You’ll find this file in ejb3_grails/grails-app/conf/. (Note that you’ll need to change the username and password to the appropriate values for your MySQL account.)
    import org.codehaus.groovy.grails.orm.hibernate.cfg.GrailsAnnotationConfiguration
    
    class ApplicationDataSource {
       def configClass = GrailsAnnotationConfiguration.class
       boolean pooling = true
       //String dbCreate = "create-drop" // one of 'create', 'create-drop','update'
       String url = "jdbc:mysql://localhost/ejb3example"
       String driverClassName = "com.mysql.jdbc.Driver"
       String username = "ejb3example"
       String password = "ejb3example"
    }

    In addition to specifying the connectivity settings, we also need to define the configClass member to allow Grails to support the annotations used in our entity beans.

    Lastly, we want to comment out the dbCreate setting. This setting allows you to have Grails update your database schema at runtime to synchronize it with your domain classes. While this is a powerful option, we simply don’t need it for this example. By commenting out this property, we’re instructing Grails to leave the schema as is.

  4. Next, we need to copy the entity beans - EmployeeBean and ComputerBean - into our Grails project. Grails looks for Java classes in the src/java directory. Be sure to create the full directory structure matching the package name for these classes.
    jMac:~/dev/ejb3_grails/src/java/com/jasonrudolph/ejb3example/entity jason$ ls
    ComputerBean.java       EmployeeBean.java

    Long-term, you’ll want to make sure that these files stay in sync with the official copy of these classes (in the source tree of your JEE project). To do so, you could easily instruct your build script to copy these files from the JEE project into the Grails project at build time.

  5. Grails allows us to work with any Java classes, but we want Grails to give special treatment to these particular Java classes (i.e., our entity beans). We want Grails to recognize these classes as our domain classes and to provide all the ORM and dynamic method goodness that comes with a Grails domain class. To do so, we’ll register these classes by adding the following hibernate.cfg.xml file to the hibernate directory of our application.
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE hibernate-configuration PUBLIC
    		"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
    		"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
    
    <hibernate-configuration>
        <session-factory>
            <mapping package="com.jasonrudolph.ejb3example.entity" />
            <mapping class="com.jasonrudolph.ejb3example.entity.EmployeeBean" />
            <mapping class="com.jasonrudolph.ejb3example.entity.ComputerBean" />
        </session-factory>
    </hibernate-configuration>

Step 4 - Generate the Scaffolding

Now we’re ready for the real time savings to begin. There is just no escaping most of the things we’ve done so far. (No matter how smart your framework is, you’ll always have to tell it where to find your database.) However, building a good and functional starting point for your user interface is no longer a manual task.

  1. Make sure you’re in the project’s root directory - in our case, it’s ejb3_grails. Then, enter grails generate-controller. When asked for the domain class name, enter the fully-qualified class name for our first entity bean - com.jasonrudolph.ejb3example.entity.EmployeeBean.
    jMac:~/dev/ejb3_grails jason$ grails generate-controller
    …
    input-domain-class:
        [input] Enter domain class name:
    com.jasonrudolph.ejb3example.entity.EmployeeBean
    …
    [java] Generating controller for domain class
    [com.jasonrudolph.ejb3example.entity.EmployeeBean]
         [java] Controller generated at ./grails-
    app/controllers/EmployeeBeanController.groovy
    
    BUILD SUCCESSFUL
    Total time: 10 seconds
  2. Now that we have the controller, let’s generate the corresponding views. Enter grails generate-views. When asked for the domain class name, enter com.jasonrudolph.ejb3example.entity.EmployeeBean.
    jMac:~/dev/ejb3_grails jason$ grails generate-views
    …
    input-domain-class:
        [input] Enter domain class name:
    com.jasonrudolph.ejb3example.entity.EmployeeBean
    …
    [java] Generating views for domain class [com.jasonrudolph.ejb3example.entity.EmployeeBean]
         [java] Generating list view for domain class
    [com.jasonrudolph.ejb3example.entity.EmployeeBean]
         [java] list view generated at /Users/jason/dev/ejb3_grails/./grails-
    app/views/employeeBean/list.gsp
         [java] Generating show view for domain class
    [com.jasonrudolph.ejb3example.entity.EmployeeBean]
         [java] Show view generated at /Users/jason/dev/ejb3_grails/./grails-
    app/views/employeeBean/show.gsp
         [java] Generating edit view for domain class
    [com.jasonrudolph.ejb3example.entity.EmployeeBean]
         [java] Edit view generated at /Users/jason/dev/ejb3_grails/./grails-
    app/views/employeeBean/edit.gsp
         [java] Generating create view for domain class
    [com.jasonrudolph.ejb3example.entity.EmployeeBean]
         [java] Create view generated at /Users/jason/dev/ejb3_grails/./grails-
    app/views/employeeBean/create.gsp
    
    BUILD SUCCESSFUL
    Total time: 11 seconds
  3. Repeat this process to generate the controller and views for the other entity bean (i.e., com.jasonrudolph.ejb3example.entity.ComputerBean).
  4. Now let’s run our application and see just how much we can get for such little effort. Enter grails run-app, and we’re ready to go. Open your browser to http://localhost:8080/ejb3_grails/.

  5. OK. We have our two controllers. And, as is suggested by the text here, we’ll eventually want to replace this page with our own custom landing page. For now, let’s move on to the EmployeeBeanController.

We see most of the information we’d want here. Obviously the Computers column needs some work, but otherwise this page can probably be ready to go with just a few cosmetic changes.

Take some time to look around the application and see what we have so far. Try to create a new employee, edit an employee, and then (if you’re feeling particularly powerful) terminate one of those poor souls. Try out similar features for managing computers. Along the way, make note of the things you’d want to change as well as the things we need to change. At the same time, be sure to consider those things that already meet your needs. Those are the features you got for free!

Done? OK. Here’s my take on the list of things we need, and then we can talk about those nice-to-have items later.

  • Relationship Management - The scaffolding clearly tries in this area, but it just doesn’t meet our needs. Luckily, this is pretty easy to remedy. (Heck. Even the Ruby on Rails scaffolding doesn’t give you relationship management for free!)
  • Validation - It’s just missing. Plain and simple. But, we can quickly add that as well.

That’s it. If we can implement proper relationship management and validation, we will have a fully-functioning web app to manage our entity beans. After that, the rest is just gravy. (Though we’ll be sure to sample some of that tasty gravy before we’re finished.)

Step 5 - Add Relationship Management

What do we expect from the application in regards to relationship management? Well, I’d say we should reasonably be able to …

  • View all computers assigned to an employee.
  • View the details for a single computer (including its assignment status).
  • Create, update, and delete a computer (including its assignment status).

Ready? Let’s get started.

  1. It doesn’t really make sense to list computers on the Employees page, so let’s remove that column. Open grails-app/views/employeeBean/list.gsp, and remove that column. Now just refresh the browser, and verify the updated page.

  2. Next, click the Show link to view the details for an employee.

    At the very least, we need to clean up the text listed for each computer. But perhaps we don’t want to see the computers directly on this page at all. Instead of showing the computers on this page, let’s include a link to this employee’s list of computers.

    Open the template for this page (i.e., grails-app/views/employeeBean/show.gsp), and remove the row that currently displays the employee’s computers. Then, add the following row to link to a separate page showing the computers for this employee.

    <tr class="prop">
        <td colspan="2" align="left" class="name">
    	   <g:link controller='computerBean' action='showComputersByEmployee'
    	           id='${employeeBean.id}' >Show Computers</g:link>
        </td>
    </tr>

    We’re using the Grails tag library to help us out here. The link tag will generate a link to the ComputerBeanController and invoke a new action that we need to define called showComputersByEmployee. That link will also include the ID for the employee in question.

    Let’s refresh the browser and see our changes.

    OK. We have our link. Now we need to define the new action for that link. Open grails-app/controllers/ComputerBeanController.groovy in your editor. Because the new action will search for computers by employee, we first need to add an import statement for the EmployeeBean class.

    import com.jasonrudolph.ejb3example.entity.EmployeeBean

    Then we just add the new action.

    def showComputersByEmployee = {
        render(view:'list', model:[ computerBeanList:
    	ComputerBean.findAllByEmployeeBean(EmployeeBean.get(params.id)) ])
    }

    This action gives us a good look at just how much you can say in Groovy (and Grails) in a few concise lines. In those few lines, we’re telling Grails that any calls to showComputersByEmployee should …

    • Get the employee ID from the request using params.id
    • Get the EmployeeBean for that employee ID using the EmployeeBean#get method
    • Find all computers assigned to that employee using the ComputerBean#findAllByEmployeeBean method
    • Put the results in an object named computerBeanList
    • render the view, using the computerBeanList object as the model, in a template named list

    Remember defining the get method in EmployeeBean and the findAllByEmployeeBean method in ComputerBean? No? You’re right. Those methods are just a small sampling of the many dynamic methods that Grails provides for your domain classes. We’ll explore these items more later. In the meantime, we’re ready to click on the Show Computers link.

    We’re getting close. We still need to change the text in the Employee Bean column. We certainly want something with a bit more human meaning here.

    Also, we might prefer to identify the employee to which these computers belong. We’re currently reusing the list template (generated as part of the scaffolding for the ComputerBean), and that template is designed primarily to list all computers. However, we could always define a separate template for displaying this subset of computers or perhaps make the list template more dynamic in order to support both scenarios. For now, we’ll tuck this feature away as nice-to-have but not essential.

    That should complete all the changes we need for managing employees. Now we just need to clean up the computer management features.

  3. Since we’re here, let’s clean up the computer list template. Instead of the current text in the Employee Bean column, let’s change it to display the employee’s network ID. Open grails-app/views/computerBean/list.gsp. Find the Groovy scriptlet that renders the text in the Employee Bean column …
    ${it.employeeBean}

    … and change it to render the employee’s network ID.

    ${it.employeeBean.networkId}

    Refresh the browser and let’s see how it looks. (The Employee column seemed a little awkward between the Brand and the Model columns, so I switched things around a bit. Feel free to do the same.)

    The list template is complete. On the show template.

  4. Click the Show link, and let’s assess what we need to change.

    It looks like we just need to change the text for the employee link. We’re almost pros at this by now. So, open grails-app/views/computerBean/show.gsp, and find the scriptlet that renders the current text for the link.

    ${computerBean?.employeeBean}

    Just like we did for the list template, change the code to display the employee’s network ID.

    ${computerBean?.employeeBean.networkId}

    Let’s refresh the browser again and verify our changes. (Again, the Employee row seemed a little awkward between the Brand and the Model rows, so you’re welcome to rearrange the rows as you see fit.)

  5. Let’s move on the edit functionality.

    We’re starting to see a theme here. We need to change the select box to provide a list of network IDs. Find the <g:select> tag in grails-app/views/computerBean/edit.gsp, and tweak it like so.

    <g:select optionKey="id"
        from="${com.jasonrudolph.ejb3example.entity.EmployeeBean.list()}"
        name='employeeId'
        optionValue='networkId'
        value='${computerBean.employeeBean?.id}'>
    </g:select>

    By adding the optionValue parameter to the tag, the text in the select box has taken on a more meaningful form.

    The view is correct now, but the update functionality requires a bit of effort outside of the view as well. We also need to enhance the controller (i.e., ComputerBeanController.groovy). If the user changes the employee associated with a computer, we need to make sure we persist those association changes properly. In other words, we need to disassociate the computer from the current employee and assign it to the new employee. The enhanced update method requires just a few additional lines of code.

    def update = {
        def computerBean = ComputerBean.get( params.id )
        if(computerBean) {
               if (computerBean.employeeBean) {
                      computerBean.employeeBean.computers.remove(computerBean)
               }
    
               computerBean.properties = params
    
               def employeeBean = EmployeeBean.get(params.employeeId)
               employeeBean.computers.add(computerBean)
               computerBean.employeeBean = employeeBean
    
               if(computerBean.save()) {
                      redirect(action:show,id:computerBean.id)
               }
               else {
                      render(view:'edit',model:[computerBean:computerBean])
               }
        }
        else {
               flash.message = "ComputerBean not found with id ${params.id}"
               redirect(action:edit,id:params.id)
        }
    }

    Save your changes, and we’re ready to try it out. Let’s change the brand for this computer - it’s a Lenovo now - and let’s reassign it to John Doe.

  6. Of course, we also need to be able to add new computers to our inventory. So, let’s click on New ComputerBean.

    After our last change to the Edit page, we’re well-qualified to clean up this page. We need to make the same adjustments to the select box. Open grails-app/views/computerBean/create.gsp, adjust the <g:select> tag, and refresh your browser.

    <g:select optionKey="id"
        from="${com.jasonrudolph.ejb3example.entity.EmployeeBean.list()}"
        name='employeeId'
        optionValue='networkId'
        value='${computerBean.employeeBean?.id}'>
    </g:select>

    As we saw for the edit functionality, we need to make a slight enhancement to the controller. When we create a new computer, we need to make sure we assign it to an employee before we save it. Edit ComputerBeanController.groovy to include this updated save method.

    def save = {
        def computerBean = new ComputerBean()
        computerBean.properties = params
    
        def employeeBean = EmployeeBean.get(params.employeeId)
        employeeBean.computers.add(computerBean)
        computerBean.employeeBean = employeeBean
    
        if(computerBean.save()) {
               redirect(action:show,id:computerBean.id)
        }
        else {
               render(view:'create',model:[computerBean:computerBean])
        }
    }

    Back in the browser, we’re ready to create a new computer. Fill in the empty fields and create away.

    Jane now has a hot new laptop.

  7. And the last piece we need is the delete functionality. We don’t need any template changes this time. We just need to add one line to the controller. When we delete a computer in ComputerBeanController.groovy, we also need to remove the computer’s association to the employee. The fourth line below will take care of that.
    def delete = {
        def computerBean = ComputerBean.get( params.id )
    
        if(computerBean) {
               computerBean.employeeBean.getComputers().remove(computerBean)
               computerBean.delete()
               flash.message = "ComputerBean ${params.id} deleted."
               redirect(action:list)
        }
        else {
               flash.message = "ComputerBean not found with id ${params.id}"
               redirect(action:list)
        }
    }

    It looks like Jane’s new MacBook has been recalled. Shall we delete it?

    And there we have it! In just a few quick steps, we now have a functioning web application built on top of our entity beans. It can still use a little polish, of course. At the very least, it’s completely sufficient as a working prototype. Better yet, it’s a prototype that is fully capable of growing into the finished product.

Step 6 - Define Validation Rules

One thing we certainly need in the near term is some validation logic. Fortunately, Grails offers a very convenient declarative validation mechanism. For each of our entity beans, we simply need to add a Groovy script to define the appropriate constraints. By convention, Grails looks for a script with the same name as your domain class but ending with the word “Constraints” (e.g., EmployeeBeanConstraints.groovy).

So, let’s define the constraints for each of our entity beans. At a minimum we need our constraints to match our data model. We’ll also add in some basic business validation. For example, the database requires that network IDs not exceed eight characters in length, but we’ll also enforce our business rule that a network ID must be no fewer than six characters in length.

Grails looks for the constraints declarations in the same directory as our domain class. For the EmployeeBean class, we need to create a file named EmployeeBeanConstraints.groovy and place it in ejb3_grails/src/java/com/jasonrudolph/ejb3example/entity/. The file should include the following rules:

constraints = {
      networkId(length:6..8,blank:false,unique:true)
      firstName(maxLength:20,blank:false)
      lastName(maxLength:20,blank:false)
      startDate(nullable:false)
}

Next, we’ll define the constraints for the ComputerBean class. The file goes in the same directory, and we need to name it ComputerBeanConstraints.groovy.

constraints = {
      serialNumber(maxLength:20,blank:false)
      brand(maxLength:20,blank:false)
      model(maxLength:20,blank:false)
}

To make these constraints take effect, we need to restart the application. In the console where you started the application, enter Control-C to stop the application. Then, enter grails run-app, and we’re ready to test the validation.

Now, if we try to sneak in a new employee with an invalid network ID, our application knows not to accept it.

Naturally we’ll want change the error message to something more business-focused and less technical. Grails provides a message resources file for you to define your own custom error message.

The constraints we defined represent just a small sample of the validation that Grails offers. Be sure to check out the Grails documentation for the complete list of available constraints.

Step 7 - Get Dynamic

Everything up to this point has shown us that we can build web applications more quickly than we might have thought, and we’ve seen some impressive features of this up-and-coming framework. That said, here’s where the real magic begins. Recall our brief mention of dynamic methods back when we added the ability to see all computers assigned to a user? Let’s take a deeper at look at this feature.

Once we have some basic CRUD functionality like this, one of the first requests we get is, “I need a way to see all employees by _______.” Or, “Show me all computers made by _______ with serial numbers starting with _______.” These are reasonable enough requests, but how much effort typically goes into building these simple reports? Too often it requires a new method in some session bean, a new mapping in one of my web framework’s configuration files, perhaps even some SQL, etc. Not only can we get by without those things, we can do so and be ready to quickly adapt to the next change.

For starters, let’s say we need to be able to find all employees by last name. We’ll add a new menu option to the Employee List page to take us to our new query page. Add this block to the menu section of grails-app/views/employeeBean/list.gsp.

<span class="menuButton">
	<g:link action="search">Search Employees</g:link>
</span>

Clicking this menu option will invoke a new action in our controller named search. We don’t need that action to do anything more than render our search input page. So, add an empty method in EmployeeBeanController.groovy to accept these requests.

def search = {
}

This empty action tells Grails that search is a valid action for this controller. When Grails receives a request for this action, it will simply look for a template with the same name (i.e., search.gsp) in grails-app/views/employeeBean/ and render its content.

Since we really just want a simple form with input fields for an employee, we can use the create.gsp template as a good staring point. When we’re finished, our new search.gsp template should look like this:

<html>
    <head>
         <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
         <meta name="layout" content="main" />
         <title>Search Employees</title>
    </head>
    <body>
        <div class="nav">
            <span class="menuButton">
                <a href="${createLinkTo(dir:'')}">Home</a></span>
            <span class="menuButton">
            <g:link action="list">EmployeeBean List</g:link></span>
        </div>
        <div class="body">
           <h1>Search Employees</h1>
           <g:form action="showSearchResults" method="post" >
               <div class="dialog">
               <table>
                    <tr class='prop'>
                        <td valign='top' class='name'>
                            <label for='lastName'>Last Name Like:</label>
                        </td>
                        <td valign='top' class='value'>
                            <input type='text' name='lastName' value='' />
                        </td>
                   </tr>
               </table>
               </div>
               <div class="buttons">
                   <span class="formButton">
                       <input type="submit" value="Search"></input>
                   </span>
               </div>
           </g:form>
        </div>
    </body>
</html>

If you’re thinking that we shouldn’t be repeating so much of the wrapper content (e.g., the <head> tag, etc.), you’re right. Grails offers various layout mechanisms to avoid this duplication. (We’ll consider that an exercise for the reader.) In the meantime, our search page awaits. (While Grails generally provides dynamic deployment of such changes, some readers have reported the need to restart the application in order to successfully access the new search page. To do so, enter Control-C in the console where you started the application. Then, enter grails run-app, and make your way to the search page.)

You’ll notice that in search.gsp we specified that the form should post all requests to a new action named (plainly enough) showSearchResults. So, we need to define that new action in EmployeeBeanController.groovy.

def showSearchResults = {
    render(view:'list', model:[ employeeBeanList:
        EmployeeBean.findAllByLastNameLike("%" + params.lastName + "%") ])
}

Because we just want to display a list of matching employees, we can safely use the existing list.gsp template. This is another example of Grails’s ability to provide significant functionality in a few succinct commands. All requests to the showSearchResults action will …

  • Get the search criteria from the request using params.lastName
  • Get a list of EmployeeBean objects for employees matching that last name
  • Put the results in an object named employeeBeanList
  • render the view, using the employeeBeanList object as the model, in the list template

When we click Search, sure enough, we get the matching results.

Of course, if we can search employees by last name, why not search by first name as well? We can easily add a new input field to our search page.

<tr class='prop'>
    <td valign='top' class='name'>
        <label for='lastName'>First Name Like:</label>
    </td>
    <td valign='top' class='value'>
        <input type='text' name='firstName' value='' />
    </td>
</tr>

That’s trivial enough, but what do we have to change in our controller? Very little. Instead of using the findAllByLastNameLike method, we’ll now invoke findAllByLastNameLikeAndFirstNameLike.

def showSearchResults = {
    render(view:'list', model:[ employeeBeanList:
        EmployeeBean.findAllByLastNameLikeAndFirstNameLike("%" + params.lastName + "%",
            "%" + params.firstName + "%") ])
}

Grails automatically provides dynamic finders for just about every query combination you can think of! Try it out. Our search from above yields just what we’d expect given our updated query.

Step 8 - Build Your Own Criteria

Over time, you may find that your requirements grow in complexity. How can we handle queries that need to group various sets of criteria? For example, suppose I want to find all employees where…

  • The network ID partially matches some value with case-sensitivity, or
  • The first name and the last name exactly match their respective criteria.

That kind of query is beyond the capabilities of the dynamic finders that we just saw. No worries. That doesn’t mean that your application has to take on any additional complexity. Grails offers the immensely flexible Hibernate Criteria Builder to satisfy that need without sacrificing any of the functionality we’ve seen so far.

First, let’s modify our search page to capture the input for our new requirements. If we edit search.gsp and replace the current input fields with the following fields, it should give us what we’re looking for.

<tr class='prop'>
    <td valign='top' class='name'><label for='lastName'>Network ID Like:</label></td>
    <td valign='top' class='value'>
        <input type='text' name='networkId' value='' />
    </td>
</tr>
<tr><td>-- or --</td></tr>
<tr class='prop'>
<td valign='top' class='name'><label for='lastName'>First Name Equals:</label></td>
<td valign='top' class='value'>
    <input type='text' name='firstName' value='' /></td>
</tr>
<tr class='prop'>
    <td valign='top' class='name'><label for='lastName'>Last Name Equals:</label></td>
    <td valign='top' class='value'>
        <input type='text' name='lastName' value='' />
    </td>
</tr>

Now let’s look at the actual query logic. The following code satisfies our (admittedly odd) requirements in just a few short lines. (This code should replace our current showSearchResults method in EmployeeBeanController.groovy.)

def showSearchResults = {
    def criteria = EmployeeBean.createCriteria()

    def results = criteria {
        or {
            ilike("networkId", "%" + params.networkId + "%")
            and {
                eq("firstName", params.firstName)
                eq("lastName", params.lastName)
            }
        }
    }

    render(view:'list', model:[ employeeBeanList: results.adaptee ])
}

Even if you’ve never used Hibernate or Grails before, you can quickly get the gist of what’s going on here. In a Groovy builder, each component is referred to as a “node.” The or node tells us that we’ll match any rows that satisfy one or more of the criteria specified by its child nodes. In this case, it has two child nodes.

The first child node returns results that satisfy a case-sensitive like operation on the networkId attribute.

ilike("networkId", "%" + params.networkId + "%")

The second child node is an and node. It returns results that match all of its child nodes. Its child nodes look for rows that exactly match (eq) the firstName and the lastName attributes.

and {
    eq("firstName", params.firstName)
    eq("lastName", params.lastName)
}

Together, these nodes fulfill our query requirements.

If the grouping operators (and, or, etc.) seem oddly positioned at first, it’s because the Hibernate Criteria Builder somewhat resembles a Polish notation syntax, where you specify the operator before the operands. That’s certainly a departure from Java’s use of relational operators, but it should become relatively intuitive after your first few queries.

Now let’s see it in action.

Here we’re looking for all employees where the network ID contains “jr” or the employee’s name is “John Doe”.

And when we click Search, we get exactly that.

Summary

How does this development process compare to the approach you use today? With each feature we added along the way, how many components would you touch to make that same change in your existing framework? XML files? DAOs? Form/view classes? Others? And what do you gain by having those additional components to maintain? Ultimate flexibility? If so, do you really need it? Some shops definitely do require that flexibility, but for the other 80%, aren’t some sensible defaults (al a convention over configuration) well worth the productivity gains?

We’ve written very little code in this exercise, and yet we have a functioning and flexible application. We didn’t change a single line in our existing entity beans. And because we’ve written such little code to get to this point, we have less code to maintain. We’ll be writing less code tomorrow when the requirements change again. Just think how quickly you can respond to evolving business needs when your application is this agile!

Resources

About the Author

Jason Rudolph is an Application Architect at Railinc, where he develops software that helps keep trains moving efficiently throughout North America. He recently delivered an industry-wide inspection reporting and management system relied on for operational safety by Fortune 500 railroads, equipment leasing companies, and the Federal Railroad Administration. Jason’s interests include dynamic languages, lightweight development methodologies, improving developer productivity, and a quest to keep programming fun. Jason holds a degree in Computer Science from the University of Virginia. He currently lives in Raleigh, NC with his wife (who can take a functional web app and make it actually look good) and his dog (who can outrun him, but is no match for squirrels). You can find Jason online at http://jasonrudolph.com.

Jason Rudolph, via InfoQ

Tags: , ,