Chapter 12. Effectively integrating EJB 3 across your application tiers

This chapter covers

  • Design patterns
  • Accessing session beans from the web tier
  • Packaging and using JPA from web applications

If you’ve made it this far, you’ve come a long way on our journey to the center of EJB 3. So far we’ve seen how to use session and message-driven beans for business logic, and how to use various facets of JPA to store and retrieve data. So what’s next, you ask?

Most enterprise applications are distributed across various tiers: presentation, application (or business logic), persistence. The names and number of tiers varies somewhat depending on the application and its runtime environment, as well as the scalability expectations it is designed to handle. Each of these tiers can utilize a number of possible frameworks, which vary radically due to their purpose and creator’s intent. Sprinkle in a few new mechanisms such as dependency injection and the whole thing can leave a developer asking, “Just how can I get all these new toys to work together?”

In this chapter we demonstrate how to integrate EJB 3 into your applications at specific tier boundaries. While drawing the tiers of a distributed application on a diagram is relatively straightforward, making various technologies work to integrate those tiers and coaxing an application to life is usually somewhat more involved. This chapter will expose the core concepts you need to understand regarding multi-tier development with EJB 3, and provide examples of specific combinations you can put to work in your applications.

To start with, we introduce some design patterns to make implementing these concepts easier. Then we discuss various options for invoking EJBs from the presentation tier. And finally, we look at how you can use JPA from web applications and outside of a Java EE container. Let’s start by donning our application developer hat and looking at some proven design patterns you can leverage in your applications.

12.1. Design patterns and web technologies

Design patterns are generally accepted solutions that typically work for common problems. They help avoid “Rediscovering the Wheel Syndrome,” and offer advice for when and how they should be used. Sun’s Java Blueprints Program provides a catalog of core design patterns for building Java EE applications. You can access the catalog of Java patterns online at http://java.sun.com/blueprints/corej2eepatterns/Patterns/index.html.

We’ll introduce some important design patterns and technologies in this section by tier:

  • For the presentation tier, we’ll discuss the Model-View-Controller (MVC) pattern.
  • For the persistence tier, we’ll introduce the Entity Access Object (EAO) pattern, a version of the Data Access Object pattern, updated for JPA.
  • For the application or business logic tier, the Session Façade pattern will be covered. (Sorry, but there’s no cool acronym for this pattern...)

Shall we get started? First on deck: the presentation tier.

12.1.1. Presentation tier

While EJB 3 is primarily designed to deal with server-side functionality, it has to be integrated with a front end at some point in order for the whole application to do anything useful as far as an end user is concerned. This section covers a pattern for this tier that focuses primarily on a web point of view, since Java EE functionality is most often accessed from a web tier. Please note that we use the terms presentation tier and web tier interchangeably. Because EJB 3 is not a presentation-tier technology, this pattern is not demonstrated with EJB 3; we mention it only for completeness and to provide some perspective for how EJB 3 fits into the distributed landscape.

Reviewing the Model-View-Controller pattern

Since you’ll need to call all that special business logic you’ve so cleverly placed in your EJBs from somewhere, there’s a good chance it will be from a web application, given the universal drive to “webify” almost everything these days. That means you’ll be in the market for a good practice to manage all these EJB calls, and it just so happens there’s a great, industry-accepted design pattern for doing this: the Model-View-Controller (MVC) pattern.

Traditionally, the MVC design pattern has been quite popular among Java developers for building web applications, specifically for the presentation tier. This pattern involves three main components, each designed to isolate code into a specific area of responsibility. The Model represents the enterprise data and business logic. You may use session beans and entities for business logic for creating the model of your application. The View is what a user interacts with, and the Controller is the traffic cop in the middle, making sure things work together in an orderly, predictable manner. The MVC pattern commonly has multiple models and multiple views, but usually has only one controller for any specific grouping of models and views at runtime.

You can do all heavy-duty work and implement the MVC pattern in your applications by building your own web framework. However, many frameworks are available to help you do so without your having to reinvent the wheel. Next, we discuss web frameworks and briefly introduce Ajax.

Determining if you need a web framework

Although a web framework isn’t required, it’s a good place to start when investigating how your web tier will interact with your EJBs in your application tier. Having a solid understanding of design patterns helps during this evaluation; it allows you to not only understand each framework’s inner workings, but also to better predict how each may impact design decisions you still need to make.

The market for web frameworks is quite muddled, with more than 50 open source web frameworks from which to choose. By far the most popular framework in this arena is Struts. Other popular frameworks available for your applications are Apache Tapestry, WebWork, Spring MVC, and the heir apparent to Struts: JavaServer Faces (JSF). On the other hand, you may be tempted to build your own web framework, but unless you have very peculiar requirements, we recommend you go with one of the aforementioned frameworks instead of spending your time and energy reproducing others’ work.

Manning has published several books on popular web frameworks:

  • WebWork in Action, by Patrick Lightbody and Jason Carreira
  • JavaServer Faces in Action, by Kito D. Mann
  • Tapestry in Action, by Howard M. Lewis Ship
  • Art of Java Web Development, by Neal Ford
  • Struts in Action, by Ted Husted, Cedric Dumoulin, George Franciscus, and David Winterfeldt

