Skip to main content

Seamless JSF, Part 1: An application framework tailor-made for JSF

Discover Seam's unique enhancements to the JSF life cycle

Dan Allen (dan.allen@mojavelinux.com), Senior Java engineer, CodeRyte, Inc.
Dan Allen
Dan Allen is currently a senior Java engineer at CodeRyte, Inc. He is also a passionate open source advocate and gets a bit manic whenever he catches sight of a penguin. After graduating from Cornell University with a degree in Materials Science and Engineering, Dan became captivated by the world of Linux and open source software. He has been slaving over Web applications ever since, with the last several years focused exclusively on Java-related technologies, including Spring, Hibernate, Maven 2, and the abundant JSF stack. You can keep up with Dan's development experiences by subscribing to his blog at http://www.mojavelinux.com.

Summary:  JavaServer Faces (JSF) is the first standardized user interface framework for Java™ Web applications. Seam is a powerful application framework that extends JSF. Discover the strong chemistry that these two frameworks share in this first article of a new three-part series. Dan Allen introduces Seam's enhancements to the JSF life cycle, including contextual state management, RESTful URLs, Ajax remoting, proper exception handling, and convention over configuration.

View more content in this series

Date:  17 Apr 2007
Level:  Intermediate
Activity:  13404 views

JSF is beginning to dominate the Java Web application market because of its status as a Java Web standard. As more developers are being mandated to architect applications using JSF as the foundation, they are discovering something that is clearly stated in the core specification: JSF was not designed to be a complete Web application framework. Rather, it provides a sturdy, event-driven API and UI component library on which to build a more complete application framework.

In my search for an extension to complement JSF's component-driven architecture, I recorded short stints with both Shale and Struts 2. I ruled out Struts 2 because it treats JSF as merely a stepchild to a much broader design. Shale seems to come closer, being fundamentally based on JSF, but I have some reservations about it. In contrast, JBoss Seam is a comprehensive application framework that builds on the foundation of JSF without compromising any of its core goals.

About this series

Seamless JSF showcases Seam as the first application framework that truly fits JSF, compensating for its major weaknesses like no other extension framework does. Read the articles in this series and decide for yourself whether Seam is a worthy complement to JSF.

This three-part series introduces the Seam application framework, demonstrates its strengths, and hopefully will convince you that it is the perfect companion to JSF for developing Java enterprise applications. Refer to the Resources section if you would like to download Seam before you begin reading the series.

Searching for Seam

After reading just one page of an article about JBoss Seam (see Resources), I knew that Seam was the project for which I had been searching. The developers of Seam, most notably Gavin King, have logged enough painstaking, real-world development hours to know that a Web application framework must attack tough issues from the very start, which include contextual state management, RESTful and user-friendly URLs, Ajax remoting, proper exception handling, and convention over configuration. Blissfully for Java developers, Seam delivers on all of these requirements and more. If you are using JSF and haven't heard of Seam, I highly recommend that you check out the Seam reference documentation (see Resources). The manual provided with Seam is one of its best assets!

About Shale

Shale has a spotty history. It grew out of the Struts-JSF integration package, but later fell out with the Struts developers. It exists today as a top-level Apache project dedicated entirely to JSF.

My issue with Shale is its positioning as a set of loosely coupled services, which puts the burden of integration onto the developer. Shale's Java 5 language enhancements are beneficial, but they're all sheltered in an extension package. The coupling of the view controller to a single template via naming convention is also very limiting. Both the Shale application controller and dialog manager are massive add-ons that seem to take too much responsibility away from the standard JSF life cycle.

Seam gives you all the features you would expect to find in Shale, but brings them together in a well-integrated, tightly fitted package.

Despite its apparent suitability as a complement to JSF, Seam has been met with some degree of indifference among heavy competition. In a market already flooded with Web application frameworks -- including Shale and Struts 2 -- newcomers are treated as yearlings, and Seam has yet to fully establish itself among the majority. Another reason Seam's adoption has been slow is that certain myths about the framework have kept Java developers from recognizing its immediate benefits.

The myth that I would like to shatter is that Seam is useful only when used in conjunction with EJB3, or that you need an EJB3 container to develop applications with Seam. In fact, the Seam documentation clearly refutes this misconception: "Seam does not require that components be EJBs and can even be used without an EJB 3.0 compliant container." Claiming that you can only use Seam if you also use EJB3 is analogous to implying that you can only use Spring if you also use Hibernate. While both pairings have a strong chemistry, they are not dependent on one another.

