Wednesday, May 5, 2010

IPP IFrame Grails Printing with Tabs

Step 0:
First thing's first: IE7 + Iframe + window.print() = non-functioning print button. The solution for this is to use: document.execCommand('print', false, null);

Now that that's out of the way.

For our Grails page we are using tabs (yui 2.7.0.1) to organize and display things in a more user-friendly fashion. The problem with this comes when you're ready to print. There have been several solutions (none of them pretty) that I've come across that have attempted to solve this problem. With the help of Heidi, we have come up with one more:

Step 1: Print Button


This can also be done with a link:
<a onclick="document.execCommand('print', false, null);" href="#">PRINT</a>


Step 2: print.css
You need to fix your style sheet to remove the yui tabs and display the content in-line. This is what worked for us in IE7.

.buttons {
display: none;
}

.yui-navset .yui-content .yui-hidden {
border:0;
height:100%;
width:100%;
padding:0;
position:relative;
left:0px;
overflow:auto;
visibility:visible;
}

.dialog table {
padding: 0;
border:0;
}

If you're using firefox you need to add:

.tabInner {
display: none;
}

3. Make sure this tab removal only happens when you're printing:
<link rel="stylesheet" type="text/css" href="css/print.css" media="print">


And you're done! Please feel free to share other solutions you've found when printing. I'm always looking for a better, more eloquent solution.

Brandy

Wednesday, April 28, 2010

Mock Testing with Grails

For unit testing controllers that make calls to injected spring beans, we can use Grails' mock framework.

Take for example a Controller and Service class defined as follows
class MyService {
boolean transactional = true

def serviceMethod(param1) {
return 'hi'
}
}

class MyDomainController {
def myService

def doSomething = {
def val = myService.serviceMethod('input1')
return val }
}

Our test case for the doSomething closure would look as follows
import grails.test.*

class MyDomainControllerTests extends ControllerUnitTestCase {

protected void setUp() {
super.setUp()
}

protected void tearDown() {
super.tearDown()
}

void testSomething() {
GrailsMock serviceMock = mockFor(MyService)

/*
* Mock the method being called
* the 1..1 specifies the min & max number of times the method is expected to be called
* the closure defines the code executed each time the method is called
*/

serviceMock.demand.serviceMethod(1..1) {param1 ->
assertEquals 'input1', param1
return 'hi'
}

/*
* The service needs to be manually set in the controller
*/

controller.myService = serviceMock.createMock()

assertEquals 'hi', controller.doSomething()

/*
* Verifies that the service was accessed
* in the manner established earlier.
*/

serviceMock.verify()
}
}

Wednesday, April 14, 2010

Bypassing Acegi Security

Acegi Security is rather easy to include in your application, but because our application needs to integrate with a single-sign on system, some method of bypassing Acegi or automatically logging into our application is required.

Since Acegi is built upon a list of filters that intercept HttpServletRequests, we can inject our own filter into the chain that will automatically log a user into our application. For simplicity, we assume the SSO is providing user information in a request header parameter.

The first step is include our filter in the list of filters to be invoked by Acegi. Edit conf\SecurityConfig.groovy, which should have been created during installation of the Acegi plugin, to include the following:
filterNames = ['httpSessionContextIntegrationFilter',
'logoutFilter',
'authenticationProcessingFilter',
'securityContextHolderAwareRequestFilter',
'rememberMeProcessingFilter',
'mySsoFilter',
'anonymousProcessingFilter',
'exceptionTranslationFilter',
'filterInvocationInterceptor']

The filters listed are the common filters invoked by Acegi in the listed order. We've included our filter mySsoFilter.


Since the filters in Acegi are actually Spring beans, the next step is to define the bean representing our filter in conf\spring\resources.groovy
mySsoFilter(MySsoFilter) {
userDetailsService = ref("userDetailsService")
}

The userDetailsService bean passed to our filter is pre-defined by Acegi and Grails. It's purpose is described later.


Finally we create our filter file, MySsoFilter.groovy, in the utils directory. The skeleton is listed below. Note
-- we defined an instance field userDetailsService, the Spring bean injected into our filter bean.
-- the method getOrder() defines the order and priority for the filter during invocation
-- the method doFilterHttp(...) is where the functionality of our filter will be contained.
import org.apache.commons.logging.LogFactory

