Use Groovy has Spring bean in a JSF web application

1 04 2009

It’s easy and powerful use Groovy classes in your Java web application using the Spring Framework. Here you can find a tutorial.

In my last project I had to scan a complex xml file and copy the information to a database. A Java class (using org.wc3.dom.* and DocumentBuilder) did the work but the hundreds lines of code were complex and not easy to maintain.

Ex.

DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder        docBuilder        = docBuilderFactory.newDocumentBuilder();
doc = docBuilder.parse(fileName);
doc.getDocumentElement().normalize();
NodeList listOfEntries = doc.getElementsByTagName("entry");
for (int s = 0; s < listOfEntries.getLength(); s++) {
  Node firstEntityNode = listOfEntries.item(s);
  if (firstEntityNode.getNodeType() == Node.ELEMENT_NODE) {
  ListEntry entry              = new ListEntry();
  Element   firstEntityElement = (Element) firstEntityNode;
  NodeList  uidList            = firstEntityElement.getElementsByTagName("uid");
  ...

For this reason I decided to integrate groovy in the Spring-JSF application, Groovy has the XMLSlurper class that allows to easily access an XML file like if it is a collection of classes.

You can see here a tutorial for SMLSlurper.

In my application the role of the first Groovy class were the following:

  • accept 2 parameters from a traditional java class (xml file address and an integer parameter)
  • process the xml file
  • use 2 existing Java classes
  • return an ArrayList of custom objects with the values found in the list

Tasks:

1. add the groovy jar to the libraries of your application

2. create a traditional Java Interface

package ch.genidea.checknames.importer;
import java.util.List;

import ch.genidea.checknames.model.ListEntry;
import ch.genidea.checknames.model.SourceList;

public interface Parser {
    List parse();
    void setFilename(String filename);
    void setSourceList(SourceList sourceList);
}

I had to declare the setters for the 2 variables to import in the groovy class.

3. create the groovy class in the classpath. If you are using maven add it to the src/main/resources directory.

Ex.

package ch.genidea.checknames.importer

import java.util.List;
import ch.genidea.checknames.model.ListEntry;
import ch.genidea.checknames.model.SourceList;

public class ParserImpl implements ch.genidea.checknames.importer.Parser{
    String filename
    List <ListEntry> result
    SourceList sourceList

    public List<ListEntry> parse(){
        def pers=new XmlSlurper().parse(new File(filename))

        List <ListEntry> result = new ArrayList<ListEntry>()
        def allEntry = pers.Entry

        allEntry.each{
                 result.add(addEntry(it))
                 it.akaList.aka.each{
                 result.add(addEntry(it))
                 }
        }
        return result
    }
    ListEntry addEntry(def it)
    {
            ListEntry entity = new ListEntry()
             entity.uid = (it.uid.text() as Integer)
             entity.sourceList=sourceList
             entity.familyName = it.lastName.text()
             entity.firstName = it.firstName.text()
             return entity
    }

    void setFilename(String filename)
    {
        this.filename = filename
    }
    void setSourceList(SourceList sourceList)
    {
        this.sourceList = sourceList
    }

}

In few lines the class did the same work of hundreds of lines of code of the previous implementation :)

In this groovy class we use ListEntry and SourceList that are traditional java classes and we return a List<ListEntry> object

4. Declare the bean in Spring


<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:lang="http://www.springframework.org/schema/lang"
 ...
http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang-2.5.xsd"
...
>
<lang:groovy id="parser" script-source="classpath:ch/genidea/checknames/importer/ParserImpl.groovy" />

<bean name = "listImportService" class="ch.genidea.checknames.lists.service.ListImportServiceImpl">
<property name="parser" ref="parser"></property>
</bean>

 

5. use the groovy class in your sourcecode :)

parser.setFilename(fileSource);
parser.setSourceList(sl);
List<ListEntry> list = parser.parse();

The only drawbacks I had are:

  • with Eclipse is not easy to debug groovy, but I used the groovyconsole to test rapidly the changes
  • 4MB added using the groovy-all.jar

Small issues compared to the great benefits of having less and more readable codeeasy a