As far as ActionBazaar goes, we’re neutral with respect to which web framework you decide to use. However, we do realize that most web frameworks utilize servlets and possibly JSPs as the respective Controller and View mechanisms of these frameworks, so we’ll focus our discussion on servlets. You can easily integrate the web tier with EJBs to provide business logic for your applications by turning these servlets into clients that invoke your EJBs. We’ll cover how to invoke EJBs directly from your servlets in this chapter. If you want to see how to invoke EJBs exposed as a web service, drop by chapter 15 when you’re done here.

It’s worth mentioning that JSF 1.1 is included in Java EE 5 and provides respectable tool support for the majority of Java EE tool vendors. Because it’s a part of Java EE 5, JSF integrates well with EJB 3 and we expect to see JSF grow in popularity in the future.

Introducing Ajax and Web 2.0

Since Tim O’Reilly’s article (www.oreillynet.com/pub/a/oreilly/tim/news/2005/09/30/what-is-web-20.html) pondered the possibility of a Web 2.0 on the horizon, it seems as if the whole Internet has been one big buzz trying to define what Web 2.0 might consist of. While we’re not sure anyone has arrived at the definitive answer yet, it does appear that one technology which folks can agree on for building Web 2.0 applications is Ajax (Asynchronous JavaScript and XML). You can use Ajax with practically any web framework, and we believe using EJBs with Java EE–based Ajax applications is not significantly different than using other web frameworks. You can easily expose stateless session beans as web services and access them from Ajax-based applications using some popular APIs such as JavaScript Object Notation (JSON).


More on Ajax

If you are interested in learning more about Ajax, check out the following resources:


That’s a quick overview of MVC design patterns and technologies used in the presentation tier. Let’s jump to the persistence tier to see what useful patterns we can find there.

12.1.2. Using the Entity Access Object pattern

Before ORM frameworks like Hibernate gained popularity, many application developers went with straight JDBC to develop data access code. Use of JDBC from business logic led to several maintenance problems, and the Data Access Object (DAO) design pattern was invented to decouple data access code from business logic. The DAO design pattern has been quite popular and has worked not only with JDBC but also with ORM frameworks and CMP entity beans. The Entity Access Object pattern is a new incarnation of the DAO pattern that you can use with JPA.


Note

While both DAO and EAO are variations of the same pattern, the EAO pattern has been updated to refer to EJB 3 entities. Since EJB 3 entities are POJOs, there is no need to continue the use of the Transfer Object/Data Transfer Object pattern in conjunction the EAO pattern. Therefore, be aware that no transfer object is required for the EAO pattern.


Introducing the Entity Access Object pattern

Chapter 9 demonstrated how to use the EntityManager API directly from the business logic in a session bean. The problem with this approach is that entity access code gets sprinkled throughout the business logic, which is a maintenance nightmare. The Entity Access Object (EAO) pattern decouples the entity access logic from the business logic and improves code maintainability. It allows you to easily change your underlying entity access code without affecting the business logic. If you implement the EAO pattern in your applications, it is significantly easier to change your persistence-tier mechanism from JDBC, EJB 2 CMP, or some proprietary persistence mechanism to JPA.

You can learn more about data access objects from Sun’s blueprints website (http://java.sun.com/blueprints/corej2eepatterns/Patterns/DataAccessObject.html). Just replace all references to DAO with EAO, and references to transfer objects with entities.

The EAO pattern abstracts data access code, for example, using JPA from the business logic code. Usually you have one EAO object for every domain object (entity) that performs the CRUD operations for the domain objects (entities). Figure 12.1 shows the class diagram of the EAO defined for the Bid entity of the ActionBazaar system.

Figure 12.1. BidEAO is the interface for the EAO object. BidEAOImpl is the EAO class that implements the logic for CRUD operations for the Bid entity.

As shown in figure 12.1, BidEAO is the entity access object that manipulates the Bid entity. A business object such as the PlaceBid EJB will persist and retrieve instances of the Bid entity by using BidEAO. It hides from the PlaceBid EJB the actual persistence mechanism used to store the entity.

Now let’s explore how to implement an entity access object for the Bid entity.

Implementing the entity access object

The following code for the BidEAO interface exposes the operations that can be performed on a Bid:

public interface BidEAO {
public Bid addBid(Item item, String bidderId, double bidPrice);
public Bid cancelBid(Long bidId);
...
}

Some developers believe that using an interface for the entity access object is too much trouble. However, you’ll learn just how advantageous it is do so when we discuss using the EJB 3 JPA with Spring in chapter 16. An interface allows you to change the underlying persistence provider with no effect on the classes that use the EAO interface.

Listing 12.1 shows the implementation class for the EAO that performs the CRUD operations.

Listing 12.1. JPA-specific implementation class for BidEAO

The code in the implementation class is straightforward. The getEntityManager method uses JNDI lookup to grab an instance of a container-managed EntityManager. Note that because the EAO is a regular POJO, you cannot use DI, so we have used JNDI to look up and grab an instance of an EntityManager. You’ll need to make appropriate changes if you want to use an application-managed entity manager. The rest of the code is nothing but moving the entity access code into the EAO instead of embedding it in your business logic. The addBid method uses the getEntityManager to get an instance of EntityManager and then persist an instance of Bid entity .

Let’s assume that the client for your EAO code is the PlaceBid EJB. Listing 12.2 shows how the code will look.

Listing 12.2. Using BidEAO from the PlaceBid EJB

Listing 12.2 references the persistence unit using the @PersistenceContext annotation because we used JNDI lookup in the EAO to grab an instance of EntityManager. We then used the EAOFactory to create an instance of an EAO . After creating an instance of the EAO, we can use it to perform entity operations .

In the code we used an EAOFactory to create EAO instances. Here is a simple EAO factory that you can use to create instances of EAOs via JPA:

public abstract class EAOFactory {
public static final EAOFactory jpa = new JPAEAOFactory();
public abstract ItemEAO getItemEAO();
public abstract BidEAO getBidEAO();
...
}

public class JPAEAOFactory extends EAOFactory {
public JPAEAOFactory(){}
public BidEAO getBidEAO() {
return (new BidEAOImpl());
}
}

The advantage of having loose coupling between your business logic and your persistence code should be obvious. If you want to change to a different persistence tier, then you only have to modify your EAO implementation classes. Many tools and utilities such as FireStorm/DAO and Hibernate’s hbm2java are available that will help generate EAOs for your entities, so adopting EAOs should be relatively painless. This is a good practice to follow, although it may require some additional coding to manage a few extra classes.

Using session beans as EAOs

Since EJB 3 session beans are POJOs, they are clear candidates for EAOs if you are deploying your enterprise applications to a Java EE container. EAOs can simplify things via injection and do not require using an EAOFactory. If you decide to implement your EAOs using session beans, then the code will look like this:

@Stateless
public class BidEAOImpl implements BidEAO {
@PersistenceContext(unitName = "actionBazaar")
private EntityManager em;
public BidEAOImpl() {
}

public Bid addBid(Item item, String bidderId, double bidPrice) {
Bid bid = new Bid();
...
em.persist(bid);
return bid;
}

public Bid cancelBid(Long bidId) {
...
}
}

This code looks much simpler than the earlier code and is easier to maintain. The code that uses the EAOs is simpler too:

@Stateless
public class PlaceBidBean implements PlaceBid {
@EJB
private BidEAO bidEAO;

public Long addBid(String userId, Long itemId, Double bidPrice)
throws BidException {
...
Bid bid = bidEAO.addBid(item, userId, bidPrice);
return bid.getBidId();
}
}

Implementing EAOs using session beans looks lean and mean. Some purists will resent you considering this approach, but we recommend that you seriously contemplate it because, as a side effect of using session beans for your EAOs, you automatically receive declarative transactions and a container-managed EntityManager. That’s nothing to sneeze at!

We’ll discuss how the Spring framework uses the JpaTemplate to provide EAO support in chapter 16, when we discuss JPA with Spring applications. But now, let’s review the Session Façade pattern.

12.1.3. Visiting the Session Façade pattern

One of the primary reasons the Session Façade pattern was invented was to reduce the number of remote calls for previous EJB incarnations, and this still holds true for EJB 3. In EJB 2 entity beans were remotely accessible by the clients. However, the remoteness comes at a price—namely reduced performance and tight coupling of clients with domain data. With a session bean façade, you can use entity beans locally and expose the session beans to the clients. This cuts a significant number of RMI calls and encourages loose coupling between client and entity beans, thus improving code maintenance. Figure 12.2 shows the class diagram for the Session Façade design pattern.

Figure 12.2. The Session Façade design pattern. Client applications may need to access entities or business logic remotely. JPA entities are POJOs and cannot be accessed remotely. You can use a session bean as a façade to the entities and consolidate the logic to manipulate entities in the session façade. Then, using other beans, you can let the clients access the session façade. A coarse-grained session façade also becomes a good candidate for being exposed as a web service.

Whipping up a session façade amounts to nothing more than designing a coarse-grained session bean and making it available to the client. If you think about it, there are several benefits to making a session bean coarse-grained. One advantage is that it makes managing the transactional and security aspects of your business logic a lot less work than implementing the same functionality for every operation using the fine-grained approach. Let’s take a closer look.

Using a session façade for ActionBazaar

Figure 12.3 shows how you might start with the basic Session Façade pattern, and use it for the ActionBazaar application. Instead of using the EntityManager API from the client applications, you can create a session façade that manipulates the entities. The client applications access the session façade to manipulate the entities. For example, the ActionBazaar web module uses a stateless session bean (the PlaceBid EJB) to manipulate the entities instead of having to manipulate the entities directly from the web applications, such as JSF backing beans. If you have too many fine-grained session beans that you invoke from your web application, you will be better off creating a coarse-grained session façade that uses the session beans and expose the coarse-grained session façade to the clients.

Figure 12.3. Applying the Session Façade pattern to ActionBazaar. Using this pattern improves loose coupling between the client and the business-logic tier. If you access EJBs remotely using the Session Façade pattern, it reduces the number of RMI calls, thus improving application performance.

So how would you actually code this? We’ll first show some fine-grained session beans that use entities and illustrate how using the fine-grained session beans creates tight coupling between the web and the application tiers. You’ll also see how using these fine-grained session beans will increase the number of remote calls. Then we’ll demonstrate how you can create a coarse-grained session façade using the fine-grained session beans, thus improving your application design, achieving better performance, and reducing maintenance costs.

Listing 12.3 shows some examples of fine-grained session beans that can be used by a web client such as a servlet or JSF managed bean.

Listing 12.3. Fine-grained session beans

In listing 12.3, we have three fine-grained session beans. UserManagerBean has a method named findByUserId, ItemManagerBean has a findByItemId method that helps find items by Id, and BidManagerBean exposes two methods: findHighestBid and createBid, to find the highest bid item and create a new bid, respectively. You can expose these session beans to the client, and expect the client to perform the business logic as follows:

public class ActionBazaarServlet extends GenericServlet {
@EJB private ItemManager itemManager;
@EJB private UserManager userManager;
@EJB private BidManager bidManager;
...

public void createBid(String userId, Long itemId, Double bidPrice)
throws BidException {
Item item = itemManager.findByItemId(itemId);
Bid highBid = bidManager.findHighestBid(item);
if (bidPrice <= highBid.getBidPrice()) {
throw new
BidException("Bid Price is lower than the current bid price");
}
...
Bid bid = bidManager.createBid(item, bidder, bidPrice);
}
}

The problem with this approach is that the client is coupled to the persistence and internals of the business logic layer. It quickly becomes a nightmare to manage the security for so many session beans. Also, some of the real business logic gets scattered in multiple places in the code. A better option is to create a session façade like the PlaceBidBean EJB shown here, which uses these operations and exposes PlaceBidBean to the client:

@PersistenceContext(unitName = "actionBazaar", name = "actionBazaar")
@Stateless(name = "PlaceBid")
public class PlaceBidBean implements PlaceBid {
public PlaceBidBean() {
}

public Long addBid(String userId, Long itemId, Double bidPrice)
throws BidException {
...
Item item = itemEAO.findByItemId(itemId);
Bid highBid = itemEAO.findHighestBidForItem(item);
if (bidPrice <= highBid.getBidPrice()) {
throw new
BidException("Bid Price is lower than the current bid price");
}
...
return bidEAO.addBid(item, userId, bidPrice);
}
}

There are several merits to the Session Façade pattern. First, it centralizes the real business logic in a single place instead of duplicating it many times. Second, with this pattern the clients don’t have to know the internal design of the system. Third, it helps to manage transactions and security centrally instead of managing it for multiple session beans. A final advantage is that it makes the client code much simpler. Take a look at how much the client knowledge is reduced using this approach:

@EJB
private PlaceBid placeBid;
...
Bid bid = placeBid.addBid(userId, itemId, bidPrice);

If you decide to expose EJBs to remote clients, you will see a dramatic improvement in performance. In addition, such EJBs may be good candidates for being exposed as web services, enhancing reusability and the ability to distribute your enterprise applications.

Stateful vs. stateless session façade

As we saw in the PlaceBid EJB example, most business logic spans only a single method call; therefore, most of your session façades will be stateless in nature. You may choose to make your session façade stateful if your business requires multiple method invocations as a part of some business process and you must maintain conversational state. A stateful session façade also has the benefit of an extended persistence context (discussed in chapter 9) that helps you keep the entities in a managed state that may span across a transaction, and the persistence context is automatically closed when the bean instance is removed. For example, the user registration process is a multistep process. You want to keep the entities managed during the registration process and end the persistence context when the user has completed the registration process. A stateful session façade may be useful in such situations.

This finishes our discussion on EJB design patterns. If you are interested in exploring other design patterns from Sun’s blueprints website, please visit http://java.sun.com/reference/blueprints/index.html.

A book about EJB must have an EJB-centric view of the world, mustn’t it? In other words, you are probably using a Java EE container with EJBs, or you are using a totally different framework that is incompatible with everything related to EJB 3, right? These statements are true neither of the authors nor of reality. It is useful to know that many aspects of the EJB 3 specification are both available and compatible with alternate approaches to enterprise Java development. The next section delves into some of the options that you may be interested in implementing on your next project.

12.2. Accessing session beans from the web tier

You may remember from our discussion in chapter 1 that EJB helps build applications with tiered architecture. You can use session beans to build the business logic of your applications and access the session beans from the presentation or web tier of your enterprise application. Figure 12.4 illustrates where EJBs fit into the architecture of ActionBazaar and how EJBs are accessed from the ActionBazaar web module.

Figure 12.4. ActionBazaar application architecture. The ActionBazaar web module accesses the EJBs that implement the business logic and manipulate entities.

As we discussed in chapter 3, session beans can be accessed using either dependency injection or JNDI lookup. Dependency injection is supported only with managed classes—classes such as servlets, whose lifecycle is managed by the container. While both managed and nonmanaged classes can use JNDI lookup, you’ll probably use it only with classes that are not managed. Table 12.1 provides some insight as to types which of classes can access EJBs using dependency injection.

Table 12.1. An EJB can be accessed from different types of classes in the web tier. Only managed classes can use dependency injection; nonmanaged application components have to use JNDI lookup to obtain a reference to a session bean.

Class Type

Injection

Servlets, filters, event listeners

Yes

JSP tag handlers, library event listeners

Yes

JSF managed beans

Yes

Helper classes, JSPs

No

Regardless of which method you use to access your EJBs, you’ll interact with them in the same manner after you have obtained an EJB reference.

Your web application may contain a mixture of managed and nonmanaged application components, and in the next sections we’ll discuss how you can access session beans from both types of application components. We’ll show you how to invoke an EJB 3 session bean from managed classes, such as a servlet, and nonmanaged classes, such as a helper class. We’ll also explore what you have to do to demarcate a transaction and the steps required to build a stateful application using stateful session beans.

12.2.1. Accessing session beans using dependency injection

Dependency injection is by far the easiest way to access an EJB 3 session bean. In this section you’ll see how to use dependency injection from the web module to access a session bean. You learned about the @EJB annotation in chapter 3, and you probably want to jump into using dependency injection for all your session beans. However, we’ll explain why you would want to avoid using dependency injection when accessing a stateful session bean from a multithreaded client.

You can obtain a reference to an EJB in your managed class by using injection in one of two ways:

  • By using the @EJB annotation
  • By using the ejb-ref or ejb-local-ref element in the web.xml deployment descriptor

Assume that ActionBazaar uses a controller servlet. You can use @EJB to inject a reference to an EJB as follows:

public class ActionBazaarBidControllerServlet extends HttpServlet {
@EJB private PlaceBid placebid;

...
placeBid.addBid(bidderId, itemId, bidPrice);
...
}

This example shows the PlaceBid EJB being injected into the ActionBazaarBidControllerServlet. The @EJB annotation here is clean and straightforward.

If instead we use the ejb-ref or ejb-local-ref element in the deployment descriptor, we would have a web.xml like this:

  <ejb-ref>
<ejb-ref-name>PlaceBid</ejb-ref-name>
<ejb-ref-type>Session</ejb-ref-type>
<remote>actionbazaar.buslogic.PlaceBid</remote>
<injection-target>
<injection-target-name>placeBid</injection-target-name>
<injection-target-class>
actionbazaar.web.ActionBazaarBidControllerServlet
</injection-target-class>
</injection-target>
</ejb-ref>

Compare these two examples. Which one makes more sense to you?

Avoid injecting stateful session beans

If you are using stateful session beans, then you must avoid injecting them into classes that are multithreaded in nature, such as servlets and JSF managed beans.

Let’s look at an example. Suppose you inject the BidderAccountCreator bean into a servlet that is multithreaded, as shown here:

@Stateful(name = "BidderAccountCreator")
public class BidderAccountCreatorBean {

private LoginInfo loginInfo;
private BiographicalInfo biographicalInfo;
private BillingInfo billingInfo;

@Remove
public void cancelAccountCreation() {
...
}
}

In this case, the single BidderAccountCreator instance will be shared by all users of the servlet. This is not the desired behavior since loginInfo, biographicalInfo, and billingInfo are designed to be specific to an individual client.

This becomes trickier when we have a method annotated with the @Remove annotation. When a particular user invokes the cancelAccountCreation method, the EJB instance will be destroyed. The next time a user tries to access the BidderAccountCreator EJB, the container will generate a javax.ejb.NoSuchEJBException.

If you want to use stateful session beans in your web application, then you need to perform a JNDI lookup and store the returned EJB instance in the HttpSession object. This way, the same user reaches the same bean instance for future activity. This also scopes the EJB instance to the user’s session, avoiding the possibility of other sessions acquiring or deleting it. We’ll explain more about working with stateful session beans in section 12.2.4.

12.2.2. Referencing session beans from helper classes

Sometimes you’ll find that you need to access a session bean from a class that is not managed. Dependency injection is not supported in nonmanaged classes. For example, your JSF managed bean may be using some utility classes that are not managed by the container. You cannot inject an instance of an EJB into those classes. Again, in this case you must use JNDI lookup to access your session bean. This method is also used by managed classes when you want to avoid injection. For looking up an EJB from a helper class you have to do the following:

  1. Establish the reference to EJB by using the @EJB annotation at the class level or the ejb-ref (ejb-local-ref) descriptor element.
  2. Look up the session bean.

Remember from our discussion in part 2 of this book that the @EJB annotation can be used for injecting session bean references to a field or a setter method or can be applied at the class level to establish a reference that can be used with JNDI lookup.

The class where you use the @EJB annotation should be the managed class that uses a helper class. For example, say you have a helper class named BidProcessor that is used by ActionBazaarBidControllerServlet. The BidProcessor class looks up the PlaceBid EJB. You cannot use the @EJB annotation with the BidProcessor class because it is not a managed class. Here the entry point for the BidProcessor class is ActionBazaarBidControllerServlet, and that’s the reason we can use the @EJB annotation as follows:

@EJB (name = "ejb/PlaceBid", beanInterface = PlaceBid.class)
public class ActionBazaarBidControllerServlet extends HttpServlet {
}

Then look up the EJB in the helper class (BidProcessor) like this:

PlaceBid placeBid = (PlaceBid)context.lookup("java:comp/env/ejb/PlaceBid");

placeBid.addBid(bidderId, itemId, bidPrice);

In other cases the entry point of your web framework may be a managed class, but you may not be able to modify the code in a way that allows you to use an annotation to establish EJB references. For example, if you are using a framework such as Struts, the entry point for your application is the controller class in the framework, and modifying such frameworks to establish EJB references may not be part of your project. In this case you can use the ejb-ref element in web.xml to establish the EJB references so that the EJBs being used will be bound to the JNDI tree, and thereby visible to your classes via JNDI lookup.

Using the global JNDI name

With some application servers, you may be able to work around specifying references using the @EJB annotation or the web.xml descriptor element by using the global JNDI name. Recall from our discussion earlier that many vendors allow EJB access using global JNDI names, such as the EJB name or by using an EJB class name without having to specify the ejb-ref or ejb-local-ref.

For example, some application servers will allow the lookup of an EJB as follows:

PlaceBid placeBid = (PlaceBid)context.lookup("PlaceBid");

while others may allow the following type of lookup:

PlaceBid placeBid =
(PlaceBid)context.lookup("actionbazaar.buslogic.PlaceBid");

Keep in mind that these approaches are not portable across containers and we recommend you use an EJB reference during lookup.


JNDI and Service Locator design pattern

If you have used EJB 2 or J2EE 1, then you are probably very familiar with service locators. If you haven’t used them, take a look at http://java.sun.com/blueprints/corej2eepatterns/Patterns/ServiceLocator.html.

Simply put, the Service Locator design pattern is used to abstract the complexities of JNDI by helping reduce repetitive JNDI code, enforcing a single point of control for lookup, and improving performance of EJB lookups with caching. Many developers believe that the Service Locator pattern will no longer be used with EJB 3 due to dependency injection taking a front-row seat. However, the reality is that EJB 3 dependency injection is not supported in all circumstances and you may still need to rely on good ol’ JNDI lookup. Therefore, service locators may not be dead just yet.

There are alternatives to using the Service Locator pattern and JNDI for using resources or EJBs. One such alternative is injecting a bean instance in the managed class and passing it to the helper class as a parameter to its constructor. For example, the BidManager EJB uses a helper class, BidManagerHelper, that invokes a method in the ItemManager EJB. BidManagerHelper is a regular POJO, so we cannot inject the ItemManager instance. However, we can inject the ItemManager EJB into BidManagerEJB and pass it to the helper class as follows:

@Stateless
public class BidManagerBean implements BidManager {
@EJB ItemManagerLocal itemManager;

public Bid placeBid() {
BidManagerHelper helper = new BidManagerHelper (itemManager);
...
}
}

Be sure you evaluate such alternatives before deciding which one best meets your needs.


12.2.3. Dealing with transactions

Remember from our discussion in chapter 6 that in your EJB applications you can use either container-managed transactions (CMT) or bean-managed transactions, in which you programmatically manage transactions using the UserTransaction API. While CMT is not available in the web container, if your application uses session beans they allow you to use CMTs and avoid UserTransaction. We highly recommend you take advantage of CMT. For example, if you want to make multiple EJB method calls from the same transaction, then you may be tempted to do the following:

public class ActionBazaarRegistrationControllerServlet
extends HttpServlet {
...
//--- Do NOT do this!!! This is NOT recommended!!!
@EJB ItemManager itemManager;
@EJB categoryManager categoryManager;
@Resource private UserTransaction ut;
...
public void doPost(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
...
ut.begin();
...
categoryManager.addCategory(category);
itemManager.addItem();
itemManager.setCategory(category);
...
ut.commit();

}
...
}

In this example we are injecting the instances ItemManager and CategoryManager and then invoking several methods on injected session beans. The first issue here is that you have to write error-prone code to demarcate the transaction. Second, because your EJBs are fine-grained, the business logic gets scattered between the EJBs and the web module. Finally, if the EJBs are remote, these translate to three RMI calls, which can be expensive from a performance perspective. We suggest you avoid this practice. If your application includes such a requirement, we recommend you create a session façade and use that to perform all operations, and then invoke that EJB from the web tier. (We covered the Session Façade design pattern earlier in this chapter.)

12.2.4. Working with stateful session beans

If you are building an application that requires maintaining client state end-to-end, you’ll most likely use stateful session beans. In section 12.2.1 we listed some reasons why you must avoid injecting instances of stateful session beans into multithreaded classes and use JNDI instead. In this section we’ll look at how you can successfully use JNDI and stateful session beans from your web application.

In order to look up a session bean, you have to establish a reference or dependency using the @EJB annotation at the class level and then look up the bean from the environment naming context (discussed in chapter 5) using the reference name specified. If you have worked with EJB 2, using @EJB at the class level is the same as using ejb-ref. The session beans get bound to the environment naming context, or ENC (see chapter 5) as java:comp/env/<name specified with @EJB>.

To begin, you can use the @EJB annotation at the class level to establish an EJB reference or dependency on EJB as follows:

@EJB(name = "UserRegistrationBean",
beanInterface = UserRegistration.class)
public class ActionBazaarRegistrationControllerServlet
extends HttpServlet {
...
}

You must make a JNDI lookup and store the EJB object in the HttpSession object. This will ensure that the same user session gets back the desired bean instance as follows:

try {
InitialContext ctx = new InitialContext();
userReg = (UserRegistration)ctx.lookup(
"java:comp/env/UserRegistrationBean");
session.setAttribute("user_reg", userReg);
} catch (Exception e) {
handleException(e);
}

Now the reference to the session bean can invoke any number of methods. The container ensures that there is a bean instance reserved for a user session and that the bean instance is not shared between multiple user sessions. Be sure to remove the EJB object from the HttpSession when you are invoking a method that is annotated with @Remove. Here’s the code that removes the bean instance from the session:

userReg.createAccount();
session.removeAttribute("user_reg");

Note that the createAccount method has been annotated with @Remove (see chapter 3), and we must remove the reference to the stateful EJB when the bean instance is destroyed. Otherwise, if we try to use it in the future all we’ll get will be the aforementioned javax.ejb.NoSuchEJBException. And we wouldn’t want that now, would we?

Understanding how clients can best access session beans is great, but what about times when we need to access the persistence mechanism directly?

12.3. Using JPA from the web tier

You may not need the power or additional complexity of EJBs for every Java EE application, and therefore decide to forego session beans on occasion. For instance, you may choose to stick with POJOs and servlets to implement business logic, and include the entities directly in the web module (or WAR). In this section, we’ll show you how to use entities directly from the web tier.

In chapter 11, we explained that entities can be packaged in the web module, but we skipped over the details of how to do it. You can make your entity classes available to your web module in one of two ways:

  • Place entity classes directly in WEB-INF/classes. When you package classes in the WEB-INF/classes directory of a WAR module, the persistence.xml and optional orm.xml are placed in the WEB-INF/classes/META-INF/ directory.
  • Alternatively, you can package entity classes in a JAR file and place the file in the WEB-INF/lib directory. That way, you can package the persistence. xml and optional orm.xml descriptors in the META-INF directory of the JAR.

This means the structure of your WAR module will look something like this:

If you don’t package entities in the WEB-INF/classes, then you don’t have to package persistence.xml and the optional orm.xml in the WAR file. The entities.jar packaged in our example contains entities.

As you can see, packaging the entities with the web module is easy, but you may be wondering how to use them. There are three common scenarios for using EJB 3 JPA from the web container:

  • Using a container-managed entity manager in a Java EE 5 container
  • Using an application-managed entity manager with a JTA transaction manager in a Java EE 5 container
  • Using an application-managed entity manager with local transactions outside the container

The first two cases will be more prevalent because of the power of container-managed entity managers and JTA transactions, but for completeness we’ll discuss all three scenarios in this section.

12.3.1. Using a container-managed entity manager

Many developers think developing session beans is complex and primarily useful for large applications, and they want to use JPA directly from the web application. If you choose this approach, and if you’re using JPA within a Java EE container, a container-managed entity manager is probably the best option, but you still must be careful in the way you use it. For instance, you should avoid dependency injection. Let’s look at why this is so.

If you’re planning to use JPA from a managed class like a servlet, you may be tempted to inject an instance of an EntityManager by using the @PersistenceContext annotation like this:

//--- Do NOT do this!!! This is NOT recommended!!!
public class ActionBazaarBidControllerServlet extends HttpServlet {
@PersistenceContext(unitName = "actionBazaar")
private EntityManager entityManager;
...
}

If you use this and test your application, it will probably run successfully in your first few attempts. However, you’ll likely run into issues when more users try to access the servlet at the same time. You may remember that in chapter 9, we explained that EntityManager is not designed to be thread-safe in nature. When you inject an instance of EntityManager into a class like a servlet, it is stored in an instance variable at the servlet class level and may be shared by multiple users at the same time. This can result in unexpected errors. Because of this you must avoid injecting an instance of EntityManager unless your container vendor (such as Oracle Application Server) guarantees that their EntityManager implementation is thread safe. You also have to remember that your code may not be portable when you depend on the thread safety of EntityManager.


Note

You may want to work around this by having your servlets implement SingleThreadModel. Although doing so may seem harmless, keep in mind that this is a deprecated feature (since servlet 2.4) and we don’t recommend using it because of the many limitations it imposes on applications. This topic is beyond the scope of this book (see www.esus.com/javaindex/j2ee/servlets/servletdiffthread.html).


The right way to use a container-managed EntityManager is by avoiding dependency injection and instead performing a JNDI lookup. Bear in mind that the JNDI lookup mechanism can be used in any nonmanaged or managed class.

To use a container-managed EntityManager, you must first establish the references to the persistence unit using either the @PersistenceContext annotation at the class level or the persistence-context-ref element in web.xml.

If you’re using a managed class such as a servlet or JSF managed bean, then you can establish the reference as follows:

@PersistenceContext(name = "actionBazaar/EntityManager",
unitName = "actionBazaar")
public class ActionBazaarBidControllerServlet extends HttpServlet {
private EntityManager entityManager;
...
}

If you are using a web framework like Struts where the action classes are not managed, then you can’t use annotations to establish references to the persistence context. In this case you will have to use the persistence-context-ref element in the web.xml as follows:

<persistence-context-ref>
<persistence-context-ref-name>
actionBazaar/EntityManager
</persistence-context-ref-name>
<persistence-unit-name>actionBazaar</persistence-unit-name>
</persistence-context-ref>

Regardless of which previous approach you use, your next step is to grab an instance of an EntityManager by using JNDI:

Context context = new InitialContext();
EntityManager entityManager =
(EntityManager)context.lookup(
"java:comp/env/actionBazaar/EntityManager");

One thing you need to remember when you don’t use session beans to access the entities is that you have to programmatically manage your transactions since CMT is not available in the web container. You must use the UserTransaction API in the following way:

@Resource private UserTransaction ut;
...
ut.begin();
...
entityManager.persist(item);
...
ut.commit();

You’ll recall that in chapter 6 we discussed the disadvantages of programmatic transaction; it’s also evident from the previous code that you have to write error-prone code to manage transactions. If you plan to deploy your web module to a Java EE container, an EJB container is included as well. We recommend that you take full advantage of your container by using a session bean to façade your entity operations. With this approach, you don’t have to worry about programmatic transactions, and you receive extra benefits, such as the ability to inject EntityManager and the power of extended persistence context.

Next we’ll discuss how you can use an application-managed EntityManager with the JTA transaction manager.

12.3.2. Using an application-managed EntityManager with JTA transactions

As you know, we don’t typically recommend using an application-managed EntityManager, but in some cases it’s your best choice. For instance, you may not want to use JNDI to grab a container-managed EntityManager instance because you are a fan of dependency injection. In that case, there is another option. You can consider using the @PersistenceUnit annotation to inject an instance of an EntityManagerFactory, and then create an application-managed instance of EntityManager as follows:

public class ActionBazaarBidControllerServlet extends HttpServlet {
@PersistenceUnit(unitName = "actionBazaar")
private EntityManagerFactory emf;
...

}

Just remember that you have to manage the lifecycle of an application-managed EntityManager (see listing 12.4); the container is not going to do it for you in this situation.

Listing 12.4. Using an application-managed entity manager with a JTA transaction

In listing 12.4 we are doing a lot of housekeeping to manage the lifecycle of the EntityManager and to manually manage transactions. Unless you have a specific reason to use an application-managed EntityManager, we recommend using the Session Façade design pattern (discussed in 12.2.3) with CMT, and a container-managed EntityManager. The EJB 3 incarnation of session beans are lightweight POJOs, which make life easier by not requiring the developer to manage the lifecycle of entity managers or transactions.

12.3.3. Accessing an application-managed EntityManager outside the container

Developers write all sorts of applications. You might have some applications, such as a Swing or SWT application, for which you’d prefer to use JPA outside the EJB 3 container. Or perhaps you just want to utilize web containers like Tomcat or Jetty that are not Java EE 5 containers, or one of the other lightweight containers that do not have support for a container-managed EntityManager or JTA transactions.

Another case in which you might want to use JPA outside the EJB 3 container is when you’re testing your entities. You can use the approach we discuss here in conjunction with a test framework such as JUnit and to test entities outside the container.

It’s simple to use JPA without an EJB 3 container. All you need to do is create a persistence unit and create an EntityManager from the EntityManagerFactory obtained from the Persistence class. Let’s look at an example.

Defining a persistence unit

As you know from chapters 9 and 11, a persistence unit requires a DataSource configured in the application server that is used by the persistence provider to connect to the database. Normally, the Java EE container will provide this, but if you are using JPA outside the container, you must provide the JDBC configuration as vendor-specific properties in the persistence.xml file.

Listing 12.5 shows a sample persistence.xml that illustrates the JDBC configuration for the GlassFish server. The property names will vary depending on which persistence provider you’re using.

Listing 12.5. JPA outside a container: an example persistence.xml

Creating an application-managed EntityManager

To perform CRUD operations on entities, you need to grab an instance of an EntityManager. An EntityManager may not be available in the JNDI registry or accessible by dependency injection when using JPA outside the Java EE container. In such cases, you have to create an EntityManager from the EntityManagerFactory that can be created from the javax.persistence.Persistence factory class. This is typically the case when you’re trying to use JTA in environments such as Java SE or when you’re using a web container like Tomcat. (JTA transactions are unavailable outside the Java EE container.)

Listing 12.6 shows an example of how you can use entities outside the container when JTA transactions are not available.

Listing 12.6. Persistence outside the container: a Java SE class using the EJB 3 JPA

Note that we are using the javax.persistence.Persistence class to create an instance of EntityManagerFactory. Persistence is the bootstrap class outside the Java EE container that allows us to access the EntityManagerFactory by invoking the createEntityManagerFactory method. You can create an EntityManager instance after initializing the factory. Keep in mind that you have to use the EntityTransaction interface to begin and commit a transaction and . Finally we close the EntityManager .

When running JPA outside the container, you have to make sure you include all the required files in the CLASSPATH. Check the appropriate documentation for your persistence provider to determine any additional requirements it may have.

12.4. Summary

In this chapter you learned how to use EJBs from other tiers. We first looked at how you can use EJB 3 session beans and JPA from the web tier. We described some design patterns that you can use to build better applications. The Model-View-Controller pattern helps separate code based on lines of responsibility. It is most commonly used in frameworks dealing with user interfaces (such as web frameworks). The Entity Access Object design pattern upgrades the trusted DAO pattern to support EJB 3 entities. EAO reduces tight coupling between application tiers, and provides the ability to change persistence code without impacting business logic. Similarly, the Session Façade design pattern reduces the presentation tier’s dependencies on the internal workings of the application tier, and improves centralization of transaction management and security. You can access EJB 3 session beans using either dependency injection or JNDI lookup, but you must avoid injecting stateful session beans into multithreaded clients. JPA can be used from web applications without having to depend on session beans. As we showed you in this chapter, you have to use UserTransaction to demarcate transactions when using JPA directly from the web tier.

The next chapter discusses performance and scalability issues around real EJB 3 applications.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset