Archive for January, 2009

Migrating from Rails to Grails

January 19, 2009

I have been developing with Java for over 10 years and over the last couple of years got interested in Ruby and Rails. I have developed a few Rails applications mostly for personal use and use Ruby extensively on the job for utilities that I used write in Perl.

So I am a huge fan of Ruby and Rails, and then along came Grails. Grails is an implementation of Rails written in Groovy. Derived from Java syntax, Groovy is easy for Java developers to pick up. In addition, Grails uses familiar Java frameworks under the covers, most notably Spring and Hibernate. Recently SpringSource acquired G2one, the company behind Grails and some interesting work has been happening to integrate Grails and Spring integration. Reading the Grails documents and various posts, it was clear to me that Grails down-plays its Rails heritage. I expected some significant differences so I thought it would be interesting to port a Rails application to Grails.

I started with the Rails tutorial which guides you through a simple blog application. I used Mysql 5 for the database and got it up and running in no time. The application allows you to post blog entries and comments on the entries. Two tables are created, posts and comments. Of course there is a one-to-many relationship, so a post has many comments and a comment belongs to a post.

I basically wanted to retain the existing database tables and create the application with Grails. In the process, I discovered some of the key differences between these two frameworks.

The first step is to install Grails. It’s best to stick with the stable release. Being adventurous, I decided to check out the latest code from the svn trunk and build it myself. This is currently version 1.0.5. The latest stable version is 1.0.4. There is also a 1.1 beta release. Version 1.0.5, and 1.1 beta are buggy and caused some problems with object relational mapping. I eventually resigned myself to using 1.0.4, and everything worked as expected.

To create the blog application, type
grails create-app blog
This is analogous to the rails command. It creates the directory structure for your application and sets up a default configuration.

Next, configure the data source for Mysql. Edit grails-app/conf/Datasource.groovy, so that it looks something like this (changes are bolded):


dataSource
{
  pooled = true
  driverClassName = "com.mysql.jdbc.Driver"
  username = "root"
  password = "mysql"
  dialect = "org.hibernate.dialect.MySQL5Dialect"
}


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 = "create-drop"
        url = "jdbc:mysql://localhost/blog_development"
      }
    }
    test {
      dataSource {
        //dbCreate = "update"
        url = "jdbc:mysql://localhost/blog_test"
      }
    }
    production {
      dataSource {
      //dbCreate = "update"
      url = "jdbc:mysql://localhost/blog_production"
    }
  }
}

Note that like Rails, Grails provides development, test, and production environments. This configuration provides access to the Mysql database I created with Rails. Note the dbCreate property is commented out. The default behavior for the development environment is to drop and re-create the tables every time you run Grails. In this case, I want to retain the schema and the existing data. Removing this property prevents Grails from destroying the database.

Next, you need to provide the declared driver class. This is the standard JDBC driver for Mysql in this case and is provided in mysql-connector-java-5.0.8-bin.jar, for example. Install this in the application lib directory.

Now, create the domain classes. These are somewhat analogous to the Rails model (ActiveRecord) classes. Grails provides Grails ORM (GORM) which uses Hibernate under the covers. GORM provides some nice features, and a nice DSL, but is somewhat incompatible with Rails in its “convention over configuration.” Key differences include:

  • No pluralization of table names
  • Automatic record versioning for optimistic locking
  • No timestamping records by default. Timestamping uses different field names by default
  • DB column names with underscores are converted to camelCase field names by default

So after some experimentation, the Rails compatible domain classes, providing the same features as in the Rails tutorial , are


class Post {
  String title
  String name
  String content
  Date lastUpdated
  Date dateCreated

  static constraints = {
    title(minSize:5, blank:false)
    name(blank:false)
  }
  static hasMany = [ comments : Comment]

  static mapping = {
    version false
    table 'posts'
    columns {
      content type : 'text'
      lastUpdated column:'updated_at'
      dateCreated column:'created_at'
    }
  }
}


class Comment {
  String commenter
  String body
  Date lastUpdated
  Date dateCreated

  static mapping = {
    version false
    table 'comments'

    columns {
      body type: 'text'
      lastUpdated column:'updated_at'
      dateCreated column:'created_at'
    }
  }

  static belongsTo = [post: Post]
}

Notice the boilerplate code required here. The timestamp fields are Grails defaults and will be automatically updated as appropriate. Unlike, Rails, they must be explicitly declared and mapped to the Rails conventional column names.

Versioning is turned off, as the tables do not include version columns. (I am a big fan of optimistic locking, but this is KISS). The constraints closure in the Post class demonstrates how field validation is done in Grails, similar to the Rails tutorial.

I struggled for a while attempting to refactor this code into a base class. I eventually gave up. GORM provides some conventions around mapping inherited domain classes. Also, I couldn’t figure out how to get the mapping closure to execute the base class mapping. It is likely due to my lack of Groovy and GORM expertise, so I suspect there is an easy way to do this.

From this point, it is fairly straight forward. Execute the commands:
grails generate-all post
grails generate-all comment

to generate the controller and view scaffolding code. Then
grails run-app
and you should be good to go.

As a final step, Grails scaffolding creates inputs for dateCreated and lastUpdated. This also behaves differently then Rails. So I went in and edited the view pages, e.g., grails-app/views/post/create.gsp and removed the date fields.

The blog application on Rails

The blog application on Rails



The blog application on Grails

The blog application on Grails