Archive for the ‘Grails’ Category

Nested set plugin for Grails

We are happy to announce that our NestedSet plugin for the Grails framework has been released. The plugin creates a hierarchical structure on top of plain database records. A description of the “nested set” data structure can be found in Wikipedia.

The NestedSet Grails plugin is

  • non-intrusive – it does not change your data model, just adds one table
  • easy to use – just add “static nestedSet = true” to the domain class
  • versatile – it supports multiple hierarchies

Installation instructions and usage details can be found at the NestedSet plugin homepage.

If you find it useful, tell your friends. If there is a problem, please register at grails.cz and create a new issue.

Playing with Grails application configuration

This small tutorial will show how to create a configuration file and how to manage configuration of your Grails application. It will show how to

  • Access configuration parameters
  • Create external configuration
  • Configure Spring for different environments
  • Create a new environment

Accessing configuration parameters

The configuration of Grails is stored in grails-app/conf directory. Parameters are stored in configuration files in “plain text way”

app.default.user = "tester"

or in “structured way”

app{
	default{
		user = "tester"
	}
}

In an application, one can access the parameters easily. Just import the correct class and ask it the correct question.

import org.codehaus.groovy.grails.commons.ConfigurationHolder
 
class TestController {
	def query = {
		render ConfigurationHolder.config.app.default.user
	}
}

The example above should render the string “tester”. Moreover, in the configuration files, one can easily define distinct config values for each of three different environments – production, development and test.

environments {
	production {
		grails.serverURL = "http://www.changeme.com"
	}
	development {
		grails.serverURL = "http://www.do-not-change.cz"
	}
	test {
		grails.serverURL = "http://www.just-for-test.de"
	}
}

External configuration

The configuration mechanism of Grails is nice, but there is a small trouble. The configuration files are compiled and packed into the deployment package (WAR) during project build phase. However, one usually does not want to rebuild the whole application just to change say a database password. So, how to do it?

The first step is to create an external configuration file. Let’s name it externalConfig.groovy. Its structure will be the same as the structure of the other configuration files – “flat text” or “structured”.

Now, how do you tell Grails to find and use it? Adding the following code to the beginning of your config.groovy will do the trick. It expects that there is an OS environment variable MY_GREAT_CONFIG that points to the configuration file.

if(System.getenv("MY_GREAT_CONFIG")) {
	println( "Including configuration file: " + System.getenv("MY_GREAT_CONFIG"));
	grails.config.locations << "file:" + System.getenv("MY_GREAT_CONFIG")
} else {
	println "No external configuration file defined."
}

Spring configuration

The grails-app/conf/spring/resources.groovy file gives the developer a convenient way to define beans. Distinguishing environments is slightly more complex than in other configuration files, but still elegant.

