Wednesday, March 3, 2010

Grails Unit Testing for Beginners

When you use grails generators for domain classes, controllers, services or portlets, it automatically creates tests for you. Simply running "grails test-app" will run all unit and integration tests and is great for build processes. However, when you're developing you simply want to invoke the tests of the class you're editing. This can be accomplished by passing arguments to test-app like this:

grails test-app MyService -unit

or

grails test-app MyController -integration

Using println for testing is bad form but many times println in the code or tests is helpful for debugging. Grails generates test reports and one of them is the System.out. Open a tail tool (such as Baretail for Windows) on the file and you'll see the new results everytime the test runs (it does delete and replace the file.) These are located in:

my-app-home\target\test-reports\plain\
TEST-unit-unit-MyServiceTests.txt
TEST-unit-unit-MyServiceTests-err.txt
TEST-unit-unit-MyServiceTests-out.txt

You can also view an html report on the results of your tests. This is useful for seeing stacktraces:
my-app-home\target\test-reports\plain\index.html



-Ben Hidalgo

Tuesday, March 2, 2010

Input for One-to-Many Relationships Revisited

In our previous post, we discussed a method for logically displaying and constructing objects in a one to many relationship. However, this was not ideal - a lot of display logic was being written in the taglib, and writing html in code is painful and plain ugly. While this problem can be overlooked when only one additional text input was being displayed, a new feature which requires the display of a full domain object forces us to re-examine our approach.

Our solution uses templates and the ability to pass code to taglibs. Any content written within the tag is passed to the taglib in the 'body' parameter. This content, which can be additional html, a closure, or a template, can then be invoked within the taglib as a method.

Our example is a student report card: each report card has at most one class in a particular category, though it is not required to have a class in every category. First, we have the domain on the many end of the relationship.
class CourseCategoryType {
String category
String status

static constraints = {
category(inList:['History', 'Civics' ,'Math', 'Science', 'Art'])
status(inList:['Active', 'Inactive'])
}
}
class Course {
CourseCategoryType courseCategoryType
String name
String courseCode
BigDecimal gpa
}


Next we have the taglib. Notice we are invoking body as a method, and passing a parameter. The parameter will be available to the content of body as the variable 'it'.
class CourseTagLib {
def courseTag = {attrs, body ->
def from = attrs.from
def courses = attrs.courses

from.each {
def course
// find if the course has been selected
for (Course c: courses) {
if (c.courseCategoryType.id == it.id) {
course = c
}
}

// build parameters to pass to the template
def params = [
courseCategory: it,
course: course
]
out << body(params)
}
}
}


Finally we have the gsp snippet which calls our taglib. Notice that the template is passed 'it' as the bean. Remember, any information passed to body in the taglib is referenced by 'it'.
<g:courseTag from="${CourseCategoryType.findAllByStatus('Active')}" 
courses="${reportCardInstance.courses}">
<g:render template="course" bean="${it}" />
</g:courseTag>


The template is the Grails generated create gsp with a few changes
1. It's been renamed to _course.gsp
2. The bean being used is different than the default generated template - it is no longer an instance of Course, it is the array passed by the taglib. The bean is also named 'it'. Thankfully, these are cut-and-paste changes.

The disadvantage of our new method is that we're tightly coupling the taglib and template to a domain class; there is no possibility of reuse. However, the taglib is relatively simple to create - it is essentially massaging data into a format to be used by the template.

Monday, March 1, 2010

Object Marshalling and Transients Fields

By default, the converters found in the grails.converters package only marshal persistent fields on domain objects. To override this behavior, use GroovyBeanMarshaller instead. It comes in 2 flavors, XML and JSON.

example:
grails.converters.JSON.registerObjectMarshaller(Contact, {o, c ->
new org.codehaus.groovy.grails.web.converters.marshaller.json.GroovyBeanMarshaller().marshalObject(o, c)
})

Monday, February 22, 2010

Grails-Hibernate Custom Data Type Mapping

Since the underlying ORM technology used by Grails is Hibernate, it is possible to manually specify how to persist datatypes by using Hibernate's UserType interface -- the class that establishes how to translates between a Java object and the db. This ability, in combination with custom property editors, provides a simple method of saving information from UI text input to domain objects to db and back.

