Spring-centric JSF with Spring Faces
Spring Faces takes a much more prescriptive approach to integration between JSF and Spring. A
further strength of JSF is the many extension points it provides, and Spring Faces takes full
advantage of this to fit JSF more naturally into a Spring world. It makes a number of assumptions
about the environment it is running in, such as a Spring MVC DispatcherServlet being configured
to handle request routing, and Spring Web Flow 2.x being available as the primary controller
JSF Ajax components that focus on web development best practices, such as progressive
enhancement, graceful degradation, and accessibility. (Spring Faces is designed to work with any
JSF component library, thus the use of these components is entirely optional.) Figure 1 below
gives a high-level picture of the Spring Faces architecture:
Figure 1 - High-level View of Spring-Faces Architecture
For the remainder of this article, I will be using pieces of the Spring Faces version of the
Spring Travel sample application (included in the Spring Web Flow 2 distribution ) to
illustrate the Spring Faces approach to building a JSF web application.
The full source for the Spring Faces sample can be found under
/projects/spring-webflow-samples/booking-faces/ from the root of the distribution.
If you want to at least familiarize yourself with the functionality of the application, a
running version of the sample is available here.
Structure of the Spring Faces sample
One of the first things worth noting about the sample is the content of
/src/main/webapp/WEB-INF/faces-config.xml. The only piece of infrastructure configured there is
the standard FaceletViewHandler. Since Spring Faces takes a more prescriptive approach, all of
its JSF integration artifacts are configured automatically through inclusion of spring-faces.jar
on the classpath.
You will also want to familiarize yourself with the basic setup for the routing infrastructure
of the application by looking at:
I won't explore the gory details of the configuration here, as that is well covered in the Spring Web
Flow 2 Reference Guide, but I will briefly examine the result of this configuration.
All requests that have a /spring path get routed through the Spring DispatcherServlet. The
DispatcherServlet then looks at the rest of the URL and selects either a stateless JSF view to
render, or it hands control over to SWF for rendering of a stateful JSF view.
So for example:
renders the stateless Facelets template at /WEB-INF/intro.xhtml
/spring/main -> hands control over to the flow defined at /WEB-INF/flows/main/main.xml
/spring/booking?hotelId=5 -> hands control over to the flow defined at
/WEB-INF/flows/booking/booking.xml, passing the hotelId parameter as input to the flow
As you can see by examining the contents of the /flows directory (Figure 2), Spring Faces
enables and encourages the organization of controller and view artifacts into logical re-usable
Figure 2 - Logical Organization of Modules
Agile JSF controllers with Spring Web
The core power of Spring Faces comes from its deep integration with Spring Web Flow, and the
ability to use the high-level flow DSL that provides concise and elegant constructs for event
handling, domain model orchestration, and view navigation. Flow definitions are dynamic and
hot-refreshable without an application restart, as well as fully unit-testable standalone without
having to be deployed to the web container. This gives you a much more agile JSF development
process that can better keep pace with the flow of ideas. Its finer-grained scopes (flash, view,
and flow scopes) allow you to work directly with your domain model across multiple requests, so
you can focus more energy on adding value to your domain model and spend less time worrying about
the infrastructural concerns of saving and restoring the model on every request. This stateful
nature makes for an excellent pairing with rich JSF views, where the model needs to be frequently
manipulated in response to multiple events.
With Spring Faces, the JSF postback lifecycle is executed under the control of SWF. As opposed
to SWF 1.x's limited integration approach where the flow execution was wedged into the JSF
lifecycle via a PhaseListener, the Spring Faces JSF extension points build directly on SWF
constructs. This allows for several architectural advances that weren't previously possible such
- JSF views now work smoothly with SWF's automatic POST+Redirect+GET behavior, eliminating the
step-behind-URL and browser refresh warning problems inherent in typical JSF applications.
- FacesMessages are adapted to and from Spring Binding's lower-level web-independent
MessageContext, providing deep integration with Spring's strong i18n support. Messages are
stored in flash scope so that they will be preserved across redirects.
- The component tree state is automatically synchronized with the flow execution state, with
pluggable storage mechanisms to allow handling of various clustering scenarios
All of the integration classes use the standard JSF delegation approach, so for non-Spring
requests, everything will pass through to the default implementation. This allows you to
incrementally introduce Spring Faces into a traditional JSF application. In the next installment,
I'll examine in detail some of the code from the sample application, to show how SWF addresses
the aforementioned deficiencies of the traditional JSF controller model, and enables the "Spring
all the way down" approach.