What about EJB3?

As I will shortly explain, Seam extends the default JSF life cycle with valuable hooks and component-management processes. You can also use it in complete isolation from EJB3. However, keep in mind that like EJB3, Seam does rely on JDK 5 annotation metadata for component declaration, so using it requires that you also use a Java 5-compliant JVM. Figure 1 shows the application stack for a Seam POJO implementation:

JBoss Seam and JSR 299

JBoss Seam is an open source application framework designed to improve the integration of JSF with business components such as EJB3 and Spring beans. Seam manages components across the various contexts of a Web environment and nearly eliminates the XML configuration required to develop JSF applications. The project is the brainchild of Gavin King, the creator of Hibernate, and is currently hosted in the JBoss labs.

Recently, JBoss submitted a proposal to the JCP to standardize the concepts behind Seam. That proposal was accepted as JSR 299, Web Beans. The purpose of the specification is to unify the JSF managed-bean component model with the EJB3 component model, resulting in a significantly simplified programming model for Web-based applications.


Figure 1. A Seam POJO application stack
Seam POJO architecture diagram

You can actually leverage much of Seam's power without even a reference to an EJB3 jar or descriptor file. When using Seam with POJOs, the framework retains complete control of component instantiation and does not require any special configuration. Seam handles most of the Java 5 annotation processing rather than relying on any mechanisms in EJB3. The bounded set of annotations that do depend on an EJB3 container are geared specifically for that environment. In some cases, integrating Seam into a current IT investment without the EJB3 coupling will prove more cost-effective. How you use Seam really is just a matter of preference.


Configure and go

Given the vast pool of Java frameworks and the limited number of hours in each day, it's obvious that Seam doesn't stand a chance if it is difficult to integrate. Fortunately, adding Seam to your project is trivial. Because the JSF life cycle remains the central piece of a Seam application, there is no retraining period to endure. Just add four additional jar files, register both a servlet listener and a JSF phase listener, and finally, toss in an empty java properties file. Once that setup is complete, you can shift your native JSF application to Seam one managed bean at a time.

The first thing you need to do to start using Seam is to add the required jar files to your project. If you are not using Hibernate or have not upgraded to the latest version, that will count as an extra step in the setup. You will need to include the jars from the Hibernate 3.2 distribution, as well as its numerous dependencies. Seam also uses Hibernate annotations for data validation, so you must include that extension jar in addition to the main Hibernate jar. The libraries required from the Seam distribution are jboss-seam.jar and jboss-seam-ui.jar, as well two supporting libraries: Javassist (a load-time reflective system for Java) and the Java Persistence API. The project tree in Figure 2 illustrates the cumulative set of jars in a Seam project. Most of the additional libraries shown in the figure support the MyFaces implementation of JSF.


Figure 2. Libraries in a Seam project
JAR file listing

Configuring Seam

The next step is to install the servlet listener class in the web.xml file, as shown in Listing 1. This listener initializes Seam when the application is deployed.


Listing 1. Seam servlet listener configuration
                
<listener>
  <listener-class>org.jboss.seam.servlet.SeamListener</listener-class>
</listener>

Next, you add the JSF phase listener to the faces-config.xml file, as shown in Listing 2. This listener integrates Seam into the standard JSF life cycle. (See Figure 3 for an overview of the enhancements Seam weaves into this life cycle.)


Listing 2. Seam phase listener configuration
                
<lifecycle>
  <phase-listener>org.jboss.seam.jsf.SeamPhaseListener</phase-listener>
</lifecycle>

Finally, you place an empty seam.properties file in the root of the classpath so that Seam is instructed to load, as shown in Listing 3. The empty file is used as a JVM classloader optimization to give Seam a narrower region of the classpath in which to search for components, drastically reducing load time.


Listing 3. Seam properties file
                
# The mere presence of this file triggers Seam to load
# It can also be used to tune parameters on configurable Seam components

Of course, many features of Seam are not available with this minimal setup. These instructions are merely intended to demonstrate that Seam has a very small footprint for entry-level use. For instance, Seam includes a servlet filter that extends the scope of its features beyond the JSF life cycle. Uses of this servlet filter include integration with non-JSF requests, propagating conversations over redirects, and managing file uploads. See Resources for the Seam reference documentation, which discusses configuration files that control additional functionality -- most notably the EJB3 integration.