switch(GrailsUtil.environment) {
	case "production":
		myBean(package.BeanClass, 1, "prod")
		break
	case "test":
		myBean(package.BeanClass, 1, "test")
		break
	case "development":
		myBean(package.BeanClass, 1, "dev")
		break

Configuration parameters can be used here the same way as in the controller example above.

myBean(package.BeanClass, 1, ConfigurationHolder.config.app.default.user)

Adding more environments

It might seem that the development, test and production environments are just enough. Yes, that is true for most basic scenarios. However, if you develop for a large company with sophisticated deployment procedures, there are typically several production-level application server environments (one for user acceptance testing, one for system patch analysis and performance testing, one for production etc.), all of them corresponding to the Grails “production” environment.

How to address this scenario? Easily. Just introduce another environment into your configuration

environments {
	production {
		grails.serverURL = "http://www.changeme.com"
	}
	development {
		grails.serverURL = "http://www.do-not-change.cz"
	}
	test {
		grails.serverURL = "http://www.just-for-test.cz"
	}
	uat {
		grails.serverURL = "http://www.uat-testing-environment.cz"
	}
}

and run the application or create a war file with an extra parameter

	grails -Dgrails.env=uat war
	or
	grails -Dgrails.env=uat run-app

Configuration and usage of Gldapo in a Grails project

Configuration and usage of Gldapo in a Grails project

Gldapo is a groovy library for object oriented LDAP access. “The Gldapo is to LDAP what GORM is to SQL”.

Gldapo is packaged in Grails LDAP plugin, its installation is easy. In the root of your Grails project run command:

grails install-plugin ldap

Configuration

The Gldapo is configured in the Config.groovy file. Here follows an example.

ldap {
    directories {
        user { 
            url = "ldap://ldap.zmok.net"
            base = "OU=Users,DC=zmok,DC=net"
            userDn = "CN=usernameToLogToLdap,OU=Users,DC=zmok,DC=net"
            password = "passwordToLogToLdap" 
            searchControls { 
                countLimit = 40 
                timeLimit = 600 
                searchScope = "subtree" 
            }
        }
        group { 
            url = "ldap://ldap.zmok.net"
            base = "OU=Groups,DC=zmok,DC=net"
            userDn = "CN=usernameToLogToLdap,OU=Users,DC=zmok,DC=net"
            password = "passwordToLogToLdap"
            searchControls { 
                countLimit = 40 
                timeLimit = 600 
                searchScope = "subtree" 
            }
        }
    }
 
    schemas = [ 
        net.zmok.ldap.User,
        net.zmok.ldap.Group
    ]
 
}

The configuration is self-explaining, except of the schemas part. This is where the magic starts. The classes are object representation of the LDAP entities. So, let’s look how the classes are defined.

package net.zmok.ldap
import gldapo.schema.annotation.GldapoNamingAttribute
 
class User{
	@GldapoNamingAttribute
	String cn
	String title
	String displayName
	Set memberOf
}
package net.zmok.ldap
import gldapo.schema.annotation.GldapoNamingAttribute
 
class Group{
	@GldapoNamingAttribute
	String cn
	Set members
	@GldapoSynonymFor("mgr")
	String manager
}

Here, @GldapoNamingAttribute is mandatory and defines the key of the entity. The @GldapoSynonymFor redefines the LDAP names to human-readable format. In our case mgr will be translated to manager.

Manipulation

Usually, one needs to find a few records in an LDAP directory and do something with them. Lets say we need to find members of groups named like “Groovy*” (means GroovyProgrammers, GroovyFans, GroovyHaters) and their managers.
The Gldapo offers findAll method similar to GORM. So, here is the code to list them:

Group.findAll( directory: "group", filter: "(cn=Groovy*)" ).each{ group ->
	def groupName = group.cn
	group.members.each{ member ->
		def user = User.find( directory:"user", filter:"(cn=${member})")
		println "User ${user.displayName} managed by ${group.manager} is member of ${groupName}."
	}
}

Pretty easy, isn’t it? The User and Group classes are similar to GORM classes, so one can create, update, move, replace, delete… and much more. For details see http://http://gldapo.codehaus.org/schemaclasses/entries.html.

Grails RichUI - Incorrect international characters of the month names

I am working on a small project and I decided to use RichUI plugin do display a timeline.
The plugin is just great and working like a charm. If you want to try it, this tutorial is a very good one.

The english version works perfectly, but I have found a small bug in the czech localization. The czech characters were displayed incorrectly.
The whole page, including data of the timeline, was using utf-8 encoding (it was specified in the heading of the page), but the names of the months were in cp1250.

The problem lays in the source code of the RichUI plugin (I guess). A file with the czech names of the months was saved as cp1250 file, not as a utf-8 file.
So, the solution is simple. Change character set of the localization file

to utf-8 and save it.

Do not forget to delete

Update: The bug has been fixed in version 0.6. See Jira.

Web services in Grails

This article summarizes my experience with web services in Grails (and also Groovy). It will focus the on client side –
consuming web services. If you are looking for server size – providing services, you can use plugins like Metro or XFire.

Options

Once you want to create a web service client in pure groovy, you do not have much options. I have found just two libraries: Groovy SOAP and Groovy WS.

The first one is a deprecated module, so one have to use the Groovy WS.

Sisyphean challenge

Libraries

Making it running is a hard job. There are handy examples on the home page of the Groovy WS, but none of the examples was working. I spent significant amount of time to find out what is the problem. I was receiving this strange error message:

	Oct 26, 2008 9:48:19 PM org.apache.cxf.bus.spring.SpringBusFactory createBus
WARNING: Failed to create application context.
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.apache.cxf.wsdl.WSDLManager' defined in class path resource [META-INF/cxf/cxf.xml]: Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [org.apache.cxf.wsdl11.WSDLManagerImpl]: Constructor threw exception; nested exception is java.lang.ClassCastException: org.apache.xerces.jaxp.DocumentBuilderFactoryImpl
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:881)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:837)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:440)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory$1.run(AbstractAutowireCapableBeanFactory.java:409)
        at java.security.AccessController.doPrivileged(Native Method)
 
 
	blah blah blah

After investigation I did find that the problem is with libraries. The groovy WS library does not like xerces and xml-apis libraries.

SSL

The second difficulty was SSL. I do not remember details. It was somehow unable to download WSDL over SSL. It was necessary to download it and store into file system.

Compatibility

GroovyWS uses the Apache CXF libraries and they do not support RPC/Encoded web services.

java.lang.RuntimeException: Error compiling schema from WSDL at {https://my.url?wsdl}: undefined simple or complex type 'soapenc:Array' 
at org.apache.cxf.endpoint.dynamic.DynamicClientFactory$InnerErrorListener.error(DynamicClientFactory.java:418)

Conclusion

I did not find the groovyWS to be a matured library. It is possible to use it for consuming web services, but only for the simplest ones. As soon as there is SSL, authentication… one have to use a “bigger hammer”. In my case, the hammer was Netbeans, that generated all the necessary classes.

Last, but not least. At the beginning I was not really sure what is the problem. I was suspecting the web services not to work correctly. So, I did use the soapUI testing tool to check that the web services are alive.