Jboss seam framework Tutorial

how jboss seam works and jboss seam architecture and jboss seam interview questions
GregDeamons Profile Pic
GregDeamons,New Zealand,Professional
Published Date:03-08-2017
Your Website URL(Optional)
Comment
Introducing JBoss Seam This chapter covers ■ Web application development with JSF and EJB 3.0 ■ Improving web applications with Seam ■ Integrating Seam with Hibernate Validator ■ Managing persistence contexts with Seam 747748 CHAPTER 17 Introducing JBoss Seam In this last chapter, we show you the JBoss Seam framework. Seam is an innovative new framework for web application development with the Java EE 5.0 platform. Seam brings two new standards, JavaServer Faces (JSF) and EJB 3.0, much closer together, by unifying their component and programming models. Most attractive for developers who rely on Hibernate (or any Java Persistence provider in EJB 3.0) is Seam’s automatic persistence context management and the first-class constructs it provides for the definition of conversations in the application flow. If you’ve ever seen a LazyInitializationException in your Hibernate application, Seam has the right solutions. There is much more to be said about Seam, and we encourage you to read this chapter even if you already made a decision for a different framework or if you aren’t writing a web application. Although Seam currently targets web applica- tions and also relies on JSF as a presentation framework, other options should be available in the future (you can already use Ajax calls to access Seam components, for example). Furthermore, many central concepts of Seam are currently being standardized and brought back into the Java EE 5.0 platform with the Web Beans JSR 299 (http://www.jcp.org/en/jsr/detail?id=299). There are many ways to explain Seam and equally many ways to learn Seam. In this chapter, we first look at the problems Seam promises to solve; then, we discuss various solutions and highlight the features that are most appealing to you as a Hibernate user. 17.1 The Java EE 5.0 programming model Java EE 5.0 is significantly easier to use and much more powerful than its prede- cessors. Two specifications of the Java EE 5.0 platform that are most relevant for web application developers are JSF and EJB 3.0. What’s so great about JSF and EJB 3.0? We first highlight major concepts and features in each specification. You’ll then write a small example with JSF and EJB 3.0 and compare it to the old way of writing web applications in Java (think Struts and EJB 2.x). After that, we’ll focus on the issues that are still present and how Seam can make JSF and EJB 3.0 an even more powerful and convenient combination. Note that it’s impossible to cover all of JSF and EJB 3.0 in this chapter. We rec- ommend that you read this chapter together with the Sun Java EE 5.0 tutorial (http://java.sun.com/javaee/5/docs/tutorial/doc/) and browse through the tutorial if you want to know more about a particular subject. On the other hand, ifThe Java EE 5.0 programming model 749 you’ve already had some contact with JSF or EJB 3.0 (or even Hibernate), you’ll likely find learning Seam easy. 17.1.1 Considering JavaServer Faces JSF simplifies building web user interfaces in Java. As a presentation framework, JSF provides the following high-level features: ■ JSF defines an extensible component model for visual components, often called widgets. ■ JSF defines a component programming model for backing beans, or managed beans, which contain the application logic. ■ JSF defines the interaction between the user interface and the application logic and allows you to bind both together in a flexible fashion. ■ JSF allows you to define navigation rules declaratively in XML—that is, which page is displayed for a particular outcome in your application logic. Let’s spend a little more time on each of these features and what makes them useful. JSF defines a set of built-in visual components that every JSF implementation has to support (such as buttons and input text fields). These visual components HTML (and Javascript). At the time of writing, several are rendered on pages as high-quality open source and commercial JSF widget libraries are available. Ready- made visual components are great for you as a developer; you don’t have to code them by hand, and, most important, you don’t have to maintain them or make them work on different browsers (which is especially painful if you need more sophisticated visual components that use Javascript). HTML templating engine that understands JSF Pages are created with any widgets. Although JSP seems like an obvious choice, in our experience it isn’t the best. We found that JavaServer Facelets (https://facelets.dev.java.net/) is a perfect fit for building JSF views and creating HTML templates that contain JSF widgets. (Another nice bonus of using Facelets is that you get the new unified expression language for free, even without a JSP 2.1-capable servlet container.) We’ll use JSF examples in this chapter. Facelets in all JSF-managed application components, called backing beans, make your web application interface work; they contain the application code. These are regular POJOs, and they’re defined and wired together in JSF XML configuration files. This wiring supports basic dependency injection, as well as lifecycle management750 CHAPTER 17 Introducing JBoss Seam of backing bean instances. The available scopes for a backing bean (where it lives) are the current HTTP request context, the current HTTP session context, and the global application context. You write application logic by creating beans and letting JSF manage their lifecycle in one of these contexts. You can bind model values from a backing bean to a visual component with an expression language. For example, you create a page with a text input field and bind it to a named backing bean field or getter/setter method pair. This backing bean name is then mapped in JSF configuration to an actual backing bean class, along with a declaration of how an instance of that class should be handled by JSF (in the request, in the HTTP session, or in the application context). The JSF engine automatically keeps the backing bean field (or property) synchronized with the state of the widget as seen (or manipulated) by the user. JSF is an event-driven presentation framework. If you click a button, a JSF ActionEvent is fired and passed to registered listeners. A listener for an action event is again a backing bean you name in your JSF configuration. The backing bean can then react to this event—for example, by saving the current value of a backing bean field (which is bound to a text input widget) into the database. This is a simplified explanation of what JSF does. Internally, each request from the web browser passes through several phases of processing. A typical request-processing sequence on the server, when you click a button on a JSF page, is as follows (this process is illustrated in figure 17.7): 1 Restore View of all widgets (JSF can store the widget state on the server or on the client). 2 Apply Request Parameters to update the state of widgets. 3 Process Validations that are necessary to validate user input. 4 Update Model Values that back the widget by calling the bound fields and setter methods of a backing bean. 5 Invoke Application, and pass the action event to listeners. 6 Render Response page the user sees. Obviously a request can take different routes; for example, Render Response may occur after Process Validations, if a validation fails. A nice illustration of the JSF lifecycle and the processing phases can be found in the already mentioned Sun Java EE 5 tutorial in chapter 9, “The Life Cycle of a JavaServer Faces Page.” We’ll also get back to the JSF processing model later in this chapter. The Java EE 5.0 programming model 751 Which response is rendered and what page is shown to the user depends on the defined navigation rules and what the outcome of an action event is. Outcomes in JSF are simple strings, like “success” or “failure.” These strings are produced by your backing beans and then mapped in a JSF XML configuration file to pages. This is also called free navigation flow; for example, you can click the Back button in your browser or jump directly to a page by entering its URL. JSF, combined with Facelets, is a great solution if you’re looking for a web framework. On the other hand, the backing beans of your web application—the components that implement the application logic—usually need to access transac- tional resources (databases, most of the time). This is where EJB 3.0 comes into the picture. 17.1.2 Considering EJB 3.0 EJB 3.0 is a Java EE 5.0 standard that defines a programming model for transac- tional components. For you, as a web application developer, the following features of EJB 3.0 are most interesting: ■ EJB 3.0 defines a component programming model that is primarily based on annotations on plain Java classes. ■ EJB 3.0 defines stateless, stateful, and message-driven components, and how the runtime environment manages the lifecycle of component instances. ■ EJB 3.0 defines how components are wired together, how you can obtain ref- erences to components, and how components can call each other. ■ EJB 3.0 defines how crosscutting concerns are handled, such as transactions and security. You can also write custom interceptors and wrap them around your components. ■ EJB 3.0 standardizes Java Persistence and how you can access an SQL data- base with automatic and transparent object/relational mapping. If you want to access an SQL database, you create your domain model entity Item, User, Category) and map them with annotations from the classes (such as Java Persistence specification to a database schema. The EJB 3.0 persistence API, the EntityManager, is now your gateway for database operations. manager You execute database operations in EJB 3.0 components—for example, stateful or stateless session beans. These beans are plain Java classes, which you enable as EJBs with a few annotations. You then get the container’s services, such as EntityManager when you need it) automatic dependency injection (you get the and declarative transaction demarcation on component methods. Stateful session752 CHAPTER 17 Introducing JBoss Seam beans help you to keep state for a particular client, for example, if a user has to go through several pages in a conversation with the application. Can you use EJB 3.0 components and entities as backing beans for JSF actions and widgets? Can you bind a JSF text field widget to a field in your Item entity class? Can a JSF button-click be directly routed to a session bean method? Let’s try this with an example. 17.1.3 Writing a web application with JSF and EJB 3.0 The web application you’ll create is simple; it has a search screen where users can enter an identifier for a particular item, and a detail screen that appears when the item is found in the database. On this detail screen, users can edit the item’s data and save the changes to the database. (We don’t think you should necessarily code this application while reading the examples; later, we make significant improvements by introducing Seam. That’s the time to start coding.) Start with the data model for the entity: an Item. Creating the entity class and mapping The Item entity class comes from CaveatEmptor. It’s also already annotated and SQL database (listing 17.1). mapped to the Listing 17.1 An annotated and mapped entity class package auction.model; import ...; Entity Table(name = "ITEM") public class Item implements Serializable Id GeneratedValue Column(name = "ITEM_ID") private Long id = null; Column(name = "ITEM_NAME", length = 255, nullable = false, updatable = false) private String name; ManyToOne(fetch = FetchType.LAZY) JoinColumn(name="SELLER_ID", nullable = false, updatable = false) private User seller; Column(name = "DESCRIPTION", length = 4000, nullable = false) private String description; Column( name="INITIAL_PRICE", nullable = false)The Java EE 5.0 programming model 753 private BigDecimal initialPrice; Item() // Getter and setter methods... This is a simplified version of the CaveatEmptor Item entity, without any collections. Next is the search page that allows users to search for item objects. Writing the search page with Facelets and JSF The search page of the application is a page written with Facelets as the templat- ing engine, and it’s valid XML. JSF widgets are embedded in that page to create the search form with its input fields and buttons (listing 17.2). Listing 17.2 The search.xhtml page in XHTML with Facelets DOCTYPE html PUBLIC B "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd" html xmlns="http://www.w3.org/1999/xhtml" xmlns:ui="http://java.sun.com/jsf/facelets" C xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core" head titleCaveatEmptor - Search items/title D link href="screen.css" rel="stylesheet" type="text/css"/ /head body E ui:include src="header.xhtml"/ h:form F G span class="errors"h:message for="itemSearchField"//span div class="entry" div class="label"Enter item identifier:/div H div class="input" I h:inputText id="itemSearchField" size="3" required="true" value="itemEditor.itemId" J f:validateLongRange minimum="0"/ /h:inputText /div /div div class="entry"754 CHAPTER 17 Introducing JBoss Seam div class="label"&160;/div div class="input" 1) h:commandButton value="Search" styleClass="button" action="itemEditor.doSearch"/ /div /div /h:form /body /html Every valid XHTML file needs the right document type declaration. B In addition to the regular XHTML namespace, you import the Facelets and two C JSF namespaces for visual HTML components and core JSF components (for exam- ple, for input validation). The page layout is handled with cascading stylesheets (CSS) externalized to a sep- D arate file. E A common page header template is imported with ui:import from Facelets. A JSF form (note the h namespace) is an HTML form that, if submitted, is pro- F cessed by the JSF servlet. JSF can output messages, such as validation errors. G Each div is a label or a form field, styled with the CSS class label or input. H The JSF input text component that renders an HTML input field. The identifier is I useful to bind it to error-message output, the size defines the visual size of the input field, and user input is required when this form is submitted. The most interesting part is the value binding of the input field to a backing bean (named itemEditor) and a getter/setter method pair (named getItemId()/set- ItemId()) on that backing bean. This is the data model this input field is bound to, and JSF synchronizes changes automatically. JSF also supports input validation and comes with a range of built-in valida- J tors. Here you declare that user input can’t be negative (item identifiers are positive integers). The submit button of the form has an action binding to the method doSearch() of 1) the backing bean named itemEditor. What happens after the action executes depends on the outcome of that method. This is how the page looks rendered in the browser (figure 17.1).The Java EE 5.0 programming model 755 Figure 17.1 The search page with JSF widgets If you look at the URL, you see that the page has been called with the suffix .jsf; you probably expected to see search.xhtml. The .jsf suffix is a servlet mapping; the JSF servlet runs whenever you call a URL that ends in .jsf, and after installation of Facelets, you configured it in web.xml to use .xhtml internally. In other words, the search.xhtml page is rendered by the JSF servlet. If you click the Search button without entering a search value, an error message is shown on the page. This also happens if you try to enter a noninteger or nonpositive integer value, and it’s all handled by JSF automatically. If you enter a valid item identifier value, and the backing bean finds the item in the database, you’re forwarded to the item-editing screen. (Let’s finish the user interface before focusing on the application logic in the backing bean.) Writing the edit page The edit page shows the details of the item that has been found in the search and allows the user to edit these details. When the user decides to save his changes, and after all validation is successful, the application shows the search page again. The source code for the edit page is shown in listing 17.3. Listing 17.3 The edit.xhtml page with a detail form DOCTYPE html PUBLIC ... html xmlns= ... head ... body ... B h2Editing item: itemEditor.itemId/h2 h:form span class="errors"h:messages//span756 CHAPTER 17 Introducing JBoss Seam div class="entry" div class="label"Name:/div div class="input" C h:inputText required="true" size="25" value="itemEditor.itemName" f:validateLength minimum="5" maximum="255"/ /h:inputText /div /div div class="entry" div class="label"Description:/div div class="input" h:inputTextarea cols="40" rows="4" required="true" value="itemEditor.itemDescription" f:validateLength minimum="10" maximum="4000"/ /h:inputTextarea /div /div div class="entry" div class="label"Initial price (USD):/div div class="input" h:inputText size="6" required="true" value="itemEditor.itemInitialPrice" f:converter converterId="javax.faces.BigDecimal"/ /h:inputText /div /div div class="entry" div class="label"&160;/div div class="input" h:commandButton value="Save" styleClass="button" D action="itemEditor.doSave"/ /div /div /h:form /body /html You can place a value-binding expression outside of any component. In this case, B the getItemId() method on the itemEditor backing bean is called, and the return value ends up in the HTML page. C Again, a value binding is used to bind the input text field to a getter/setter method pair (or field) in the backing bean. The Java EE 5.0 programming model 757 This action binding references the doSave() method in the itemEditor backing D bean. Depending on the outcome of that method, either the page is displayed again (with error messages) or the user is forwarded to the search page. Figure 17.2 shows the rendered page. Figure 17.2 The edit page with loaded item details Why is the URL showing search.jsf? Shouldn’t it be edit.jsf? Consider the request processing of the JSF servlet. If the user clicks the Search button on the search.jsf page, the backing bean’s doSearch() method runs after input validation. If the outcome of that method triggers a forward to the edit.xhtml page, this document is rendered by the JSF servlet, and the HTML is sent to the browser. The URL doesn’t change Users can’t bookmark the edit page, which in this simple application is desirable. Now that you’ve completed the top layer of the application, the view, consider the layer that accesses the database (you might call this the business layer). Because accessing an SQL database is a transactional operation, you write an EJB. Accessing the database in an EJB If you’ve worked with EJB 2.x (and Struts) before, the code that accesses the data- base is most likely procedural code in a stateless session bean. Let’s do that in EJB 3.0 (listing 17.4). 758 CHAPTER 17 Introducing JBoss Seam Listing 17.4 A stateless session bean with a data access facade package auction.beans; import ...; B Stateless C TransactionAttribute(TransactionAttributeType.REQUIRED) public class EditItemBean implements EditItem D PersistenceContext EntityManager em; E F public Item findById(Long itemId) return em.find(Item.class, itemId); G public Item save(Item item) return em.merge(item); A Stateless annotation turns this plain Java class into a stateless session bean. B At runtime, a pool of instances is prepared, and each client that requests a session bean gets an instance from the pool to execute a method. All methods that are called on this session bean are wrapped in a system transac- C tion, which enlists all transactional resources that may be used during that proce- dure. This is also the default if you don’t annotate the bean. A session bean needs an interface. Usually you implement this interface directly. D The EditItem interface has two methods. When the runtime container hands out a session bean instance from the E pool, it injects an EntityManager with a (fresh) persistence context scoped to the transaction. If a client calls findById(), a system transaction starts. The EntityManager opera- F tion executes an SQL query in that transaction; the persistence context is flushed and closed when the transaction commits (when the method returns). The returned Item entity instance is in detached state. If a client calls save(), a system transaction starts. The given detached instance is G merged into a (new) persistence context. Any changes made on the detached Item instance are flushed and committed to the database. A new handle to the now up-to-date Item instance is returned. This new Item instance is again in detached state when the method returns, and the persistence context is closed. The Java EE 5.0 programming model 759 You can call the session bean shown in listing 17.4 a data access object (DAO). It can also be a session facade. The application isn’t complex enough to make a clear distinction; if more nondata access methods were added to its interface, the session bean would represent part of the business layer interface with a traditional (mostly procedural) session facade. A piece is still missing from the puzzle: The JSF input widgets and buttons have value and action bindings to a backing bean. Is the backing bean the same as the session bean, or do you have to write another class? Connecting the layers with a backing bean Without Seam, you have to write a backing bean that connects your JSF widget state and actions to the transactional stateless session bean. This backing bean has the getter and setter methods that are referenced with expressions in the pages. It can also talk to the session bean and execute transactional operations. The code for the backing bean is shown in listing 17.5. Listing 17.5 A JSF backing bean component connects the layers. package auction.backingbeans; import ... B public class ItemEditor C private Long itemId; D private Item item; public Long getItemId() return itemId; public void setItemId(Long itemId) this.itemId = itemId; public String getItemName() return item.getName(); E public void setItemName(String itemName) this.item.setName( itemName ); public String getItemDescription() return item.getDescription(); public void setItemDescription(String itemDescription) this.item.setDescription( itemDescription ); 760 CHAPTER 17 Introducing JBoss Seam public BigDecimal getItemInitialPrice() return item.getInitialPrice(); E public void setItemInitialPrice(BigDecimal itemInitialPrice) this.item.setInitialPrice( itemInitialPrice ); public String doSearch() F item = getEditItemEJB().findById(itemId); return item = null ? "found" : null; public String doSave() G item = getEditItemEJB().save(item); return "success"; private EditItem getEditItemEJB() H try return (EditItem) new InitialContext() .lookup("caveatemptor/EditItemBean/local"); catch (NamingException ex) throw new RuntimeException(ex); You don’t implement any interfaces; this is a plain Java class. B The backing bean maintains an item identifier internally with a field. C The backing bean also holds the Item instance that is being edited by a user. D Getter and setter methods for all value bindings in search.xhtml and E edit.xhtml. These are the methods used by JSF to synchronize the backing beans internal model state with the state of UI widgets. The doSearch() method is bound to the action of a JSF button. It uses the EJB ses- F Item instance for the current itemId in the sion bean component to find the backing bean. Its outcome is either the string found or null. The doSave() method is bound to the action of a JSF button. It uses the EJB ses- G sion bean component to save the state of the item field. (Because this is a merge, item field with the returned value, the state after merg- you have to update the ing.) Its outcome is either the string success or an exception. The helper method getEditItemEJB() obtains a handle on the EJB session H bean. This lookup in JNDI can be replaced with automatic dependency injectionThe Java EE 5.0 programming model 761 if the runtime environment supports the Java Servlet 2.5 specification. (At the time of writing, Tomcat 5.5 implements only Java Servlets 2.4, and Tomcat 6 is in alpha stage.) The backing bean is a component that is managed by the JSF runtime. The expressions you use in the pages refer to a backing bean by name, itemEditor. In the JSF XML configuration file (WEB-INF/faces-config.xml usually), you map this name to the backing bean class (listing 17.6). Listing 17.6 A JSF configuration describes the backing bean and navigation flow. ?xml version="1.0"? DOCTYPE faces-config PUBLIC "-//Sun Microsystems, Inc.//DTD JavaServer Faces Config 1.0//EN" "http://java.sun.com/dtd/web-facesconfig_1_1.dtd" faces-config managed-bean managed-bean-nameitemEditor/managed-bean-name managed-bean-class auction.backingbeans.ItemEditor /managed-bean-class managed-bean-scopesession/managed-bean-scope /managed-bean navigation-rule from-view-id/search.xhtml/from-view-id navigation-case from-outcomefound/from-outcome to-view-id/edit.xhtml/to-view-id /navigation-case /navigation-rule navigation-rule from-view-id/edit.xhtml/from-view-id navigation-case from-outcomesuccess/from-outcome to-view-id/search.xhtml/to-view-id /navigation-case /navigation-rule /faces-config This application has one backing bean and two navigation rules. The backing bean is declared with the name itemEditor and implemented by auction.back- ingBeans.ItemEditor. Expressions in JSF pages can now reference methods and762 CHAPTER 17 Introducing JBoss Seam fields of that backing bean in a loosely coupled fashion, by name. The JSF servlet manages instances of the backing bean, one instance for each HTTP session. Let’s take this one step further: An expression in a JSF page is a string, such as itemEditor.itemId. This expression basically results in a search for a variable named itemEditor. Searched, in that order, are the current request, the current HTTP session, and the current application context. If a JSF page renders and this expression has to be evaluated, then either a variable with that name is found in the HTTP session context, or the JSF servlet creates a new backing bean instance and binds it into the HTTP session context. The navigation rules declare which page is rendered after an action outcome. This is a mapping from strings, returned by actions, to pages. Your application is now complete; it’s time to analyze it in more detail. 17.1.4 Analyzing the application Possibly you look at the code in the previous sections and think, “This was a lot of code to write to put four form fields onto web pages and connect them to four columns in the database.” Or, if you’ve spent a lot of time with EJB 2.x and Struts, you’ll probably say, ”This is great: I don’t have to manage the HTTP session myself anymore, and all the EJB boilerplate code is gone.” You’re right either way. Java EE 5.0 and especially JSF and EJB 3.0 are a significant step forward for Java web applications, but not everything is perfect. We’ll now look at the advantages of Java EE 5.0 and compare it to J2EE 1.4 and web frameworks before JSF. But we’ll also try to find things that can be improved, code that can be avoided, and strategies that can be simplified. This is where Seam comes in later. Comparing the code to J2EE J2EE 1.4/Struts background, this JSF and EJB 3.0 application already If you have a looks much more appealing. There are fewer artifacts than in a traditional Java Item instance from the session web application—for example, you can detach an bean facade and transfer it into the JSF backing bean. With EJB 2.x entity beans, DTO) to do this. you needed a data transfer object ( The code is much more compact. With EJB 2.x, the session bean must SessionBean interface with all its maintenance methods. In EJB implement the 3.0, this is resolved with a simple Stateless annotation. There is also no Struts ActionForm code that manually binds the state of an HTML form field to an instance variable in the action listener. The Java EE 5.0 programming model 763 Overall, the application is transparent, with no obscure calls that maintain val- ues in the HTTP session or in the HTTP request. JSF transparently puts and looks up values in these contexts. If you consider the object/relational mapping of the Item class, you’ll probably agree that a few annotations on a POJO are simpler than a deployment descriptor for an EJB 2.x entity bean. Furthermore, object/relational mapping as defined by Java Persistence is not only much more powerful and feature-rich than EJB 2.x. entity beans, but also a lot easier to use (even compared to native Hibernate). What we couldn’t show in a simple application is the power behind JSF and EJB 3.0. JSF is amazingly flexible and extensible; you can write your own HTML wid- gets, you can hook into the processing phases of a JSF request, and you can even create your own view layer (if Facelets isn’t what you want) without much effort. EJB 3.0 is much easier to tame than EJB 2.x, and it also has features (such as inter- ceptors and dependency injection) that have never before been available in a standardized Java programming model. The application can easily be tested with a testing framework like JUnit or TestNG. All classes are plain Java classes; you can instantiate them, set (mock) dependencies manually, and run a test procedure. However, there is room for improvement. Improving the application JSF/EJB 3.0 application is the JSF backing The first thing that stands out in this bean. What’s the purpose of this class? It’s required by JSF, because you need to bind values and actions to its fields and methods. But the code doesn’t do anything useful: It passes any action to an EJB, one to one. Worse, it’s the artifact with the most lines of code. You might argue that it decouples the view from the business layer. That EJB with a different view layer (say, a rich seems reasonable, if you use your client). Still, if the application is a simple web application, the backing bean results in tighter coupling between the layers. Any change you make to either the view or the business layer requires changes to the component with the most lines of code. If you want to improve the code, get rid of the artificial layering and remove the backing bean. There is no reason why an EJB shouldn’t be the backing bean. A programming model shouldn’t force you to layer your application (it shouldn’t restrict you, either). To improve the application, you need to collapse artificial layers. The application doesn’t work in several browser windows. Imagine that you open the search page in two browser windows. In the first, you search for item 1;764 CHAPTER 17 Introducing JBoss Seam in the second, you search for item 2. Both browser windows show you an edit screen with the details of item 1 and item 2. What happens if you make changes to item 1 and click Save? The changes are made on item 2 If you click Save in the first browser window, you work on the state that is present in the HTTP session, where the backing bean lives. However, the backing bean no longer holds item 1—the current state is now the state of the second browser window, editing item 2. In other words, you started two conversations with the application, but the conversations weren’t isolated from each other. The HTTP session isn’t the right context for concurrent conversation state; it’s shared between browser windows. You can’t fix this easily. Making this (trivial) application work in several browser windows requires major architectural changes. Today, users expect web applications to work in several browser windows. JSF page first tries to resolve the item- The application leaks memory. When a Editor variable, a new instance of ItemEditor is bound to the variable in the HTTP session context. This value is never cleaned up. Even if the user clicks Save on the edit screen, the backing bean instance stays in the HTTP session until the user logs out or the HTTP session times out. Imagine that a much more sophisticated application has many forms and many backing beans. The HTTP session grows as the user clicks through the application, and replicating the HTTP session to other nodes in a cluster gets more expensive with every click. If a user comes back to the item search screen, after working with another module of the application, old data is shown in the forms. One solution for this problem would be manual cleanup of the HTTP session at the end of a conversation, but there is no easy way to do this. With JSF and EJB 3.0, you must code this manually. In our experience, handling variables and values in the HTTP session manually is a common source of issues that are incredibly difficult to track down. The flow of the application is difficult to visualize and control. How do you know where clicking the Search button will take you? At a minimum, you have to look into two files: the backing bean, which returns string outcomes, and the JSF XML configuration file, which defines the page shown for a particular outcome. There is also the ever-present problem of the Back button in the browser, a nasty problem in any conversation that has more than two screens. Think also about the business process. How can you define that your flow of pages is part of a larger business process? Imagine that searching and editing an item is only one task in a business process that involves many more steps—for example, as part of a review process. No tools or strategies help you integrate business process management in your application. Today, you can no longerImproving the application with Seam 765 afford to ignore the business processes of which your applications is a part; you need a programming model that supports business-process management. Finally, this application includes too much XML. There is no way around meta- data in the application, but not all of it has to be in an XML file. Metadata in XML files is great if it changes independently from code. This may be true for naviga- tion rules, but it probably isn’t true for the declaration of backing beans and the context they live in. This kind of metadata grows linearly with the size of your application—every backing bean must be declared in XML. Instead, you should put an annotation on your class that says, “I’m a backing bean for JSF, and I live inside the HTTP session (or any other) context.” It’s unlikely that your class will suddenly change its role without any changes to the class code. If you agree with this analysis, you’ll like Seam. 17.2 Improving the application with Seam The web application you’ve written to search and edit web items can be improved if you add Seam into the mix. You start with basic Seam features: ■ Seam makes the JSF backing bean unnecessary. You can bind JSF widget values and actions directly to EJB stateful and stateless session beans. Seam introduces a unified component model: All your classes can be turned into Seam components with annotations. Components are wired together in a loosely coupled fashion, with string expressions. ■ Seam introduces new contexts and manages component scope automatically. This rich context model includes logical contexts that are meaningful to the application, such as a conversation or business-process context. ■ Seam introduces a stateful programming model, which is great for conversations. A stateful application with Seam-managed conversations works in multiple browser windows with no extra effort. This is a short list of what Seam can do; there is much more that you’ll put to use later. Let’s first create a basic conversational, stateful, simple Seam application. Your first step is Seam setup and configuration. If you want to follow the examples with code, download the CaveatEmptor package for Seam from http://caveatemptor.hibernate.org, and open it in your IDE. This is also a good starting point if you want to code your own Seam project later. 766 CHAPTER 17 Introducing JBoss Seam 17.2.1 Configuring Seam Figure 17.3 shows the files before and after the changes you make to the web application in the following sections. Figure 17.3 The application archive before and after Seam was introduced Two major changes are made: The JSF backing bean is no longer necessary, and the beans.jar archive has a new file, seam.properties. This file contains two Seam configuration options for this simple application (listing 17.7). Listing 17.7 A simple seam.properties configuration file org.jboss.seam.core.init.jndiPattern = caveatEmptor/ejbName/local org.jboss.seam.core.manager.conversationTimeout = 600000 The first setting is necessary for Seam to integrate with an EJB 3.0 container. Because Seam is now responsible for wiring component instances at runtime, it