http://www.developer.com/java/ejb/article.php/3650661/EJB-3-Session-Beans.htm
This article will discuss EJB 3 session beans, the core business service objects used by EJB client applications. You'll gain an understanding of the new and simplified EJB 3 session bean model, with insight into the following topics: Session beans are Java components that run in either stand-alone EJB containers or EJB containers that are part of standard Java Platform, Enterprise Edition (Java EE) application servers. These Java components are typically used to model a particular user task or use case, such as entering customer information or implementing a process that maintains a conversation state with a client application. Session beans can hold the business logic for many types of applications, such as human resources, order entry, and expense reporting applications. Session beans are of two types, as follows: You will drill down into more specifics of stateless and stateful beans in the following sections. Session beans are used to write business logic, maintain a conversation state for the client, and model back-end processes or user tasks that perform one or more business operations. Typical examples include the following: Session beans can be used in traditional 2-tier or 3-tier architectures with professional/ rich client applications, or in 3-tier web-based applications. These applications can be deployed in different logical and physical tier combinations. In the next section, you will investigate some of the possible combinations. Figure 1 shows a typical architecture for a session bean in 3 tiers, with a rich client front-end application that has some data entry screens used by end users like customer service representatives, bank tellers, and so on. These client applications can be developed using Java Swing technology with the Java Platform, Standard Edition (Java SE), or they can be plain old Java objects (POJOs) that are run from the command line. Generally, the end user launches the client application from his desktop, enters some data, and triggers an event by pressing some user interface component such as a Submit button. The general workflow may look something like this: Figure 1. Session beans in a 3-tier architecture This architecture, as shown in Figure 2, is typically front-ended by a web application running in the browser of a desktop or laptop machine. These days, other types of client devices, such as PDAs, cell phones, and telnet devices, are also being used to run these applications. The web application running in a browser or mobile device renders the user interface (data entry screens, Submit buttons, etc.) using web technologies such as JavaServer Pages (JSP), JavaServer Faces (JSF), or Java Servlets. Typical user actions, such as entering search criteria or adding certain items to the web application shopping cart, will invoke/call session beans running in an EJB container via one of the aforementioned web technologies. Once the session bean gets invoked, it processes the request and sends a response back to the web application, which formats the response as required, and then sends the response on to the requesting client device (browser, PDA, telnet, etc.). Figure 2. Session beans in a 3-tier architecture with a web application In the 3-tier architecture just discussed, the client application (which is the web application) and the session beans can be run within the same instance of an application server (colocated) or from different instances running on the same machine. They can also be run in physically separate machines that have an instance of an application server. Stateless session beans are comprised of the following elements: To illustrate the use of stateless session beans, you will create a SearchFacade session bean that provides various search facilities to client applications regarding available wines. The workflow is as follows: Listing 1 shows the definition of the SearchFacade bean. In the following sections of this article, you will build the code that will show the preceding workflow in action. SearchFacadeBean is a standard Java class with a class-level annotation of @Stateless. Listing 1. SearchFacadeBean.java A stateless session business interface is a standard Java interface that does not extend any EJB-specific interfaces. This interface has a list of business method definitions that will be available for the client application. Every session bean must have a business interface that can be implemented by the bean class, generated at design time by tools such as Oracle JDeveloper, NetBeans, or Eclipse; or generated at deployment time by the EJB container. Business interfaces can use annotations as well, as described in the following list: If no annotation is specified in the interface, then it is defaulted to the local interface. If your architecture has a requirement whereby the client application (web application or rich client) has to run on a different JavaVirtual Machine (JVM) from the one that is used to run the session beans in an EJB container, then you need to use the remote interface. The separate JVMs can be on the same physical machine or on separate machines. If your application architecture is going to use the same JVM for both the client application and the session beans, then use the local interface. It is possible that your application architecture requires both remote and local interfaces. For example, an enterprise might have an order entry application that is developed using session beans that have business methods for submitting new orders and also addressing administrative tasks, such as data entry for the products. Potentially, you could have two different client applications that access the back-end order entry application, as follows: Figure 3. A web client using local interfaces of session beans
Figure 4. A rich client using remote interfaces of session beans The SearchFacade session bean has both remote and local interfaces, as shown in Figure 5. Figure 5. The business interfaces of the SearchFacade session bean Listing 2 shows the code snippet for the SearchFacade remote business interface, with an @Remote annotation and a wineSearch() method declaration. The wineSearch() method takes one parameter that represents the type of the wine, and returns a list of wines that match the wine type criteria. Listing 2. SearchFacade.java Listing 3 shows the code snippet for the SearchFacade local business interface, with an @Local annotation and a wineSearch() method declaration. Listing 3. SearchFacadeLocal.java The methods implemented in the bean class must correspond to the business methods declared in the remote or local business interfaces. They are matched up based on the convention that they have the same name and method signature. Other methods in the bean class that do not have the corresponding declaration in the business interfaces will be private to the bean class methods. The SearchFacade bean implements one method, wineSearch(), which has been declared in both remote and local business interfaces. The wineSearch() method returns a static wines list based on the type of wine. Listing 4 shows the implementation for wineSearch(). Listing 4. SearchFacadeBean.java In this section, you will look into using dependency injection in stateless session beans. EJB 3 containers provide the facilities to inject various types of resources into stateless session beans. Typically, in order to perform user tasks or process requests from client applications, the business methods in the session bean require one or more types of resources. These resources can be other session beans, data sources, or message queues. The resources that the stateless session bean is trying to use can be injected using annotations or deployment descriptors. Resources can be acquired by annotation of instance variables or annotation of the setter methods. Listing 5 shows an example of setter and instance variable.based injection of myDb, which represents the data source. Listing 5. Data Source Injection or You typically use the setter injections to preconfigure or initialize properties of the injected resource. There will be certain instances or use cases in which the application using session beans requires fine-grained control over things like an object's creation, removal, and so on. For example, the SearchFacade session bean might need to perform some database initialization when it is created, or close some database connections when it is destroyed. The application can gain fine-grained control over the various stages of the bean life cycle via methods known as callback methods. A callback method can be any method in the session bean that has callback annotations. The EJB container calls these methods at the appropriate stages of the bean's life cycle (bean creation and destruction). Following are two such callbacks for stateless session beans: PostContruct callbacks happen after a bean instance is instantiated in the EJB container. If the bean is using any dependency injection mechanisms for acquiring references to resources or other objects in its environment, PostConstruct will occur after injection is performed and before the first business method in the bean class is called. In the case of the SearchFacade session bean, you could have a business method, wineSearchByCountry(), that would return the wine list for a particular country, and have a PostConstruct callback method, initializeCountryWineList(), that would initialize the country's wine list whenever the bean gets instantiated. Ideally, you would load the list from a back-end datastore; but in this article, you will just use some hard-coded values that get populated into a HashMap, as shown in Listing 6. Listing 6. The PostConstruct Method The PreDestroy callback happens before the container destroys an unused or expired bean instance from its object pool. This callback can be used to close any connection pool that has been created with dependency injection, and also to release any other resources. In the case of the SearchFacade session bean, you could add a PostConstruct callback method (destroyWineList()) into the SearchFacade bean, which would clear the country wine list whenever the bean gets destroyed. Ideally, during PostContruct, you would close any resources that have been created with dependency injection; but in this article, you will just clear the HashMap that has the countries and wine list. Listing 7 shows the destroyWineList() code. Listing 7. The PreDestroy Method Callback methods defined on a bean class should have the following signature: Callback methods can also be defined on a bean's listener class; these methods should have the following signature: where Object may be declared as the actual bean type, which is the argument passed to the callback method at run time. The EJB 3 specification provides annotations called interceptors, which allow you to intercept a business method invocation. An interceptor method can be defined for session and message-driven beans (MDBs). You will show you the usage of interceptors in the session bean context. There are number of use cases for interceptors in a typical application, in which you would find a need to perform a certain task before or after the business method is invoked. For example, you may wish to do one of the following:[
You can either add an @AroundInvoke annotation on a particular method, or you can define an interceptor class whose methods are invoked before a business method is invoked in the bean class. An interceptor class is denoted by the @Interceptor annotation on the bean class with which it is associated. In the case of multiple interceptor classes, the @Interceptors annotation is used. Methods that are annotated with @AroundInvoke should have the following signature: The definition of InvocationContext is as follows: The following list describes the methods in the preceding code: In the SearchFacade session bean, you can add an interceptor that logs the time taken to execute each business method when invoked by the client applications. Listing 8 shows a time log method that will print out the time taken to execute a business method. InvocationContext is used to get the name of bean class and the invoked method name. Before invoking the business method, current system time is captured and deducted from the system time after the business method is executed. Finally, the details are printed out to the console log using System.out.println. Listing 8. The Interceptor Method Similar to stateless session beans, stateful beans comprise a bean class and a business interface. A stateful session bean class is any standard Java class that has a class-level annotation of @Stateful. If deployment descriptors are used instead of annotations, the bean class should be denoted as a stateful session bean. In the case of mixed mode, in which you are using annotations and deployment descriptors, the @Stateful annotation must be specified if any other class-level or member-level annotations are specified in the class. To illustrate a stateful session bean, you will create a ShoppingCart session bean that will keep track of the items added to a user's shopping cart and their respective quantities. In this article, you will use hard-coded values for the shopping cart to illustrate the state and conversation maintenance between the client and stateful session bean. Listing 9 shows the definition of a ShoppingCart session bean.
Listing 9. ShoppingCartBean.java There will be certain use cases in which the application wants to be notified by the EJB container before or after transactions take place, and then use these notifications to manage data and cache. A stateful session bean can receive this kind of notification by the EJB container when it implements the javax.ejb.SessionSynchronization interface. This is an optional feature. There are three different types of transaction notifications that the stateful session bean receives from the EJB container, as follows: For example, the ShoppingCart session bean could implement the javax.ejb.SessionSynchronization interface to get an afterCompletion notification, so that it can clear out the shopping cart cache. Business interfaces for stateful session beans are similar to those for stateless session beans, and are annotated in the same way, using @Local and @Remote annotations. The ShoppingCart session bean has both remote and local interfaces, as shown in Figure 6. Figure 6. Business interfaces for ShoppingCart You will primarily use the local interface from our web application. The remote interface is added to facilitate unit testing of the bean in this article. Listings 10 and 11 show the remote and local ShoppingCart business interfaces, with @Remote and @Local annotations, respectively.
Listing 10. ShoppingCart.java Listing 11. ShoppingCartLocal.java Alternatively, you can use the coding style shown in Listing 2-12, in which you can specify the @Local and @Remote annotations before specifying @Stateful or @Stateless with the name of the business interface. Listing 12. ShoppingCartBean.java Business methods in stateful session beans are similar to those in stateless session beans. You will augment the ShoppingCart bean by adding business methods that will add and remove wines from the shopping cart, and return a list of cart items. Listing 13 shows the ShoppingCart bean implementing the addWineItem(), removeWineItem(), and getCartItems() methods. Listing 13. ShoppingCartBean.java Stateful session beans support callback events for construction, destruction, activation, and passivation. Following are the callbacks that map to the preceding events: The PostContruct callback happens after a bean instance is instantiated in the EJB container. If the bean is using any dependency injection mechanism for acquiring references to resources or other objects in its environment, the PostConstruct event happens after injection is performed and before the first business method in the bean class is called. In the case of the ShoppingCart session bean, you could have a business method called initialize() that initializes the cartItems list, as show in Listing 14. Listing 14. The PostConstruct Method The PreDestroy callback happens after any method with an @Remove annotation has been completed. In the case of the ShoppingCart session bean, you could have a business method called exit() that writes the cartItems list into a database. In this article, you will just print out a message to the system console to illustrate the callback. Listing 15 shows the code for the exit() method, which has the @PreDestroy annotation. Listing 15. The PreDestroy Method The @Remove annotation is a useful life cycle method for stateful session beans. When the method with the @Remove annotation is called, the container will remove the bean instance from the object pool after the method is executed. Listing 16 shows the code for the stopSession() method, which has the @Remove annotation. Listing 16. The Remove Method The PrePassivate callback kicks in when a stateful session bean instance is idle for too long. During this event, the container might passivate and store its state to a cache. The method tagged with @PrePassivate is called before the container passivates the bean instance. The PostActivate event gets raised when the client application uses a passivated stateful session bean again. A new instance with restored state is created. The method with the @PostActivate annotation is called when the bean instance is ready. There are some minor differences between interceptors for stateless and stateful session beans. AroundInvoke methods can be used with stateful session beans. For stateful session beans that implement SessionSynchronization, afterBegin occurs before any methods that have AroundInvoke annotations, and before the beforeCompletion() callback method. The EJB 3 specification outlines two types of exceptions: Application exceptions are exceptions related to execution of business logic that the client should handle. For example, an application exception might be raised if the client application passes an invalid argument, such as the wrong credit card number. System exceptions, on the other hand, are caused by system-level faults, such as Java Naming and Directory Interface (JNDI) errors, or failure to acquire a database connection. A system exception must be a subclass of a java.rmi.RemoteException, or a subclass of a java.lang.RuntimeException that is not an application exception. From the EJB application point of view, application exceptions are done by writing application-specific exception classes that subclass the java.lang.Exception class. In the case of a system exception, the application catches particular exceptions—such as a NamingException that results from a JNDI failure—and throws an EJBException. In this particular article, our examples aren't using any resources as such. A session bean can be seen as a logical extension of a client program or application, where much of the logic and data processing for that application happens. A client application typically accesses the session object through the session bean's client view interfaces, which are the business interfaces that you're discussed in the earlier sections. A client application that accesses session beans can be one of three types: Table 1. Considerations for Choosing Between Local and Remote Clients In some cases, the session beans need to have both local and remote business interfaces to support different types of client applications. A client can obtain a session bean's business interface via dependency injection or JNDI lookup. Before invoking the methods in the session bean, the client needs to obtain a stub object of the bean via JNDI. Once the client has a handle to the stub object, it can call the business methods in the session bean. In the case of a stateless session bean, a new stub can be obtained on every invocation. In the case of a stateful session bean, the stub needs to be cached on the client side so that the container knows which instance of the bean to return on subsequent calls. Using dependency injection, you can obtain the business interface of the SearchFacade session bean with the following code: If the client accessing the session bean is remote, the client can use JNDI lookup once the context interface has been obtained with the right environment properties. Local clients can use JNDI lookup as well, but dependency injection results in simpler code. Listing 17 shows the SearchFacadeTest client program's JNDI code, which looks up the SearchFacade bean, invokes the wineSearch() business method, and prints out the returned list of wines. Listing 17. SearchFacadeClient.java Listing 18 shows the ShoppingCartTest client program, which looks up the stateful ShoppingCart session bean, calls the addWineItem() business method to add a wine to the shopping cart, calls the getCartItems() business method to get the items in the cart, and finally prints the list of wines in the shopping cart./p>
Listing 18. ShoppingCartTest.java This article has covered EJB 3 session bean details using a specific set of examples. You looked at the new and simplified EJB 3 model for developing session beans using standard Java language artifacts, such as Java classes and interfaces. You looked at session beans, and some typical use cases in which session beans can be used for developing applications. You discussed two different types of session beans (stateless and stateful), including the differences between them and some general use cases for each. You covered session bean usage in 2-tier and 3-tier application architectures. You discussed the usage of dependency injection in stateless and stateful beans. You considered ways to gain fine-grained control over application flow, including the use of callback methods and interceptors in stateless and stateful beans, as well as the use of annotations like @PostContruct and @PreDestroy. Raghu R. Kodali is a consulting product manager and SOA evangelist for Oracle Application Server. He has worked in the software industry for over 10 years as a developer, consultant, and presales engineer in emerging technologies. He is responsible for J2EE features with expertise in SOA technologies like EJB, Web Services, and application development frameworks. Raghu has been the lead product manager for EJB design-time features in Oracle JDeveloper since the EJB 1.1 specification. His current area of focus is evangelizing service-oriented infrastructure and implementing service-oriented applications.
Jonathan Wetherbee is a consulting engineer and tech lead for EJB development tools on Oracles JDeveloper IDE. He has over 10 years of experience in development at Oracle, working on a variety of O/R mapping tools and holding responsibility for Oracles core EJB toolset since EJB 1.1.
Peter Zadrozny brings over 20 years of experience to StrongMail Systems, where he serves as chief technology officer. Peter joined StrongMail Systems from Oracle, where he was vice president and chief evangelist for Oracle Application Server. Previously, Peter served as chief technologist of BEA Systems for Europe, the Middle East, and Africaa role he held since launching WebLogics operations in Europe in 1998. Prior to BEA, Peter held executive and technical positions in many countries around the world for companies such as Macromedia, McKesson, Electronic Data Systems, Petróleos de Venezuela, and Sun Microsystems, for whom he started operations in Mexico.
Published: September, 2006, Paperback: 512 pages
EJB 3 Session Beans
December 22, 2006
Introduction to Session Beans
Types of Session Beans
When Do You Use Session Beans?
3-Tier Architecture with Rich Client

Click here for a larger image.
3-Tier Architecture for a Web Application

Click here for a larger image.
Stateless Session Beans
The Bean Class
A stateless session bean class is any standard Java class that has a class-level annotation of @Stateless. If deployment descriptors are used instead of annotations, then the bean class should be denoted as a stateless session bean. If you use both annotations and deployment descriptors (mixed mode), then the @Stateless annotation must be specified if any other class-level or member-level annotations are specified in the bean class. If both annotations and deployment descriptors are used, then the settings or values in the deployment descriptor will override the annotations in the classes during the deployment process.
package com.apress.ejb3.chapter02;
import javax.ejb.Stateless;
@Stateless(name="SearchFacade")
public class SearchFacadeBean implements SearchFacade,
SearchFacadeLocal {
public SearchFacadeBean() {
}
}
The Business Interface

Click here for a larger image.

Click here for a larger image.
package com.apress.ejb3.chapter02;
import java.util.List;
import javax.ejb.Remote;
@Remote
public interface SearchFacade {
List wineSearch(String wineType);
}
package com.apress.ejb3.chapter02;
import java.util.List;
import javax.ejb.Local;
@Local
public interface SearchFacadeLocal {
List wineSearch(String wineType);
}
Business Methods
package com.apress.ejb3.chapter02;
import java.util.ArrayList;
import java.util.List;
import javax.ejb.Stateless;
@Stateless(name="SearchFacade")
public class SearchFacadeBean implements SearchFacade,
SearchFacadeLocal {
public SearchFacadeBean() {
}
public List wineSearch(String wineType) {
List wineList = new ArrayList();
if (wineType.equals("Red"))
{
wineList.add("Bordeaux");
wineList.add("Merlot");
wineList.add("Pinot Noir");
}
else if (wineType.equals("White"))
{
wineList.add("Chardonnay");
}
return wineList;
}
}
Dependency Injection
@Resource
DataSource myDb;
@Resource
public void setMyDb(DataSource myDb) {
this.myDb = myDb;
}
Callback Methods
@PostConstruct
public void initializeCountryWineList()
{
//countryMap is HashMap
countryMap.put("Australia", "Sauvignon Blanc");
countryMap.put("Australia", "Grenache");
countryMap.put("France","Gewurztraminer");
countryMap.put("France","Bordeaux");
}
@PreDestroy
public void destroyWineList()
{
countryMap.clear();
}
public void <METHOD>()
public void <METHOD>(Object)
Interceptors
public Object <METHOD>(InvocationContext) throws Exception
package javax.ejb;
public interface InvocationContext {
public Object getBean();
public java.lang.reflect.Method getMethod();
public Object[] getParameters();
public void setParameters(Object[] params);
public EJBContext getEJBContext();
public java.util.Map getContextData();
public Object proceed() throws Exception;
}
@AroundInvoke
public Object TimerLog (InvocationContext ctx) throws Exception
{
String beanClassName = ctx.getClass().getName();
String businessMethodName = ctx.getMethod().getName();
String target = beanClassName + "." + businessMethodName ;
long startTime = System.currentTimeMillis();
System.out.println ("Invoking " + target);
try {
return ctx.proceed();
}
finally {
System.out.println("Exiting " + target);
long totalTime = System.currentTimeMillis() - startTime;
System.out.println("Business method " + businessMethodName +
"in " + beanClassName + "takes " + totalTime + "ms to execute");
}
}
Stateful Session Beans
The Bean Class
package com.apress.ejb3.chapter02;
import javax.ejb.Stateful;
@Stateful(name="ShoppingCart")
public class ShoppingCartBean implements ShoppingCart,
ShoppingCartLocal {
public ShoppingCartBean() {
}
}
The Business Interface

Click here for a larger image.
package com.apress.ejb3.chapter02;
import javax.ejb.Remote;
@Remote
public interface ShoppingCart {
}
package com.apress.ejb3.chapter02;
import javax.ejb.Local;
@Local
public interface ShoppingCartLocal {
}
package com.apress.ejb3.chapter02;
import javax.ejb.Local;
import javax.ejb.Remote;
import javax.ejb.Stateful;
@Local({ShoppingCartLocal.class})
@Remote({ShoppingCart.class})
@Stateful(name="ShoppingCart")
public class ShoppingCartBean implements ShoppingCart,
ShoppingCartLocal {
public ShoppingCartBean() {
}
}
Note: In this article, you will follow the earlier convention, in which @Local and @Remote annotations are marked on the business interfaces.
Business Methods
package com.apress.ejb3.chapter02;
import java.util.ArrayList;
import javax.ejb.Stateful;
@Stateful(name="ShoppingCart")
public class ShoppingCartBean implements ShoppingCart,
ShoppingCartLocal {
public ShoppingCartBean() {
}
public ArrayList cartItems;
public void addWineItem(String wine) {
cartItems.add(wine);
}
public void removeWineItem(String wine) {
cartItems.remove(wine);
}
public void setCartItems(ArrayList cartItems) {
this.cartItems = cartItems;
}
public ArrayList getCartItems() {
return cartItems;
}
}
Callback Methods
@PostConstruct
public void initialize()
{
cartItems = new ArrayList();
}
@PreDestroy
public void exit()
{
// items list into the database.
System.out.println("Saved items list into database");
}
@Remove
public void stopSession()
{
// The method body can be empty.
System.out.println("From stopSession method with @Remove
annotation");
}
Interceptors
Exception Handling
Client View for Session Beans
Remote
Local Loose coupling between the bean and the client
Lightweight access to a component Location independence
Location dependence Expensive remote calls
Must be colocated with the bean Objects must be serialized
Not required Objects are passed by value
Objects are passed by reference @EJB SearchFacade searchFacade;
Note If the remote client is a Java application or command-line program, an application client container can be used to invoke the session beans. Application client containers support dependency injection for remote clients.
package com.apress.ejb3.chapter02.client;
import com.apress.ejb3.chapter02.SearchFacade;
import java.util.List;
import javax.naming.InitialContext;
import javax.naming.NamingException;
public class SearchFacadeTest {
public SearchFacadeTest() {
}
public static void main(String[] args) {
SearchFacadeTest searchFacadeTest = new SearchFacadeTest();
searchFacadeTest.doTest();
}
@EJB
static SearchFacade searchFacade;
void doTest(){
InitialContext ic;
try {
ic = new InitialContext();
System.out.println("SearchFacade Lookup");
System.out.println("Searching wines");
List winesList = searchFacade.wineSearch("Red");
System.out.println("Printing wines list");
for (String wine:(List<String>)winesList ){
System.out.println(wine);
}
} catch (NamingException e) {
e.printStackTrace();
}
}
}
package com.apress.ejb3.chapter02.client;
import com.apress.ejb3.chapter02.ShoppingCart;
import java.util.ArrayList;
import java.util.List;
import javax.naming.InitialContext;
import javax.naming.NamingException;
public class ShoppingCartTest {
public ShoppingCartTest() {
}
public static void main(String[] args) {
ShoppingCartTest shoppingCartTest = new ShoppingCartTest();
shoppingCartTest.doTest();
}
@EJB
static ShoppingCart shoppingCart;
void doTest(){
InitialContext ic;
try {
ic = new InitialContext();
System.out.println("ShoppingCart Lookup");
System.out.println("Adding Wine Item");
shoppingCart.addWineItem("Zinfandel");
System.out.println("Printing Cart Items");
ArrayList cartItems = shoppingCart.getCartItems();
for (String wine:(List<String>)cartItems ){
System.out.println(wine);
}
} catch (NamingException e) {
e.printStackTrace();
}
}
}
Conclusion
About the Authors
About the Book
Beginning EJB 3 Application Development: From Novice to Professional
By Raghu R. Kodali, Jonathan R. Wetherbee, and Peter Zadrozny
Published by APress Press
ISBN: 1590596714
Retail price: $44.99
This material is from Chapter 2 of the book.
Reprinted here with the publisher's permission.