Grails Tip # 6: Service layer transitions

On my last Grails project, as good Grails developers, we faithfully put core application logic inside various service methods. Delightfully, the benefits of doing so paid off and we began re-using services though out the application.

One day, while using our application on a fairly complex set of test data (both in volume and the fact our domain model graph is complex), we stumbled on a huge performance problem. After profiling the controller-action, the problem was traced down to a call to a service method. Simplified, it look like:

class ArticlesController {
   def service

   def handleAction = {
      // stuff ...
      // more stuff ...
      for(int i=0;i < loopLimit;i++){
         service.serviceMethod(someParameters)
      }
      render(view: "article"...)
   }
}

This was a commonly re-used service method, but the interesting part of this method was the fact it was being called within a loop, a loop that could potentially be called several hundred times. The looping itself is not a problem (nor could it be avoided).

By trial and error, we discovered that the actual call to the serviceMethod() was causing the performance issue. If we
1) Simply removed the service method and embedded the application logic in the service method into the loop or
2) Made the service class non-transactional

The performance issue disappeared.  We realized that the under-the-hood work that goes on to setup the transactional service boundry, when there is a complex or large volume of data in the Hibernate session, causes a dramatic perfomrance impact when we repeadly cross the controller- service layer boundry.

The simplest and cleanest solution was to loop inside the service method, thus the application cross the boundary only once. This has the side effect that any errors will roll-back the entire set of data and not just the single record being updated but we were ok with this.

class ArticleService {
   static transactional = true
   def serviceMethod(def params){
      // do stuff..
   }

   def serviceMethodMultiple(def params){
      for(int i=0; i < loopLimit; i++){
         serviceMethod(params)
      }
   }
}

And in the controller:

class ArticlesController {
   def service

   def handleAction = {
      // stuff ...
      // more stuff ...
      service.serviceMethodMultiple(someParameters)
      render(view: "article"...)
   }
}

From the standpoint of a intermediate Grails developer, this isn’t a problem that could have been detected beforehand since it only manifests itself when there is a complex domain model graph already in the session.

We chalked this up as a life lesson. The final solution, avoid any code that may repeatedly crosses into the service layer, especially for services marked as transactional. Instead, create a new method that does the looping inside the service boundary. Identification and avoidance was the best action forward as we were in no position to fix any potential underlying issue with the framework (if there even was any).

Grails Tip # 5: Apache POI

Apache POI with Grails

Many people have asked how to use Apache POI with Grails. A quick search on the Internet
reviews bits and pieces but no official documentation or tutorial. So I decided two quick ways of incorporating POI
with your Grails applications.

In a nutshell, POI provides a Java API for reading and writing MS documents such as Word and Excel documents.
You can find the library and full details here.

Write directly out to the output stream

The first method involves obtaining a handle to the response output stream and writing directly to it. You must
remember to set the content response header and content type appropriately or the user will see garbage.

        package com.ex
        import javax.servlet.ServletOutputStream
        import org.apache.poi.hssf.usermodel.*

        class ShelfController {

            def index = {

                HSSFWorkbook wb = generateWorkbook();
                response.setHeader("Content-disposition", "attachment; filename=serverList.xls");
                response.setContentType("application/excel");

                // Write the output to the OutputStream
                ServletOutputStream f = response.getOutputStream();
                wb.write(f);
                f.close();
            }

            private HSSFWorkbook generateWorkbook() {
                HSSFWorkbook wb = new HSSFWorkbook();

                HSSFSheet sheet = wb.createSheet("new sheet");

                // populate the spreadsheet
                HSSFRow row = sheet.createRow((short)0);
                    .
                    .
                    .
                return wb
            }

    }
  

Use AbstractExcelView

Because Grails is built on Spring and your Grails controllers can return Spring’s ModelAndView objects, you can
extend Spring’s AbstractExcelView and implement its buildExcelDocument method. Your Grails controller will simply
return this Excel view as the one to render. It will set the header and content type for you.

        package com.ex
        import javax.servlet.ServletOutputStream
        import org.apache.poi.hssf.usermodel.*

        class ShelfController {

            def index = {
                // forward to the list view to show them
                return new ModelAndView(new SheflExcelView(), [ bookList : "abc" ])
            }


        }
    