import org.springframework.beans.factory.InitializingBean
import org.springframework.security.GrantedAuthority
import org.springframework.security.GrantedAuthorityImpl
import org.springframework.security.context.SecurityContextHolder
import org.springframework.security.providers.UsernamePasswordAuthenticationToken
import org.springframework.security.ui.FilterChainOrder
import org.springframework.security.ui.SpringSecurityFilter

import javax.servlet.FilterChain
import javax.servlet.http.HttpServletRequest
import javax.servlet.http.HttpServletResponse


class MySsoFilter extends SpringSecurityFilter implements InitializingBean
{
static final HEADER_ATTRIBUTE_LOGIN = 'x-login'
static final HEADER_ATTRIBUTE_FIRSTNAME = 'x-firstname'
static final HEADER_ATTRIBUTE_LASTNAME = 'x-lastname'
static final HEADER_ATTRIBUTE_EMAIL = 'x-email'

static final log = LogFactory.getLog(MySsoFilter.class)

def userDetailsService

void afterPropertiesSet() {
log.debug '************************ inside afterPropertiesSet'
}


void doFilterHttp(HttpServletRequest request, HttpServletResponse response, FilterChain chain) {
chain.doFilter(request, response)
}

int getOrder() {
return FilterChainOrder.REMEMBER_ME_FILTER
}
}



Now that we have a filter being invoked in the proper order, containing information about the user who has been logged in via SSO, the difficulty now lies in simulating a login in Acegi.

First, we get information about the user we're trying to log in. This is provided by the userDetailsService bean, an instance of the Acegi implementation of the UserDetailsService. The interface's only method returns an instance of UserDetails, which is a wrapper around the loginUserDomainClass and authorityDomainClass defined during Acegi installation (and also defined in SecurityConfig.groovy).
def details = userDetailsService.loadUserByUsername(username) 


Next, we create a security token, by using the concrete class UsernamePasswordAuthenticationToken. The password is obtained during lookup of the user.
def token = new UsernamePasswordAuthenticationToken(
details, passwd, details.authorities)


Finally, we give the token to the SecurityContextHolder, an Acegi object which manages the security token per executing thread.
SecurityContextHolder.context.authentication = token 



Our final implementation for doFilterHttp(...) is as follows
    void doFilterHttp(HttpServletRequest request, HttpServletResponse response, FilterChain chain) {
log.debug '************************ inside doFilterHttp'
log.debug 'req value ' + request.getHeader(HEADER_ATTRIBUTE_LOGIN)

// no SSO header, do not continue
def login = request.getHeader(HEADER_ATTRIBUTE_LOGIN)
if (!login) {
log.debug('no sso header found, continuing')
chain.doFilter(request, response)
return
}

// user not in our system, do not continue
def user = User.findByUsername(login)
if (!user) {
log.info('username ' + login + ' not found')
chain.doFilter(request, response)
return
}

// user does not have admin role, do not continue
def adminRole = Role.findByAuthority('ROLE_ADMINISTRATOR')
if (!user.authorities.contains(adminRole)) {
log.info('user ' + login + ' does not have admin permission')
chain.doFilter(request, response)
return
}

log.info('user ' + login + ' given SSO access')
def details = userDetailsService.loadUserByUsername(user.username)
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(
details, user.passwd, details.authorities)
SecurityContextHolder.context.authentication = token
chain.doFilter(request, response)
}

Tuesday, April 13, 2010

GrailsUI Tab Manipulation

We've been using the Tab Layout available in the GrailsUI plugin in our application, but one minor annoyance we've discovered is that while saving the form resets the active tab.

The javascript library that renders the tabs gives you access to the tab information, through the variable GRAILSUI

For example, the following gsp would always display the first tab on save.

<gui:tabView id="myTabs">
<gui:tab label="Basic" active="true">
</gui:tab>
<gui:tab label="Firms">
</gui:tab>
</gui:tabView>



We can now access the tabs in custom javascript by using
GRAILSUI.myTabs.get('activeIndex')


all that's left is to save a hidden field, and change the tab 'active' definitions

Custom Grails Error Handling