Lock stitching with Seam

Developing a managed bean with Seam is almost shockingly easy compared to the typical JSF configuration process. To expose your bean to the JSF life cycle, all you need to do is place a single annotation, @Name, above the class definition. Seam takes care of controlling the visibility and life cycle of the component thereafter. Best of all, you do not need to define this bean in the faces-config.xml file.

The @Name annotation, along with @DataModel, @DataModelSelection, @In, @Out, and @Factory are depicted in Listing 4. These annotations enable a bidirectional flow of variables between the view template and Seam components.

In Seam parlance, this action is called bijection, short for bidirectional injection. When property data is outjected, it becomes directly visible to the view by name. Data is injected into a component either on postback or when the component is initialized. The latter is an implementation of the well-known inversion of control (IOC) pattern and can be used to tie in delegate objects. The major difference between classic IOC and Seam's bijection is that bijection enables components in a long-term scope to have references to those in a short-term scope. The connection is possible because Seam resolves dependencies each time a component is invoked, rather than once when the container is started. Bijection is a cornerstone of stateful component development.

Obviously the POJO bean in Listing 4 barely scratches the surface of how Seam operates. I'll explore additional ways to implement Seam as the series continues.


Listing 4. A typical Seam POJO bean
                
@Name("addressManager")
public class AddressManagerBean {
    
    @DataModel
    private List<Address> addresses;

    @DataModelSelection
    @Out( required = false )
    private Address selectedAddress;

    @Factory( value = "addresses" )
    public void loadAddress() {
        // logic to load addresses into this.addresses
    }

    public String showDetail() {
        // no work needs to be done to prepare the selected address
        return "/address.jspx";
    }

    public String list() {
        return "/addresses.jspx";
    }
}

An injection of Spring

To leverage your investment in service-layer objects managed by an existing Spring container, you need to inject any Spring beans that handle related business logic into your Seam component. You first need to ensure that you have the Spring-JSF integration configured, which is handled by a custom variable resolver included with the Spring framework (see Resources). With that bridge in place, integrating Spring with Seam is just a matter of using the @In Java 5 annotation in combination with a value binding expression to indicate which properties of the Seam component should receive an injection of a Spring bean, as shown in Listing 5. (Future versions of Seam will include a custom namespace for Spring that will absorb the need for the value binding expression.)


Listing 5. Injecting a Spring bean
                
@Name("addressManager")
public class AddressManagerBean {
    @In("#{addressService}")
    private AddressService addressService;
}

This example setup supports the use of stateless service and data access (DAO) layers that are configured using a lightweight container, in this case Spring. Because EJB3 is not required, the target of the deployment can be any basic servlet container.

Now that you've had a first look at a Seam-JSF implementation, I'll delve a little deeper into the challenges I have encountered using JSF and how Seam alleviates them.

JSF revisited

To fully appreciate what Seam brings to JSF, you need to understand how JSF differs from other popular approaches to Web-based programming. JSF is a Web framework that implements the classic Model-View-Controller (MVC) architecture. The difference is that it employs an exceptionally rich implementation of the pattern. The MVC implementation in JSF more closely approximates the style of a traditional GUI application than the Model 2, or "push-MVC" approach used in frameworks such as Struts, WebWork, and Spring MVC. These later frameworks are classified as action-based, whereas JSF is a member of a new family of frameworks based on a component model.

The distinction becomes easier to grasp if you think of action-based frameworks as using a "push" model, whereas component frameworks utilize a "pull" model. Instead of taking an active role in the request for a page up front (as it would in an action-based framework), the controller in a component framework takes a back seat in the request life cycle and invokes data-providing methods from within the view. Additionally, elements on the page, known as components, are bound to events that can trigger method invocations on server-side objects when activated, which results in either a redisplay of the same view or a transition to another page. Hence, component frameworks are also classified as event-driven. A component framework abstracts away the underlying request-response protocol that is used to communicate events.

The event-driven approach is beneficial because it reduces the amount of work that must be done up front, in a single method, to prepare for the rendering of the view. In a component framework, invocations are a direct result of either UI events or resolved value-binding expressions.

Once an application reaches even a moderate level of maturity, it generally requires a lot of unrelated activity on any given page. Stuffing the management of all of this information into a single action, or even a chain of actions, quickly becomes a maintenance nightmare. As a result, developers often find their code departing from the object-oriented model and diving instead into a procedural programming style. Component frameworks, by contrast, isolate the work and more naturally enforce the roles and responsibilities of objects.