Implement the buildExcelDocument method in your Excel view:

        package com.ex

        import javax.servlet.http.HttpServletRequest
        import javax.servlet.http.HttpServletResponse
        import org.apache.poi.hssf.usermodel.*
        import org.springframework.web.servlet.view.document.AbstractExcelView

        class SheflExcelView extends AbstractExcelView{

            protected void buildExcelDocument(Map<String, Object> model,
                HSSFWorkbook workbook, HttpServletRequest request,
                HttpServletResponse response) throws Exception {

                HSSFWorkbook wb = generateWorkbook(workbook);
            }

            private HSSFWorkbook generateWorkbook(HSSFWorkbook wb) {
                HSSFSheet sheet = wb.createSheet("new sheet");
                .
                .
                .
            }
       }
    

I personally prepare the second method. The Excel document is a “view” so I don’t want to pollute the controller
with a whole lot of code generate the Excel report. In addition, AbstractExcelView also sets your response and content
type headers on your behalf.

Grails Tip # 4: java.lang.Boolean.call()

No signature of method: java.lang.Boolean.call()

As specified by , Grails provides convenience method to check if a object contains errors and set the CSS class on the element.

I came across this problem where suddenly, under some conditions, I was seeing the following error:

No signature of method: java.lang.Boolean.call()

Further down the stacktrace, I notice something more interesting.

Caused by: groovy.lang.MissingMethodException: No signature of method: java.lang.Boolean.call() is applicable for argument types: (java.util.LinkedHashMap, java.lang.String) values: [[bean:{}, field:asc], input-error]Possible solutions: wait(), any(), dump(), wait(long), wait(long, int), and(java.lang.Boolean)

At first glance, the stacktrace looks like complicated garbage. However, after a few minutes of looking though the stacktrace, the parameter’s in the exception cause looked suspiciously like those specified in a invocation of the GSP’s hasErrors method.

I soon realized that this exception only occurs during situations where errors would be displayed on the GSP. Looking though the code flow, I soon realized something suspicious.

		def save = {
			.
			.
			.
			
			command.validate()
			if (command.hasErrors()){
				render (view:input, model:[command:command, hasErrors:true])
				return
			}
		}
	

Notice that the if the command object has errors after validation, the model being returned to generate the GSP contains both the command and a variable hasError which is assigned to true.

I ran a quit test, what happens if try and execute the value of a boolean as a method.

		true()
	

And volila, a No signature of method: java.lang.Boolean.call() error. It appears, when there is a variable in the model with the same name as a GSP method, under some conditions, Grails replaces the method invocation with the value of the variable and then it executes the method.

In this example, it appears that hasErrors(…) was being replaced by the value of the hasError variable, true, and then being executed. Thus the final statement looked like the following: true(bean:command, …) This of course, would result in a no method signature found error.

After changing the name of the hasError variable to something else, say, showErrors, the GSP rendered as expected. By reading this article, I hope that you can save yourself a couple of hours of struggle.

Grails Tip # 3: refresh()


refresh() is not an undo()

In your application, you may come across a time when you need to revert or undo
changes done on a domain object. discard() comes to mind, but there may be instances where
that is not an option. refresh() also looks like an tantalizing option, but there is one critical
feature of refresh() you need to be aware:

If you have a trasient object associated to the domain object you are calling
refresh() on, you will get a
org.hibernate.AssertionFailure: null identifier
error.

Consider the following example to see why you might need to use refresh
and what you have to watch out for.

The Domain

Consider the following domain, a Car has several models
(for each year) and most of the details of a “car” is
in the model domain. There are a few description fields on
the Car domain object however.

The Code

The Car domain object:

		package com.ex
			
		class Car {
			String name
			String description
			static hasMany = [models:Model]
		}
	

The Model domain object:

		package com.ex
			
		class Model {
			String name
			int year
			Engine engine
			. (other properties)
			.
			.
			static belongsTo = [car:Car]
		}
	

Users are able to modify car details and model details at the same time.
They can also add new models to the car as well. All changes to the
Car (and it’s models) must be atomic. That is, all changes
must be committed as one transaction. Lets take a
look of the UI:

