You are on page 1of 65

Building EJB 3.

0 applications with WebSphere Application Server


Using the WebSphere Application Server V6.1 Feature Pack for Enterprise JavaBeans 3.0
Roland Barcia, Senior Technical Staff Member, IBM Jeffrey Sampson (jrsamps@us.ibm.com), WebSphere Technical Sales Specialist, IBM Summary: EJB 3.0 is a major step forward in simplifying application development in the enterprise. By using the IBM WebSphere Application Server V6.1 Feature Pack for Enterprise JavaBeans 3.0, you can benefit from the simplified development experience, new persistence model, and new features such as interceptors, while still deploying to a robust WebSphere platform. This content is part of the IBM WebSphere Developer Technical Journal. Tags for this article: 7, ejb, ejb_(enterprise_javabeans)_technology, upgrade, websphere Tag this! Update My dW interests (Log in | What's this?)Skip to help for Update My dW interests Date: 12 Dec 2007 Level: Intermediate Also available in: Chinese Activity: 35944 views Comments: 0 (View | Add comment - Sign in)

Average rating (28 votes) Rate this article

Introduction
Enterprise JavaBeans 3.0 is a major enhancement to the EJB specification, introducing a new POJO-based programming model that greatly simplifies development. The EJB 3.0 specification was created under JSR 220, and is divided into three documents: y EJB 3.0 Simplified API: Defines the new simplified API used to code EJB components; specifically, session beans and message-driven beans. y Enterprise JavaBeans Core Contracts and Requirements: Defines the EJB contracts between the bean and the EJB container. y Persistence API: Defines the new Persistence Model for Java. This article introduces you to the IBM WebSphere Application Server V6.1 Feature Pack for EJB 3.0, and shows you how to build a Java Persistence API (JPA) and session bean POJO from scratch, plus how to run it inside WebSphere Application Sever. To highlight aspect oriented programming enhancements to the EJB 3.0 specification, this article will also walk you through building an additional session bean, demonstrating POJO injection, and help you build an EJB 3.0 interceptor. This article uses the WebSphere Application Server Toolkit V6.1 and the Dali plug-in available from Eclipse. IBM Rational Application Developer V7.5 was released as an open beta bundled with the Eclipse Dali functionality, so you might want to consider looking into that. You will notice future articles use Rational Application Developer V7.5 to build EJB 3.0 applications.

Preparation
In this article, you will build an EJB 3.0 application within WebSphere Application Server V6.1 using the new Feature Pack for EJB 3.0. For this example, the sample application is a simple customer order system, in which a customer creates an order, adds line items, and then submits the order. Figure 1 illustrates the use cases in this sample system, and the sequence in which the use cases are executed is shown in the activity diagram in Figure 2. Figure 1. Sample application use cases

Figure 2. Sample application use case sequence

This article assumes: y WebSphere Application Server V6.1 is installed. y WebSphere Application Server V6.1 Feature Pack for Enterprise JavaBeans 3.0 has been downloaded. y WebSphere Application Server Toolkit v6.1 is installed. y Database schema and test data has been configured. (The DDL for populating a Derby database is provided in the download materials for this article.)

Install the feature pack


To deploy EJB 3.0 applications inside WebSphere Application Server V6.1, you need to install the EJB 3.0 Feature Pack. This section summarizes highlights of installing the Feature Pack onto an existing WebSphere Application Server V6.1. Be sure to check the Feature Pack Read Me file for other prerequisites. The steps below explain how to install the Feature Pack for EJB 3.0 into a simple configuration consisting of a single application server profile. For planning and installation guidance for installing to a Network Deployment configuration, refer to the links on the results panel of the installation wizard. (For complete installation instructions, see the WebSphere Application Server Information Center) 1. Locate the EJB3 directory in your feature pack install image. Double-click install.exe to launch the installation wizard. 2. On the Welcome panel of the installation wizard, verify that you are installing the EJB3 feature pack by clicking Next. 3. Accept the terms of the licence agreement and click Next. 4. A prerequisite check is performed. The feature pack installation image also contains two required fixpacks and will prompt you to install them if they are not present. Click Next to continue the installation. 5. Use the Browse button to navigate to the WebSphere Application Server installation directory. 6. If the application server is still running you might be presented with the perquisite error message shown in Figure 3. If so, go Back and stop the application server manually. After the application server is stopped, click Next again on the preceding panel to continue. Figure 3. Prerequisite Error

7.

A summary panel will display next, listing the items to be installed (Figure 4). Click Next to install the feature pack.

Figure 4. Installation Summary

8.

When the installation completes, the panel shown in Figure 10 will display. Un-check Launch the Profile management tool and click Finish. (Links with instructions and considerations for installing the feature pack to a Network Deployment topology are also available on this panel.) Figure 5. Launch Profile Manager

Add Dali to the Application Server Toolkit

Dali is a Object/Relational mapping plug-in for Eclipse that provides a Java Persistence perspective that supports top-down, bottom-up, and meet-in-the-middle O/R mapping. Dali also provides wizards and edit boxes for managing various Java Persistence API (JPA) annotations. Dali can be added to either the WebSphere Application Server Toolkit or Rational Application Developer V7.0.x. (Keep in mind that Dali is an open source plug-in so support comes from Eclipse. You can also use the Rational Application Developer V7.5 Beta as an alternative, which comes with the Dali plug-in installed. SeeResources for more.) To add Dali to the Application Server Toolkit: 1. Download the latest 0.5 version of Dali. 2. Make sure that the Application Server Toolkit is stopped. 3. Extract the contents of the Dali download file to the main Application Server Toolkit installation directory. (This is done because the file contains the directory path starting with the eclipse subdirectory that resides in the Application Server Toolkit install directory.) 4. From a command prompt, go to the Application Server Toolkit install directory and use this command to start the toolkit:

ast.exe -clean
This command will make sure the Dali plug-in will be detected. Back to top

A simple example
You are now ready to build your first EJB 3.0 application for WebSphere Application Server. By following the steps in this section, you will develop a simple JPA POJO and a session bean using the example described earlier, and then test the scenario: A. Set up the development environment B. Create your first JPA POJO C. Create a simple sessions bean D. Import the client

A. Set up the development environment


1. First, you need to create the desired projects: a. From the J2EE Perspective in the Application Server Toolkit, right-click within the Project Explorer and selectNew => Enterprise Application Project (Figure 6). Figure 6. New Enterprise Application Project

b. c.

In the New EAR Application Project wizard under the Target Runtime section, click New. In the New Server Runtime wizard (Figure 12), select WebSphere Application Server v6.1 and click Next. Figure 7. WebSphere Application Server v6.1 runtime

d. e.

Enter the name of the WebSphere Application Server installation directory, if yours is different than the default. Click Finish. Name the project OrderSystem and ensure that the Target Runtime is WebSphere Application Server v6.1(Figure 8). (Do not select the stub option). Press Finish. Figure 8. EAR Application Project Wizard

f. g.

Your EAR file should display an error because there are no Java EE modules. EJB 3.0 is a plain POJO model, so you will create a simple Java project as a utility project that will contain your EJB 3.0 POJOs. Right-click the OrderSystem EAR and select New=>Other (Figure 9). Figure 9. Create new project

h.

Expand J2EE => Utility Project and click Next (Figure 10). A utility project is a plain Java project that is packaged within the EAR. You will mark this project as an EJB module later in the application.xml.

Figure 10. Select Utility Project

i.

Name the project OrderSystemEJB (Figure 11). Ensure that the EAR Project Name matches the already created EAR project. Figure 11. Utility Project Wizard

2.

You now need to update the EAR file so that it sees the Java project as an EJB Module: a. Expand the OrderSystem and double click the Deployment Descriptor Editor (Figure 12).

Figure 12. Open Deployment Descriptor

b.

Go to the source tab, shown in Figure 13. Add these XML fragments after the display name tag:
<module> <ejb>OrderSystemEJB.jar</ejb> </module>

c. d. e.

The result should look similar to Figure 13 Figure 13. application.xml

3.

f. Save the editor and close the Application Deployment Descriptor. Add the local WebSphere Application Server to the Application Server Toolkit workspace as a server: a. In the J2EE perspective, go to the Servers tab. Right-click within the servers list and select New=>Server(Figure 14). Figure 14. New Server

b. c.

Accept the defaults, then Next. Un-check Run server with resources within the workspace, then Finish. Figure 15. WebSphere Server Settings

4.

d. Right-click on the new server and select Start. Add a data source for the Derby database that you populated with the CUSTSCH schema provided in CUSTSCH-derby.ddl: a. Right-click on the server and select Run administrative console (Figure 16). Figure 16. Launch administrative console

b. c.

In the administrative console, navigate to Resources=>JDBC=>Data sources. Select a scope for the data source (Figure 17). What you choose will vary depending on your installation. Select a server scope for your local server, then click New. Figure 17. Create a DataSource

d.

On the Step 1 panel (Figure 18), enter Order DS for the Data source name and jdbc/orderds for the JNDI name, then Next.

Figure 18. DataSource wizard

e.

On the Step 2 panel (Figure 19), select Create new JDBC Provider, then Next. Figure 19. JDBC Provider

f.

On the Step 2.1 panel (Figure 20), select the following values:  Database type: Derby  Provider type: Derby Network Server Using Derby Client  Implementation type: Connection pool data source Enter optional Description text, then click Next.

Figure 20. JDBC Provider

g.

On the Step 3 panel (Figure 21), enter JPATEST for the database name, then Next.

Figure 21. Database Specific Properties

h.

On the Step 4 panel (Figure 22), review the data to make sure all values were entered correctly, then clickFinish. Figure 22. Summary

i. j.

Save your changes by clicking the Save link at the top of the page. Verify that the Derby network database is running, then select the Order DS data source and click Test Connection (Figure 23). Figure 23. Test Connection

k.

You should receive a message at the top of the panel similar to that shown in Figure 24 Figure 24. Connection Confirmation

B. Create your first JPA POJO


The EJB 3.0 specification defines a new persistence architecture, called the Java Persistence Architecture (JPA), that enables you to map simple POJOs to relational databases. JPA POJOs are no longer EJB components. Instead, the EJB 3.0 spec defines how JPA objects are managed in an EJB 3.0 container. However, JPA applications can run inside a Java SE environment as well. In this example, you will to create a JPA object that runs inside WebSphere Application Server. 1. First, create a simple POJO: a. Expand the OrderSystemEJB project. Right-click on the src directory and select New => Class (Figure 25).

Figure 25. New Class

b.

In the New Java Class panel (Figure 26), store the class in the Package calledcom.ibm.ejb3.order.entities, name the class Customer, then Finish.

Figure 26. Class Wizard

c.

Create two simple properties:  customerId: int  name: String


package com.ibm.ejb3.order.entities; import java.io.Serializable; public class Customer implements Serializable { private int customerId; private String name; }

d. e.

In the Ourtline view, right-click on the Customer class, then select Source => Generate Getters and Setters(Figure 27).

Figure 27. Generate Getters and Setters

f.

Click Select All and OK (Figure 28).

Figure 28. Select properties

g.

The result is a simple POJO, as shown in Figure 29.

Figure 29. Customer Class

2.

You are now ready to make your POJO a JPA entity. In most cases, all you need is a good Java editor. This example uses the editor in Eclipse that you use to create JPA applications: a. Over the class declaration, begin typing @Enti, then press Ctrl-Space to trigger the Eclipse content assist. Select @Entity. (Figure 30)

Figure 30. Entity Annotation

b.

An Entity class needs a primary key. Over the customerId property, add the @Id annotation (Figure 31). Figure 31. Id Annotation

3.

If your property names match that of the database, you are done and you have your first JPA POJO. However, the schema in this example is slightly different, and you will use the JPA Eclipse tools for help: a. Switch to the Java Persistence perspective. You can begin the Open Perspective wizard by rightclicking on the perspective icons in the upper right corner of the panel and selecting Other. (Figure 32)

Figure 32. Open Other

b. c.

Select Java Persistence from the list that displays. Go to the Database Explorer view. To load your database, right-click on Connections, then select New => Connection... (Figure 33) Figure 33. New Connection

d.

Enter or select the following properties (Figure 34):  Uncheck Use default naming convention  Connection Name: OrderDB  Database Manager: Derby => 10.1  Database Name: JPATEST  Class Location: navigate to Derby lib directory (for example: \WebSphere\AppServer\derby\lib\derbyclient.jar)  User Id and Password: Enetr appropriate values for your system. Figure 34. Connection Parameters

e.

Navigate to OrderDB => JPATEST => Schemas => CUSTSCH => Tables => CUSTOMER and examine the fields (Figure 35). Figure 35. CUSTOMER Table

4.

You need to add the persistence.xml file to the JPA project. This file is the JPA deployment descriptor for configuring JPA Properties. You can use the JPA development tools for this: a. In the Package Explorer view, right-click OrderSystemEJB and select Java Persistence => Add Java Persistence... (Figure 36)

Figure 36. Add Java Persistence support

b.

For Connection, select OrderDB, and for Schema, select CUSTSCH. (The connection could have timed out. If so, select the Reconnect... link and enter the same user ID and password). For Persistence unit name, enterOrderDB (Figure 37).

Figure 37. JPA Project Content

c. d.

Once you do this, your Customer POJO will have an error because the Eclipse JPA plug-in will detect a mismatch between the database model and the JPA object model. You will fix this in the next step. Open the META-INF folder of OrderSystemEJB, and open the newly generated persistence.xml (Figure 38).

Figure 38. persistence.xml

e.

You need to add the data source to the JPA provider. Open persistence.xml and click on the Source tab. Add this xml tag within the persistence-unit tag, as shown in Figure 39:
<jta-data-source>jdbc/orderds</jta-data-source>

f. Figure 39. Adding DataSource

5.

Save and close persistence.xml. (Because you are running inside a Java EE container, the default provider will be used.) Because the database does not match exactly with your POJO, you need to fix your mappings a bit: a. In the Outline view, select the customerId property. b. In the lower right corner of the panel, ensure that Map As is set to Id. Under Column Name, select CUST_ID. Ensure the rest of the fields match the values shown in Figure 40. Figure 40. Persistence Properties

g.

c.

Select the PK Generation tab. Check the Primary Key Generation and select Identity for Strategy (Figure 41). JPA enables a few strategies for automatic primary key generation. In this case, JPA will delegate to DB2's identity feature. Figure 41. Identity Strategy

d.

In the Customer POJO, you need to override the default schema name because the database is stored in a different schema. Add the @Table annotation as shown in Figure 42. Add CUSTOMER for name and CUSTSCH for schema.

Figure 42. Set Schema

e.

Save and close Customer.java.

C. Create a simple sessions bean


Much like JPA, all of EJB 3.0 has been simplified with a POJO programming model, making EJB 3.0 easy to code. Below, you will create a simple session bean that uses the JPA API to access the Customer JPA POJO. 1. First, you need to create a simple interface; having an interface is usually a good practice. Otherwise, the EJB provider will generate one for you. In this exercise, you will just create a simple Interface. a. Under the OrderSystemEJB project, right-click the src folder and select New=>Interface (Figure 43).

Figure 43. New Interface

b.

For Package name, enter or browse to com.ibm.ejb3.order.session. For class name, enter CustomerTask(Figure 44).

Figure 44. Interface Wizard

c.

Add the method below to the interface, then Finish.


public Customer findCustomer(int customerId) throws CustomerDoesNotExist ;

d. e.

You should have an error, because there is no class called CustomerDoesNotExist. Use the Eclipse suggestion to create the class, as in Figure 45. Figure 45. Create Exception

f.

Make sure that Constructors from superclass is checked and that the superclass is java.lang.Exception(Figure 46). Figure 46. Class Wizard

g.

Next, add a @Local annotation above the class declaration, as shown in the Figure 47. This makes your session bean a local EJB. Figure 47. Local Annotation

h.

Right click in the editor and select Source => Organize Imports (Figure 48) Figure 48. Adding Imports

2.

Next, you will create your Session Bean POJO: a. Right-click the com.ibm.ejb3.order.session package and select New => Class (Figure 49).

Figure 49. New Class

b.

Name the class CustomerTaskImpl, and add the CustomerTask interface to the Interface list (Figure 50).

Figure 50. Class Wizard

c.

To make CustomerTaskImpl a session bean, add an @Stateless annotation, as shown in Figure 51. This makes your POJO a stateless session bean. Figure 51. Stateless Annotation

3.

An EJB 3.0 container is also an injection server. To have persistence actions, you need an entity manager. This can be easily added to the session bean through injection. When using JPA within an EJB 3.0 container, the container automatically manages passing the correct persistence context for you. This is known as a container managed entity manager. Using JPA in this fashion, the EJB 3.0 container will properly manage the lifecycle of the persistence context, and propagate the correct context across EJB invocations. a. Add the EntityManager declaration shown below to the CustomerTaskImpl class.
@PersistenceContext(name="OrderDB") EntityManager em;

b. c.

You can use code assist to bring in the PersistenceContext Import (Figure 52). Figure 52. PersistenceContext Annotation

d.

Add this code snippet to the findCustomer method:


Customer customer = (Customer) em.find(Customer.class, customerId); if (customer == null) { throw new CustomerDoesNotExist("Customer does not exist"); } return customer;

e. f.

Organize imports as before (Figure 53), then save and close the file.

Figure 53. Customer implementation

D. Import the client


Next, you will import a simple WAR file with a servlet that will be used to test your session bean and JPA object. The servlet demonstrates how easy it is to access a session bean from Web applications. A simple WAR file is included with this article with the code already in place. 1. Import the Web application and examine the code: a. From the File Menu, select File => Import. b. In the Import wizard, expand Web => WAR File (Figure 54).

Figure 54. Import WAR File

c.

For WAR file, Browse to the location where you saved the provided OrderClient.war file. Keep the default name for the Web project, and ensure that OrderSystem is the EAR Project Name (Figure 55).

Figure 55. Select EAR Project to Import to

2.

Next, you can examine the servlet code. a. Expand the Java Resources: src folder and open the EJBClientServlet.java file (Figure 56).

Figure 56. Test Servlet

b.

Notice that the EJB session bean can be injected right into the servlet.
public class EJBClientServlet extends javax.servlet.http.HttpServlet implements javax.servlet.Servlet { /* (non-Java-doc) * @see javax.servlet.http.HttpServlet#HttpServlet() */ @EJB private CustomerTask customerTask = null;

c. d.

In the displayCustomerAndOrder method, notice that once you have the session bean instance, it is just simple Java.
private void displayCustomerAndOrder(int customreId, PrintWriter out) throws CustomerDoesNotExist { Customer customer = customerTask.findCustomer(customreId); out.println("<br>Customer ID => " + customer.getCustomerId()); out.println("<br>Customer Name => " + customer.getName());

3.

e. You will now deploy and test the application: a. From the J2EE perspective, go to the Servers view, right-click the server and press Start (Figure 57).

Figure 57. Start the Server

b.

Once the server is started, right-click the server again and select Add and Remove Projects... (Figure 58) Figure 58. Add the Project

c.

Add the OrderSystem application by selecting the application from the Available projects list on the left and press Add (Figure 59).

Figure 59. Move project

d.

Back in the Project Explorer view, expand the Deployment Descriptor => Servlets, then rightclickEJBClientServlet and select Run As => Run on Server (Figure 60).

Figure 60. Run the Servlet

e.

Select Choose an existing server and check the Set server as project default option, then Finish (Figure 61).

Figure 61. Associate Server as default

f.

The browser should display the Customer ID and Customer Name (Figure 62). Figure 62. Examine Browser

g.

Close the browser and remove the project from the server (Figures 63 and 64) Figure 63. Remove the Project

Figure 64. Remove the Project

h.

Close and save all the files. Back to top

Advanced EJB features


EJB 3.0 provides a simple programming model without compromising function. The fundamental principal is to use default values, and only override where you must. For example, EJB 3.0 still permits XML configuration. XML deployment descriptors can override annotations so you can externalize configurations and override settings for different deployment environments. In this section, you will continue to use annotations, but will add more functionality to the application to see some other features of EJB 3.0. (The application used here was designed solely for illustrating different EJB 3.0 and JPA features, and not to be an example of application design best practices.) The steps in this section: A. Building JPA objects B. Build another session bean C. Add an interceptor D. Test the application

A. Building JPA objects


The steps below show how to use the JPA Eclipse tools to generate more JPA POJOs, after which you will update the mappings to customize for the use case. 1. The JPA Eclipse tools support top-down, meet-in-the-middle, and bottom-up mappings. You will use the bottom-up tools to generate the remaining entities: a. In the Package Explorer view, right-click OrderSystemEJB and select Java Persistence => Generate Entities(Figure 65).

Figure 65. Generate Entities

b.

Select your Connection (your database connection may have closed by now; select the Reconnect link and enter your credentials again, if necessary), and select the CUSTSCH schema. Press Next (Figure 66).

Figure 66. Select Connection and Schema

c.

On the Generate Entities from Tables panel, only select LINEITEM, CUSTORDER, and PRODUCT. Make sure your Package name is com.ibm.ejb3.order.entities. Since the CUSTORDER table name is different than the Entity Name ("Order," which is the desired name of the entity), enter Order as the Entity name for CUSTORDER (Figure 67). Press Finish.

Figure 67. Select the Tables

2.

Next, you will update the mappings: a. Open the Order entity (Figure 68). Figure 68. Examine Order Class

b.

Use the Java Persistence Properties Editor or add the annotations marked below in bold:  @Table annotation is needed to override the schema name.  @NamedQuery is adding a query to your JPA POJO. JPA has a very rich query language you can use, called EJB-QL. This query is asking for an open order from the customer.  The ordered property needs to be annotated as an ID, as you did before. Also, you are adding a generation strategy of Identity.  Finally, notice the Order has a relationship to LineItems. You will add a fetch rule of Eager. This means that when someone asks for an order, the JPA engine will fetch all the line items that are associated with the order as well.
@Entity @Table(name="CUSTORDER", schema="CUSTSCH") @NamedQuery(name="getCurrentOrder", query="select o from Order o where o.customerId = :customerId and o.status ='OPEN'") public class Order implements Serializable { @Id @Column(name="ORDER_ID") @GeneratedValue(strategy=GenerationType.IDENTITY) private int orderId; private String status; private double total;

@Column(name="CUSTOMER_ID") private int customerId; @OneToMany(mappedBy="orderId",fetch=FetchType.EAGER) private Set<Lineitem> lineitemCollection;

3.

c. You need to update the Customer entity to have a relationship to Order. The requirements of the system are such that a Customer has only one open Order. You want to create a relationship to that open Order. You do not want to generate the relationship because a Customer has many orders, but only when he has one Open Order. a. Open the Customer entity. Add Order currentOrder, as shown in the code below. Generate the setters and getters using the Eclipse Java tools.
package com.ibm.ejb3.order.entities; import import import import import import import java.io.Serializable; javax.persistence.Entity; javax.persistence.Id; javax.persistence.GeneratedValue; javax.persistence.GenerationType; javax.persistence.Column; javax.persistence.Table;

@Entity @Table(name="CUSTOMER", schema="CUSTSCH") public class Customer implements Serializable { @Id @GeneratedValue(strategy=GenerationType.IDENTITY) @Column(name="CUST_ID") private int customerId; private String name;

private Order currentOrder; public int getCustomerId() { return customerId; } public void setCustomerId(int customerId) { this.customerId = customerId; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Order getCurrentOrder() { return currentOrder; } public void setCurrentOrder(Order currentOrder) { this.currentOrder = currentOrder; } }

b. c.

Add the following @OneToOne and @JoinColumn annotations, as shown below.  Notice that the fetch rule is set to lazy, so you will not fetch the order when someone asks for the customer.  You have set some cascading rules. If someone updates the open order, changes will cascade as defined.  The relationship is optional, which means the customer will not always have an open order.

You have specified the Join column (the name corresponds to the foreign key on the Customer table, while the referencedColumn name corresponds to the primary key of the Custorder table.) If you do not specify the Join column, JPA will attempt to resolve the keys based on a naming scheme.

@OneToOne(fetch=FetchType. LAZY,cascade = {CascadeType.MERGE,CascadeType.REFRESH},optional=true ) @JoinColumn(name="OPEN_ORDER_ID",referencedColumnName="ORDER_ID") private Order currentOrder;

d. e.

Update the LineItem class to point to the correct schema, as you did for Customer and Order (Figure 69). Figure 69. LineItem Schema

f.

Similarly, override the schema for Product (Figure 70). Figure 70. Product Schema

g.

Save and close the entities.

B. Build another session bean


Here, you will build another session bean to see how you can inject another session bean into it. 1. As before, create an interface:

a.

In the session package, select New => Interface (Figure 71) and name the Interface OrderTask. Click Finish. Figure 71. New Interface

b.

Annotate the class as Local, and add the getCurrentOrder method, as shown below.
package com.ibm.ejb3.order.session; import com.ibm.ejb3.order.entities.Order; @Local public interface OrderTask { public Order getCurrentOrder(int customerId) throws CustomerDoesNotExist; }

2.

c. Create a new stateless session bean. a. Right-click the session's package and select New => Class (Figure 72). Figure 72. New Class

b.

Make sure the class implements the OrderTask Interface you just created (Figure 73). Figure 73. OrderTaskImpl

c.

Annotate the bean as stateless. Add the code in bold below. Notice that you can inject the CustomerTask into the OrderTask. This greatly simplifies things by avoiding JNDI lookup code. Also, you are also injecting an entity manager, as you did before.
package com.ibm.ejb3.order.session; import javax.ejb.EJB; import javax.ejb.Stateless; import com.ibm.ejb3.order.entities.Order; @Stateless public class OrderTaskImpl implements OrderTask {

@EJB(beanName = "CustomerTaskImpl") CustomerTask customerTask; @PersistenceContext(name="OrderDB") EntityManager em; public Order getCurrentOrder(int customerId) throws CustomerDoesNotExist { // TODO Auto-generated method stub return null; } }

d. e.

Finally, add the code in bold below to the getCurrentOrder method. Notice how easy it is to access queries. Also notice that the order method interacts with the Customer object. It is important to understand that because both classes are using @PersistenceContext, they will get proper propagation of the Entity Manager.
public Order getCurrentOrder(int customerId) throws CustomerDoesNotExist { Query query = em.createNamedQuery("getCurrentOrder"); query.setParameter(1, customerId); Order currentOrder = (Order)query.getSingleResult(); if(currentOrder != null) { Customer customer = customerTask.findCustomer(customerId); Order alreadySet = customer.getCurrentOrder(); if(alreadySet == null) { customer.setCurrentOrder(currentOrder); } } return currentOrder; }

f. g.

Don't forget to organize your imports.

C. Add an interceptor
EJB 3.0 also adds the ability to use Aspect Oriented Programming techniques in your application. EJB 3.0 supports interceptors, which enable you to intercept code for cross cutting techniques. Next, you will create an audit interceptor that displays the customer's actions on the administrative console. 1. Create a simple Audit class: a. Create a class called AuditInterceptor (Figure 74).

Figure 74. New Java Class

b.

Add the code below in bold. @AroundInvoke tells the container what method to call when the interceptor intercepts. The code accesses the customerId and method name and displays them.
package com.ibm.ejb3.order.session; import java.lang.reflect.Method; import javax.interceptor.AroundInvoke; import javax.interceptor.InvocationContext; public class AuditInterceptor { @AroundInvoke public Object audit(InvocationContext invocationContext) throws Exception { Method operation = invocationContext.getMethod(); String name = operation.getName();

Object param[] = invocationContext.getParameters(); System.out.println("Customer Id " + param[0] + " executing operation => " + name); return invocationContext.proceed(); } }

2.

c. You can add the interceptor to the session beans by annotating the class with the @Interceptor annotation. You will do this for simplicity in this exercise, but it is often a best practice for a class not to be aware of who is intercepting it. EJB 3.0 supports partial XML deployment descriptors where you can define interceptor bindings that externalize matching an interceptor to a class. It is usually best to externalize interceptors. a. Open the OrderTaskImpl class and add the @Interceptors (AuditInterceptors.class), as shown below.
@Stateless @Interceptors(AuditInterceptor.class) public class OrderTaskImpl implements OrderTask {

b. c.

Do the same for the CustomerTask.


@Stateless @Interceptors(AuditInterceptor.class) public class CustomerTaskImpl implements CustomerTask {

d.

D. Test the application


You need to modify the client to invoke the new function: 1. The code you need is provided with this article, but it is commented out. Uncomment the OrderTask declaration as shown below in bold.
public class EJBClientServlet extends javax.servlet.http.HttpServlet implements javax.servlet.Servlet { /* (non-Java-doc) * @see javax.servlet.http.HttpServlet#HttpServlet() */ @EJB private CustomerTask customerTask = null; @EJB private OrderTask orderTask = null; public EJBClientServlet() { super(); } @Override public void init() throws ServletException { super.init(); }

2. 3.

Uncomment the code in bold below. Notice that you access the Order and Iterate functions through the LineItems. The LineItems will be populated because of the eager fetching rule you set.
private void displayCustomerAndOrder(int customerId, PrintWriter out) throws CustomerDoesNotExist { Customer customer = customerTask.findCustomer(customerId); out.println("<br>Customer ID => " + customer.getCustomerId()); out.println("<br>Customer Name => " + customer.getName()); Order order = orderTask.getCurrentOrder(customerId); if(order != null)

{ out.println("<br>order id => " + order.getOrderId()); out.println("<br>status => " + order.getStatus()); out.println("<br>Total => " + order.getTotal()); Collection<Lineitem> lineItems = order.getLineitemCollection(); for(Lineitem lineItem: lineItems) { out.println("<br>****"); out.println("<br>Line Item Id => " + lineItem.getLiId()); out.println("<br>Quantity => " + lineItem.getQuantity()); out.println("<br>Total => " + lineItem.getAmount()); } } else { out.println("<br>Customer has no open order..."); } }

4. 5.

Add the project to the server as you did before (Figure 75). Figure 75. Add Project Again

6.

Run the servlet (Figure 76).

Figure 76. Run on Server

7.

The browser should display the customer, the current order, and all the line items (Figure 77).

Figure 77. Examine Result

8.

Finally, examine the console to see the print statements for the interceptor (Figure 78). You will notice the findCustomer task is called twice, once from the client and once from the order task, and the getCurrentOrder task is called once. Figure 78. Examine Interceptor result

Back to top

Conclusion
EJB 3.0 is a major step forward in simplifying application development in the enterprise. This article showed you how to build EJB 3.0 applications for WebSphere Application Server V6.1 using the simplified programming model, the

new Java Persistence API, and interceptors. By using the EJB 3.0 Feature Pack for WebSphere Application Server, you can benefit from the simplified development experience, new persistence model, and new features such as interceptors, while still deploying to a robust WebSphere platform. Back to top

Acknowledgements
The authors wish to acknowledge Tom Alcott, Jim Knutson, Randy Schnier, Kevin Sutter, Tim Francis, and Keys Botzum for their contributions to the article. Back to top

Download
Description Code sample Name WAS_EJB3_LAB.zip Size 10 KB Download method HTTP

Information about download methods

You might also like