GORM: Controller vs Service

2009 March 23
by noisyheads

Scaffolds, generated codes, and lots of tutorials in the web or in print usually show Grails controllers directly invoke GORM methods. You will often see a list(), a findBySomething() in there. Simple invocations, I really have no problems. Usually, I would think of controllers as really thin callers to the business layer of your app. A single call to get() in your “show” action is a call to a business method, quite simply. But chaining a lot of GORM inside your action:

def someAction = {
  def book = new Book(params["book"])
  def chapter = new Chapter(params["chapter"])
  def snippet = Snippet.findByKeyword(params.keyword)
  if(snippet) {
    chapter.addToSnippets(snippet)
  }
  book.addToChapters(chapter)
  if(book.save())
  {
    do something
  }
  else
  {
    do something else
  }
  def bookShelf = new BookShelf(params["bookShelf"])
  bookShelf.addToBooks = book
  book.bookShelf = bookShelf
  if(!bookShelf.save()) {
    etc.. etc..
  }
  ....
}

A little messy. First, that doesn’t make our controller appear like the thin business logic caller that it should be. Another is that some parts of this example need to be transactional. For this case, we’ve got three different domain models (book, chapter, bookshelf) to persist in one go. That would probably rule out the withTransaction GORM method as well. So perfect situation to make use of a Grails Service. You can wrap around all these logic inside a service method, and make sure to make the service transactional. So in your controller action, you can simply have:

def yourService

def someAction = {
  def book = new Book(params["book"])
  def chapter = new Chapter(params["chapter"])
  def bookShelf = new BookShelf(params["bookShelf"])

 yourService.bookServiceMethod(book, chapter, bookShelf, params.keyword)
}

Now YourService should have something like:

boolean transactional = true

def bookServiceMethod(book, chapter, bookShelf, snippetKeyword) {
  ..same as codes above..
}

Take note that the transaction breaks (and hence triggers rollback) when a RuntimeException is incurred during the service method call. So be smart about placing those within the method logic.

One Response leave one →

Trackbacks & Pingbacks

  1. Beware: Controller and Service Dirt and Flush « noisyheads: Development Blog

Leave a Reply

Note: You can use basic XHTML in your comments. Your email address will never be published.

Subscribe to this comment feed via RSS