Error handling in your Grails app is especially important, as Groovy is a non-checked language -- methods need not declare a throws clause. While UrlMappings.groovy provides a default page for general 500 errors, in our application, we'd like to display different error pages in different situations.

There are several approaches to this problem. One solution is to separate error handling by exception class. This can be done by modifying Bootstrap.groovy

exceptionHandler is an instance of GrailsExceptionResolver, and can be auto injected. Note the last entry is needed for default handling.

Also, be sure to remove the "500" entry from UrlMappings.groovy, as interferes with the definitions here.

class BootStrap {
def exceptionHandler

def init = {
exceptionHandler.exceptionMappings = [
'SpecialException' : '/myController/someAction',
'java.lang.Exception' : '/error'
]
}
}



Another approach is to modify the handling in UrlMappings.groovy. By default, the "500" entry points to error.gsp in the views directory, but it can be changed to another view, or a controller with optional action specified.
"500"(controller:'myController', action:'handleExceptions')

Monday, March 22, 2010

Calling Stored Procedures in Groovy

As expected, Groovy provides some compact syntax for calling stored procedures. All the magic is contained in the Sql class.

For example, a stored procedure with the following signature:
insert_book(p_title IN VARCHAR2, p_author IN VARCHAR2, p_isbn OUT VARCHAR2, p_id OUT INTEGER)


Can be invoked with the following Groovy code:
public saveBook(book) {
def isbn
def bookId

Sql sql = new Sql(dataSource)
sql.call "{insert_book(?, ?, ?, ?)}",
[book.title, book.author, Sql.VARCHAR, Sql.INTEGER],
{ spIsbn, spId ->
isbn = spIsbn
bookId = spId
}
}

Note:
  • the first parameter is a string containing the stored proc call that also parameterizes the in/out variables.
  • the second parameter are the variables to be passed in or the corresponding type of the out parameter
  • the third parameter is a closure that is given the out parameters of the executed stored procedure in the order they are declared in the sproc.
dataSource is an instance of the data source created in DataSource.groovy. Our snippet assumes the saveBook method is contained in a spring bean, where the dataSource variable can be automatically injected.


More information on Groovy and db objects can be found here.

Thursday, March 4, 2010

Mapping Domain Classes with Hibernate Annotations

Save the following file as grails-app/conf/hibernate/hibernate.cfg.xml. Note that it specifies a single class being mapped, all classes in a package can be specified by using:

<mapping package="com.test.domain" />


<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>

<session-factory>
<mapping class="Firm"/>
</session-factory>

</hibernate-configuration>

Our domain class looks as follows. Note that the table name is a Oracle Database Link.

import javax.persistence.Column
import javax.persistence.Entity
import javax.persistence.Id
import javax.persistence.Table

@Entity()
@Table(name="firm@remote")
class Firm {
@Id
Integer id
@Column(name="name")
String name
@Column(name="status")
String status

@Column(name="key")
String key
@Column(name="short_name")
String shortName
}

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

Tuesday, February 2, 2010

Custom Grails Property Editor

Grails uses Spring's mechanism for binding the html (String) representation of an object with the object representation on the server side. I wanted all my currency fields (which are BigDecimal) to be formatted with dollar signs so I declared a CustomPropertyEditorRegistrar to modify how the BigDecimal conversion.

1. Added this to my resources.groovy
configurer(org.springframework.beans.factory.config.CustomEditorConfigurer) {
propertyEditorRegistrars = [ref("registrar")]
}

registrar(com.sungard.stallion.format.CustomPropertyEditorRegistrar)
2. Create a class that implements PropertyEditorRegistrar
import org.springframework.beans.PropertyEditorRegistrar;
import org.springframework.beans.PropertyEditorRegistry;

public class CustomPropertyEditorRegistrar implements PropertyEditorRegistrar {
public void registerCustomEditors(PropertyEditorRegistry registry) {
registry.registerCustomEditor(java.math.BigDecimal.class, new CurrencyPropertyEditor());
}
}


3. It seems like this could have been done in a single step... but also define the class that the Registrar adds which implements PropertyEditor. Spring provides a helper class, PropertyEditorSupport, that the custom editor can extend:

import java.math.BigDecimal;
import java.beans.PropertyEditor;
import java.beans.PropertyEditorSupport;

public class CurrencyPropertyEditor extends PropertyEditorSupport implements PropertyEditor {

public void setAsText(String text) {
setValue(... parsing goes here...);
}

public String getAsText() {
Object value = getValue();
if (value instanceof BigDecimal) {
return ... formatting goes here...;
}
return ("" + value);
}

}

- Ben Hidalgo

Custom Constraints

Grails constraints are short circuited when a field is declared nullable:true. This means if an attribute starts out nullable, say when the instance is in "Draft" status, but becomes required later, say when the user "Submits", the validator constraint can be used. Since validator takes a closure it can be invoked by reference or in-line. Or... pass arguments to make it more generic by wrapping the closure in a method like this:

    static Object requiredIfStatusEqual(status) {
// return a closure that will perform the validation
return {value, paf ->
// if the status is equal, the field is not required
if(status != paf.status) { return true }

// if the status is not equal, the value must be populated
return value ? true : 'default.blank.message'
}
}


Then, call the method in the static constraints block


static constraints = {
status( inList:[DRAFT, SUBMITTED])
shortTitle( validator:requiredIfStatusEqual(SUBMITTED))
}
- Ben Hidalgo

Override Default Grails Constraints

The defaults for nullable, blank and the other gorm constraints can be configured in Config.groovy by adding a snippet such as:

grails.gorm.default.constraints = {
'*'(nullable:true,blank:true)
}

Tuesday, January 19, 2010

Retrieving the current user from Acegi

The Grails Acegi plugin automatically puts the AuthenticateService into the Spring beans. This can be accessed in any controller simply by adding the member variable "authenticateService"

class MyController {
def authenticateService
...
}

The current user is retrieved with:
authenticateService.principal()

This returns an instance of:
org.codehaus.groovy.grails.plugins.springsecurity.GrailsUserImpl

but of course we handle it dynamically:
def principal = authenticateService.principal()


The username can be retrieved by:
authenticateService.principal()?.getUsername()


Note, the "?" operator to prevent NullPointerException. The principal() is null when no one is logged in. You can always secure the page to prevent that but I usually develop unsecured and then add authentication before testing.

-Ben Hidalgo

Thursday, January 14, 2010

Grails Multiple Select Tag

Though it would seem like a feature available right out of the box, having a tag that allows a user to select multiple options in a select box is in fact, a custom tag.

The src code for the tag can be found here. just copy the src into a file named MultiselectTagLib.groovy in the taglib dir.

Directions for use, can be found here

As an example, suppose we had a Statement class which contains multiple payments

class Statement {
String name
Date stmtDate

static hasMany = [payments:Payment]

static constraints = {
payments(nullable:false)
}
}

class Payment {
Double amt
Date txnDate

static constraints = {
amt(nullable:false)
txnDate(nullable:false)
}
}


then the gsp tag to select payments for a statement would look like

<g:select optionKey="id" optionValue="amt" from="${Payment.list()}" name="payments"
value="${statementInstance.payments}" multiple="multiple" />

Wednesday, January 13, 2010

Using Acegi tags in GSP

Using the Acegi security tags is very simple and described nicely here

The tags are basically:
<g:isNotLoggedIn>
...
</g:isNotLoggedIn>

<g:isLoggedIn>
...
</g:isLoggedIn>

<g:ifAnyGranted role="ROLE_ADMINISTRATOR,ROLE_VIEWER">
...
</g:ifAnyGranted>


To place a login link use:
<g:isNotLoggedIn>
<div style="margin-left:20px;">
<g:link controller="login" action="auth">Click Here to Login</g:link>
</div>
</g:isNotLoggedIn>
Here's a trick, if you're using views instead of tables to define your roles (for tables, use Bootstrap.groovy) you can fake results from a remote system like this:

create view role_vw as
select 1111 as ID,
'ROLE_ADMINISTRATOR' AS AUTHORITY,
0 as VERSION,
'Admin' as DESCRIPTION
from dual
union
select 2222 as ID,
'ROLE_VIEWER' AS AUTHORITY,
0 as VERSION,
'Viewer' as DESCRIPTION
from dual
And follow a similar trick for the Person and PersonRole views.