Seam and JSF

Enough about the basics of JSF and component frameworks. The fact of the matter is -- as many Java developers have recently discovered -- moving to JSF is not all smooth sailing. Adopting the component model brings with it a whole new set of problems, beginning with the reality that you often must attempt to force your application into the action-based Web world. There are times when JSF simply needs to behave like an action-based framework, but that's not a viable option in native JSF, at least not without resorting to using phase listeners that execute for every request.

JSF's other major shortcomings include a heavy reliance on the HTTP session (especially when propagating data across a sequence of pages), cursory exception handling, lack of bookmarking support, and XML-hell configuration. Seam rectifies many of these problems by naturally integrating with JSF while at the same time weaving in new functionality that the JSF specification committee either renounced or simply overlooked. Seam's framework encourages very compact, readable, and reusable code, void of all the "glue" logic that routinely leaks in to manage the aforementioned problems. Figure 3 covers most of Seam's extension points in the JSF life cycle that help to simplify your application's code:


Figure 3. Seam life cycle enhancements
Seam life cycle diagram

Let's consider some of these enhancements as they apply to the common challenges of JSF development.

No-fuss configuration

Seam demonstrates a very practical use of Java 5 annotations. Seam's deployment scanner examines all archives containing a seam.properties file and creates a Seam component for any class marked with a @Name annotation. Many XML configurations were devised because the Java language lacked a common syntax for adding metadata at the code level. When annotations were added in the Java 5 specification, a better solution had arrived. Because most backing beans are developed for use within a specific application, there is no reason to "abstract" the configuration of these beans into any file other than the class itself. As an added benefit, you're left with one less file to juggle. Seam offers an entire catalog of annotations that help to integrate the beans into the JSF life cycle. Listing 4 shows several of them in use.

Page actions and RESTful URLs

One familiar crutch that you must do without in a component framework is processing each request up front, as you do in action-based frameworks. Use cases affected by this trade-off are RESTful URLs, bookmarking support, security through URL patterns, and page-flow validation, to mention a few. Hands down, this deficiency is one of the primary sources of confusion for developers learning to use JSF. Some JSF vendors work around this by offering an onPageLoad functionality (see Resources) with their developer tools, but it is not part of the core specification.

Consider what commonly happens when a user requests an item detail screen directly, perhaps from a bookmark. Because the JSF controller works in a passive manner, once the page begins rendering you cannot reroute the user to the start of logical flow, even when it becomes apparent that the target data is absent. Instead, you have no choice but to display a page with blank values and other potential rendering glitches.

At first, you may instinctively think to implement a "prerender" method on the page's primary backing bean. However, in a component framework, the association between backing bean and page is not necessarily one-to-one. Each page can rely on a mixture of backing beans, and each of those beans can also be used across several different pages. Instead, there must be some way to associate a single view ID (such as /user/detail.jspx) with one or more methods that you want to have invoked when the corresponding view template is selected for rendering. You could use a phase-listener approach, but that would still require custom logic to determine whether or not the functionality should be executed for the current view and phase. Not only does this solution lead to a lot of redundant logic, but you end up hardcoding the view IDs -- easily the most irresolute component of the application -- into your compiled Java code.

Page actions to the rescue!

Seam's page actions give you a way to intercept rendering glitches before they happen. Page actions are specified using method bindings that are executed when entering a page, just prior to the Render Response phase. You can configure any number of method bindings for a given view ID in the /WEB-INF/pages.xml configuration file. (Alternatively, you can split up the definitions on a per-page basis by placing them in a file adjacent to the view template, cloning its name but replacing the file extension with *.page.xml.) In the case of page actions, the XML is desirable since view IDs are volatile to change. Just as JSF maps post data onto model objects through value bindings during the Apply Request Values phase, Seam can map arbitrary request parameters onto model objects through value bindings prior to the execution of the page action. The configuration of these request parameter injections are nested within the page action XML declaration. If a page action method invocation returns a non-null string value, Seam treats it as a navigation event. Hence, without migrating to a full-blown action-based framework, it is still possible to emulate the most distinctive feature of one. Seam includes an ample set of built-in page actions that are commonly used across applications. The set includes an action to verify that a conversation is established; actions that can start, nest, and end conversations; an action to handle bubbled exceptions; and an action that ensures proper credentials.

