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





JSF and Spring Security (Acegi) using facelets

26 03 2009

Two tips for the people who is fighting with these technologies:

1. Implement the login page: here you have a great tutorial that explains how to implement a login page in JSF using Spring Security in only few lines of code.

2. Somebody is implementing the tags for jsf. You can try his library : BodyGuard





Spring MVC 3.0

11 03 2009

I found two interesting presentations of Spring MVC 3 (part of Spring Framework, still in RC phase)
Slides
and a second presentation in pdf

The big improvement is the full support of REST and logical URI parameters. Spring EL is now available and there is no more dependency with other EL libraries (JBoss and OSGI).





Using Spring with JSF – the managed bean – tutorial

6 03 2009

Two J2EE technologies are becoming dominant in the Java environment: Spring and Java ServerFaces.
Spring beans could be easily integrated in a JSF project. Spring Beans can coexists with JSF managed beans or interact directly with the view.

The steps necessary to use Spring in a JSF projects are the following:

Libraries
Spring libraries must be accessible :)

web.xml
In web.xml you have to declare your spring listener:

<listener>
<listener-class>
    org.springframework.web.context.ContextLoaderListener
  </listener-class>
</listener>

To use the request values between the view (jsp/jsf) ad the bean you have to add a second listener:

<listener>
<listener-class>
org.springframework.web.context.request.RequestContextListener
</listener-class>
</listener>

faces-config.xml
In faces-config.xml usually you define the managed beans. To use spring beans you have to add the following lines:

<application>
<variable-resolver>
org.springframework.web.jsf.DelegatingVariableResolver
</variable-resolver><code>
</application>

applicationContext.xml
In the applicationContext.xml you have to declare your beans like a standard Spring application, the only difference is the property scope:

<bean name ="personMB" class="ch.genidea.ofac.web.jsf.Person" <strong>scope="request"</strong>>
<property name= ... />
</bean>

Usually the scope property is set as singleton (default). For the web application you have 3 possibilities:

  • request: Scopes a single bean definition to the lifecycle of a single HTTP request; that is each and every HTTP request will have its own instance of a bean created off the back of a single bean definition.
  • session: Scopes a single bean definition to the lifecycle of a HTTP Session.
  • global session: Scopes a single bean definition to the lifecycle of a global HTTP Session. Typically only valid when used in a portlet context.

page.jsp

In your page you can call the bean directly :

<h:outputText value="First name"/> <h:inputText value="#{personMB.firstName}" id="personName"/>
<h:outputText value="Family name"/> <h:inputText value="#{personMB.lastName}" id="personFamilyName"/>




JSF: commandLink and datatable a small nightmare

26 06 2007

Many developers had problems using a commandLink in a column’s datatable.
Often when the user clicks on the link the backing bean method linked by the action is not called.

In the picture the first icon edits and the second delete the row …

Row of Datatable

According to Sun this is a feature and it will not be solved.

The most used workaround is to place the managed bean with the methods in the session scope :(

You can find a good explanation of the problem and an alternative solution here:
http://typo.ars-subtilior.com/articles/2007/02/07/jsf-datatable-and-commandlink