Posted by pierre
on January 9, 2006 at 5:16 PM PST
Some thoughts on the experience of migrating the Duke's Bookstore
sample web application (in the J2EE 1.4 tutorial) from JNDI and JDBC to the
new Resource-Injection and Java-Persistence-API combo.
The Java EE tutorial constitutes a great resource to help
developers better understand what the Java EE platform is all
about. It covers the technologies you will be interested in if you
write enterprise applications using EJBs as well as simpler web
applications. See the tutorial roadmap diagram to get an
idea of the key topics that are addressed by the tutorial.
Lately, I've been helping Jennifer (one of the tutorial writers)
update the "Duke's Bookstore" sample application of the tutorial so it
leverages some of the new Java EE 5 features.
Here is the tutorial's description of the Duke's Bookstore sample app:
In Chapters 11 through 22 a common example--Duke's Bookstore--is
used to illustrate the elements of Java Servlet technology,
JavaServer Pages technology, the JSP Standard Tag Library, and
JavaServer Faces technology. The example emulates a simple online
shopping application. It provides a book catalog from which users
can select books and add them to a shopping cart. Users can view
and modify the shopping cart. When users are finished shopping,
they can purchase the books in the cart.
More specifically, we've been looking at migrating the 'database
access' portion of the app from JNDI and JDBC to the new Java EE 5
Resource Injection and Java Persistence API (from the EJB 3.0
I must admit we've struggled a little bit with some of the concepts
that one must master to properly use this new combo. Even if Resource
Injection and the Java Persistence API can be used independently of
EJBs, it appeared to us that familiarity with EJB usage patterns makes
it easier to understand how to properly use these new features in the
context of webtier applications.
Here are therefore a few thoughts on the topic.
Basic concepts, the EJB way
In the EJB world, an entity bean represents a business object in a
persistent storage mechanism. In Duke's bookstore, 'Book' is the typical
business object. In the Application Server, the persistent storage
mechanism is a relational database. Each entity bean has an
underlying table in a relational database, and each instance of the
bean corresponds to a row in that table.
A session bean, be it stateless or stateful, is an entry point into
the business logic of the enterprise application. So when a user wants
to add a book to the shopping cart, the ShoppingCart session bean is
invoked and it takes care of properly handling the operation.
Finally, all of the resources exposed by an enterprise application
need to to be accessible. Getting a handle to these resources is
typically handled through JNDI.
Most will agree that the above concepts are simple and
straightforward. Unfortunately, the complexity associated with the
implementation of EJBs have scared more than one developer in the
past. Luckily, much of this is changing with the Ease of Development
focus of Java EE 5. Not only is it easier to work with EJBs, but
benefits associated with traditional EJBs can be now be leveraged
without even using them, as is the case with web applications.
The new order: Java Persistence API and Resource Injection
As stated in the EJB 3.0 specification, the Java Persistence API is
"the Java API for the management of persistence and object/relational
mapping with Java EE and Java SE". Entity beans are therefore no
longer an exclusive feature of the Enterprise platform. The Java
Persistence API is totally independent of EJBs and provides the
Object-Relational Mapping layer that is so convenient to persist
As can be seen in the tech tip Converting a POJO to a Persistent
Entity , taking advantage of Java Persistence is quite easy.
The only issue though is that using Java Persistence is much easier if
you can rely on a container that supports "Resource Injection", a new
feature also introduced in Java EE 5.
Note though that Resource Injection is limited to components that are
managed by a Java EE compliant container. Session beans therefore fit
the model perfectly.
But web applications live in a world that is EJB-free. While there are
no session beans in a webapp, the need to implement business logic
that is accessible over the web still exists. To fill that need, web
app developers can choose from a variety of technologies.
This choice is clearly showcased with the Dukes Bookstore web
application. The webapp is implemented using three different technologies:
pure Servlets, JSP, and finally JSF (and one could easily think of a
Struts-based implementation to complement the offering).
The challenge for a webapp developer that uses the Java Persistence API
is therefore to design the application such that Resource Injection can
be used (go with the flow young man, don't fight it!).
As mentioned above, Resource Injection can only be used by classes that
are managed by a Java EE compliant container. This is for two
reasons. First, for performance considerations, a container can
restrict its search of annotations only to the components it manages,
which are defined in a deployment descriptor or accessible in specific
locations of the classpath. Second, the container must have control
over the creation of the component to be able to transparently perform
the injection into the component.
While it is true that Resource Injection would be most useful in the
webtier if it were applicable to any POJO (Plain Old Java Objects),
this will have to wait for a future release. In Java EE 5, the
support for resource injection in the webtier is limited to the
following webtier-managed components:
- Servlet Specification: Servlets, Servlet Filters, Event Listeners
- JSP Specification: Taglib listeners, Taglib Tag Handlers
- JSP Specification: Managed Beans
What's important to note though is that this limitation is quite
acceptable if one follows a pattern similar to the one employed by
session beans. A Service Locator pattern to get access to
resources is no longer required because a controller can be
transparently injected with the resources it needs to carry on
If the entry point into the business logic of a web application
is a webtier-managed component, then all resources required to
support the Java Persistence API can be injected transparently.
This therefore works very well in a Servlet environment because
servlets act as controllers into the business logic. The same holds in
a JSF environment where managed beans associated with a page also act
as controllers into the business logic of the application.
The situation is unfortunately not as straightforward with JSPs.
JSP pages cannot be the target of resource injection
because all the information represented by these injection annotations
needs to be known at deployment time. If an annotation is included
in a JSP page, it won't be seen at deployment time.
[actually, it would if the page had been precompiled, but one cannot
assume that all pages are precompiled].
A possible solution is to use a tag library since tag handlers can
be the target of resource injections. See Sahoo's blog for an example.
The problem though is that this promotes the use of scriptlets in
a JSP page, which should ideally be avoided.
Ideally, we'd want a bean that is declared in a JSP page via
<jsp:useBean> to act as a controller and be "injectable", just as is
the case with managed beans in JSF. Since this is not possible,
a solution is to allow this controller bean to access resources
that have been injected elsewhere.
That's what we're planning to do in Duke's bookstore; simply use a
ServletContextListener to save global instances of the injected
resources. These resources can then be accessed from the controller
Confused? In a forthcoming blog I'll describe how JNDI and
JDBC are used in the J2EE 1.4 version of Duke's bookstore, and how we're
planning to modify the different implementations of the webapp (servlets, JSP, and JSF) to take advantage of Resource Injection and the Java
Persistence API introduced in Java EE 5. And if you have comments on
the topic, please share them with us all...
Thanks to Jennifer, Sahoo, and Marina for their contributions in
helping clarify the migration path to Resource Injection and the
Java Persistence API.