<%= image_tag "articles/grailstip3/flow.png" %>

When the user decides to change their changes,
they exectue the saveChanges action on CarController.

Because of the belongsTo relationship on Models to Cars, we
can save any user changes to Car model and it’s models by
calling save() on the Car object.

		package com.ex
			
		class CarController {
			def saveChanges = {
				.
				.
				.
				// save car under edit
				car.save(failOnError:true)
				.
				.
				.
			}
		}
	

The Problem

Due to a requirement, the users have the ability
to revert changes on a particular Model, but
still save their changes on the Car.

		package com.ex
			
		class CarController {
			def saveChanges = {
				.
				.
				.
				// model to revert
				if (some condition)
					// rever model
				.
				.
				.
				// save car under edit
				car.save(failOnError:true)
				.
				.
				.
			}
		}
	

One might think we can call discard(), but this will
not work in this situation because further down
the code, we end up calling save on Model’s parent,
the Car. Even if we discard a particular Model of a Car,
it will still be saved when Car is saved due to the
cascade behaviour brought on by belongsTo relationship.

We also are unable to change the cascade settings between
Car and Model. In this particular instance, we could
prevent cascade on save, but in other cases, we do need it.

The other other option is to call refresh() on the Model
being reverted. And we do this.

		package com.ex
			
		class CarController {
			def saveChanges = {
				.
				.
				.
				// model to revert
				if (some condition)
					model.refresh()
				.
				.
				.
				// save car under edit
				car.save(failOnError:true)
				.
				.
				.
			}
		}
	

Done right? well, not quite. Under some use cases, we
discover this exception being thrown:
org.hibernate.AssertionFailure: null identifier

The error only occurs when new objects are associated to
a Model. For example, if the user adds a new Engine to
the reverted Model. What’s going on?

When you call refresh on the Model, Hibernate will traverse
though the object’s object graph and overwrite its data
with what is in the database.

If there is a transient object associated to the Model,
Hibernate will not find an id associated with this entity
and thus will throw a null identifier assertion failure.

The Solution

To be able to use the refresh() method, you must break all
associations with transient objects in the graph in the
current Hibernate session.

This can be done by calling clear() on any hasMany associations
and re-assigning any variables assigned to transient objects to null.

		package com.ex
			
		class CarController {
			def saveChanges = {
				.
				.
				.
				// model to revert
				if (some condition){
					model.engine = null
					model.tries.clear()
					model.refresh()
				}
				.
				.
				.
				// save car under edit
				car.save(failOnError:true)
				.
				.
				.
			}
		}
	

Many people believe this to be hackish — a workaround
and, well, though this might be true, Hibernate’s API is being
used correctly and instances such as this, transient objects
are known and can be properly be removed from the session.

Though Grails itself does not offer an “undo” method, I
would argue the solution above deals with the problem at hand
using the API as it was designed. However, one of the reasons
I’ve posted this is to see if there are any others who have faced
similar problems have found a different way of solving it.

Grails Tip # 2: Hibernate Session


A different object with the same identifier value was already associated with the session

The Domain

Say we are managing a store with shelves full of items. Whenever an
item on a shelf is empty, we need to create a restock order form.
Lets represent this as 3 domain classes: Shelf, Item, RestockOrder

The Code

A restock order is created when an existing item on a shelf runs out,
BUT, a order is also created for brand new items. The client has requested
that when creating new items, restock orders can also be created.

The Shelf domain object:

			package com.ex
			
			class Shelf {
				int number
				static hasMany = [items:Item, restockOrders:RestockOrder]
			}
		

The Item domain object:

			package com.ex
			
			class Item {
				String name
				String description
				double price
			}
		

The RestockOrder domain object:

			package com.ex
			
			Item item
			static belongsTo =[shelf:Shelf]
			static mapping = {
				item cascade:'save-update'
			}	
		

The editing of a Shelf takes place over several pages, similar
to a web-flow, thus the Shelf object is created and stored in
the HTTP session (therefore detached from the Hibernate session).
On subsequent HTTP requests, the user adds more data to this
object in the session. Finally, after filling out the last
page, we are able to persist the domain object to the session.

On the last page, if the user made important changes to Shelf,
the user is showing a confirmation page comparing the old values
with the current one. This was done by simply populating
the model with the current version in the session and also
re-loading the same model from the database. If the user did not
make any changes that require confirmation, we save right away.

<%= image_tag "articles/grailstip2/flow.png" %>
In ShelfController:
The index() method loads the required shelf and puts it into the
HTTP session, detaching it from Hibernate session.

		    def index = {	
				Shelf s = Shelf.findByNumber(1)
				session.putValue("shelf", s)
			}
		

The save controller

			def save = {
				// get from sesion
				def shelfUnderEdit = session.getAt("shelf")
				
				// bind update
				shelfUnderEdit.parameters = params
				
				Shelf originalShelf = Shelf.findByNumber(1)
				
				// user hasn't confirmed, might have to show confirmation page.
				if (showConfirmation(shelf, original) && params.noComfirmation){
					render("showUpdates", model:[shelfUnderEdit:shelfUnderEdit, originalShelf:originalShelf])
					return
				}
				
				// save
				shelfUnderEdit.save(failOnError:true)
			}
		

However, when we try to run the code above, we get the
“A different object with the same identifier value was already associated with the session”
error.

The Problem

Hibernate tries to keep one instance of a persisted object
in the session at one time. In this example, for any “Shelf”
in the database, Hibernate tries to make sure only 1 instance
of a Shelf object represents that Shelf.

The problem resides in the save(), there is the original Shelf we
detached and put into the HTTP session. When we try to re-attach
it, Hibernate finds that another one is found in the session.
This second object was created when we loaded the same Shelf from
the database to do our comparison. Two objects representing the
same Shelf now resides in the session and much to the dislike to
Hibernate.

The Solution

Though there are several ways to solve this problem, the method
we took was to discard the re-load Shelf object that was used
for the comparison. Therefore, when save() is called on the
Shelf that is under edit, it is reattached to the Hibernate
session and is the only object representing that particular
Shelf in the database. Thus Hibernate is able to persist the
changes without error.

			def save = {
				// get from sesion
				def shelfUnderEdit = session.getAt("shelf")
				
				// bind update
				shelfUnderEdit.parameters = params
				
				Shelf originalShelf = Shelf.findByNumber(1)
				
				// user hasn't confirmed, might have to show confirmation page.
				if (showConfirmation(shelf, original) && params.noComfirmation){
					render("showUpdates", model:[shelfUnderEdit:shelfUnderEdit, originalShelf:originalShelf])
					return
				}
				
				originalShelf.discard()
				
				// save
				shelfUnderEdit.save(failOnError:true)
			}
		

References

Grails Tip # 1: Transient Values


Not Null Property References A Null Or Transient Value

Introduction

I recently started working on Grails applications and as expected, I’ve seen the same problems come up over and over again. So, I thought it would be a good idea to accumulate the common (and some uncommon) problems we”ve seen and write about them. The domain objects and code used in the posts are purpose built examples simulating the actual problems that we’ve seen developing with Grails.

The goal is not to explain the full underlying details of GORM and Hibernate, but instead, show examples of what caused issues for me and hopefully can save you time in solving your problems. Here we go with tip number 1:

org.hibernate.PropertyValueException: not-null property references a null or transient value

Example 1

The Domain

Say we are managing a store with shelves full of items. Whenever an item on a shelf is empty, we need to create a restock order form. Lets represent this as 3 domain classes: Shelf, Item, RestockOrder

The Code

A restock order is created when an existing item on a shelf runs out, BUT, a order is also created for brand new items. The client has requested that when creating new items, restock orders can also be created.

The Shelf domain object:

		package com.ex
		
		class Shelf {
			int number
			static hasMany = [items:Item]
		}
	

The Item domain object:

		package com.ex
		
		class Item {
			String name
			String description
			double price
		}
	

The RestockOrder domain object:

		package com.ex
		
		class RestockOrder {	
			Item item
			Shelf shelf
		}
	

