How to use CDI with EJB 3.0?

This article is based on EJB3 in Action, Second Edition and the book will released on October 2011. It is being reproduced here by permission from Manning Publications. Manning publishes MEAP (Manning Early Access Program,) ebooks and pbooks. MEAPs are sold exclusively through Manning.com. All print book purchases include an ebook free of charge. When mobile formats become available all customers will be contacted and upgraded. Visit Manning.com for more information.

also read:

Introduction

CDI plays a vital role by providing robust, next-generation, annotation-driven dependency-injection to all Java EE components including EJB 3. In this article, we will show you some of the most common ways CDI is used with EJB 3—namely, as a more robust replacement to JSF-managed beans and complementing EJB with components that are not in the business tier and do not need to use EJB services directly.

Using CDI with JSF 2.0 and EJB 3.0

In order to see how CDI can be used as the superglue between JSF and EJB 3, let’s look at a bid service stateless session bean example. The bid service allows us to save bids into the database. Clearly, the add bid functionality would likely be used on a page that allows the bidder to place a bid on an item. If you are familiar with auction sites, this page could look something like figure 1.

Most of the page displays the details about the item, the bids, the seller, and the bidder such as the item title, description, highest bid, current bidders, seller information, and so on. The part we are most interested in is the text box to enter a bid amount and the button to place a new bid. The JSF 2 code for these two page elements will look like listing 1.

Listing 1 JSF page to add bid

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets">
<h:body>
...
<h:form id="bid-form">
...
<h:inputText id="input-bid" value="#{bid.amount}"/> #1
...
<h:commandButton id="place-bid-button" #1
value="Place Bid!" #1
action="#{bidManager.placeBid}"/> #1
...
</h:form>
...
</h:body>
</html>

#1 Binding expressions to CDI managed beans

