Injecting Spring Beans into JSF 2 @ManagedBean Classes

This particular example is taken from some PoC work done with JSF 2 and Spring 3 running within a Tomcat 6 server (on JDK 5). The reason I wanted to inject Spring references into my JSF managed beans was both for ease of use, and because we haven’t made a decision architecturally (yet) to use JAX-WS or Hessian web services, and the only change would be the Spring configuration of the service definition.

The issue I was seeing was that the @ManagedProperty annotation was not being handled correctly by the application server when the managed bean was created during the JSF lifecycle. At the point that the managed bean class was created Tomcat threw a ClassNotFoundException on org.apache.AnnotationProcessor. After searching the web for similar references I tried unsuccesfully to add catalina.jar to the classpath of Tomcat but this caused even more issues.

I then attempted to get Spring to manage the bean, and found that JSF is able to delegate resolution of managed beans to an external resolver if it is configured correctly. In order to achieve this functionality the following needs to be done: 

web.xml

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

The web.xml listener is an additional listener and compliments both the <context-param> reference defining the Spring configuration file, and the ContextLoaderListener which bootstraps the Spring configuration for the web application.

faces-config.xml

<application> 
    <el-resolver>org.springframework.web.jsf.el.SpringBeanFacesELResolver</el-resolver>
</application>

Each backing bean into which you wish to inject Spring references into needs to be managed by Spring, so need to be annotated with Spring stereotypes.

page1_backing.java

package com.test.jsf;

@ManagedBean
@Controller
@Scope(value = "request")
public class page1_backing
{
    @Autowired
    private UserInfo ui;

    ...
}

The @Autowired annotation is a Spring annotation indicating that the reference will be injected when the Spring bean is created. As the bean is scoped to “request”, the managed bean will be created each time it is referenced by the JSF request lifecycle. In this example, the UserInfo class is a simple POJO that contains user-sensitive data such as forename, surname etc.

The final piece of the puzzle is to add the component-scan annotation to the Spring configuration file so that stereotypes are automatically picked up when the Spring context is loaded.

application-context.xml

<context:component-scan base-package="com.test.jsf" />

You should now be able to inject any Spring managed bean into your JSF @ManagedBeans at runtime, through configuration.

  1. September 7, 2011 at 3:33 pm

    Fascinating. Although I didn’t have any problems accessing spring beans from within JSF beans using ManagedProperty with EL expressions, your solution makes code more readable and apparently the bean is not created twice 🙂

    I wonder if this will work correctly with @ViewScoped, which doesn’t exist in Spring.

  1. No trackbacks yet.

Leave a comment