A Shelf has a list of items and is represented by the hasMnay relationship to Items. A restock order needs an Item, it just doesn’t make sense without one. But an Item does not belong to a restock order. Thus, we do not have a belongsTo RestockOrder relationship on Item. If a restock order is deleted, we certainly do not want to delete the Item record.

The Problem

Somewhere in our RestockController, we have the following code. It creates an instance of a RestockOrder and Item. It assigns the item to the restock order.

		def createOrder = {
				.
				.
				.
				RestockOrder ord = new RestockOrder()
				ord.shelf = currentShelf
				ord.item =  new Item(name:name, description:desc, price:price)
				ord.save(failOnError:true)
			}
		}
	

When the RestockOrder is saved, we get the following error:

          not-null property references a null or transient value: com.ex.RestockOrder.item

and the only way to resolve it is to create AND save an instance of Item and then assign it to RestockOrder. This might be confusing because, you can create and assign an instance of Item to a Shelf, like the following:

			Shelf shelf = new Shelf(number:1)
			shelf.addToItems(new Item(name:name, description:desc, price:price))
			shelf.save(failOnError:true)
		

without any error.

The Solution

A transient object is an object that has been instantiated but is not yet associated to the Hibernate session. When you associate this object to a property of a object that is associated to the session and try to save, Hibernate will complain and give you the
“Not Null Property References A Null Or Transient Value error”

This problem has to do with how GROM (Hibernate) cascades saves. Saves are automatically cascaded from parent to child when there is a hasMany relationship. This is why you can add a new Item to Shelf and save the shelf without explicitly saving the Item first. The save cascades from Shelf to Item via the hasMany relationship.

With RestockOrder, there is no such relationship and Hibernate will not do the cascading automatically. You have two solutions:

1 ) Explicitly save the Item before assigning.

		Item itm = new Item(name:name, description:desc, price:price)
		itm.save(failOnError:true)
		
		RestockOrder ord = new RestockOrder()
		ord.shelf = currentShelf
		ord.item =  itm
		ord.save(failOnError:true)
	

2) Configure the cascading behavior for Item in RestockOrder.

Here we set a save-update cascading behaviour.

		package com.ex
		
		class RestockOrder {	
			Item item
			Shelf shelf
		}
		
		static mapping = {
			item cascade:'save-update'
		}
	

Conclusion

Though this error is relatively simple (especially for this example) problem, it is very problem and can be difficult to track down as your domain model grows. Thus it is extremely helpful to have a understanding when these errors occur so you know what to look for in your application.


Example 2


The Domain

In this example, we’ll use the same domain as in Example 1. The domain objects are slightly diffrent however.

The Code


We’ll use the same domain objects as Example 1, but with slight modifications:
The Shelf domain object:

		package com.ex
		
		class Shelf {
			int number
			static hasMany = [items:Item, restockOrders:RestockOrder]
		}
	

The Item domain object:

		package com.ex
		
		class Item {
			String name
			String description
			double price
		}
	

The RestockOrder domain object:

		package com.ex
		
		Item item
		static belongsTo =[shelf:Shelf]
		static mapping = {
			item cascade:'save-update'
		}	
	

The Problem


We need to allow the user to create a new shelf but during this process we also allow them to assign restock orders to the newly created shelf. To do this, we create a new RestockOrder domain object and assign it’s parent as the newly created shelf.

Somewhere in a controller we have the following code:

		RestockOrder ord = new RestockOrder()
		ord.shelf = newShelf
		ord.item =  new Item(name:name, description:desc, price:price)
		
		newShelf.save(failOnError:true)
	

The problem is, when you run it, you get the “org.hibernate.PropertyValueException” error. This is because at the time of saving the RestockOrder, the instance of Shelf is still transient.

You get a similar exception if you try and add to the list of RestockOrder’s within a Shelf by adding directly to the Shelf’s restockOrders list:

		def currentShelf = Shelf.findByNumber(1)
		RestockOrder ord = new RestockOrder()
		ord.item =  Item.findByName("a")
		currentShelf.restockOrders.add(ord)
		currentShelf.save(failOnError:true)
	

instead of using Shelf’s addToRestockOrder() method. By using native Collection methods to add to the list, Grails will not automatically set the parent on the child entity.