As you can see, both the input text field and the button are bound to the underlying beans using binding expressions (#1). The input text field is bound to the amount field of a bean named bid. This means that the text field displays the value of the bound bean field, and any value entered into the text field is automatically set into the bean field. The place-bid button is bound to the placeBid method of a bean named bidManager. This means that the bound method is automatically invoked when the button is clicked. Listing 2 shows code that the JSF page elements are bound to.

Listing 2 BidManager CDI managed bean

@Named #1
@RequestScoped #2
public class BidManager {
	@Inject #3
	private BidService bidService;
	@Inject #4
	@LoggedIn #4
	private User user;
	@Inject #5
	@SelectedItem #5
	private Item item;
	private Bid bid = Bid();
	@Produces #6
	@Named #6
	@RequestScoped #6
	public Bid getBid() {
		return bid;
	}
	public String placeBid() {
		bid.setBidder(user);
		bid.setItem(item);
		bidService.addBid(bid);
		return “bid_confirm.xhtml”;
	}
}

#1 Names bid manager CDI managed bean

#2 The bid manager is request scoped

#3 Injects bid service EJB

#4 Injects currently logged-in user

#5 Injects currently selected item

#6 Produces a request-scoped CDI managed bean named 'bid'

The bid manager component is not an EJB but simply a CDI-managed bean. This means that, other than life cycle, dependency injection, and context management, no enterprise services such as transaction management are available directly to the bid manager component. This is perfectly fine in this case since the bid manager simply acts as the glue between the JSF page and transactional EJB service tier.

As such, the bid manager is probably self-explanatory even with the various CDI annotations. The @Named CDI annotation (#1) on the bid manager names the component. By default, the component is named as the simplified class name in camel-case. In the case of the bid manager component, the name assigned will be ‘bidManager’. Naming a component is necessary in order to reference it from JSF EL. As you’ve seen, the BidManager.placeBid method is bound to the place bid button via an EL binding expression. The @RequestScoped CDI annotation (#2) specifies the scope of the bid manager. Because the bid manager is request scoped, the bean will be created when the JSF page is loaded and is destroyed when the user navigates to another page.

A number of other beans are injected into the bid manager component as dependencies. The first is the bid service stateless session bean (#3) we are already familiar with. The injections for the bidder (#4) and item (#5) are a bit more interesting. The @LoggedIn and @SelectedItem annotations are CDI user-defined qualifiers. Qualifiers are user-defined meta-data used to specify that you want a specific type of bean injected. For example, in case of injecting the user into the bid manager, we are specifying that we want a special kind of user—namely, the currently logged-in user. The code assumes that CDI has reference to a suitable User instance in some known accessible scope. Most likely, the User bean corresponding to the logged-in user is in the session scope and was placed there as part of the login process. Similarly, the bid manager code uses the @SelectedItem qualifier to specify that it depends on the item that the user has currently selected. The selected Item bean was likely placed into the request scope when the user clicked on the link to view the item details.

The @Produces, @RequestScoped, and @Named annotations (#6) placed on the getBid method are very interesting as well. As you may have guessed, the @Produces annotation is a key piece of functionality. The @Produces annotation tells CDI that the getBid method returns a Bid object that it should manage. The @Named and @RequestScoped annotations on the getBid method tells CDI that the returned Bid object should be named and it should be in the request scope. Because the bid object is named, it can be reference in EL just as we did in the JSF page. It is a JPA 2 entity that holds all bid data, including the bid amount that is bound by EL to the input text field on the JSF page. Because the bid manager creates and holds a reference to the bid object, it automatically has access to the bid data entered via the JSF page.

When the placeBid method is invoked in response to the button-click on the JSF page, the bid manager uses all the data it has reference to and properly populates the bid object. It then uses the bid service stateless session to have the bid into the database. Finally, the user is redirected to a page that confirms the bid.

That is all that we need to say about using CDI with EJB 3 at the presentation tier at the moment. CDI is used with EJB 3 in a number of other different ways, including at the persistence tier to implement DAOs. Let’s take a look at that next.

Using CDI with EJB 3.0 and JPA 2.0

In Java EE 5-based systems, the DAO layer is often implemented as EJB 3 beans. This technique makes a certain amount of sense, especially if the DAO is marked with the ‘transaction required” attribute. This forces all clients that use the DAOs to handle transactions and is a great safeguard since DAOs often utilize resources that require transactions such as the database. However, for in-house applications where the service and DAO layers are often developed by the same team, these safeguards are not always needed. In fact, it is possible to develop DAOs using plain CDI managed beans and inject them into EJBs at the service tier. To see what the code looks like, let’s check out the bid manager stateless session bean in listing 3.

Listing 3 BidService stateless session bean code

@Stateless #A
public class DefaultBidService implements BidService {
	@Inject #B
	private BidDao bidDao;
	...
	public void addBid(Bid bid) {
		bidDao.addBid(bid);
	}
	...
	}
	@Local
	public interface BidService {
	...
	public void addBid(Bid bid);
	...
	}

#A Marks POJO as stateless session bean

#B Injects non-EJB DAO

#C Marks interface as local

The bid DAO injected into the EJB is a CDI managed bean with an interface. The DAO relies on the transaction and thread-safety context of the EJB and does not need to have any services other than basic dependency injection offered by CDI. Any other services such as security and asynchronous processing are also likely best applied at the service tier rather than the persistence tier. Listing 4 shows the code for the DAO.

Listing 4 BidDao CDI managed bean

public class DefaultBidDao implements BidDao {
	@PersistenceContext #A
	private EntityManager entityManager;
	...
	public void addBid(Bid bid) {
		entityManager.persist(bid);
	}
	...
	}
	public interface BidDao {
	...
	public void addBid(Bid bid);
	...
	}

#A Injects the JPA 2 entity manager

As such, the DAO is very simple. In fact, some of you might be surprised that neither the DAO class nor the interface has any annotations on it at all. This is really quite normal in the CDI world since CDI-managed beans truly are bare POJOs. When CDI sees the @Inject annotation in the bid service EJB, it simply looks for any object that implements the BidDao interface and injects it. It is important to note that the bid DAO is nameless—it does not have an @Named annotation. This is because the DAO really does not need to be referenced by name anywhere. The DAO also does not have a defined scope. When this happens, CDI assumes that the bean belongs in the default scope. By default, CDI creates a brand new instance of the bean and injects it into the dependent component—basically the same behavior as a “new” operator at the injection point. Notice also that the bid DAO itself can request injection as well. In the example, CDI injects a JPA 2 entity manager into the DAO that is used to save the bid entity into the database.

The CDI features you saw in this article are truly the tip of the iceberg. CDI has a vast array of other features like stereotypes, events, interceptors, and decorators.

Summary

We showed you what to expect from the new version of the Java enterprise platform, specifically, how CDI and EJB 3 work together seamlessly across application tiers.

also read:

Comments

comments

About Krishna Srinivasan

He is Founder and Chief Editor of JavaBeat. He has more than 8+ years of experience on developing Web applications. He writes about Spring, DOJO, JSF, Hibernate and many other emerging technologies in this blog.

Trackbacks

  1. […] Using CDI with EJB 3.0 […]

Speak Your Mind

*