When
we began work on Alfresco,
our Open Source Enterprise Content Management System, we had two
requirements. Firstly, to build a web-based client that would run as
a portlet from within a JSR
168 Portal environment,
and secondly run as a standard web application (see figure 1). Further, the
application needed to be easily customizable and extendable by
developers. Java Server Faces appeared to be the natural choice due
its event-based architecture, standardized component model and the
promise of rich tool support. The majority of our development team
had previously worked on defining the architecture for Documentum's
Web Development Kit, which takes a very similar approach to JSF. In
fact, some of the representatives of the team were members of the JSF
expert group, so we knew we were taking the correct architectural
approach.

Figure 1. Alfresco utilizes JSF to provide an attractive, easy-to-use, web-based interface.The
Alfresco repository uses the latest open source technologies at its
core, including Spring, Hibernate and Lucene. Repository capabilities
are exposed as a set of services, and to inject behavior, aspects
such as transaction management, security, versioning and auditing are
employed. Each service is exposed as a Spring bean with a well
defined interface, allowing the web client to use standard JSF
support to bind and communicate with the repository (see figure 2). Because of the
modular architecture of the repository, it is possible to upgrade,
replace and extend its capabilities for the particular business
requirement at hand. By default, the repository supports a wide range
of content management services such as content and meta-data storage,
powerful search, categorization, versioning, workflow and rules. The
implementations have been designed with performance in mind, with
services lending themselves to a more stateless approach, ideal for
any client that needs to scale the application.
The
Alfresco client development team consisted of Gavin Cornwell, Kevin
Roast, Paul Holmes-Higgin (as project lead), and Linton Baddeley, a
graphical designer and user interface specialist. Using JSF, we were
able to build the first client from scratch in three months - much
faster than it would have taken using other web-based frameworks. Due
to the flexibility of the JSF framework, the client runs seamlessly
as both a JSR-168 portlet inside JBoss
Portal 2.0 and as a
plain JSP/servlet based web application inside Tomcat 5,. Our
development environment is Eclipse and Ant on MS Windows, using JBoss
Portal 2.0 and Tomcat, both with MySQL. We also provide and test
deployments on Linux.

Figure 2. Alfresco's architecture takes a layered approach to integrating JSF, Spring, JBoss Portal, Hibernate, and Lucene.Foundation: MyFaces
We
chose to use the Apache
MyFaces implementation
due to its large user community . We started with Sun's
reference implementation, but we found several problems including
issues with the browser back button and the lack of a file upload
component.
Our switch to MyFaces
was painless and required no code changes, proving the advantage of
using a standards-based framework. However, even with this move we
are still experiencing some minor issues with the back button,
requiring users to click an action twice after performing a browser
back action. We also found we could not use the MyFaces upload
component as it doesn't fit into the constrained JSR 168 portal
architecture. This is due to the fact that MyFaces relies on a
servlet filter to process the multipart form data, but servlet
filters are not executed in a portal environment. Overall, however,
we are pleased with the quality of the MyFaces implementation.
So far, we have avoided
using any custom components that are specific to MyFaces because we
were unclear about how well they would work with other JSF
implementations (it has since become clear that the components are
not tied to the MyFaces implementation). However, we have written
several custom components to provide advanced navigation and
presentation functionality for the Alfresco repository. For example,
we have built a clipboard component for copying and pasting files and
folders, a folder selector component, and a property sheet component
for displaying meta-data of content objects.
We
have also written a growing library of custom components that are
completely independent of the repository. For example, we have
written a data-list component that greatly extends the basic UIData
concepts and allows multiple list rendering views onto the same
dataset. We have also added a breadcrumb navigation component, a
popup menu component, and a collapsible/expandable panel component.
As they are independent from the repository, these components are all
usable by anyone building a JSF application. They are in the source
download of Alfresco, but still need documentation. We also intend to
participate in JSR
276 to ensure that we
expose these components to a wider audience. You can see the
technology preview release of Alfresco for examples of all these
components in use.
The Early Days: JSF
Hell
In the early part of
our development, we found ourselves entering what we termed "JSF
Hell." We had believed we were well versed in JSF and at the
top of the learning curve, only to find we were suddenly slipping
back down into confusion as we hit another snag with the subtle
nature and complicated lifecycle of the framework. This was caused by
the somewhat confusing terminology and the sometimes overly flexible
nature of JSF. We could build pages using standard components
quickly, but we when we started creating custom components we were
surprised to hit a fairly steep learning curve.
As
with many flexible frameworks there can be more than one way to
implement a solution, and it may be difficult to know what the
"correct" approach is. For instance, since a component is
also capable of implementing the rendering methods and managing the
data-flow and processing events, even the renderer concept is
optional. When implementing a new JSF class, you need to have a deep
knowledge of the JSF component tree to know which standard component
to use as a base class. It is not always clear whether you should
create a new tag, a new component, or a new renderer. If you extend
any of the existing classes you may find that you do not get the
functionality you are looking for. You may also find that they apply
unforeseen constraints on the way you work with your components.
There
are many details about writing components that are not immediately
obvious. For example, when using the component or renderer decode()
method you should examine the submitted value before setting the
components' value. You must then apply the submitted value if it has
been set, the previous value if it exists, or a default value if
there is no previous value. This level of knowledge can be confusing
for the uninitiated.
Some
of the JSF terminology caused confusion in the early days. One would
expect component-type to be a class name, but it is actually
an identifier that looks similar to a class name. We believe
component-id would have been a better choice of name. The
broadcast() method does
not broadcast an event, it consumes an event. The renderer
classes do not encapsulate pure rendering functionality; they render
with additional responsibility of managing data-flow between the
client response and the component instance that supports the
renderer.
Success upon Mastery
Fortunately,
once we reached the top of the learning curve, development progressed
rapidly and it was a quick and easy process to add new pages to the
application. The component model with its automatic state
persistence, the friendly JSF navigation mechanism, powerful bean
data-binding language and the relatively straightforward way of
adding new custom components all helped this rapid development. The
absence of multiple code lines supporting portal servers and servlet
engine based web clients is a significant benefit. We envisage that
JSF will be at the centre of our architecture for client applications
in the future.
We
found that the Command, Strategy and Singleton patterns fit nicely
with our architecture. The Command style pattern, used throughout JSF
for binding component action handlers, is a powerful means of
separating the resulting action implementation from the component. We
either extended or duplicated this same style of processing for our
custom components. We often used the Strategy pattern, particularly
in our custom components. For example, our UIRichList
component interfaces use delegates to de-couple optional rendering
mechanism from our core components. We plan to continue with this
pattern by modularizing our client-side business code into a
non-web-specific client-side service layer. This is useful where we
make multiple granular calls to our repository for building complex
client objects, such as a fully-fledged content document with
attached rules and actions. Hopefully, this kind of approach will
mean writing future clients is as painless as possible, with very
little code duplication.
The feedback from
people that have tried the technology preview of Alfresco has been
very positive. It looks good, response is snappy and it is robust,
thanks in part to the quality, flexibility and performance of JSF and
the MyFaces implementation. Rather than complaining about what does
not work, users provide us with feed back on new functionality they
would like to see. Our experience with JSF makes us think we can
deliver this functionality faster and more effectively than we have
been able to in the past.