Spring a surprise on a JSF developer - how Spring beans can become "JSF Managed Beans" html

Spring a surprise on a JSF developer – how Spring beans can become "JSF Managed Beans"

Recently I was looking at a JavaServer Faces application, that did something relatively simple – but was exhibiting strange behavior. The output shown on the page (and this is a simplified version of the real life situation) was:

dlroWolleH

I had been asked to look into the situation and correct it. Before starting to make any changes I decided to familiarize myself with the application as it currently was. And then they almost tricked me.

The JSF page had a simple outputText component with an EL Expression in its value attribute. Something like:

<h:outputText value="#{someBean.property}"/>

I decided to take a look at the code for that bean, to understand the logic behind deriving the value of the outputText. So I first opened the faces-config.xml file to find the managed bean declaration that would tell me which class definition was behind the bean included in the EL expression. However, the faces-config.xml did not contain any managed bean definitions at all. None. And yes, I tried to see whether the web.xml specified any other faces-config.xml alternatives. But it did not.

Slowly it dawned on me

– and perhaps the listener-class in the web.xml referring to a class from the springframework was the missing link – that this JSF application had been configured to also recognize Spring Beans as references in EL expressions.

The EL expression #{someBean.property} was not being evaluated in the normal JSF way, but in an extended manner – including all Springs Beans in the evaluation of the someBean reference. This has been configured in the faces-config.xml file:

<faces-config version="1.2" xmlns="http://java.sun.com/xml/ns/javaee">
<application>
<el-resolver>org.springframework.web.jsf.el.SpringBeanFacesELResolver</el-resolver>
</application>
</faces-config>

Note that this is the JSF 1.2 way of extending the variable resolver; in JSF 1.1 this was done using the variable-resolver  element and the Spring DelegatingVariableResolver class.

In order for this EL Resolver to find the Spring Bean Context, we need to configure the web.xml with two elements

<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/my-other-managed-beans.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

:

 

This configures the ContextLoaderListener to be called when the application has been first loaded in the Application Server. It will use the context parameter specifying the location of the Spring Bean Configuration file.

Upon inspecting that file, I found the someBean that I had been looking for

<bean id="someBean"/>

:

 

However, the source of the bean did not give any clue as to why we would have this strange output in the web application. It simply said:

package nl.amis.simplejsf;

public class MyBean {

  public StringBuffer getProperty() {
    return new StringBuffer("HelloWorld");
  }
}

And what could possibly turn HelloWorld into dlroWolleH?A trick of the Spring ELResolver? What would turn a string into the reverse?

Searching all the files in the project for the word reverse gave me the solution – as did a closer inspection of the Spring Context. The first approach returned the Gotcha class – all by itself relatively innocent:

package nl.amis.simplejsf.aop;

public class Gotcha  {

  public void reverseResult(StringBuffer result) {
     result.reverse();
  }
}

However, this class had been set up in the Spring Context to intercept all method calls with a StringBuffer as return result and reverse the results from those calls

<aop:aspectj-autoproxy/>
<!-- proxy-target-class forces the use of CGLIB proxies, which allows proxying classes in addition to interfaces.-->
<aop:config proxy-target-class="true">
<aop:pointcut id="someBeanPc" expression="bean(someBean)"/>
<aop:aspect id="reverseAspect" ref="gotchaBean">
<aop:after-returning pointcut="execution(java.lang.StringBuffer *(..))"
method="reverseResult" returning="result"
arg-names="result"/>
</aop:aspect>
</aop:config>
<bean id="gotchaBean"/>

.

 

This configuration instructed the Spring Framework to step in to intercept the “Hello World” stringbuffer returned by MyBean, take its result and reverse it.

While this funny little left over from the developer who just started his trip around the world was interesting enough in a nerdy sort of way, the techniques shown here are quite powerful. Both the integration between JSF and Spring and the use of AOP open many interesting opportunities.

 

Resources

JEE Web Application (configured for WebLogic 10.3 but quite generally applicable): SimpleJSF_sources.zip.

Spring Framework – documentation on JSF integration.

2 Comments

  1. Sibendu January 7, 2010
  2. Emiel Paasschens December 11, 2009