I found an annoying quirk when attempting to use constants in the @Secured annotation.
@Secured(['ROLE_ADMINISTRATOR']) works fine but @Secured([RoleNames.ADMIN]) where RoleNames.ADMIN is a public static final constant in a class or interface doesn't work. This is tedious because I'll have to search and replace the role names if the product owner changes them. The GSPs also have the roles hardcoded, so not a big deal.

-Ben Hidalgo

Tuesday, January 12, 2010

Apache JAMES

Today I installed Apache JAMES to use as our development mail server. I've found this to be easy to use and setup whenever I need a quick mail server. When using e-mail that requires proper formatting, the default "localhost" servername will not work, so to solve this problem, I added
localhost.com
to \apache-james-2.3.2\apps\james\SAR-INF\config.xml

<servernames autodetect="true" autodetectip="true">
<servername>localhost</servername>
<servername>localhost.com</servername>
</servernames>

An easy fix for what can sometimes be an annoying problem.


-Brandy Brewster

Piggyback Acegi on external user/role management

For a variety of reasons, we need to store our users and roles in a different database schema and structure than comes with Grails... but we definitely want to use the Acegi plugin. Also, there is no LDAP or SSO so the goal was to make Role and Person use tables in another schema in the same database (managed by a different web app.)

The approach is to map the Role, Person and RolePerson (implicit) entities to views. Using a view to select from the other tables, makes one-way synchronization trivial.

1. Create a view called ROLE_VW which selects from the roles table and maps the columns to what Role.groovy expects. I appended 'ROLE_' to the Authority so that Acegi will respect it as a role. The actual role names in the other schema don't include it and are named like: "Administrator." I also did an "upper" just to follow an all-caps convention in the annotation based @Secured in the controllers. "Participant" is the table name in the other schema (from the existing app with user mgmt capability).

create view role_vw as
select OID as ID,
'ROLE_'||upper(id) AS AUTHORITY,
0 as VERSION,
id as DESCRIPTION
from otherapp.participant
/

create view people_vw as
select
oid as id,
account as USERNAME,
firstname||' '||lastname as USER_REAL_NAME,
password as PASSWD,
email as EMAIL,
1 as EMAIL_SHOW,
1 as ENABLED,
0 as VERSION,
description as DESCRIPTION
from otherapp.workflowuser
/

create view people_to_role_vw as
select ID as ROLE_ID,
up.WORKFLOWUSER AS PERSON_ID
from otherapp.user_participant up, otherapp.participant p
where up.participant = p.oid
/

Then update the groovy classes to use these:

Role.groovy:
static mapping = {
// mapping to a view because info is maintained in a separate schema
table 'role_vw'
people joinTable:[name:'PEOPLE_TO_ROLE_VW']
}
Person.groovy
static mapping = {
// mapping to a view because info is maintained in a separate schema
table 'people_vw'
authorities joinTable:[name:'PEOPLE_TO_ROLE_VW']
}

Lastly, the passwords stored by the other app are unencrypted. Therefore, to disable encryption place this snippet in the ./conf/spring/resources.groovy:

beans = {
passwordEncoder (org.springframework.security.providers.encoding.PlaintextPasswordEncoder)
}
-Ben Hidalgo

GrailsUI Tab Layout

Using the tab view layout in grails is pretty simple

First, install the GrailsUI plugin

grails install-plugin grails-ui


Second, include the gui resource in your gsp file by adding the following within the head of your document. There are several components available in the plug-in, we're just including one here.

<gui:resources components="['tabView']"/> 


Finally, use the tags in your gsp. Note that the tags need to be used with a particular css style - something that, bafflingly, needs to be done manually.

<div class="yui-skin-sam">
<gui:tabView>
<gui:tab label="Default Tab" active="true">
<g:render template="myTemplate" bean="${myBeanInstance}" />
</gui:tab>
<gui:tab label="Tab 2" controller="myController" action="foo">
</gui:tab>
</gui:tabView>
</div>



The first tab is the default tab, as indicated by the active attribute. The contents for the tab are contained within the template myTemplate.

The second tab is making a server call, and will display the template returned by the foo action on the controller myController.

