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

2

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.

Share.

About Author

Lucas Jellema, active in IT (and with Oracle) since 1994. Oracle ACE Director for Fusion Middleware. Consultant, trainer and instructor on diverse areas including Oracle Database (SQL & PLSQL), Service Oriented Architecture, BPM, ADF, Java in various shapes and forms and many other things. Author of the Oracle Press book: Oracle SOA Suite 11g Handbook. Frequent presenter on conferences such as JavaOne, Oracle OpenWorld, ODTUG Kaleidoscope, Devoxx and OBUG. Presenter for Oracle University Celebrity specials.

2 Comments

  1. Dear Lucas
    Thank you for the nice article with new approach to explain it starting the reverse way :-) I was sure at beginning its some aspect applied in a weird way, but enjoyed reading till the end, and liked your closing note on potentials.
    Yes, I am also opposed to liberal usage of AoP, it should be just restricted to proper concerns only (e.g. security) and not just anything. 
    Cheers. 
    sibendu 

  2. Quite a good example showing a disadvantage of aspects: maintenance.
    Good luck that the ‘reverse’ search result pointed you to the aspect, otherwise it might have taken some time to find it…