Page actions are the key to enabling bookmarking support for JSF. Seam's creators leveraged this feature by allowing the magic request parameter actionMethod to trigger a method invocation upon entering a page. Even better, you don't need to do any extra work to create links for bookmarking. Seam provides two component tags, s:link and s:button, to handle the details for you. These two tags correspond to their native JSF counterparts, h:commandLink and h:commandButton, respectively. The difference is that links assembled by the Seam component tags issue requests using an HTTP GET operation, rather than the HTTP POST form submission model indicative of JSF. Thus, links created by Seam are "friendlier" to bookmarking and considered to be far more convenient for developers.

You may also notice that when you use page actions, the URL in the location bar corresponds to the page being shown rather than always being one page behind. (The latter situation occurs because JSF configures forms to post back to the same URL that generated them. The location bar does not get updated to reflect the new view after an action because JSF advances to it through a server-side redirect.) If you really want to demonstrate the flexibility of page actions, you can use them to create RESTful URLs (for example, /faces/product/show/10). To do so, you map the page action method to the view ID "/product/show/*", where the /faces prefix is the JSF servlet-mapping portion. The page action method then mines the request URL to determine the type of data and the data identifier, loads that data, and then navigates to the appropriate template. This example clearly demonstrates that the one-to-one mapping between a JSF request URL and view template is not imperative.

Factory components

One of the biggest frustrations with JSF is that it provides no definitive moment during which to prepare data for the view, apart from within a user-triggered action or action-listener method. Placing the logic inside an action method does not guarantee that it will be executed prior to rendering because a page view is not always preceded by a user-triggered event.

For example, consider what happens when the URL to a JSF application is initially requested. If you are required to display a collection of data retrieved from the service layer on this page, there is just no good opportunity in the JSF life cycle to fetch the data. You might assume that you can stick the logic inside the getter method of the backing bean that maps to the value binding expression in the view. However, each time JSF resolves that expression, it triggers an additional invocation, which could in turn hit the service layer. With just a few components on the page, it is possible that the getter method will be called upwards of a half-dozen times. Clearly this is not optimal in terms of performance! Even if you maintain state by using a private property on the managed bean, you still have to add extra plumbing each time you are faced with this use case. One solution, as you've learned, is to use Seam's page actions. But this task is so common that Seam offers an even easier solution.

Seam introduces the concept of a factory data provider, which is designated by the @Factory Java 5 annotation. While there are a couple of ways to configure the factory, the end result is that the data is prepared exactly once, when first requested. Seam ensures that subsequent requests for the same data will return the previously created result set rather than triggering an additional invocation of the lookup method. Combined with conversations, the factory data provider becomes a very powerful feature for implementing a short-term cache of data that could otherwise be expensive to retrieve. Given that JSF does not care to reduce the number of times it resolves a value binding expression, Seam's factory feature often comes in handy.

Stateful conversations