The Solution

To resolve this, instead of assigning the parent of a child, you can use the addTo* method on the parent to add the Item as a child of the parent.

When you add the hasMany relationship, Grails provides an addTo* method. In the example above, you will have a addToRestockOrder() method which accepts a RestockOrder instance. This relationship automatically cascades saves from the parent to child.

  • You do not need to call save on the child.
  • It also updates the child’s parent reference.

Conclusion

In this example, I showed how you can use the addTo* method to avoid some common Grails errors, but as with all other programming problems, there are always several ways to solve the issue.

So, hopefully after reading this article, you have a slightly better understanding why these errors appeared in your code by looking at how it was caused on ours. I will continue to update this article if I find any other notable or interesting causes to this particular error.

References

Grails: First Project

Groovy and Grails has been much talked about in the last couple of years and though I’ve fooled around with small sample projects I never really had the chance to do anything more. Recently, a client approved to use Grails on a new J2EE web application and this will be my first time using it on a large complex system.

There are many postings that talk about the general positives of the framework, but in this article, I want to focus on what worked and didn’t in my project and in particular, what didn’t work. My hope is after you read this article, my insights on using Grails for the first time will help you make the right technological decisions for your project.

Introduction

I am no Grails expert.

The team started up with Grails very quickly. As new members joined the team, the overall ramp up time was, as advertised by Grails, very quick and pain free. As you all many know, ramp up and installation of traditional J2EE applications can be extremely painful and take a lot of time, so the ease of ramping up new members was a great relief.

The transition between traditional J2EE to Grails was easy. I would attribute this to the “Convention over Configuration” paradigm that Grails (and Rails) use. By understanding the convention and looking at samples and existing code, developers were able to focus on implementing business logic rather then figuring out how XML configurations and flows work.

Positives

  • Easily change the domain model without having complex SQL migration scripts.
    With a domain model actively changing thoughout early development,
    incorporating the changes in short time would not have been possible.
  • Most of the advantages as advertised by Grails worked for us.
    Such as: clear built-in separation of environments, GROM, automatic binding, etc
    See the additional resources for a other postings on the advantages of Grails.
  • Active Groovy and Grails community. Even for a new framework, there is substantial
    knowledge on the internet and questions are quickly answered by the community.
  • The small things: Groovy syntax, smoother development, integrated environment.
    All that dynamic synamic syntax and sugar code.

Negatives

  • The installation of the plugin in directories outside the project and
    overall in-house plugin setup via the IDE added much confusion during the
    periods of active development of those plugins.
  • Though Springsource’s STS Eclipse integration with Grails is pretty adequate,
    there are some annoying gotcha’s that keep creeping up, especially dealing with
    the installation of in-house plugins.
  • Some developers can to revert back to standard Java techniques when exposed to
    difficult situations. For this reason, I found code reviews very important.
    Detected in reviews, the more experienced reviewer can often pass knowledge on
    how to solve a particular problem the Grails way.
  • Though novice developers can quickly become significant contributors, without
    a solid knowledge in Spring or Hibernate, it is often left up to the more senior
    members to deal with strange Hibernate errors.
  • We are developing the application using the built-in Grails development
    (Tomcat and Java DB) environment. However, the test and production
    environments are using a WebSphere server and Oracle database. Though development
    though Grails is faster, we have seen a number of gotcha’s
    during our switch over to the WebSphere and Oracle database.
  • These compatibility issues do not produce meaningful Exceptions messages and
    usually require a trial-and-error approach to figure out the problem. Examples
    are restricted Oracle keywords used as properties on domain objects and issues when
    Controllers and Domains share the same name as certain WebSphere classes.
  • It remains to be seen how well the client’s IT teams will adapt to
    this new technology.

In conclusion, I would recommend Grails as a framework going forward. Much of Grails’s advertised benefits are true and work. The big question remains is how organizations who are used to traditional J2EE frameworks such as Struts and Spring can adapt to using dynamic language frameworks such as Groovy.

As development continues, I will update this blog entry.

Additional Resources

Here are some additional resources to help you decide if Grails is right for you.