3.2 Seam JSF Enhancements
Seam provides its own JSF enhancements that work with both Facelets XHTML and JSP pages. You can use Seam UI tags in your JSF view pages, use Seam's special extension to the JSF EL, and use the Seam filter to make Seam work better with the JSF URL redirecting and error handling mechanisms. Those Seam JSF components work with Seam framework features not yet discussed in the book. In this section, we will provide an overview of those enhancements but leave the details to later chapters of the book. Impatient readers can safely skip to Section 3.3 for instructions on how to install those Seam JSF components.
3.2.1 Seam UI Tags
The Seam UI tags give regular JSF UI components access to the Seam-managed runtime information. They help integrate Seam's business and data components more tightly with the web UI components. Seam UI tags can be roughly divided into the following categories:
- validation The Seam validation tags allow you to use Hibernate validator annotations on entity beans to validate JSF input fields. They also allow you to decorate an entire invalid (or valid) field when the validation fails. See Chapter 12 for more on using those components.
- conversation management A key concept in Seam is the arbitrarily long web conversation (see Chapter 8). Normally, the web pages in a conversation are connected via hidden fields in HTTP POST operations. But what if you want to click on a regular hyperlink and still stay in the same conversation? Seam provides tags that can generate conversation-aware hyperlinks. See Sections 8.3.6 and 9.2.2 for more.
- business process management Seam provides tags that can associate web page content with business processes in the background (see Chapter 24).
- performance The <s:cache> tag encloses page content that should be cached on the server. When the page is rendered again, the cached region is retrieved from the cache instead of being dynamically rendered (see Chapter 30).
- JSF replacement tags Some Seam tags are a direct replacement for JSF tags to fix certain deficiencies in JSF. Right now, the only such tag is <s:convertDateTime>, which fixes JSF's annoying default time zone problem.
- alternative display output In addition to the standard HTML output, Seam provides JSF tags that render PDF and email outputs based on Facelets templates. It also provides tags to render Wikitext snippets into HTML elements. Refer to Section 3.4 for more details on those alternative display technologies supported by the Seam tag library.
Later chapters cover the use of these Seam UI tags when we discuss specific Seam features related to them. Here, we use the <s:convertDateTime> tag as an example to demonstrate how Seam UI tags are used. The <s:convertDateTime> tag replaces JSF's converter tag, <f:convertDateTime>, to convert the backend Date or Time objects to formatted output/input strings in the server's local time zone. The JSF tag is insufficient because it converts the time stamp to the UTC time zone by default. The sensible default time zone in the Seam tag makes life a lot easier for developers. To use the Seam UI tags in a web page, you need to declare the Seam taglib namespace as follows:
<html xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core" xmlns:s="http://jboss.com/products/seam/taglib"> ... ... The old hello date is:<br/> <h:outputText value="#{manager.helloDate}"> <s:convertDateTime/> </h:outputText> Please enter a new date:<br/> <h:inputText value="#{manager.helloDate}"> <s:convertDateTime/> </h:inputText> </html>
3.2.2 Seam JSF EL Enhancement
Chapter 2 showed that the JSF #{...} EL notation is highly useful. However, in standard JSF EL, the "property" (value expression) and "method" (method expression) on the backend component are the same. As a result, the EL method expression cannot take any call arguments. For instance, the name property on the person component is expressed as follows:
<h:inputText value="#{person.name}" size="15"/>
The event handler method sayHello() on the manager component is written the same way, as shown below, and therefore cannot take any call arguments. All the objects the method operates on must be injected into the component before the method is called.
<h:commandButton type="submit" value="Say Hello" action="#{manager.sayHello}"/>
With the Seam EL extension, you can now call any component method with the () to improve readability:
#{component.method()}
The method can now take call arguments as well. So, with the following example, you no longer need to inject the person component into the manager component. That reduces the need for dependency injection and makes the application easier to read.
<h:commandButton type="submit" value="Say Hello" action="#{manager.sayHello(person)}"/>
Here is the new ManagerAction class with the new sayHello() method:
@Stateless @Name("manager") public class ManagerAction implements Manager { private Person person; @Out private List <Person> fans; @PersistenceContext private EntityManager em; public void sayHello (Person p) { em.persist (p); fans = em.createQuery("select p from Person p").getResultList(); } }
The enhanced EL allows multiple call arguments separated by commas. If the backend method takes a String argument, you can pass it directly in the EL as follows:
... action="#{component.method('literal string')}"/>
The new Seam JSF EL makes your code more readable and more elegant. Use it!
3.2.3 Use EL Everywhere
Seam not only expands the syntax of JSF EL but also makes the EL available beyond JSF web pages. In a Seam application, you can use JSF expressions to substitute static text in configuration files (Section 9.2.1), test cases (Chapters 26 and 27), JSF messages (Section 8.1.2), and jBPM processes (Chapter 24).
The expanded use of JSF EL greatly simplifies application development.
3.2.4 Seam Filter
Seam provides a very powerful servlet filter. The filter does additional processing before the web request is processed by JSF and after the web response is generated. It improves integration between Seam components and JSF.
- The filter preserves the conversation context during JSF URL redirects. That allows the Seam default conversation scope to span from the request page to the redirected response page (Chapter 8).
- It captures any uncaught runtime errors and redirects to custom error pages or the Seam debug page, if necessary (Chapter 17).
- It provides support for the file upload JSF component in Seam UI.
- It allows any non-JSF servlet or JSP page to access Seam components via the Seam Component class.
See Section 3.3 for how to install the Seam filter in your web.xml.
3.2.5 Stateful JSF
Perhaps the most important feature of Seam is that it is a stateful application framework. The stateful design has great implications for JSF. For instance, it enables much tighter integration between JSF and ORM solutions such as Hibernate (Section 6.1) and allows JSF messages to propagate across different pages (Section 8.1.2). Throughout the rest of this book, we will cover how Seam's stateful design improves web application development.