Modularizing Your Grails Application - Domain Classes

- - posted in Grails/Groovy, Reviews | Comments

This is the second installment of my What Grooves You? series of posts, this time discussing how to modularize your Grails application. While Grails does an awesome job of enforcing MVC once your application reaches a certain size, or you have multiple applications which may have shared components, you’re going to have to start thinking about how your going to modularize the reusable parts of your code.

I encountered this pretty quickly because the application I am working on is broken out into two distinct parts, a public facing web form for submitting data (the “Front End”) and a private back office application for managing those user submissions (the “Back End”). These two parts of the application (for compliance reasons) cannot run on the same internet facing system, and the “Back End” must only be available on the internal network. Of course, both of these applications are going to work with the same database and therefore the same Domain classes. It would be dangerous and tedious to try to keep the separate domain classes in each project synchronized with one another.

What won’t work

The RESTful JSON Service

My first thought was to deploy a 3rd application which would be internet visible and act as a proxy for all the database requests. I could then query that application with REST and handle a JSON payload which would be my domain object. This actually seemed pretty elegant since I wouldn’t have to actually share any code between the Front End and Back End applications and I still got a well defined object on either end. The problem of course is that all I get is the data for my domain class, and I don’t have access to any of the functionality that GORM gives me “for free”. I’d have to duplicate search functionality, limits, grouping, sorting, and all sorts of other querying tools in my service. That seemed like an awful lot of work for functionality that is offered by GORM and works very well!

Just JAR it man

The next obvious conclusion is to just toss my domain classes into a library JAR file and reference that library in both of my other applications. This way I actually have the whole domain class and access to the dynamic find methods and all that other good stuff. But, how do you package these? Do you compile the Groovy classes then package the .class files? Will the data source information have to be set for the domain class(es) in the JAR, or will the data source of the application referencing the library be used?

Now some more seasoned Java and Hibernate developers might simply laugh at that barrage of questions, but for me it presented a serious barrier to entry. Fortunately there is a better way.

Just plug it in!

It didn’t take me long to discover that putting my reusable code into a Grails Plugin was the best and most scalable approach. For the sake of demonstration I’m going to take you through an example comment submission and administration application, kinda like blog comments.

The plugin project

First, let’s go ahead and create our plugin project.

grails create-plugin Modular-DAL

Once you’ve got your shiny new plugin created, open it up with your favorite IDE (I use Spring Source Tool Suite) and add a new domain class that you’re going to be sharing.

grails create-domain-class com.nslms.modular.domain.Comment

Now we specify some properties for our new shared domain class.

package com.nslms.modular.domain

class Comment {
  static constraints = {
  String name   
  String email
  String website
  String comment
  Boolean isApproved = false

With our new shared domain class created, we want to package up our plugin so we can load it into the other projects which we’ll be creating in a moment.

grails package-plugin

That’s it, you’ve just created a (very small) module of your application which contains a shared domain class. This could, of course, contain any number of domain classes, controllers, or services, views, javascript, css, etc. that would be used by other parts of your application, or by other applications.

The Front End

Now, lets create an application which will serve as the “front end” or externally facing form for collecting data.

grails create-app Modular-FrontEnd

Then the very important part of installing the plugin we just created

grails install-plugin ../Modular-DAL/

Because you can download the project I created, I’m not going to go into excruciating detail about the controller and view(s) I setup in my front end, but sufficed to say I am accessing the “Comment” domain class that is supplied by the Modular-DAL plugin project!

CommentsController.groovy (snippet) mark:1,5
import com.nslms.modular.domain.*

class CommentsController {

    def index = { [comments: Comment.findAllByisApproved(true)] }

The result of the front end app should be a list of comments which are approved (by the backend) and a submission form to allow you to submit new comments.