Loading...

August 26, 2009

Grassroots Groovy: the Spring Route (part 1)

We can introduce Groovy into our projects at grassroots level. If we are already using Spring on our project we can use Groovy to define classes and define them in our Spring configuration files. It is even possible to have Groovy code in the configuration files themselves. The nice thing about the Groovy support in Spring is that we can define a reload interval on Groovy source files. This means new versions of the Groovy source file are automatically picked up and ready to be used.

Let's see how we can leverage the Groovy support with Spring by a little example. We have a simple Data Access Object (DAO) class and interface to get a list of Person objects. The DAO class is used by a service to get any person without an e-mail address. We are going to write the service in Groovy. All these classes are connected by a Spring configuration file. We start with a simple Person class to hold a username and e-mail address:

package com.mrhaki.blog;

public class Person {

    private String username;
    private String email;

    public Person() {
    }

    public Person(String username, String email) {
        this.username = username;
        this.email = email;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    @Override
    public String toString() {
        return "[Person: username=" + username + ", email=" + email + "]";
    }
}

Next we define a PersonDao interface and a Java implementation class PersonDaoImpl:

package com.mrhaki.blog;

import java.util.List;

public interface PersonDao {

    List<Person> list();
}
package com.mrhaki.blog;

import java.util.ArrayList;
import java.util.List;

public class PersonDaoImpl implements PersonDao {

    public List<Person> list() {
        final List<Person> result = new ArrayList<Person>();
        result.add(new Person("mrhaki", "test@email.com"));
        result.add(new Person("test", null));
        return result;
    }
}

We have our DAO part ready. It is time to create the interface PersonService:

package com.mrhaki.blog;

import java.util.List;

public interface PersonService {
    List<Person> listPersonsNoEmail();
}

Notice we only have created plain old Java classes, no Groovy to be seen. But that changes when we create the Spring configuration file. To use Groovy support we must have the Groovy libraries in our classpath, and we must use the lang namespace in the configuration file. First we write the Groovy code in our Spring configuration file. Later on we move the code from the configuration file to a separate source file. We create the file spring-config.xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:lang="http://www.springframework.org/schema/lang"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
       http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang-2.5.xsd">

    <bean id="personDao" class="com.mrhaki.blog.PersonDaoImpl"/>

    <lang:groovy id="personService">
        <lang:inline-script>
            <![CDATA[
import com.mrhaki.blog.*

class PersonServiceImpl implements PersonService {

    def personDao

    List<Person> listPersonsNoEmail() {
        personDao.list().grep{ !it.email }
    }
}           
            ]]>
        </lang:inline-script>
       <lang:property name="dao" ref="personDao"/>
    </lang:groovy>

</beans>

At lines 9-25 we define the Groovy script which implements the PersonService interface. At line 9 we assign a value to the attribute id, so we can get the resulting object. The Groovy script has one property personDao and at line 24 we assign our Java DAO object to this property. The implementation method is simple and Groovy.

We are ready to use our Groovy service in a Java application:

package com.mrhaki.blog;

import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.context.support.ApplicationContext;

public class SpringApp {

    public static void main(String[] args) {
        final ApplicationContext context =
                new ClassPathXmlApplicationContext("classpath:com/mrhaki/blog/spring-config.xml");
        final PersonService service = (PersonService) context.getBean("personService");

        assert 1 == service.listPersonsNoEmail().size();
        assert "test".equals(service.listPersonsNoEmail().get(0).getUsername());
        assert null == service.listPersonsNoEmail().get(0).getEmail();
    }

}

We can run the application SpringApp and if we enable assertions we don't get any errors. Our Groovy code is invoked correctly and in the Java code we cannot see the service is implemented in Groovy. We are going to make an adjustment to the Spring configuration file. We move the script in the file to a separate source file PersonServiceImpl.groovy. And we use the attribute refresh-check-delay to define a reload interval for the source file. Spring will check if the file has changed and if so will load the new script.

package com.mrhaki.blog

class PersonServiceImpl implements PersonService {

    def personDao

    List<Person> listPersonsNoEmail() {
        personDao.list().grep{ !it.email }
    }
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:lang="http://www.springframework.org/schema/lang"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
       http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang-2.5.xsd">

    <bean id="personDao" class="com.mrhaki.blog.PersonDaoImpl"/>

    <lang:groovy id="personService" refresh-check-delay="3000"
        script-source="classpath:com/mrhaki/blog/PersonServiceImpl.groovy">
       <lang:property name="dao" ref="personDao"/>
    </lang:groovy>

</beans>

In this post we have seen how easy it is to integrate Groovy code in our Java based project using Spring. In a next post we see how we can create the Spring configuration files in a Groovy way.