As part of the recent final release of Spring Web Flow 2, along comes the official
introduction of the Spring Faces module. This module builds on the foundation of Spring MVC and
Spring Web Flow (SWF) to provide first-class integration support between JavaServer Faces (JSF)
and Spring. Spring has long included basic JSF integration in its web module, which by itself
provides the necessary glue between a typical JSF web layer and a Spring managed business layer.
This integration is what we today refer to as the JSF-centric way of integrating the two
technologies. Though many applications have been built successfully using this approach, we on
the Spring Web team felt that there was still a disconnect between the two, with too many
artifacts and too much conceptual overhead to manage easily.
Spring Faces turns the table and approaches the integration from a different angle, with the
goal of bringing the strengths of JSF to a Spring-driven web environment. At the same time, it
alleviates many of the common frustrations that come with developing a traditional pure JSF web
application. Spring Faces pushes the Spring programming model further up the stack, and advocates
more of a "turtles all the way down" approach to using JSF with Spring. This is what we refer to
as the Spring-centric approach to developing web applications with the JSF UI component model.
This article aims to demonstrate the benefits of this approach and why it should appeal to JSF
and Spring developers.
JSF and Spring - The perfect combination?
JSF by itself offers great benefits when you are developing rich web applications, especially
when they have complex user interactions that stand to benefit from a stateful programming model.
Its UI component model is solid and powerful. When applied appropriately, it achieves well its
goals of shielding you from the complexities involved in building rich UI controls in a web
browser. The ability to declaratively build a rich user interface, combined with the flexible
binding of the values of individual controls directly to your domain model through the Unified
Expression Language (EL), enables you to quickly build complex web user interfaces without having
to worry about the internal mechanics of the components. All of this is achieved with a simple
POJO programming model.
Spring is a natural fit and the logical choice for the domain layer of a JSF-fronted
application, as it enables a similar POJO programming model. By taking advantage of a few of
JSF's many well-defined extension points, it's simple to plug a Spring-powered business layer
into a JSF front-end.
JSF-centric integration via EL
In the JSF-centric approach to integration, the JSF controller model is driving the
application and JSF managed beans delegate to Spring for business-layer concerns. Spring
provides several integration classes that can be selected and used a la carte by configuring
them in faces-config.xml. The most widely used of these classes is the
DelegatingVariableResolver (and the JSF 1.2 equivalent SpringBeanFacesELResolver). This class
effectively makes Spring beans resolvable via EL expressions. The typical usage pattern is to
use EL to inject Spring beans into JSF managed beans. For example, if you have the following
simple Spring bean defined in your WebApplicationContext:
<bean id="mySpringService" class="com.foo.MySpringServiceImpl">
You can then use EL to inject that service into a JSF managed bean by referencing it in the
<managed-bean> definition in faces-config.xml.
<managed-bean>
<managed-bean-name>myJsfManagedBean</managed-bean-name>
<managed-bean-class>com.foo.MyJsfManagedBean</managed-bean-class>
<managed-bean-scope>request</managed-bean-scope>
<managed-property>
<property-name>mySpringService</property-name>
<value>#{mySpringService}</value>
</managed-property>
</managed-bean>
This results in the Spring managed singleton service getting injected into the JSF managed
bean every time an instance of the bean is created by JSF. As of Spring 2.0, where you have the
ability to have request and session scoped Spring beans, you can even eliminate the JSF managed
beans altogether, and simply rely on the Spring container to instantiate and manage the beans the
first time they are referenced via an EL expression.
Does the JSF-centric approach go far enough?
With Spring's simple JSF integration classes, you can smoothly integrate Spring managed
services into a JSF-driven front end. But does this go far enough? I would assert that it does
not, and that this approach in fact leaves much to be desired. For one, it assumes that the
traditional JSF controller model is adequate, when in practice it has proven to have several
deficiencies:
- With it's pull-MVC approach, everything is driven by the rendering of the view, with no
convenient points for initialization of the model prior to rendering.
- The cumbersome navigation model gives little or no feedback when you make a mistake (such as
misspelling a navigation outcome) and requires an application restart anytime a rule is added
or modified.
- The validation model doesn't go far enough, as it is focused mainly on individual
field-level validation only on the server-side. A convenient way of being able to do
client-side field validation and server-side model-level validation without having to navigate
the component tree is sorely needed.
- URL mapping is rather inflexible and the URL is usually a step behind unless you perform a
redirect. The redirect support is generally not sufficient, as certain things like
FacesMessages do not get preserved across the redirect.
- Finer-grained scopes in between request and session scope are commonly needed, especially
when working with Ajax-based views that fire multiple in-page events.
- Exception handling capabilities are quite limited, especially if they occur during view
rendering (which can often be the case in using the pull-MVC approach).
- Control logic gets spread throughout JSF managed beans, which can be difficult to unit test
and require an application restart anytime changes are made.
JSF's UI component model is solid; it allows rich behavior to be encapsulated and executed
within the well-defined boundaries of the JSF component lifecycle. However its controller model
is rather limited, especially to someone who is used to the power and flexibility of Spring,
Spring MVC, and Spring Web Flow. The JSF-centric approach to integration introduces an extreme
amount of conceptual overhead, since you have to continually manage many disparate artifacts,
such as faces-config.xml, JSF managed beans, JSF view templates, and all of the components of
your Spring-based business layer.
Initially, Spring Web Flow 1.x also attempted to integrate in a JSF-centric way, but this
approach proved to have numerous limitations. It required yet more JSF artifacts to be chosen a
la carte and manually added to the faces-config.xml in order to function properly, introducing
further conceptual complexity. This approach was by no means agile.
We decided that what would be ideal was if the strengths of JSF's UI component model could be
integrated into a Spring environment, while pushing the Spring programming model further up the
stack for a more Spring-centric approach. If you could let Spring be in control of the entire
request, you could have a consistent programming and configuration model throughout the entire
application. You could also take full advantage of Spring MVC's flexible routing infrastructure
and Spring Web Flow 2.x's agile stateful controller model, which is a natural fit with stateful
JSF views. This is the motivation for the creation of Spring Faces and its addition to the Spring
portfolio.
Page:
1
2