x
Loading
 Loading
Hello, Guest | Login | Register

Rails vs. Grails vs. Helma: The JVM Web Framework Smackdown, Part 2

It’s the ultimate JVM Web Framework Smackdown! Three will enter the cage. Only one will exit the victor. Will it be JRuby on Rails? Groovy on Grails? Or Helma?

Community Tools
Recommend This [?]
1 Star2 Stars3 Stars4 Stars5 Stars (3 votes, average: 5 out of 5)
Loading ... Loading ...
Users Who Liked This [?]
No one yet. Be the first.
Tags:
Tag This!

Having covered JRuby on Rails in part 1, we now turn our attention to Grails and Helma.

Grails: Start Nimble, Scale to Enterprise

Inspired by Rails, other Web frameworks now incorporate many of its features. Grails is at the forefront of this group. In fact, at first blush, Grails mimics Rails so closely that it’s tricky to tell them apart. However, as you dig more deeply, differences begin to appear. Most importantly, Grails is built upon an enterprise-worthy Java stack. This includes Hibernate and Spring, two tools that many Java developers are already familiar with.

Whether Grails can truly scale to the enterprise level remains largely untested. What is easier to verify is that Grails adds many Java best practices to a Rails-like framework. While scriptlets are a possibility, they are generally eschewed in favor of tag libraries. Grails offers superior support for Unicode, and encourages developers to use message bundles. Both of the latter features make Grails a much better choice for internationalization.

Grails also seems more familiar to Java developers. While Groovy syntax can look unusual at times, Java developers can write much of their code using standard (pre-generics) Java syntax, and it works without a hassle. And although it’s not yet as well-established as Rails, Grails has a large and active community, a rich set of tools, and plugins for almost every major IDE.

Getting started

Installing Grails is a somewhat simpler process than installing JRoR. After you download Grails, set your $GRAILS_HOME environment variable and add $GRAILS_HOME/bin to your $PATH.

Let’s build PenguinMusic in Grails for comparison. The Grails implementation of PenguinMusic can be downloaded from here. Bootstrapping a Grails application is very similar to creating a new Rails application. The command grails create-app grailsPM creates a new project, where grailsPM is the project name.

As with Rails, the next step after code generation is to configure the database. Open grails-app/conf/DataSource.groovy
and edit the username, password, and URL to match your server settings.
Here is the sample version, which assumes the database grailsPM already exists:

dataSource {
  pooled = true
  driverClassName = "com.mysql.jdbc.Driver"
  username = "root"
  password = ""
  url = "jdbc:mysql://localhost:3306/grailsPM?autoreconnect=true"
}
hibernate {
    cache.use_second_level_cache=true
    cache.use_query_cache=true
    cache.provider_class=‘com.opensymphony.oscache.hibernate.OSCacheProvider’
}
// environment specific settings
environments {
  development {
    dataSource {
      dbCreate = "update"
    }
  }
  test {
    dataSource {
      dbCreate = "update"
    }
  }
  production {
    dataSource {
      dbCreate = "update"
    }
  }
}

Any of the settings in dataSource can be overridden for specific environments. For instance, it is generally wiser to have a separate database for testing.

  ...
  test {
    dataSource {
      dbCreate = "create-drop"
      url = "jdbc:mysql://localhost:3306/pmTest?autoreconnect=true"
    }
  }
  …

Again, this assumes the database pmTest already exists.

dbCreate tells Grails what to do with the database. The options are create, create-drop, and update. create creates and modifies tables as needed, whereas create-drop deletes the tables on shutdown. Both versions delete all records. If you get test data from some outside process, update is probably the best choice. Also, for production, you may be better off removing this setting altogether and managing the database yourself.

Running grails run-app from the root of the project starts the application. Of course, there is nothing terribly interesting to see at this point, But now that the code is interacting with the database correctly, it is time to create some domain classes.

Domain Classes

One of the most notable differences between Grails and Rails is the design of the models, or domain classes in Grails terminology. With Rails, the structure of the models lives in the database, whether you create it with SQL or migrations. In contrast, with Grails, you never touch the database directly. Instead, you structure the data in Groovy code.

Grails comes with a noticeably richer set of constraints for the data models. It is also a decided plus to see the entire structure of a class located in one central place.

To create a new domain class for artists, run grails create-domain-class Artist. This creates a new empty domain class and the corresponding unit tests. Next, let’s add the fields for the domain class, including the corresponding types. It should look like this:

class Artist {
  String name
  String url
}

As with Rails migrations, more constraints can be added, though again the details live within the domain class. For example, here is another domain class, Song.

class Song {
  static constraints = {
    trackNum()
    name(blank:false)
    playlistURL(url:true)
    durationInSeconds()
    numDownloads()
  }

  String name
  int trackNum
  String playlistURL
  int durationInSeconds
  int numDownloads
}

Grails’s constraints also serve the same role as Rails’s validation methods. The playlistURL field specifies that it should be a valid URL format. A similar constraint exists for email. Other constraints limit fields to a given set of values, or give more fine-grain control on the size of database tables. While Rails does have validation methods, they do not affect the structure of the database.

Domain classes can be wired together in the same manner as Rails’s models. The Album class is the most complicated. An Album belongs to an Artist, contains many Songs, and belongs to a given Genre. There also may be many Comments on an Album. The syntax for representing this is very similar to Rails, except that there is no hasAndBelongsToMany() method. Here is Album.groovy:

class Album {
  static constraints = {
    publicID(blank:false, unique:true)
    title(blank:false)
    price()
    url(url:true)
    albumCoverURL(url:true)
    albumCoverName()
    blurb(maxSize:5000)
  }

  static hasMany = [song:Song,comment:Comment]
  static belongsTo = [artist:Artist,genre:Genre]

  String title
  String publicID
  String url
  String albumCoverURL
  String albumCoverName
  double price
  String blurb
}

You can apply similar relationships to Artist.groovy and Song.groovy and the rest. When the application starts, the database is updated to match these classes.

Grails seems to trump Rails here. Grails does not require separate files to generate the database structure. Grails offers a significantly richer set of constraints, and only lacks the hasAndBelongsToMany() function for modeling the relationships between its domain classes.

But there is a dark side. With Grails, it is a little unclear how to update the database. Do you trust the update functionality not to mangle your production data? If not, updating production might force you to resort to SQL. At this point, you have returned to maintaining changes in two places.

It is unlikely that the Grails team will determine a good solution for this, as it seems to be an intrinsic issue with the domain classes specifying the available fields. In the end, whether you prefer the Rails or Grails approach may come down to a matter of taste; there is no clear winner.

Grails Views

Grails views are written in Groovy Server Pages (GSPs). Grails permits scriptlets, but it also offers a respectable tag library. As a result, Grails views look noticeably prettier than those in Rails. For example, here is the same sample layout used for Rails, but reformatted for Grails:

<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  <title>Welcome to LinmagMusic</title>
  <link href="${resource(dir:’css’,file:’main.css’)}" rel="stylesheet" type="text/css" />
  <link href="${resource(dir:’css’,file:’pm.css’)}" rel="stylesheet" type="text/css" />
</head>

<body>

<div id="outer">
  <div id="header">
    <div id="logo">
      <img src="${resource(dir:’images’,file:’logo.png’)}"
           alt="PenguinMusic, your source for Free* Music" />
    </div>
    <img src="${resource(dir:’images’,file:’linuxMagLogo.jpg’)}" />
    <div id="toolbar">
        <g:link controller="mostPopular" action="index">Home</g:link>
      <g:if test="${session.user}">
      | <g:link controller="user" action="logout">Logout</g:link>
      </g:if>
      <g:else>
      | <g:link controller="user" action="login">Login</g:link>
      | <g:link controller="user" action="register">Register</g:link>
      </g:else>
      | <g:link controller="mostPopular" action="faq">FAQ</g:link>
    </div>
  </div>
  <hr />
  <g:if test="${flash.message}">
    <div class="message">${flash.message}</div>
  </g:if>

  <div id="body">
    <g:layoutBody />
  </div>
</div>

</body>
</html>

Yes, Grails offers layouts and partial rendering like Rails. Unfortunately, the layouts are a little more awkward to work with. The page-specific view code contains a good deal more extraneous tags. Here is the view for the “Most Popular Songs” page, which serves as the front page for the application:

<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
    <meta name="layout" content="main" />
    <title>Most popular songs</title>
  </head>
  <body>

    <div id="left_rail">
      <h2>Featured Artists</h2>
      <span class="featured_artists">
        <g:each in="${albumList}" var="${album}">
          <div class="featured-album">
            <em>${album.artist.name}</em><br />
            <strong>${album.title}</strong><br />
            <g:link controller="album" action="display" id="${album.id}">
              <img width="150" height="150"
                 src="${resource(dir:’albumArt’,file:album.albumCoverName)}" />
            </g:link>
            <br /><br />
          </div>
        </g:each>
      </span>
    </div>
    <div class="body">
      <h1>Most Popular</h1>
      <div class="list">
        <table>
          <thead>
            <th>Song</th><th>Band</th><th>Album</th>
          </thead>
          <tbody>
            <g:each in="${songList}" var="${song}" status="i">
              <tr class="${(i % 2) == 0 ? ‘even’ : ‘odd’}">
                <td><a href="${song.playlistURL}">${song.name}</a></td>
                <td><em><a href="${song.album.url}">${song.album.artist.name}</a></em></td>
                <td><strong><g:link controller="album" action="display" 
                    id="${song.album.id}">${song.album.title}</g:link></strong></td>
              </tr>
            </g:each>
          </tbody>
        </table>
      </div>
      <div class="paginateButtons">
        <g:paginate total="${songInstanceTotal}" />
      </div>
    </div>
  </body>
</html>

The meta attribute is used to specify the layout. Otherwise, the header section is largely useless. It appears that the motivation here is to allow web designers to see a complete page, rather than forcing them to view little isolated bits, but the extra tags seem like at least a minor violation of the DRY philosophy. On the other hand, this version required no scriptlets. The g:link tags specified URLs. Outputting data uses just ${ ... }.

Read More
  1. BlazeDS for PHP Developers
  2. Keep a Paper Trail with Paper Trail
  3. Typekit: Banishing Blight from the Browser
  4. Ten Things You Didn't Know Apache (2.2) Could Do
  5. Hijack: Living on the Edge of (Ruby and) Rails, Part 4
Follow Linux Magazine
Rackspace