Monday, January 11, 2010

Logout from Acegi

To logout from Acegi, simply GET the following url: my-context-root/logout

This link gets it done:
<g:link action="logout" controller=".">Logout</g:link>


I added some inline style to move it to the right side of the screen:
<div style="text-align: right; padding: 1px 20px 0px 0px;">
<g:link action="logout" controller=".">Logout</g:link>
</div>


Placing the snippet into .\views\layouts\main.gsp will make the Logout link appear on every page.

-Ben Hidalgo

Friday, January 8, 2010

Unit tests for processes

I added a Helper class containing IPP query methods that are helpful for automated process testing. It provides methods to search for process and activity instances, complete activities, check the state of processes or activities...
For example:
import static ag.carnot.workflow.query.ProcessInstanceQuery.ROOT_PROCESS_INSTANCE_OID;

...
    /**
* Gets all process instances for ProcessOID of a process
*
* @param processId
* in model
* @param rootPoid
* root process instance oid
* @return all process instances matching process ID and root process OID
*/

@SuppressWarnings("unchecked")
public static final List<ProcessInstance> findAllProcessInstancesForProcessIdAndRootPoid(
String processId, long rootPoid) {
ProcessInstanceQuery query = ProcessInstanceQuery.findForProcess(processId);
query.where(ROOT_PROCESS_INSTANCE_OID.isEqual(rootPoid));
List<ProcessInstance> allProcessInstances = queryService.getAllProcessInstances(query);
return allProcessInstances;
}
I also added a sample test, which is at the moment only starting the Emergency Voting process and retrieves all started "Vote" subprocesses. To get the test running, you have to make sure, that the $JBOSS_HOME\client\jbossall-client.jar is on the classpath.
 public static void testEmergencyVoting() throws InterruptedException {
long votingProcessOID = startEmergencyVotingProcess();
//Wait for Subprocesses to be started
Thread.sleep(ProcessHelper.PROCESS_CHECK_RETRY_DELAY);
List<ProcessInstance> processInstances = ProcessHelper
.findAllProcessInstancesForProcessIdAndRootPoid(VOTING_PID, votingProcessOID);
LOG.info("Found "+ processInstances.size()+" Instances of Vote Subprocesses");
//TODO: real testcase to be implemented
}

-Larissa Werlein-

Custom Constraints with Grails

While Grails provides a very robust validation mechanism for domain objects, we encountered an issue where the required-ness of certain fields are dependent on the value of another field in the same object.

Enter the grails constraints plugin -- this allows you to create a custom constraint that is reusable in your application.

First install the plugin by executing the command
grails install-plugin constraints


Second, create a groovy file in the grails-app\utils folder with a name ending with 'Constraint.' This file should contain a closure named validate that returns a boolean value.

The closure has three parameters passed to it:
1. the value of the field on which the constraint was placed (val)
2. the instance of the object being validated (target)
3. a collection of validation errors (not used in example)

In addition, it implicitly has access to parameters passed to the constraint via the params property.

class CreditCardNumberRequiredConstraint {
static name = "ccReq"

def validate = { val, target ->
// find the payment method type value on the object
def paymentMethod
if (target.metaClass.hasMetaProperty("paymentMethod")) {
paymentMethod = target.paymentMethod
}

// cc number required, check if the value is populated
if (params.vals.contains(paymentMethod)) {
return val
}
// payment method type does not require cc number
else {
return true
}
}
}


Third, use the new constraint in your domain class. The default name is the camel-cased name of your groovy file, minus Constraint (i.e. - creditCardNumberRequired). This example has over-ridden the default by adding the static name line.
class Payment {
String name
String paymentMethod
String creditCardNumber

static constraints = {
name(nullable:false)
paymentMethod(nullable:false, inList:['AMEX', 'MasterCard', 'Check'])
creditCardNumber(ccReq:[vals:['AMEX', 'Mastercard']])
}
}

Finally, add an entry to the properties files under grails-app\i18n. The key for the entry should be of the format:

default.invalid.% camel-coded-constraint-name %.message

Using the sysconsole tool with ant

You can easily call all IPP-sysconsole commands as an ant script. For example drop/create the IPP schema:

