Using Spring to Manage JSF Beans

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.

About these ads

30 Responses to Using Spring to Manage JSF Beans

  1. Pingback: Integrating JSF and Spring « Cagatay Civici’s Weblog

  2. Matt Raible says:

    Looks useful – but how do you inject request parameters? In faces-config.xml, you can do:

    id
    #{param.id}

  3. Matt Raible says:

    Try that again:

    <managed-property>
    <property-name>id</property-name>
    <value>#{param.id}</value>
    </managed-property>

  4. Lars Ködderitzsch says:

    >Looks useful – but how do you inject request parameters? In faces-config.xml, you can do:

    One could extend a Springs org.springframework.beans.factory.config.PropertyPlaceholderConfigurer which accesses the RequestContext (org.springframework.web.context.request.RequestContextHolder#getRequestAttributes()) to resolve ${xyz}-like properties in the bean.
    Of course that would only work for Spring beans with “request”-scope.

  5. cagataycivici says:

    You got it Lars.

  6. Pingback:   links for 2007-09-12 by The Third Part

  7. Pingback: Usando o Spring para gerenciar beans do JSF at JavaServer Faces e outras coisas mais…

  8. terry says:

    I have try it, but there something make me puzzled. I use Spring’s IOC manage the bean, and put a JSF’s ActionListener in it. Then I click a button on the page to trigger the Listener, it carried out twice!!!Besides when I refresh the page, it also run two times!!!! It’s weird!!Can you help me~~~Thank you.
    (Myfaces1.20+Spring2.06)

  9. SpecialAgent says:

    Hey there,

    nice soltion. In my simple test app it works pretty fine. But I don’t trust it if my app is growing big. Im not a JSF expert, but what about the other stuff that I can configure in the faces-context.xml, managed-bean tag?

    Do you know about the MyFaces Orchestra project? It uses a similar solution and has some other stuff… maybe this is the better way?

    What do you think?

  10. Paulo Melo says:

    Hello Guys! When i deployed my applicattion in TomCat, the same throw the following error:
    SEVERE: Error listenerStart

    Why?

    What the spring version used in example? What the JSF implementation used in example?

    Thank you all!

  11. prabhanjan says:

    gr8 article

  12. pal says:

    Hello.
    Pretty cool stuff. I followed the steps, but my saveDVD-Method is not called (without error messages). Any ideas why?

    I appreciate any hints!

  13. bon quan says:

    @ Pal
    I run into the same problem.
    When you change applicationContext.xml,
    you have to clean the tomcat work directory.Then it works

    @ Cagataycivici
    Really cool stuff

  14. Mustafa Sait Özen says:

    What about JSF Bean’s scope? This method only works with JSF bean in request scope, doesn’t it?
    If there is a way change JSF bean scope by using this method, how can it be implemented?

  15. Adam Simone says:

    Mustafa, you can change the scope of bean at applicationContext.xml.

  16. Pingback: Springification « Standard Portlet Collection Project 7

  17. Pingback: (Not) Simple JSF+Spring « My Name is Gunna

  18. pok says:

    How will this translate in my applicationContext.xml?

    baseBean
    com.naptosa.web.jsf.BaseBean
    application

    visit
    #{sessionScope.visit}

    Will it be something like?

  19. Engin Ertilav says:

    hi,

    is there a difference between the request scope of JSF managed and Spring managed beans? here is an example:

    i have a backing bean named accountbacking. and this bean has an another bean named account.

    i define both them in spring context as:

    at JSF(iceface components) page i am using valuechangelistener of an item. whenever this event is invoked these beans are re-created. i have defined init methods to observe this. they both called at page start and event trigger.

    then i moved accountbacking bean to faces-config file as:(account bean remains at spring context)

    accountbacking

    com.mypack.AccountBacking

    request

    account
    #{account}

    at this time i observed that accountbacking is created at page startup, so does account bean. at valuechangelistener they don’t re-created.

    so i have an opinion of difference between jsf and spring request beans. am i missing something?

    thanks in advance.

    Regards. Engin

  20. Engin Ertilav says:

    is there a problem with my use of code tag. some of my previous posting did not show up correct.

  21. Pingback: Annotate JSF Beans with Spring 2.5 « Cagatay Civici’s Weblog

  22. Seshu says:

    When i try to deploy this on Weblogic 8.1 i get java.lang.NoClassDefFoundError: javax/servlet/ServletRequestListener

    is it because of servlet spec difference?

  23. Pingback: Rafael Ponte » Blog Archive » Aproveitando os beans do Spring em suas páginas JSF

  24. Pingback: Using Spring to Manage JSF Beans « Cagatay Civici’s Weblog

  25. Omar says:

    Really nice post, it’s just what I was looking for. The project that I’m working on has been evolving for some stages until I get this post.

    – First (and uglier), the service property was setted in the constructor by an ApplicationContext instance. Notice that I said setted not injected.
    – Second, the first approach you mentioned before about using spring’s jsf integration between service beans and jsf managed beans.
    – Third and last, delegating all managed beans to spring’s application context and using jsf framework for the view part.

    I think that this is a more natural way of manage pojos-based controllers as a middleware, even better than spring-mvc’s approach.

  26. Sumanta Ghosh says:

    “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.”

    – Can we make the Backing Beans Spring Transaction managed – in that case it will be very much useful to implement simple CRUD functionalities.

  27. sandeep bhandari says:

    what is the advantage of keeping the backing bean entry in the spring.xml instead of facesConfig.xml.I am new to JSF.Please elaborate.

  28. Deep says:

    Hi,

    I am developing one application using Richface,JSF and Spring. And thanks to cagatay, I followed this spring-JSF integration approach till success. The application is up and running fine but I have now some issue with the object state. The values set in object in one user session is visible in another user session. i.e. objects are holding the values from different session. I defined the bean scope as “session” in application context but still its behaving like an object in application scope.

    Can anyone please help me on this?

    Thanks,
    Deep

  29. Balkrishan Nagpal says:

    Hi
    Lars Ködderitzsch told, the way to do some thing like

    id
    #{param.id}

    in spring. I am not getting how to do that. can you please post some sample code.
    That will be really helpful.

    Thanks in Advance

Follow

Get every new post delivered to your Inbox.

Join 110 other followers

%d bloggers like this: