|
In this issue
Welcome to the Enterprise Java Technologies Tech Tips for February 24, 2007. Here you'll get tips on using enterprise Java technologies and APIs, such as those in Java Platform, Enterprise Edition (Java EE). This issue covers: These tips were developed using the Java EE 5 SDK. You can download the SDK from the Java EE Downloads page . You can download the sample archive for the tip EJB 3.0 - EJB 2.x Interoperability. You can download the sample archive for the tip Using an EJB Session Bean as a Model Facade. Any use of this code and/or information below is subject to the license terms.
The Enterprise JavaBeans (EJB) 3.0 specification introduced a new, vastly simpler, API for implementing and accessing session beans. Many developers have questions about how applications written to this new API can interact with legacy EJB applications, or how legacy applications can interact with the new API. It would be impractical to require developers to entirely rewrite all existing EJB applications in order to take advantage of any of the new capabilities. In some cases, developers plan to upgrade their applications, but would prefer to do it using a phased approach. In other cases they prefer to write new EJB 3.0 applications, but would still like to take advantage of their existing application's services. The EJB 3.0 specification makes both of these strategies possible. This tip explains how. A sample application package accompanies the tip. The code examples in the tip are taken from the source code of the sample (which is included in the package). The sample uses the Java EE 5 SDK. You can download the Java EE 5 SDK from the Java EE Downloads page EJB 3.0-to-EJB 2.x Compatibility
Let's first look at an example of an application written to the
simplified EJB 3.0 API calling a legacy EJB application. In the
source code for the sample that accompanies this tip you'll find
an EJB 3.0 stateless session bean named public interface EJB2xHome extends EJBHome { public EJB2xRemote create() throws CreateException, RemoteException; } public interface EJB2xRemote extends EJBObject { public void foo() throws RemoteException; } Here is the first part of the MigrationBean class: @Stateless public class MigrationBean implements MigrationRemote { // Inject a reference to the Home interface // of the EJB 2.x bean. @EJB private EJB2xHome ejb2xHome; private EJB2xRemote ejb2x;
An important benefit of using the
The @PostConstruct private void initialization() { try { ejb2x = ejb2xHome.create(); } catch(Exception e) { throw new EJBException(e); } } In the last part of the class, MigrationBean invokes the EJB2x business method within its own business method. public void bar() { try { // Call operation on legacy EJB. ejb2x.foo(); } catch(Exception e) { throw new EJBException(e); } } All standard EJB services such as security and transaction propagation work as expected between the two beans.
Note that using an EJB 2.x-to-EJB 3.0 Compatibility In the first example, you saw how an EJB component written using the new EJB 3.0 API could be a client of a legacy EJB component. Now let's look at the reverse case. Here you'll see how a legacy component that is coded using the EJB 2.x client API can access a session bean that is implemented using the EJB 3.0 simplified API. The idea here is to use the new EJB without making any changes to the existing EJB client code.
In this second example, a stateful session bean named
public interface AdaptedHome extends EJBHome { public AdaptedRemote create(String id) throws CreateException, RemoteException; } public interface AdaptedRemote extends EJBObject { public String getId() throws RemoteException; } Here is the AdaptedBean class : @Stateful @RemoteHome(AdaptedHome.class) public class AdaptedBean { private String myId = "unknown"; @Init public void create(String id) { myId = id; } public String getId() { return myId; } }
Notice that the bean class is implemented using the POJO-like
simplifications of EJB 3.0. However, it uses the
The other important annotation in the class is
Here is the standalone client code for accessing try { InitialContext ic = new InitialContext(); Object o = ic.lookup(AdaptedHome.class.getName()); AdaptedHome adaptedHome = (AdaptedHome) PortableRemoteObject.narrow(o, AdaptedHome.class); AdaptedRemote adapted = adaptedHome.create("duke"); System.out.println("Adapted id = " + adapted.getId()); } catch(Exception e) { ... } Notice that the client code uses the standard EJB 2.x client programming model. It does not need to know that the target bean is implemented with EJB 3.0. Running the Sample Code A sample package accompanies this tip. To install and run the sample:
Summary The EJB 3.0 specification greatly simplifies the session bean API. But it does so with the understanding that there is a large investment in EJB applications built with earlier versions of the specification. For this reason, a goal of EJB 3.0 is to ensure smooth interoperability between new and existing applications. If you are a developer using EJB 3.0, you have a lot flexibility in deciding whether to migrate legacy applications to the new API or to take advantage of those legacy applications from new components. About the Author Ken Saks is the lead architect for the EJB 3.0 container in the Java EE 5 SDK. He has been a member of the Enterprise Java group at Sun Microsystems since 1999.
The November 18, 2006 Tech Tip Using a Model Facade discussed some of the things that can lead to complexity when you use the Java Persistence API to manage persistence in the domain model of your Java EE 5 applications. The tip showed how a Model Facade (or simply a "Facade") can reduce that complexity. As an example, the tip showed a servlet interacting with a Facade that is implemented as a web tier component. In this tip you'll see how a Facade can be implemented as an Enterprise JavaBeans (EJB) technology session bean. Why Use a Session Bean as a Model Facade? Implementing a Facade as a web component is a good approach if you want to have a web-only architecture and you don't want to use an EJB container. However there are distinct advantages to using an EJB container. For example, an EJB container provides services such as support for container-managed transactions. You can leverage that support if you implement a Facade as a session bean. In that case, the EJB container manages the transactions freeing you from having to include code to manage the transactions. An Example Facade In this example a servlet interacts with a Facade that is implemented as a session bean. If you're familiar with EJB 3.0 technology, you know that a session bean requires a business interface that provides the client view of the bean. It's the business interface that the servlet uses to access the Facade. Here's what the business interface for the Facade in the example looks like: import java.util.List; import com.sun.javaee.blueprints.sessionfacade.InvalidItemException; import com.sun.javaee.blueprints.sessionfacade.model.Item; public interface CatalogFacade { public void addItem(Item item)throws InvalidItemException; public Item getItem(int itemID); public List<Item> getAllItems(); }You can find the source code for the business interface as well as for the other code examples in this tip in the sample application package that accompanies the tip. Notice that interface is quite simple. However, despite this simplicity, the interface contains all the information that the client servlet needs to access the model tier of this web application. Also notice that like any EJB 3.0 business interface it does not need to import EJB package-specific classes. This simplicity is a key benefit of using a Facade. All the client web components that need to access model tier objects go through the Facade. The Facade encapsulates any details about the Java Persistence APIs or Java Transaction APIs that might be involved in managing the persistence objects. Now let's look at the Facade. @Stateless public class CatalogFacadeBean implements CatalogFacade { @PersistenceContext(unitName="CatalogPu") private EntityManager em; public void addItem(Item item) throws InvalidItemException { if(item.getName().length() == 0) throw new InvalidItemException("The item" + " name cannot be empty." + " Please specify a name for the item. "); em.persist(item); } public Item getItem(int itemID) { Item item = em.find(Item.class,itemID); return item; } public List<Item> getAllItems() { List<Item> items = em.createQuery( "SELECT OBJECT(i) FROM Item i").getResultList(); return items; } }
There are a number of things to notice in the Facade:
Using the Facade Now let's look at the servlet that uses the example Facade: public class CatalogServlet extends HttpServlet { @EJB private CatalogFacade cf; ... public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { ... if ("additem.do".equals(selectedURL)) { //get values from request and place // them into new Item String desc = request.getParameter("item_desc"); String name = request.getParameter("item_name"); ... Item item = new Item(); item.setName(name); item.setDescription(desc); ... //use facade to add new Item to database cf.addItem(item); ... } ... }
Notice that the servlet uses dependency injection, through the
By using the Facade, the servlet is shielded from the details of the entities and from any persistence operations required to access the entities. Using the Session Bean Facade With Java Server Faces Technology In the sample code provided with this tip, a servlet accesses Java Persistence objects in the model tier through a Facade. However you could also use a JavaServer Faces technology (often referred to as JSF) component as the web component. In this approach, each JSF page would typically access a JSF-managed bean (also called a backing bean). The managed bean would then access the session bean Facade using the session bean's interface. This is the expected programming model for Java EE 5 applications using JSF and EJB 3.0. The following diagram illustrates this approach.
Running the Sample Code A sample package accompanies this tip that includes a Model Facade implemented as a session bean. To install and run the sample:
Click on the links in the displayed page to retrieve or add items in a catalog. If you examine the source for the application, you'll see that it uses an EJB session bean as a model facade for operations on the persistent entities in the catalog. When you're finished with the application you can remove it by entering the following commands: ant clean - to clean up the application workspace. ant undeploy - toun deploy the application from the application server ant unsetup - to clean up database resources from the application serverSummary If you are building a Java EE 5 web application that uses the Java Persistence API, consider refactoring your code by introducing a Model Facade. For additional information about Facades and the Java Persistence API see:
Sean Brydon is an engineer with Sun Microsystems where he is the technical lead for the Java BluePrints program. He has been involved with the Java BluePrints since its inception. He is an author of the Addison-Wesley Java-series books, "Designing Enterprise Applications with the Java 2 Platform, Enterprise Edition," and "Designing Web Services with the J2EE 1.4 Platform." He is a regular speaker on enterprise application design. Sean has also been involved in designing and developing the Java Pet Store 2.0 reference application and the Java BluePrints Solutions Catalog. Yutaka Yoshida was a Servlet 2.4 specification lead, and is currently working in the Java BluePrints project. He has been involved in designing and developing the Java Adventure Builder reference application, the Java BluePrints Solutions Catalog, and the Java Pet Store 2.0 reference application. Developer Assistance
Need programming advice on Java EE? Try Developer Expert Assistance 2007 JavaOne Conference Registration is Live
Register today for the JavaOne conference and save $200. The program is new and expanded. Check the 2007 JavaOne Conference page for details. | ||||||||||||||
|
| ||||||||||||