1) Introduction
This article provides an introduction on how Spring and Java Server Faces Technologies can be integrated. It covers the necessary details of both Spring and JSF Technology in the initial section in the context of Integration. Later on it moves towards the concept of Variable Resolvers which help in easing the integration between the two technologies. Then a full-fledged sample application is followed to get a greater feel and understanding of the integration.
also read:
2) Spring-JSF Integration
2.1) Introduction
Before getting into the details of how Sping JSF Integration, it is important to know a bit about basic details. The following section will talk about how the base architecture is structured for both Spring and JSF in the context of integration.
2.2) Spring
Spring is a framework that supports of Inversion of Control. For more information about Spring’s Introduction, readers are advised to read the article introduction spring framework in javabeat. Inversion of Control (IOC) enables you to decouple several components that fit in an Application. In Spring terminology, Beans (or Spring Beans) are nothing but regular java classes. It is possible to externalize the state of Bean objects by specifying them in the Xml file. A spring Bean has a dedicated life-cycle and it passes through various phases. Spring’s IOC is responsible for reading the Xml file and constructing Spring Beans from the various meta-data information. So, the main responsibility of IOC is to make the Spring Beans available to the client Application. And the other core of IOC is to provide wiring between Spring Beans. So, instead of Application code manually managing the relationship between Beans, now the burden of maintaining this is delegated to the Spring’s IOC. An example bean called Person is as follows,
<bean id = "personBean" class = "net.javabeat.articles.spring.Person"> <property name = "name"> <value>Anonymous</value> </property> </bean>
The above example defines a Spring Bean of type Person
with an identifier personBean
. It also defines a simple property called name
with value Anonymous
. It is also possible to relate compound values (like references to other object) and collection-like (set, map, list) values as the following code snippet will illustrate that,
<bean id = "employee1" class = "net.javabeat.articles.spring.Employee"> <property name = "name"> <value>Emp1</value> </property> </bean> <bean id = "employee2" class = "net.javabeat.articles.spring.Employee"> <property name = "name"> <value>Emp2</value> </property> </bean> <bean id = "manager1" class = "net.javabeat.articles.spring.Manager"> <property name = "name"> <value>Manager1</value> </property> <property name = "employees"> <ref bean = "employee1"/> <ref bean = "employee2"/> </property> </bean>
Note that in the above example, we have declared two employee
objects with identifiers employee1
and employee2
. We want these two employee objects to be associated with the manager
object. This is an example of a composite relationship, since we are relating Manager
to Employees
. This is achieved through the reference
tag within the property declaration.
2.3) Java Server Faces
Having seen about how Spring’s IOC manages and maintains Spring Beans, let us see an overview about Java Server Faces managing its components. JSF is responsible for providing a component oriented development for UI layer in a Web Application. A client request is directly mapped to an Action in the Web tier, which means that the event-handling mechanism resembles the one what we see in Swings or AWT. If Swings event-handling mechanism is for Desktop Applications, then JSF event-oriented architecture is for Web Applications. Similar to Spring Beans, in JSF we have something called Managed Beans or Backing Beans. These managed beans are responsible for handling all types of actions in a Web Application. How a UI component is associated with a particular action is easily configurable in Xml file. The following code shows the declaration of a managed bean in JSF.
<managed-bean> <managed-bean-name>timerBean</managed-bean-name> <managed-bean-class> net.javabeat.articles.springjsf.TimerBean </managed-bean-class> <managed-bean-scope>request</managed-bean-scope> </managed-bean>
A managed bean is also a regular Java class in JSF and it is configured in faces-config.xml
file and it made available to the Application by the JSF Framework.
2.4) Spring Beans in JSF Environment
Now that we have seen about Spring and JSF, let us see about Integration and what component gets integrated. Spring uses Spring Beans and JSF uses Managed Beans. The Spring Framework provides support in such a way that a Spring Bean is made visible to the JSF Environment. Precisely, the Spring Bean what we have configured in the Xml file can be directly referred in the faces-config.xml as if it was a JSF managed Bean. Let us further clarify this,
<bean id = "personBean" class = "net.javabeat.articles.spring.Person"> <property name = "name"> <value>Anonymous</value> </property> </bean>
The above is a Spring Bean. Now, consider the following,
<managed-bean> <managed-bean-name>personBean</managed-bean-name> <managed-bean-class> net.javabeat.articles.spring.Person </managed-bean-class> <managed-bean-scope>request</managed-bean-scope> </managed-bean>
We have used the Person
Bean which was previously given configuration in Spring in JSF Environment. This is the core of what the Spring-JSF Integration is all about.
3) Supporting API’s for Integration
3.1) Introduction
Let us turn our focus to the various API in the Spring Distribution that are related to JSF for supporting integration. The Spring API is vast and the supporting classes for JSF Integration are available in org.springframework.web.jsf
and org.springframework.web.jsf.el
packages. But for the integration to work, we need to know only about Spring Resolvers. The following section tries to provide an overview about Spring Resolvers.
3.2) Spring Resolvers
In JSF Context, Resolving is a process of identifying an object from a given symbol. More specifically given an identifier the JSF framework tries to construct and associate the object with the identifier. Going back to the declaration of managed beans,
<managed-bean> <managed-bean-name>timerBean</managed-bean-name> <managed-bean-class> net.javabeat.articles.springjsf.TimerBean </managed-bean-class> <managed-bean-scope>request</managed-bean-scope> </managed-bean>
In the above declaration, we have an identifier
(or variable
) called timerBean
. The aim of a JSF Resolver implementation should be to associate an object of type net.javabeat.articles.springjsf.TimerBean
to timerBean
. Let us see what happens when we try to identify a variable that is not managed by JSF Application Context, but rather it is in Spring’s Application Context. The JSF implementation will simply throw an error telling that the variable cannot be resolved. Because the JSF implementation doesn’t care or doesn’t know anything about the Beans that are maintained in the Spring’s Application Context.
So, in order to resolve the variables in the Spring’s Application Context, we have to replace the implementation of JSF resolver to Spring’s revolver implementation. Spring’s resolver implementation will try to resolve the variables from Spring’s Application Context also. Instead of defining a custom Variable Resolver, Spring’s distribution comes with a pre-defined Variable Resolver called “org.springframework.web.jsf.DelegatingVariableResolver”.
4) Spring and JSF – Sample Application
Let us see what exactly the sample is all about. Since the purpose of the sample is to show how the integration works, the sample does not deal in depth about the real business logic. The application is all about getting the stock value for a particular stock symbol. Initially it displays a stock input page, providing a text-box where a user can enter a stock symbol, after that pressing the submit button to get the value of the stock. If the stock symbol is not valid, an error page will be returned.
4.1) Stock Input Page
stockInput.jsp
<%@page contentType="text/html"%> <%@page pageEncoding="UTF-8"%> <%@taglib prefix="f" uri="http://java.sun.com/jsf/core"%> <%@taglib prefix="h" uri="http://java.sun.com/jsf/html"%> <f:view> <html> <head> <title> Stock Input Page </title> </head> <body> <h:form id="stockForm"> <h1> Please Enter the Stock Symbol and click the button </h1> <p> <h:inputText id="stockSymbolInput" value="#{stockBean.symbolName}" required="true"> </h:inputText> <h:commandButton id="stockSubmit" type="submit" value="Submit Symbol" action="#{stockBean.findStockValue}"> </h:commandButton> </h:form> </body> </html> </f:view>
The above stock input page renders a text-box for entering the stock symbol for which the value has to be determined. Here, we note the use of the expressions stockBean.symbolBean
and stockBean.findStockValue
. Later on we will see that these expressions are mapped to a property and a behaviour respectively.
4.2) Stock Output Success Page
stockOutputSuccess.jsp
<%@page contentType="text/html"%> <%@page pageEncoding="UTF-8"%> <%@taglib prefix="f" uri="http://java.sun.com/jsf/core"%> <%@taglib prefix="h" uri="http://java.sun.com/jsf/html"%> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>JSP Page</title> </head> <body> <f:view> <h1> The Stock Value of the symbol <h:outputText value="#{stockBean.symbolName}"> </h:outputText> is <h:outputText value="#{stockBean.symbolValue}"> </h:outputText> </h1> </f:view> </body> </html>
This page will be rendered if the user-entered stock symbol is valid and if it is available in the stock database.
4.3) Stock Output Failure Page
stockOutputFailure.jsp
<%@page contentType="text/html"%> <%@page pageEncoding="UTF-8"%> <%@taglib prefix="f" uri="http://java.sun.com/jsf/core"%> <%@taglib prefix="h" uri="http://java.sun.com/jsf/html"%> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>JSP Page</title> </head> <body> <f:view> <h1> The Stock symbol <h:outputText value="#{stockBean.symbolName}"> </h:outputText> is not found. Please check again. </h1> </f:view> </body> </html>
This error page will be displayed if the user-entered stock symbol is not available in the database.
4.4) Java Source
StockValueFetcher.java
package net.javabeat.articles.springjsf.introduction; import java.util.*; public class StockValueFetcher { private Map<String, String> stockSymbolsAndValues; private String symbolName; private String symbolValue; public StockValueFetcher() { stockSymbolsAndValues = new HashMap<String, String>(); stockSymbolsAndValues.put("ABC", "10"); stockSymbolsAndValues.put("DEF", "20"); stockSymbolsAndValues.put("GHI", "30"); stockSymbolsAndValues.put("JKL", "40"); } public String getSymbolName() { return symbolName; } public void setSymbolName(String symbolName) { this.symbolName = symbolName; } public String getSymbolValue() { return symbolValue; } public void setSymbolValue(String symbolValue) { this.symbolValue = symbolValue; } public String findStockValue(){ boolean symbolFound = stockSymbolsAndValues.containsKey(symbolName); if (symbolFound){ symbolValue = stockSymbolsAndValues.get(symbolName); return "stockOutputSuccess"; }else{ return "stockOutputFailure"; } } }
This class maintains a map of stock symbols keyed with stock values. Note that the stock information is directly maintained in the Application since this is just a sample Application. Also, it has getters and setters for holding the stock symbol and the value for the stock symbol. Note that the method findStockValue()
will be fired when the user clicks the submit button after entering the stock value. If the stock symbol is valid, the output will be redirected to the success page, else the failure page would be displayed with the appropriate message.
4.5) Faces Configuration
faces-config.xml
<?xml version='1.0' encoding='UTF-8'?> <faces-config version="1.2" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_1_2.xsd"> <application> <variable-resolver> org.springframework.web.jsf.DelegatingVariableResolver </variable-resolver> </application> <managed-bean> <managed-bean-name>stockBean</managed-bean-name> <managed-bean-class> net.javabeat.articles.springjsf.introduction.StockValueFetcher </managed-bean-class> <managed-bean-scope>request</managed-bean-scope> </managed-bean> <navigation-rule> <description>Navigation from the hello page.</description> <from-view-id>/stockInput.jsp</from-view-id> <navigation-case> <from-outcome>stockOutputSuccess</from-outcome> <to-view-id>/stockOutputSuccess.jsp</to-view-id> </navigation-case> <navigation-case> <from-outcome>stockOutputFailure</from-outcome> <to-view-id>/stockOutputFailure.jsp</to-view-id> </navigation-case> </navigation-rule> </faces-config>
The above configuration file has 3 sections. The first one specifies to use the Spring Resolver for identifying any Spring Beans and making them available into the JSF Application Context. The second one declares a managed bean instance. We will see that this Managed Bean will be resolved from Spring Application context. The third section deals with the navigation rule. For the valid user input, the control goes to the stockOutputSuccess page, else to the stockOutputFailure page.
4.6) Application Context
applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"> <beans> <bean id="stockBean" class="net.javabeat.articles.springjsf.introduction.StockValueFetcher"> </bean> </beans>
The above code snippet shows the Spring Bean declaration for the StockValueFetcher class. This Bean will be read by the Spring IOC and the Spring Resolver will make the Bean available to JSF Environment.
4.7) Web Configuration
web.xml
<?xml version="1.0" encoding="UTF-8"?> <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> <listener> <listener-class> org.springframework.web.context.ContextLoaderListener </listener-class> </listener> <context-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/applicationContext.xml</param-value> </context-param> <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>/faces/*</url-pattern> </servlet-mapping> <session-config> <session-timeout>30</session-timeout> </session-config> <welcome-file-list> <welcome-file>faces/stockInput.jsp</welcome-file> </welcome-file-list> </web-app>
In the above code snippet, we find the declaration of ContextLoaderListener
. This is needed for loading the Spring’s Web Application Context. The contextConfigLocation
tells where to look for the declaration of Spring Beans.
5) Conclusion
Spring provides a greater degree of flexibility for integration with other Web frameworks. This article provided an introduction to Spring-JSF Integration. More specifically it guided how to make Spring Beans visible to JSF Application Context.
By having this kind of integration, we can get all the benefits of Spring Beans into the JSF Environment. Above all, the Integration is not very complex. It is all about replacing the default JSF Resolver in the Application’s Configuration file.
If you have any doubts on the spring framework integration with JSF, please post it in the comments section. Also search in our website to find lot of other interesting articles related to the spring framework. There are some interesting articles about spring framework, interview questions, spring and hibernate integration, spring web services, etc.
also read:
If you would like to receive the future java articles from our website, please subscribe here.