<path id="infinity.tools.sysconsole.path">
<fileset dir="${local.dir.lib}" includes="*" />
<pathelement location="${jboss.home}/client/jbossall-client.jar" />
<pathelement location="${jboss.home}/client/log4j.jar" />
</path>
<target name="infinity-drop-schema" description="Drop Schema">
<java classname="ag.carnot.workflow.tools.sysconsole.Main"
classpathref="infinity.tools.sysconsole.path" fork="true">
<arg line="-f -dbtype ORACLE9i -dbdriver oracle.jdbc.driver.OracleDriver
-dburl ${audittrail.database.url} -dbuser ${audittrail.database.username}
-dbpassword ${audittrail.database.password} -password sysop dropschema" />
</java>
</target>
<target name="infinity-create-schema" description="Create Schema">
<java classname="ag.carnot.workflow.tools.sysconsole.Main"
classpathref="infinity.tools.sysconsole.path" fork="true">
<arg line="-f -dbtype ORACLE9i -dbdriver oracle.jdbc.driver.OracleDriver
-dburl ${audittrail.database.url} -dbuser ${audittrail.database.username}
-dbpassword ${audittrail.database.password} createschema" />
</java>
</target>

How to get the new project running

  • Checkout all 4 projects under ...stallion/apps/seattle in your workspace (as single projects)
  • Set JBOSS_HOME to your JBoss installation
  • Make sure JAVA_HOME is set
  • Create oracle user infinity/infinity and grant all rights (via web portal)
  • run build.xml target: installApp
  • This script
  1. -copies database and jms config to JBoss dir
  2. -copies db driver to JBoss dir
  3. -creates jackrabbit repository folder C:\umbroot\tools\jackrabbit\repository
  4. -copy jackrabbit files to JBoss
  5. -changes JBoss port to 8081
  6. -creates the audittrail
  7. -builds and deploys seattle ear
  8. -starts JBoss
  • Wait till JBoss is started
  • Afterwards the application should be accessible via http://localhost:8081/seattle/processPortal
  • Now run target "initializeApp"
  • This script
  1. -deploys the model
  2. -Creates users with role "Voter"
  3. -starts event and timer daemon

-Larissa Werlein-

Thursday, January 7, 2010

Universal IM Clients

To ease communication between developers while traveling, we are all using Yahoo! Messenger. While some people on our project already had accounts, I did not, thus when I created a new account I had a list of 3 contacts. Many of my other fellow work colleges use Google Talk, so if I wanted to communicate with them about best practices, or any other work related jabber, it was necessary for me to have to clients open. For some people this wouldn't be a problem, but for me it was a huge distraction. Enter Universal IM Clients. Old news to some, for me this revolutionary technology negated the need for me to have numerous blinking windows on my already busy monitor. I currently am running Pidgin, which I discovered today is rated the 2nd Best Universal Chat Client.

I know this is not the only solution available, and I'd be welcome in hearing about more technologies that help serve this purpose. Always looking for the best technology to solve problems! (Even though I'm using the 2nd best. )

-Brandy Brewster

Wednesday, January 6, 2010

Installing the Grails Security Plugin

To setup controller annotation based security, I'm following the plugin installation instructions detailed here.

Starting with:
grails install-plugin acegi

I used "InfinityUser" as my "User" class as User is a reserved word in Oracle. There are still places in the generated code where people/person is used instead of the name you pass.
# grails create-auth-domains InfinityUser Role Requestmap

Then, I generated Person/Role management support:
# grails generate-manager

I modified the SecurityConfig.groovy and deleted the ResourceMap domain, controller and views as directed in the tutorial.

I tested the app by starting it up and modified BootStrap.groovy to avoid retyping Roles and Persons in the GUI. It is very important to make your Roles begin with the word "ROLE"

new Role(authority:"ROLE_LOV_ADMIN",description:"Allows a user to modify the available List Of Values definitions.").addToPeople(new InfinityUser(username:"jdoe", userRealName:"John Doe",passwd:"81fe8bfe87576c3ecb22426f8e57847382917acf",enabled:true,email:"jdoe@gmail.com",emailShow:true,description:"An LOV Admin")).save()
new Role(authority:"ROLE_PAF_EDITOR",description:"Allows a user to modify draft Pre-Acceptance Forms.").addToPeople(new InfinityUser(username:"jsmith", userRealName:"Jane Smith",passwd:"81fe8bfe87576c3ecb22426f8e57847382917acf",enabled:true,email:"jsmith@gmail.com",emailShow:true,description:"A PAF Editor")).save()

