Using Spring to Manage JSF Beans - No Fluff Just Stuff

Using Spring to Manage JSF Beans

Posted by: Cagatay Civici on September 10, 2007

The traditional way to integrate JSF and Spring was to define JSF beans in faces-config as managed beans and refer to the spring beans using the managed-property configuration. With the help of the spring’s delegatingvariableresolver the managed property is resolved from spring application context and JSF’s IOC injects the bean to the JSF Managed bean instance. I’ve written an article it about this way before.First approach is modelled as follows

jsfspring1.jpg

And the better approach described in this article

jsfspring2.jpg

Although the way described above sounds nice at first glance, I believe it has a major issue, do we really need to have two IOC containers in your application to do dependency injection. I mean why not just one right? Actually this was necessary before spring 2 but with the addition of custom scopes, a better way for integration has come up. Now spring has the ability manage the JSF backing beans in it’s container, this results in a faces-config.xml with no managed-bean configurations. I’ve created a simple DVDStore application to show a sample configuration. Let’s start with the domain class DVD


package com.cc.blog.dvdstore.domain

public class DVD {

	private String title;
	private Integer discs;

	public DVD() {

	}

	public DVD(String title, Integer discs) {
		this.title = title;
		this.discs = discs;
	}

	public Integer getDiscs() {
		return discs;
	}

	public void setDiscs(Integer discs) {
		this.discs = discs;
	}

	public String getTitle() {
		return title;
	}

	public void setTitle(String title) {
		this.title = title;
	}

}

DVDService lives at service layer


package com.cc.blog.dvdstore.service;

import com.cc.blog.dvdstore.domain.DVD;

public interface IDVDService {

     public void saveDVD(DVD dvd);

}

package com.cc.blog.dvdstore.service;

import com.cc.blog.dvdstore.domain.DVD;

public class DVDService implements IDVDService{

	public void saveDVD(DVD dvd) {
		//Refer to a DAO or repository implementation and persist the DVD
	}

}

And the JSF Backing to handle the creation of a new DVD record


package com.cc.blog.dvdstore.view;

import com.cc.blog.dvdstore.domain.DVD;
import com.cc.blog.dvdstore.service.DVDService;

public class SaveDVDBean {

	private DVD dvd;
	private IDVDService service;

	public SaveDVDBean() {
		//NOop
	}

	public DVD getDvd() {
	    if(dvd == null)
	       dvd = new DVD();

		return dvd;
	}

	public void setDvd(DVD dvd) {
		this.dvd = dvd;
	}

	public IDVDService getService() {
		return service;
	}

	public void setService(IDVDService service) {
		this.service = service;
	}

	public String save() {
		service.saveDVD(dvd);

		return null;
	}

}

Fragment from the JSF page backed by SaveDVDBean,


<h:form>
	<h:panelGrid columns="2">
		<h:outputLabel for="title"></h:outputLabel>
		<h:inputText id="title" value="#{saveDVDBean.dvd.title}"></h:inputText>

		<h:outputLabel for="discs"></h:outputLabel>
		<h:inputText id="discs" value="#{saveDVDBean.dvd.discs}"></h:inputText>
	</h:panelGrid>
	<h:commandButton value="Save" action="#{saveDVDBean.save}"></h:commandButton>
</h:form>

web.xml


<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd" version="2.4">

<context-param>
	<param-name>contextConfigLocation</param-name>
	<param-value>/WEB-INF/applicationContext.xml</param-value>
</context-param>

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

<servlet>
	<servlet-name>Faces Servlet</servlet-name>
	<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
	<load-on-startup>1<load-on-startup>
</servlet>
<servlet-mapping>
	<servlet-name>Faces Servlet</servlet-name>
	<url-pattern>*.jsf</url-pattern>
</servlet-mapping>
</web-app>

applicationContext.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:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
default-autowire="byName"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd">

	<bean id="dvdService" class="com.cc.blog.dvdstore.service.DVDService"></bean>

	<bean id="saveDVDBean" class="com.cc.blog.dvdstore.view.SaveDVDBean" scope="request">
		<property name="service">
			<ref bean="dvdService"/>
		</property>
	</bean>
</beans>

faces-config.xml


<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE faces-config PUBLIC "-//Sun Microsystems, Inc.//DTD JavaServer Faces Config 1.1//EN"

"http://java.sun.com/dtd/web-facesconfig_1_1.dtd"><faces-config xmlns="http://java.sun.com/JSF/Configuration">
	<application>
		<variable-resolver>
			org.springframework.web.jsf.DelegatingVariableResolver
		</variable-resolver>
	</application>
</faces-config>

As seen above, faces-config has no managed-bean stuff, instead saveDVDBean is defined in spring’s application context in request scope. So here is why using Spring’s IOC to manage JSF backing beans is cool:)

- With spring aop, you can apply aop tricks to your jsf beans, for example you can do aop audit logging based on jsf events like SaveDVDBean’s save method. Add an annotation like @Auditable to the save() method, write an interceptor and then you can log who and when tried to save a dvd.
- Use autowiring on JSF beans
- Constructor Injection
- Lifecycle events like afterPropertiesSet using lifecycle interfaces or configurations like init-method, destroy-method
- Much more actually, see spring ioc container documents for more.

Cagatay Civici

About Cagatay Civici

Cagatay Civici is a member of JavaServer Faces Expert Group who defines the JSF specification(JSR-314), the founder and project lead of popular PrimeFaces Component Suite and PMC member of open source JSF implementation Apache MyFaces. He's a recognized speaker in international conferences including Jazoon, W-JAX, JSFSummit, JSFDays and many local events such as JUGs. Cagatay is also an author and technical reviewer of several books regarding web application development with Java and JSF. As an experienced trainer, he has trained over 100 java developers on Java EE technologies mainly JSF, Spring and JPA. Cagatay is currently working as a consultant for Prime Technology in Turkey.

Why Attend the NFJS Tour?

  • » Cutting-Edge Technologies
  • » Agile Practices
  • » Peer Exchange

Current Topics:

  • Languages on the JVM: Scala, Groovy, Clojure
  • Enterprise Java
  • Core Java, Java 8
  • Agility
  • Testing: Geb, Spock, Easyb
  • REST
  • NoSQL: MongoDB, Cassandra
  • Hadoop
  • Spring 4
  • Cloud
  • Automation Tools: Gradle, Git, Jenkins, Sonar
  • HTML5, CSS3, AngularJS, jQuery, Usability
  • Mobile Apps - iPhone and Android
  • More...
Learn More »