One of the common points of confusion about JSF is its state management facility. The JSF specification explains how pages are "restored" after receiving an action, during which time events are queued and selections registered. Examining the words used in the specification reveals that while the component tree is restored on a postback, the backing bean data used by those components is not restored. The components merely store value bindings (EL expressions using the syntax #{value}) as string literals, which only resolve to the underlying data at run time. This means that if a value is stored in a short-term scope, such as page or request scope, it will be absent by the time the JSF life cycle arrives at the Restore View phase.

The most noticeable downside of not storing value binding data in the component tree is the ghost event effect (see Resources), which is caused by transient parent components in the UIData family. If model data referenced by a value binding expression is no longer available or has changed prior to the component tree being restored, it can result in portions of the tree being dropped. If an event had been triggered from a component within one of these dropped branches, then it will not be discovered and its omission will be remarkably silent (except for the sound of queue developers screaming, "Why isn't my action being called?!").

While the lost events may seem like an exceptional condition, it raises no red flags in the JSF life cycle. Because these components rely on the underlying data to be stable to be properly restored, it is hard for JSF to know that something is missing.

Unfortunately, the JSF specification naively leads developers down a path of placing most backing beans in session scope -- you could even call it "convenient" scope. Server administrators then have to deal with the fallout in the form of "out of memory" errors, server affinity in clustered environments, and serialization exceptions on server restarts. The MyFaces Tomahawk project does offer a solution to ghost events in the form of the t:saveState tag. The MyFaces tag allows you to store data (including entire backing beans) as part of the component tree rather than just the value bindings. This solution is rather crude, however, closely resembling the use of hidden form fields to pass along values between requests. It also creates a tight coupling between the view and the controller. The creators of Seam recognized that the three built-in contexts (request, session, and application) in the Java Servlet specification do not constitute a sufficient set of scopes for data-driven Web applications. With Seam, they introduced the conversation scope, which is a stateful scope bounded by start and end points in the page flow.

Seam's conversation scope

"Seam emphasizes the use of stateful components." This statement, from the Seam reference documentation, embodies the core vision of Seam. The mindset surrounding Web applications has long been that they are stateless -- a philosophy that can be partially attributed to the stateless nature of the HTTP protocol. Most frameworks cater to this preference by offering one-shot-processing before concluding with the rendering of a page. This approach causes considerable impedance because any significant application demands long-running conversations to satisfy certain use cases. Examples of applications that require a stateful context include a store checkout process, product customization, multipage form wizards, and many other applications based on linear interactions. While some of these cases can certainly get away with using URL parameters (aka RESTful URLs) and hidden fields to migrate the data from page to page, doing so quickly becomes cumbersome for the developer. At this point, it also has to be considered outdated. Because most Web frameworks are still operating under the stateless model, you often find yourself stepping outside of the framework to "hack" custom solutions.

JSF attempts to introduce a stateful context by depending heavily on the HTTP session. In fact, JSF components behave much better -- one could even argue they behave as expected -- when working with session-scoped backing beans. Without careful design, overuse of the HTTP session can cause severe memory leaks, performance bottlenecks, and security problems. Additionally, using the HTTP session can cause very strange behavior in a multitab browser environment and break the user's sacred Back button. The important point here, though, is that JSF only meets you halfway: it is a stateful UI and handles all the details of saving and restoring the component tree, but it provides no assistance in saving and restoring your data. Under this agreement, JSF brings the stateful UI and you bring the stateful data. Unfortunately, the burden is placed on you to ensure that they coincide.

Prior to Seam, the only convenient way to have stateful data was to rely on the HTTP session. Seam rectifies this and completes JSF's state management picture by establishing an entirely new conversation scope. With Seam's addition to the JSF life cycle, the conversation context is tied to a single browser window (or tab), identified by a token that is submitted with each request. The conversation scope migrates data between pages using an isolated segment of the HTTP session. Keep in mind that Seam's use of the HTTP session for conversation persistence is completely transparent. Seam does not carelessly dump components into the HTTP session, leaving them there indefinitely. Instead, the life cycle of that segment of session data is carefully managed by Seam and it is automatically cleaned up when the conversation terminates. Seam cleverly uses bijection to allow data to flow in and out of each page of a "Web conversation" in a new, declarative manner. Seam's conversation scope simultaneously overcomes the limits of the HTTP session and helps to wean developers away from its use.

Exception handling

Seam's creator has said that "JSF is surprisingly limited when it comes to exception handling," and there is certainly no arguing with him on this point. The JSF specification completely disregards exception management, placing its responsibility entirely on the servlet container. The problem with allowing the servlet container to handle exceptions is that it severely limits what can be displayed on the resulting error page and makes transactional rollbacks all but impossible. Because the error page is displayed after a request-dispatcher forward, the FacesContext is no longer in scope and it is therefore too late to do any business logic. Your last-ditch hope is to reach into the Servlet API and grab the javax.servlet.error.* request attributes to search the information for some indication of what went wrong.

Once again, Seam comes to the rescue by offering elegant and declarative exception handling. Exception management is designated either through annotations or in a configuration file. The annotations @HttpError, @Redirect, and @ApplicationException can be placed on top of exception classes to indicate an action that should be taken in the event that they are thrown. For those exception classes that are not accessible for modification, the XML configuration option can be used. The exception manager in Seam is responsible for sending HTTP status codes, performing redirects, forcing page rendering, terminating conversations, and customizing user messages when an exception is raised. Because JSF cannot change the course of action after beginning to render the response, some inherent limitations dictate when these exceptions can be handled. Appropriate use of other Seam features, such as page actions, can ensure that most, if not all, exceptional situations can be addressed prior to rendering the response.

Ajax remoting

Because the release of the final JSF specification nearly coincided with the explosion of Ajax, the JSF framework offers very little assistance in the area of asynchronous JavaScript and partial page rendering. For some time, it even appeared that the two styles of programming were at odds with each other. Eventually, solutions began to roll out that suggested using JSF PhaseListeners or component Renderers to handle partial page updates. Even then, it was readily apparent that JSF made adopting Ajax more difficult than it had to be. Some projects, such as ICEfaces, went so far as to completely replace the JSF life cycle with one better designed for page-to-server communication (known as direct-to-DOM rendering).

Seam offers a unique approach to JavaScript remoting (a technology often grouped under the Ajax umbrella) that loosely parallels that of the Direct Web Remoting (DWR) library. Seam fuses the client and server together by allowing JavaScript to directly invoke methods on server components. Seam remoting is more powerful than DWR because it has access to the rich contextual component model as opposed to merely an isolated endpoint. This interaction builds on the event-driven design of JSF, allowing it to more closely follow the Swing paradigm. The best part is that this functionality is provided with almost no added development effort. A simple annotation, @WebRemote on a component's method, makes it accessible to JavaScript. Once the state of the server component has been modified, partial rendering can be then handled by the Ajax4JSF component library. In short: The Seam remoting library enables JSF to achieve the interactive design that its creators had envisioned all along.


In conclusion

Based on what you've learned so far in the Seamless JSF series, it would not seem far-fetched to argue that developing in JSF without using Seam is preposterous. For further proof, look no further than the ballot results for JSR 299, Web Beans (see Resources). It is clear that at some point in the near future, Seam will be an official spec, and the Java EE stack will finally offer "a significantly simplified programming model for Web-based applications." This is good news for JSF developers and for Seam. But even without the claim of being a Java standard, Seam is a worthy complement to JSF.

Seam requires very little setup to begin plugging the gaps in JSF -- and for that small effort, it resolves some of the most troubling conundrums of JSF development. Benefits trump effort -- and the ones discussed here are only the beginning of what there is to like about Seam.



Download

DescriptionNameSizeDownload method
Barebones Seam project1j-seam1.zip13KB HTTP

Information about download methods

Note

  1. This project skeleton uses the Maven 2 build infrastructure. All dependencies will be fetched on demand when the build is executed.

Resources

Learn

Get products and technologies

Discuss

About the author

Dan Allen

Dan Allen is currently a senior Java engineer at CodeRyte, Inc. He is also a passionate open source advocate and gets a bit manic whenever he catches sight of a penguin. After graduating from Cornell University with a degree in Materials Science and Engineering, Dan became captivated by the world of Linux and open source software. He has been slaving over Web applications ever since, with the last several years focused exclusively on Java-related technologies, including Spring, Hibernate, Maven 2, and the abundant JSF stack. You can keep up with Dan's development experiences by subscribing to his blog at http://www.mojavelinux.com.

Comments (Undergoing maintenance)



Trademarks  |  My developerWorks terms and conditions

Help: Update or add to My dW interests

What's this?

This little timesaver lets you update your My developerWorks profile with just one click! The general subject of this content (AIX and UNIX, Information Management, Lotus, Rational, Tivoli, WebSphere, Java, Linux, Open source, SOA and Web services, Web development, or XML) will be added to the interests section of your profile, if it's not there already. You only need to be logged in to My developerWorks.

And what's the point of adding your interests to your profile? That's how you find other users with the same interests as yours, and see what they're reading and contributing to the community. Your interests also help us recommend relevant developerWorks content to you.

View your My developerWorks profile

Return from help

Help: Remove from My dW interests

What's this?

Removing this interest does not alter your profile, but rather removes this piece of content from a list of all content for which you've indicated interest. In a future enhancement to My developerWorks, you'll be able to see a record of that content.

View your My developerWorks profile

Return from help

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=Java technology, Web development
ArticleID=209630
ArticleTitle=Seamless JSF, Part 1: An application framework tailor-made for JSF
publish-date=04172007
author1-email=dan.allen@mojavelinux.com
author1-email-cc=

My developerWorks community

Tags

Help
Use the search field to find all types of content in My developerWorks with that tag.

Use the slider bar to see more or fewer tags.

Popular tags shows the top tags for this particular content zone (for example, Java technology, Linux, WebSphere).

My tags shows your tags for this particular content zone (for example, Java technology, Linux, WebSphere).

Use the search field to find all types of content in My developerWorks with that tag. Popular tags shows the top tags for this particular content zone (for example, Java technology, Linux, WebSphere). My tags shows your tags for this particular content zone (for example, Java technology, Linux, WebSphere).

Rate a product. Write a review.

Special offers