Note the 'passwd' is "81fe8bfe87576c3ecb22426f8e57847382917acf". The password is "abcd" encoded by authenticateService.encodePassword(params.passwd) in PersonController.save()

Here is one of the places where the plugin fails if the Role.authority doesn't include 'ROLE'. When I tested the app I noticed there was a bug where all Roles would be removed when saving an InfinityUser. I tracked it down to InfinityUserController.update(). There is a line that removes all Roles:
Role.findAll().each { it.removeFromPeople(person) }
However, they weren't being added back in. This was a bug in addRoles(person)Adding the word 'ROLE' to your role names fixes it. However, there are other places in the plugin that rely on this convention.
    private void addRoles(person) {
for (String key in params.keySet()) {
//println "key="+key+" params.get(key)="+params.get(key)
// modified this line because it causes roles not to be added if they don't contain the word role
//if (key.contains('ROLE') && 'on' == params.get(key)) {
if ('on' == params.get(key)) {
// use Elvis '?' operator to avoid keys with "on" values that aren't Roles
Role.findByAuthority(key)?.addToPeople(person)
}
}
}
-Ben Hidalgo

JUnit Tests for IPP

I have started to write JUnit tests cases for our voting process. The current voting process has been implemented with our BPM tool, IPP. In the past to test code or model changes, I would need to redeploy the model and walk through the changes via the on-line portal. Although there are tools (Selenium for one) that can be used to test web applications by providing button clicking and web page display validation, they are limited in the fact that the range of what is tested is defined by the current logged in user. By using the api I can test my processes, activities, and the states of both simply by running a unit test. So instead of manually logging on, starting a voting process, and then validating that each user that should have a voting activity has one, a test is started that walks through this entire process via the IPP api and uses JUnit to assert the correct results.

1. Start the process:
ProcessInstance processInstance = workflowService.startProcess("VotingSystem",votingInformation,false);

2. Verify that activites are created for the correct number of voters:
ActivityInstanceQuery aiQuery = ActivityInstanceQuery.findAlive(processInstance.getProcessId(), "vote");
assertEquals("The number of activity instances in vote does not match",
voters.size(), qService.getActivityInstancesCount(aiQuery));

-Brandy Brewster

Issues with Grails and Ajax

Currently encountering an issue with the Grails gsp tag submitToRemote. The attributes defining javascript functions called at different points in the ajax call lifecycle, do not appear to invoke user defined javascript methods.

for example:

foo() isn't being invoked here
< onsuccess="foo();" url="[action:'fooAction']" value="Run Foo">

but the following alert will occur
< onsuccess="javascript:alert('hi');" url="[action:'fooAction']" value="Run Foo">

Adding to the confusion is the fact that Grails In Action states that the javascript method signature should define a parameter which contains the HttpXmlResponse object, something the documentation doesn't mention.

Strangely, the issue does not appear with other ajax tags like remoteLink and remoteFunction.

Switched Grails DataSource from hsqldb to Oracle

Yesterday, I switched the default Grails datasource that grails create-app generates into an Oracle datasource in the following steps:

1. Modify grails-app/conf/DataSource.groovy
2. Add the ojdbc14.jar to /lib
3. Install OracleXE
4. Create a database user and grant privileges

1: DataSource.groovy

dataSource {
pooled = true
driverClassName = "oracle.jdbc.OracleDriver"
}
...
development {
dataSource {
dbCreate = "create-drop" // one of 'create', 'create-drop','update'
url = "jdbc:oracle:thin:@localhost:1521:XE"
username = "scott"
password = "tiger"
}
}

4: User create script:
conn system/system@xe
drop user scott;
create user scott identified by tiger default tablespace users quota unlimited on users;
grant connect to scott;
grant create any table to scott;
grant create any view to scott;
grant create any sequence to scott;
grant create any index to scott;

-Ben Hidalgo