For our example, we'll create a new datatype called SixDecimal, which stores a numerical value with 6 digit max precision. This class is essentially no different than BigDecimal, however we need to create a new datatype because UserTypes are associated with a specific class, and we want only to translate our new SixDecimal datatype using our UserType, not all BigDecimals in general.
class SixDecimal extends BigDecimal {
public SixDecimal (Double d) { super(d) }

public SixDecimal (java.math.BigDecimal bd) { super(bd.doubleValue()) }
}


Next we create the Hibernate UserType. The interface methods are described in the documentation. Of note is the SQL_TYPES definition. Originally, we intended to use Types.DECIMAL, as this translates into NUMBER(x,d) in Oracle, and would allow us to specify precision at the db level. However, this interferes with the Grails generation of the table for the domain class, so we resort to using Types.FLOAT, and handle the setting of precision in the custom property editor.
class SixDecimalUserType implements org.hibernate.usertype.UserType {
private static final SQL_TYPES = [Types.FLOAT] as int[]

public Object assemble(Serializable cached, Object owner) { cached }

public Object deepCopy(Object o) { o }

public Serializable disassemble(Object value) { value }

public boolean equals(Object x, Object y) { x.equals(y) }

public int hashCode(Object o) { o.hashCode() }

public boolean isMutable() { false }

public Object nullSafeGet(ResultSet rs, String[] names, Object owner) {
def result = rs.getBigDecimal(names[0])
if (result) { return new SixDecimal((java.math.BigDecimal)result) }
else {return null}
}

public void nullSafeSet(PreparedStatement st, Object value, int index) {
st.setBigDecimal(index, (java.math.BigDecimal)value)
}

public Object replace(Object original, Object target, Object owner) { original }

public Class returnedClass() { SixDecimal }

public int[] sqlTypes() { SQL_TYPES }
}



Finally, we register our UserType with our new datatype. This can be accomplished system wide in Config.groovy
grails.gorm.default.mapping = {
'user-type'( type:SixDecimalUserType, class:SixDecimal )
}


or by field within a domain class
class MyDomain {
static mapping = {
interestRate type:SixDecimalUserType
}

SixDecimal interestRate
}

Tuesday, February 16, 2010

Grails - XML Conversion

Grails provides some effortless features for converting objects into XML, but some care is necessary when using them.

By default, the XML representation of an object is shallow - this means any reference to another domain object will be represented by the id in the xml document. If the xml document should contain the full object tree, a flag in the converter needs to be set.

Adding the following line to Config.groovy will set the default for the system
grails.converters.xml.default.deep = true

or if you prefer, you can do the same thing programatically
grails.converters.XML.use('deep')

in either case, you can test it out with the following code
def converter = new grails.converters.XML(myInstance)
converter.render(new java.io.FileWriter("c:\\output.xml"))
// or
def xmlStr = myInstance as XML


One issue we had with deep converters was that it was including too much information - our User domain class contained a (cleartext) password field which was being displayed in the resulting xml.

We can customize the behavior for transforming an object into xml by using the registerObjectMarshaller method. This method is passed a class name and a closure which handles writing the XML output. The closure has implicit access to both the instance of the encountered class and the converter used to transform it.
class User {
String login
String name
String password
}

def converter = new XML(aUser)
converter.registerObjectMarshaller(User, {user, conv ->
conv.build {
login(user.login)
name(user.name)
}
})

or you could set the converter for the entire system by putting the same code in Bootstrap.groovy
grails.converters.XML.registerObjectMarshaller(User) { user, converter ->
// same implementation as above...
}

Monday, February 15, 2010

Input for One-to-Many Relationships

One of the requirements we have on this project is to have a dynamic list of values that another domain object has a relationship with - the parent domain object would have a list of selected child values. While this could be accomplished relatively easily using multiple select boxes, things get a little more complicated when each selected value has a separate field associated with it.

Now, that wasn't exactly the most coherent explanation of the problem, so let's have an example. Suppose we have a 401k management system that has allows the user to choose among a list of available funds, and a percentage to allocate to each selected fund. All input should be present on a single page.

The list for available funds is dynamic, so it has its own domain class (and default generated grails pages). It also doesn't make sense to have a field for allocation % to this domain class, as every user would have a different percentage.
class Fund {
String name
BigDecimal netAssetValue
}


We solve the problem of where to put the allocation percentage by creating a second domain class which effectively maps a Fund with a percent value. We also establish the one-to-many relationship between this new class our main domain class.
class SelectedFund {
static belongsTo = [portfolio:Portfolio]

Fund fund
Double allocationPercentage

static constraints = {
fund(nullable:false)
allocationPercentage(nullable:false, min:0d)
}
}


We complete the one-to-many relationship in our main domain Portfolio class
class Portfolio {
static hasMany = [selectedFund:SelectedFund]

String name
String ssn
BigDecimal balance

static constraints = {
balance(nullable:false, min:0d)
}
}


Simple enough, but now comes a second problem - tying into the Grails validation and data binding framework. We want the validations to kick off for both the Portfolio class and SelectedFund classes. We also would like the nice highlighting of errored fields that Grails provides. Unfortunately, this is easier said than done, and manual work is required both on the controller and on the gsp side.

First, the controller. There is no automatic way to construct our SelectedFund objects, so this is our first task. We can imagine the UI as a checkbox for each Fund and an associated textfield for the allocation value.

The first step is to clear the portfolio object of any previously SelectedFunds. Note the double loop - we cannot simply iterate over the selectedFund and remove them, as that causes a ConcurrentModification exception. It appears the underlying collection grails uses to store associations is not synchronized.
if (portfolio.selectedFund) {
for (Object fund : Fund.findAll()) {
for (Object sf : portfolio.selectedFund) {
if (sf.fund.id == fund.id) {
portfolio.removeFromSelectedFund(sf)
}
}
}
}


The second step is to collect the list of Funds selected. Note the inline comments
// if only one cbox is selected, html returns a String
// if multiple cboxes are selected, a list is returned
def idList = params['fundIds']
if (idList instanceof String) {
idList = []
idList << params['fundIds']
}

def fundList = idList.collect{Fund.get(it)}


Finally we construct a SelectedFund object for each selected Fund. The second line of the closure is particularly interesting. The right of the = is some gui Grails magic - Grails will only bind to the object parameters prefixed with the passed string. Also, by assigning object field values using '.properties' we hook into the Grails validation lifecycle.
fundList.each {
def sf = new SelectedFund(fund:it)
sf.properties = params['fundIds'+it.id]
portfolio.addToSelectedFund(sf)
}


Separate to building objects from input fields but just as important, is the validation of the SelectedFund object. I was hoping that any errors encountered during object construction would propagate to the parent Portfolio object, but this was not the case. As a result, when we save we must check each SelectedFund for errors manually. Note - this is only handles errors encountered during data binding (i.e. - passing alpha characters to a numerical field), something we'll examine in further detail later when we implement the view.
def hasErrors = false
for (Object o: portfolio.selectedFund) {
if (o.hasErrors()) {
hasErrors = true
break
}
}
return hasErrors



There are also manual steps needed on gsp side - our solution is to use a custom tag. For the sake of brevity, we will skip the code for rendering the html checkbox and textfield elements, which is relatively straightforward, if not tedious. What is interesting is handling errors encountered during validation.

From the documentation, we learn that there are two phases of validation. The first is during data binding, the second during execution of declared constraints. Unfortunately for us, errors encountered during each phase are put onto the errorList of different objects - for data binding, it is on the SelectedFund object, for constraints, it is on the Portfolio object. The manual validation we provided in the controller will ensure that all validations are performed, but some steps are necessary on the view to display errors on the UI.

Finding a binding error is simple - the following code snippet assumes the custom tag has been passed the portfolio object, and is looping over each portfolio.selectedFund object.
def itemHasErrors = false

if (aSelectedFund?.hasErrors()) { itemHasErrors = true }

Finding errors on the Portfolio bean is not as simple. We must iterate over over every error and determine if the error is for a SelectedFund. We take advantage of portfolio.errors, which is an instance of the Spring Errors interface, where each error in the list is an instance of ObjectError.
else if (portfolio.errors?.allErrors) {
for (Object o: portfolio.errors.allErrors) {
if (o.getArgument[1] == SelectedFund.class) { itemHasErrors = true }
}
}


we can now use the itemHasErrors value to determine the stylesheet class to use for the html objects.

One drawback immediately evident, is the formatting of the allocation percentage. If we had created a property editor as described in an earlier post, there is no way of using it, as we are setting the value manually in the custom tag.

Wednesday, February 10, 2010

Setting a global default for Grails date format

Simply modify ./grails-app/i18n/messages.properties

default.date.format=MM/dd/yyyy