1) Introduction
Yet another Web Application Framework! This time it is from JBoss Community. JBoss provides a new Web Application Framework called “JBoss Seam” which combines the advantages from the two rapidly growing technologies Enterprise Java Beans 3.0 and Java Server Faces. JBoss Seam, by sitting on top of J2EE provides a nice way of integration between JSF and EJB Components with other great functionalities. This article is an introductory article only and it covers the idea that gave birth to JBoss Seam, its advantages, the various modules involved along with a Sample Application. This article assumes the readers to have some bit of knowledge and programming in areas like Java Server Faces and Enterprise Java Beans 3.0. For more information about these technologies, visit JSF and EJB 3.0.
2) The Need for JBoss Seam
Let us exactly define what JBoss seam is. JBoss Seam provides a Light-weight Container for J2EE standards and it addresses the long-standing issues in any Typical Web Application like State Management and Better Browser Navigation. It also neatly provides an integration between the two popular technologies, Java Server Faces (in the UI tier) and Enterprise Java Beans (EJB 3 in the Server Side). Before getting into the various details about JBoss Seam let us see the common set of problems that are being faced in a Development and the Usability of a typical Web Application using Java Server Faces and Enterprise Java Beans.
For this, let us assume an imaginary application. Let us keep the requirements of the imaginary Web Application we are going to consider very small. The Web Application is a simple Registration Application, which provides the user with a View which contains username and password text-fields. User can click the submit button after filling both the fields. If the username password information given by the user is not found in the database, the user is assumed to be a new user and he is greeted with a welcome message; else an error page is displayed with appropriate message.
Let us analysis the roles of JSF and EJB 3.0 in this Web Application. More specifically, we will analysis the various components in both the client as well the server tier along with their responsibilities.
In the Client side, for designing and presenting the form with the input controls (text-field and button) to the user, we may have written a userinput.jsp page with the set of JSF core tag libraries like <f:view> and <h:form>. And then, a JSF Managed Bean called UserBean encapsulated with properties(username and password) may have been coded which serves as a Model. The UI components values within the JSP page would have got bound to the properties of the Managed Bean with the help of JSF Expression Language. Since the logic is to query from the database for the existence of the username and the password, a Stateless Session Facade Bean would have been written whose sole purpose is to persistence the client information to the database. For persistence the information, the Session Bean may depend on the EntityManager API for querying and persisting entities.
The Data Traversal Logic from JSF to EJB Session Bean should have be taken care by the Managed Bean only. The Managed Bean apart from representing a Model may also act as a Listener in handling the button click events. Say, after clicking the register button, one of the action methods within the Managed Bean would have been called by the framework, and here the Bean might have a JNDI Look-up to get an instance of the Session Bean to persisting or querying the user information. If we look at carefully, the JSF Managed Bean is serving as an intermediary between the transfer of Data from the Client to the Server. Within this Managed Bean is the code for getting a reference to the Session Bean for doing various other functionalities. Wouldn’t a direct commnication between JSF UI Components and the Enterprise Bean Components be nice? There is no purpose of the intermediate Managed Bean in this case. JBoss Seam provides a very good solution for this. Not only this many of the outstanding problems that are faced in a Web Application are also addressed and given solution in this Framework.
3) Advantages of JBoss Seam
Following are the major advantages that a Web Application may enjoy if it uses JBoss Seam Framework. They are
- Integration of JSF and EJB
- Stateful Web Applications
- Dependency Bijection Support
Let us look into the various advantages of JBoss Seam in the subsequent sections.
3.1) Integration of JSF and EJB
Today the Web Application World see more and more matured technologies that are focusing to establish an easy-to-use development by reducing lots and lots of boiler-plate code along with some other added functionalities in their own domains. Let us consider JSF and EJB technologies to extend further discussion regarding this.
EJB 3.0 which is a specification given from Sun has gained much popularity because of its simplified yet robust programming model. Much of the middle-ware related services like Security, Transactions, Connection Pooling etc is delegated to the container itself. Comparing to its predecessors, EJB 3.0 offers a POJO programming Model. No need for your beans to extend or implement EJB specific classes or interfaces. And also, along with the new specification Java Persistence API (JPA), an unified programming model to access the underlying database along with rich set of features are now possible thereby completely eliminating the heavy-headed entity beans.
What is JPA?:Java Persistence API (JPA) provides POJO (Plain Old Java Object) standard and object relational mapping (OR mapping) for data persistence among applications. Persistence, which deals with storing and retrieving of application data, can now be programmed with Java Persistence API starting from EJB 3.0 as a result of JSR 220. This API has borrowed many of the concepts and standards from leading persistence frameworks like Toplink (from Oracle) and Hibernate (from JBoss). One of the great benefits of JPA is that it is an independent API and can nicely integrate with J2EE as well as J2SE applications.
Java Server Faces provides a Component-based approach for developing User Interface Components in a Web Application. It hides most of the boiler-plate code and provides a higher-level abstraction over the client request and the server response objects. Using Java Server Faces, a Web Application can be viewed by components making events and listeners executing the appropriate logic for the Events. No need for the traditional HttpServletRequest and HttpServletResponse object to extract the client input parameters and to generate the response.
JBoss provides a framework in which the Events that are emitted by the JSF UI Components can be directly handled by the Enterprise Beans. No need for the intermediate Managed Beans which establishes the data transfer from and to JSF and EJB.
3.2) Dependency Bijection Support
Before getting into Dependency Bijection, it is wise to look at the two types: namely Dependency Injection and Dependency Outjection. These two are the popular patterns and modern Frameworks and Containers makes use of this abundantly. Let us see these two techniques
3.2.1) Dependency Injection
This model is used when a Component or a Service which is running inside some Framework or a Container is well known in the early stages so that the Framework/Container can create instances of them thereby taking the burden from the Clients. These type of model is used heavily in most of the J2EE Components, to name a few, EJB, Servlets, JMS etc.
For example, consider the following piece of code,
MySessionBean.java
@Stateless public class MySessionBean{ @PersistentContext private EntityManager entityManager; public void query(){ // Do something with EntityManager reference. } }
In the above code, the Session Bean (MySessionBean
) is depending on the services of EntityManager
. So, before the session bean starts using the EntityManager
object, the EntityManager
instance should be available. This is made simple because the EJB Container will creates a new instance of the EntityManager
object based on the various parameters taken from the Configuration File and injects this instance to the EntityManager
reference. This way of doing is called Dependency Injection.
In Seam, injection of a Component by the Seam framework is done by the use of @In
Annotation. For example, consider the following piece of code,
MyComponent.java
public class MyComponent{ @In private MyInjectorComponent compToBeInjected; }
When the Application gets deployed, Seam Framework will keep track of these Annotated Components and during run-time, upon creation of MyComponent
class and before the invocation of any other methods, the Container will inject and instance of an object of type MyInjectorComponent
to the compToBeInjected
reference.
3.2.2) Dependency Outjection
In Dependency Injection, usually the Framework injects the services to components that are in need of, whereas the reverse happens in Dependency Outjection. Consider the following piece of code,
MyComponent.java
public class MyComponent{ @Out private MyService myService; public MyComponent(){ } public MyService getMyService(){ return createMyService(); } private MyService createMyService(){ // My own way of creating } }
MyServiceClient.java
public class MyServiceClient{ @In private MyService myService; }
In the above code, MyComponent
class is acting as a factory class for creating MyService
objects. Assume that this MyComponent
class is a controlled class meaning that is being managed by the Container or the Framework wherever it is embedded. Situations may arise such that the MyService
object might be needed by the Container so that the Container can use this MyService
to inject dependencies on other components or clients. For instance, MyServiceClient
is in need of MyService
object and the Container can inject this reference from the object that it has taken from MyComponent class. This model is Dependency Outjection where a Service is taken by the Container from the Component.
Seam supports both these models in the form of @In
and @Out
annotations. For example consider the following class,
MyClass.java
public class MyClass{ @In private MyServiceOne service1; @out private MyServiceTwo service2; }
The above code can be read like this. The container injects the reference to service1 because it is annotated with @In
(meaning for Injection). And at a later stage, the Container may taken the reference of service2 (because of @Out
) thereby serving it to other needful Components.
3.3) Stateful Web Applications
Since the underlying protocol used in a Web Application is Http, all Web Application are Stateless in nature. Precisely it means that all the requests that are coming from the Client Browser are treated as individual requests only. The Server shows no partiality for the Client Requests. It is up to the Application or the Framework to identify whether requests are coming from the same Client or not. Session Management in Web Application is a time-consuming job and typically Servlets/Jsp provides various ways to manage sessions. Even in this case, Application Developers still have to depend on HttpSession like classes for creating session objects and storing/retrieving objects from the session.
JBoss Seam provides an excellent way to Manage States amongst multiple client requests. The State Management Facility is tightly integrated with Seam Components in the form of various Contexts. Following are the most commonly used Contexts in Seam.
- Conversation – A Conversation generally represents multiple requests that come from the same client. Components that come under this category can remember the state of the client and this forms the heart of State Management in Seam.
- Application – This context generally holds information that is used by various components within the same Application.
- Session – Components that fall under this category simply uses Http Session Api for state management.
- Page – The scope of the components managing the information is restricted to the Current Page only. All the stored information is lost when the user leaves this current page.
- Stateless – Components that falls under this category don’t manage state between multiple Client Requests.
4) Seam Components
Components in Seam take over the functionality as well the Business Logic in a Web Application. The good thing is that all Seam Components are POJO Objects only meaning that Components don’t have to extend or implement any Seam specific Classes or Interfaces. The Seam Component Model follows the standard Java Bean Component Architecture. Even it is possible to Annotate Enterprise Beans (Session Beans, Entity Beans and Message Driven Beans) as Components. Seam provides an excellent framework for Integrating Enterprise Beans into the Seam Framework.
As mentioned before, Components in Seam carries the business process involved in a typical Web Application. Seam Components may also act as Listeners for JSF UI Components or they may even interact with the Database. Since Seam provides a good deal of Integration with EJB Components, Developers generally prefer having Stateful Session Beans as Listeners and the Entity Beans for interacting with the Database.
Usually Seam Components are identified by Name, Scope and Role. These are Declarative Identifications meaning that they are represented directly in the Source Code with the help of Annotations. For example, consider the following Seam Component,
MyStatefulBeanImpl.java
@Stateful @Name("MyStatefulBean") @Scope(ScopeType.SESSION) public MyStatefulBeanImpl implements MyStatefulBean{ public String statefulMethod(){ } }
In the above code, the @Name
Annotation represents the name of a Seam Component using which other Managed Seam Components can access it. @Scope
defines how life this Component will survive during the Web Application. Since the above class is actually a Session Bean, it has been marked with @Stateful
Annotation.
5) Support for Annotations
Most of the boiler-plate needed for the various parts of the Application is taken care by the Seam because of the declarative style of programming available in the form of Annotations. Most of the Annotations that we see in Seam are a mix of EJB 3.0 and Seam specific Annotations. They are a number of Annotations defined in the Seam Api and this section just provides an overview of the most commonly used Annotations. For a complete list of Annotations and their purpose, have a look at the Seam Documentation.
5.1) Annotations for Seam Components
Components in Seam are really POJO’s and they play a major role in keeping the Application stateful. Following are the most commonly used Annotations related to Seam Components are given below.
- @Name
- @Scope
- @JndiName
5.1.1) @Name Annotation
This Annotation specifies the name of a Seam Component so that other Components (Seam Components or JSF Pages) can refer the Component by its name. This Annotation is mandatory for a class that is going to act as a Seam Component. Following is an example of the Seam Component.
MyComponent.java
@Name("MyComponent") public class MyComponent{ // Some Functionalities here. }
5.1.2) @Scope Annotation
This Annotation, if given, tells to the Seam Framework about the scope (or the life-time) for a Seam Component. The values for this Annotation are taken from the org.jboss.seam.ScopeType
Enum and can be any of the following values: APPLICATION
, CONVERSATION
, SESSION
, PAGE
, STATELESS
etc. Following is a sample code snippet for using the @Scope
Annotation.
MyComponent.java
@Scope(ScopeType.SESSION) @Name("MyComponent") public class MyComponent{ // Some Functionalities here. }
5.1.3) @JndiAnnotation Annotation
This Annotation should not be applied to normal Seam Components but to Components that represent any of EJB or JMS Service. Following is an example of one such component.
MySessionBean.java
@JndiName("ejb/session/MySessionBean") Public class MySessionBean{ }
5.2) Annotations for Components Lifecycle
All Components in Seam have well defined Life-cycle Management as defined by the Seam Framework. Management of Component Life-cycle is important as it has dependencies over the state Management of Web Applications. Following are the most commonly used Annotations for Life-cycle Management.
- @Create
- @Destroy
5.2.1) @Create Annotation
When a method inside a Seam Component is marked with @Create
Annotation, then this method will be called immediately after the creation of Seam Component. Most of the costly Resources like Initializing File or Database can be coded in this method. Following is the sample code snippet for the same,
MyDatabaseUtils.java
@Name("MyDatabaseUtils") Public class MyDatabaseUtils{ @Create() public void initDatabase(){ } }
5.2.2) @Destroy Annotation
If @Create
Annotation for a Seam Component deals with initialization Stuffs for a object, then the code inside the @Destroy
Annotation can be used to Release Resources or References to other objects. This method will be called before a Component is going to get removed from any of the Context as mentioned by its Scope.
MyDatabaseUtils.java
@Name("MyDatabaseUtils") Public class MyDatabaseUtils{ @Destroy() public void closeDbResources(){ } }
6) Events
Events can occur in a Seam Application through various Sources. And the events emitted by the Sources are captured and handled by the Listeners. Let us look into the various Sources that are responsible for emitting Events. Source can be any one of the following items.
- Seam Page Events
- Seam Component Driven Events
- JSF Components Emitting Events
Let us look into the details one by one.
6.1) Seam Page Events
Before Seam renders a page to Display, it checks whether the page has registered itself for firing any Events. If that’s the case, then the Framework will fire Events on behalf of the Web Pages. For example, consider the following situation. If the Home Page of a Web-site is eager to display the hits to this page, then the following could be possible,
pages.xml
<pages> <page view-id = "/hit-count.jsp" action = "#{Hitter.initHits}"> </page> </pages>
The above is the pages.xml
file and it should be placed in the WEB-INF
directory of the Web Application module. The above code essentially tells that whenever a request comes for /hit-count.jsp
, then call the method initHits()
available in the Hitter
class.
6.2) Seam Component Driven Events
It is possible by the Seam Components also to emit Events. There is a Low-degree of Coupling between the Initiation and the Handling of Events. Even Custom Events can be declared specified either in the Xml File or through Annotations. For example, consider the following code snippet,
components.xml
<components> <event type = "myEvent"> <action expression = "#{MyComponent.myCallBack1}"/> <action expression = "#{MyComponent.myCallBack2}"/> </event> </components>
The above Xml File must be placed in the WEB-INF
directory of the Web Application Module. If anyone raises an Event of type ('myEvent'
is just a string), then the following methods defined inside the action element will be fired. For, example, consider the following code,
MyEventInitiator.java
public class MyEventInitiator{ public void initEvent(){ Events.instance().raiseEvent("myEvent"); } }
MyComponent.java
public MyComponent{ public void myCallBack1(){ System.out.println("My Call back method 1 called"); } public void myCallBack2(){ System.out.println("My Call back method 2 called"); } }
If some one initiates the Event by calling MyEventInitiator.initEvent()
, then a event of type myEvent gets raised. Since this Listeners (Actions) of this Event are defined in the components.xml file in the form of MyComponent.myCallBack1()
and MyComponent.myCallback2()
, both these methods will be fired in the order in which they are defined.
6.3) JSF Components Emitting Events
As discussed previously, Seam components can act as Listeners for the JSF UI Components emitting Events. For example, consider the following piece of Code,
calculate.jsp
<h:commandButton value = "Calculate Tax" action = "#{TaxCalculator.calculateTax}"> </h:commandButton>
In the above snippet code, whenever the User clicks the Calculate Tax button, the calculateTax()
method defined inside the TaxCalculator
class will be called. Following is how the TaxCalculator
component looks like,
TaxCalculator.java
@Name("TaxCalculator") @Scope(ScopeType.PAGE) public class TaxCalculator{ public void calculateTax(){ } }
7) Sample Application
With the concepts and theories in mind, let us develop a minimal functionality Shopping Application using JBoss Seam Framework. The following are the list of softwares/products needed for the Sample Application to work.
The functionality of the Shopping Application is simple. It initially provides a page prompting for the user name before beginning the Shopping Application. Then a List of products along with Product Id, Name, Description, Price, Number of Items to be checked-out are shown to the user. The user can select the product items he wants and continues to check-out. After that a brief summary of the Product Information is shown to the User .
Since the Shopping Application it is an Enterprise application, it involves the Creation of Jar and War files and then packaging them as an Ear File. Let us look into the various files and the directory structure required for completing this Application.
7.1) View Files
These set of files represents the view files rendered as a result of client making the client. Let us look into the various files involved one by one.
7.1.1) index.html
index.html
<html> <head> <meta http-equiv="Refresh" content="0; URL=user.seam"> </head> </html>
This is the file that will be request when the client starts the Application in the Web Browser. This file immediately redirects to user.seam
. Later, we will see that the extension seam is mapped to xhtml (for Facelets). Here is the content of user.xhtml.
7.1.2) user.xhtml
<!DOCTYPE html PUBLIC "-//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" xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core"> <body> <center> <h2>Welcome to Shopping.</h2> </center> <h:form> <center> To contine shopping, Please enter your name: <br/> <h:inputText value="#{User.name}" size="20"/><br/> <h:commandButton type="submit" value="Continue Shopping" action="product-list"/> </center> </h:form> </body> </html>
The things to note that is there is a Component called User
with a property called name
. As mentioned in the preceding sections, the user will be prompted to enter his name before continue with the shopping. The entered name will be mapped to the name property in the User class. Also note that when the clicks the “Continue Shopping” button, the action is re-directed to “product-list” which actually maps to product-list.xhtml
(which is defined the navigation.xml
) file. Given below are the contents of product-list.xhtml
file.
7.1.3) product-list.xhtml
<!DOCTYPE html PUBLIC "-//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" xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core"> <body> <center> <h2>List of available products</h2> Hi, <b>#{User.name}</b> Following are the available producst in our shopping repository </center> <h:form> <center> <h:dataTable columnClasses="list-column-center, list-column-right, list-column-center, list-column-right" headerClass="list-header" rowClasses="list-row" styleClass="list-background" value="#{ShoppingManager.products}" var="aProduct"> <h:column> <h:outputText value = "#{aProduct.id}"/> </h:column> <h:column> <h:outputText value = "#{aProduct.name}"/> </h:column> <h:column> <h:outputText value = "#{aProduct.description}"/> </h:column> <h:column> <h:outputText value = "#{aProduct.price}"/> </h:column> <h:column> <h:inputText value = "#{aProduct.noOfItems}" size = "5"/> </h:column> </h:dataTable> </center> <center> <h:commandButton action="#{ShoppingManager.checkout}" value="Checkout Products"/> <h:commandButton action="user" value="Go to user page" type = "submit"/> </center> </h:form> </body> </html>
Note that a class called Product with properties name, description, price, noOfItems, amount, id (Primary key) is defined which represent of the products in the shopping repository. Access to the product objects such as displaying is facilitated with the help of ShoppingManager Session Bean. Note that this Session Bean is configured to act as a Seam Component in this Application. As soon as this page loads, all the Product information from the Products Table, is fetched and it is displayed in this page.
We have two buttons at the bottom of the page. One is to navigate to the Home page and the other is to checkout the products. As soon as the user clicks the “Checkout Products” button, the checkOut()
method in the ShoppingManager
bean is fired which will calculate the amount of the individual products the user has selected. Upon completion of the method, checkout action is returned which is mapped with product-summary.xhtml
page as defined in the navigation.xml
file.
7.1.4) product-summary.xhtml
Given below are the contents of product-summary.xhtml
file which will display the summary information of the user selected products along with the total price information.
product-summary.xhtml
<!DOCTYPE html PUBLIC "-//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" xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core"> <body> <center> <h2>Shopping Summary</h2> Hi, <b>#{User.name}</b> </center> <h:form> <center> <h:dataTable columnClasses="list-column-center, list-column-right, list-column-center, list-column-right" headerClass="list-header" rowClasses="list-row" styleClass="list-background" value="#{ShoppingManager.products}" var="aProduct"> <h:column> <h:outputText value = "#{aProduct.id}"/> </h:column> <h:column> <h:outputText value = "#{aProduct.name}"/> </h:column> <h:column> <h:outputText value = "#{aProduct.description}"/> </h:column> <h:column> <h:outputText value = "#{aProduct.price}"/> </h:column> <h:column> <h:outputText value = "#{aProduct.noOfItems}" size = "5"/> </h:column> <h:column> <h:outputText value = "#{aProduct.amount}" size = "5"/> </h:column> </h:dataTable> </center> <center> Total Price: <b><h:outputText value = "#{ShoppingManager.totalPrice}" /></b> Happy Shopping. <h:commandButton action="user" value="Go to user page" type = "submit"/> </center> </h:form> </body> </html>
7.2) Resource Files
In Seam terms, all the Configuration Information (web.xml
, application.xml
) and the various Resources Messages are defined in terms of resources. Let us have a look into the various Configuration file.
7.2.1) application.xml
application.xml
<application> <display-name>Seam Hello World</display-name> <module> <web> <web-uri>app.war</web-uri> <context-root>/Shopping</context-root> </web> </module> <module> <ejb>app.jar</ejb> </module> <module> <java>jboss-seam.jar</java> </module> <module> <java>el-ri.jar</java> </module> <module> <java>el-api.jar</java> </module> </application>
This is the Application Level Configuration File which contains entries for the Web and the Java Module along with the libraries that are specific to JBoss and Seam.
7.2.2) ejb-jar.xml
ejb-jar.xml
<ejb-jar> <assembly-descriptor> <interceptor-binding> <ejb-name>*</ejb-name> <interceptor-class>org.jboss.seam.ejb.SeamInterceptor</interceptor-class> </interceptor-binding> </assembly-descriptor> <interceptors> <interceptor> <interceptor-class>org.jboss.seam.ejb.SeamInterceptor</interceptor-class> </interceptor> </interceptors> </ejb-jar>
These entries are necessary to make all the Ejb Components look like Seam Components. This is achieved by intercepting the functionality of the Ejb Components with the help of Interceptors.
7.2.3) persistence.xml
persistence.xml
<persistence> <persistence-unit name="ShoppingManager"> <provider>org.hibernate.ejb.HibernatePersistence</provider> <jta-data-source>java:/DefaultDS</jta-data-source> <properties> <property name="hibernate.dialect" value="org.hibernate.dialect.HSQLDialect"/> <property name="hibernate.transaction.flush_before_completion" value="true"/> <property name="hibernate.hbm2ddl.auto" value="create-drop"/> <property name="hibernate.show_sql" value="true"/> </properties> </persistence-unit> </persistence>
The above file represents the Persistence Unit that the Session Bean may use to store and retrieve information about the product Objects from the Product table. A persistence Unit generally contains information about its Database, Driver Name, Dialect etc.
7.2.4) components.xml
Since we are using Session Bean for interacting with the Entity Object, we must specify the Jndi Name of the Session Bean so that Seam framework can lookup and create an instance of the Session Bean. This is achieved with the help of the following Xml File.
components.xml
<?xml version="1.0" encoding="UTF-8"?> <components xmlns="http://jboss.com/products/seam/components" xmlns:core="http://jboss.com/products/seam/core" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation= "http://jboss.com/products/seam/core http://jboss.com/products/seam/core-1.1.xsd http://jboss.com/products/seam/components http://jboss.com/products/seam/components-1.1.xsd"> <core:init jndi-pattern="Shopping/#{ejbName}/local" debug="true"/> <core:manager conversation-timeout="120000"/> </components>
7.2.5) navigation.xml
All the navigation rules in this Shopping Application are logically expressed in terms of action in this navigation.xml
file. The advantage of providing this kind of declarative mapping is that all the components will refer only to the Logical Outcome of the Action and not the Physical Location of the Page.
A.a
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE faces-config PUBLIC "-//Sun Microsystems, Inc.//DTD JavaServer Faces Config 1.0//EN" "http://java.sun.com/dtd/web-facesconfig_1_0.dtd"> <faces-config> <navigation-rule> <from-view-id>*</from-view-id> <navigation-case> <from-outcome>user</from-outcome> <to-view-id>/user.xhtml</to-view-id> <redirect/> </navigation-case> <navigation-case> <from-outcome>product-list</from-outcome> <to-view-id>/product-list.xhtml</to-view-id> <redirect/> </navigation-case> <navigation-case> <from-outcome>checkout</from-outcome> <to-view-id>/product-summary.xhtml</to-view-id> <redirect/> </navigation-case> </navigation-rule> </faces-config>
7.3) Source Files
Now let us look into the Various Java Source Files (representing Session Beans, Entities, etc). Following is the code for the Product Entity.
7.3.1) Product.java
Product.java
package net.javabeat.articles.jboss.seam.shopping; import org.jboss.seam.annotations.*; import javax.persistence.*; import java.io.Serializable; import static org.jboss.seam.ScopeType.SESSION; @Entity @Name("person") @Scope (SESSION) public class Product { private String name; private String description; private double price; private int noOfItems; private double amount; private long id; public Product() { } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } public double getPrice() { return price; } public void setPrice(double price) { this.price = price; } public int getNoOfItems() { return noOfItems; } public void setNoOfItems(int noOfItems) { this.noOfItems = noOfItems; } public double getAmount(){ return amount; } public void setAmount(double amount){ this.amount = amount; } @Id @GeneratedValue public long getId() { return id; } public void setId(long id) { this.id = id; } }
Note that apart from qualifying this as an Entity, it has to be qualified with Annotations like @Name
and @Scope
to tell to the Seam Framework that it is a Seam Component. The Session Bean will store and retrieve the values from the Product
objects fetched from the Product Table.
7.3.2) Session Bean Interface
Following is the interface definition of the Session Bean. This Bean has various functionalities like Creating, Retrieving and Destroying products. Other that this it also performs the checkout operation which is nothing but the calculation of the no of items with the individual products along with the total amount calculation.
Shopping.java
package net.javabeat.articles.jboss.seam.shopping; import javax.ejb.*; import java.util.*; import net.javabeat.articles.jboss.seam.shopping.Product; @Local public interface Shopping { public List getProducts(); public void createProducts(); public void destroyProducts(); public String checkout(); public double getTotalPrice(); }
7.3.3) Session Bean Implementation
ShoppingManager.java
package net.javabeat.articles.jboss.seam.shopping; import java.util.List; import javax.ejb.*; import net.javabeat.articles.jboss.seam.shopping.Product; import net.javabeat.articles.jboss.seam.shopping.ProductDatabase; import org.jboss.seam.annotations.*; import org.jboss.seam.ejb.*; import static org.jboss.seam.ScopeType.SESSION; import javax.persistence.*; @Stateful @Name("ShoppingManager") @Scope (SESSION) public class ShoppingManager implements Shopping { private List products; private double totalPrice; @PersistenceContext(unitName = "ShoppingManager") private EntityManager entityManager; @Create public void createProducts () { Product product = null; product = createProduct("Sony Playstation", "Gaming Console The Sony Playstation 2", 9000d, 0); entityManager.persist(product); product = createProduct("Traffic Signal - DVD", "SKU-CODE: Traffic Signal - Sony & BMG", 240d, 0); entityManager.persist(product); product = createProduct("DVD Player", "Samsung P475 DVD Player", 3990d, 0); entityManager.persist(product); product = createProduct("COMPAQ Notebook", "COMPAQ Notebook PC - PRESARIO V6307", 49000d, 0); entityManager.persist(product); products = entityManager.createQuery( "select prdt from Product prdt").getResultList(); } private Product createProduct(String name, String description, double price, int noOfItems){ Product product = new Product(); product.setName(name); product.setDescription(description); product.setPrice(price); product.setNoOfItems(noOfItems); return product; } public List getProducts() { return products; } public String checkout(){ for(Product aProduct : products){ aProduct.setAmount(aProduct.getNoOfItems() * aProduct.getPrice()); totalPrice = totalPrice + (aProduct.getNoOfItems() * aProduct.getPrice()); } return "checkout"; } public double getTotalPrice(){ return totalPrice; } @Destroy @Remove() public void destroyProducts(){ } }
As already explained, the above code makes use of EntityManager to create and retrieve products from the products Table.
8) Conclusion
This is an Introduction article about the evolving JBoss Seam Framework. It started with the necessity of having this Framework and then continued with the discussion of having some many advantages of using this framework. The advantages like “EJB-JSF” Integration, the need for a Stateful Web Application and the exiting Dependency Bijection Functionality is covered in much detailed manner. Then the various core modules of the Seam Framework like Seam Components, the need and the usage of Seam Annotations over various modules along with the Various Types of Events emited by Seam Sources are given much consideration and discussed briefly. Then the article finally ended up with a Shopping Application thereby illustrating the various techniques and concepts available in JBoss Seam.