Friday, July 31, 2009

Grails: use a session scoped bean in a singleton bean

In my project, I had to change the scope of two of my services from the default scope (singleton) to as session scope. With grails, this is fairly easy, for a service, you simply have to add the following line in you service class:
static scope = 'session'

Now there's a problem if you use this service in a singleton scoped bean like a filter or a taglib for example. The problem is that spring will try to instantiate the singleton bean on startup, then it will try to create the service to inject it in the singleton, but as this does not occur in a session, spring cannot create the service and fails with a BeanCreationException. Anyway, even if the singleton was created within a session, the same service would be used for all sessions as the singleton wouldn't be re-injected for each session.

Fortunately, spring comes with the handy ScopedProxyFactoryBean. As its name implies, it is a proxy factory bean for scoped object. To use it, you first have to declare the service in grails-app/conf/spring/resources.groovy for an application or in the doWithSpring method of the plugin descriptor for a plugin:
sessionScopedService(SessionScopedService) { bean ->
bean.scope = 'session'

At the same place, declare the proxy factory bean:
sessionScopeProxy(org.springframework.aop.scope.ScopedProxyFactoryBean) {
targetBean = 'sessionScopedService'
proxyTargetClass = true

You can now use the sessionScopeProxy instead of the sessionScopedService in you singleton bean. It will transparently proxy to a session scoped SessionScopeService bean.

Wednesday, July 29, 2009

Grails: externalize configuration with jndi

Grails provides a very handy way to set configuration with Config.groovy file.

When developing internal applications, this solution is perfect especially with per-environment configuration.

For packaged third-party applications or complex multi-environment sites, it's harder to get a maintainable solution. Grails provides the grails.config.locations setting to load configuration from files possibly out of the application war file. The problem with this solution is to get a flexible cross-appserver cross-platform way to provide the custom config file to the application.

The solution presented here is to use jndi.

Let's say you want to provide a web service URL to an application, it will be made available to the application by the application server.

We will store the web service URL at the jndi name java:comp/env/wsUrl.

To access the value in the grails application, we will use a bit of spring magic by declaring a bean in grails-app/conf/spring/resources.groovy:

beans = {
jndiName = 'java:comp/env/wsUrl'

This will make the bean available with the value read from jndi, to use it, simply declare a variable named wsUrl in an injected object (controller, service...):
def wsUrl

For the development environment, if you use jetty, the value can be set by creating the web-app/WEB-INF/jetty-env.xml file with the following content:
<?xml version="1.0" encoding="UTF-8"?>
<configure class="org.mortbay.jetty.webapp.WebAppContext">
<new id="wsUrl" class="">
<arg type="boolean">true</arg>

If you deploy to a tomcat environment, you can set the value by creating a file conf/Catalina/localhost/<context-name>.xml in your tomcat installation containing:
<?xml version="1.0" encoding="UTF-8"?>
<Environment name="wsUrl" value=""
type="java.lang.String" override="true"/>

If the parameter has to be set in multiple applications in the same tomcat instance, it can be declared in conf/server.xml file and referenced in each application .xml file with the ResourceLink tag.

Saturday, July 25, 2009

BAF: soon something to show

It has been a long time since I last blogged. I was working hard on my new project: BAF.

BAF stands for Business Application Framework. As the name implies, it is a framework for building business applications. Of course it is built on top of grails.

People working with legacy 5250 application are used to have single sign-on, security management, modular applications. BAF is about bringing that (and more in the future) to web applications.

BAF is still in development, but you can already look at the git repository.

For more information, check the BAF page.