Posted by
arungupta on August 17, 2009 at 8:36 AM PDT
href="http://blogs.sun.com/arungupta/entry/totd_93_getting_started_with">TOTD
#93
showed how to get started with
href="http://jcp.org/en/jsr/detail?id=316">Java EE 6
using
href="http://www.netbeans.org/servlets/NewsItemView?newsItemID=1413">NetBeans
6.8 M1 and
GlassFish v3 by
building a simple Servlet 3.0 + JPA 2.0 web
application.
href="http://blogs.sun.com/arungupta/entry/totd_94_a_simple_java">TOTD
#94 built upon it by using Java Server Faces 2 instead of
Servlet 3.0 for displaying the results. However we are still using a
POJO
for all the database interactions. This works fine if we are only
reading values from the database but that's not how a typical web
application behaves. The web application would typically perform all
CRUD operations. More typically they like to perform one or more CRUD
operations within the context of a transaction. And how do you do
transactions in the context of a web application ? Java EE 6 comes to
your rescue.
The EJB 3.1
specification (another new specification in Java EE 6) allow
POJO classes to be annotated with @EJB and bundled within
WEB-INF/classes of a WAR file. And so you get all transactional
capabilities in your web application very easily.
This Tip
Of
style="font-weight: bold;">The
style="font-weight: bold;">Day (TOTD) shows how
to enhance the application created in TOTD #94 and use EJB 3.1 instead
of the JSF managed bean
for
performing the business logic. There are two ways to achieve this
pattern as described below.
Lets call this TOTD #95.1
- The easiest way to back a JSF page with an EJB is to
convert the managed bean into an EJB by adding @javax.ejb.Stateless
annotation. So change the "StateList" class from TOTD #94 as
shown below:
style="text-align: left; background-color: rgb(204, 204, 255); width: 100%;"
cellpadding="2" cellspacing="2">
@javax.ejb.Stateless
@ManagedBean
public class StateList {
@PersistenceUnit
EntityManagerFactory emf;
public List<States>
getStates() {
return
emf.createEntityManager().createNamedQuery("States.findAll").getResultList();
}
} |
The change is highlighted in bold, and that's it!
Because of "Deploy-on-save" feature in NetBeans and GlassFish v3, the
application is autodeployed. Otherwise right-click on the project and
select Run (default shortcut "F6"). As earlier, the results can be seen
at "http://localhost:8080/HelloEclipseLink/forwardToJSF.jsp" or
"http://localhost:8080/HelloEclipseLink/faces/template-client.xhtml"
and looks like:
alt=""
src="http://blogs.sun.com/arungupta/resource/images/nb68m1-jee6-ejb-1st-output.png">
The big difference this time is that the business logic is executed by
an EJB in a fully transactional manner. Even though the logic in this
case is a single read-only operation to the database, but you get the
idea :)
Alternatively, you can use the delegate pattern in the
style="font-style: italic;">managed bean as
described below. Lets call this #95.2.
- Right-click on the project, select "New", "Session Bean
..." and create a stateless session bean by selecting the options as
shown below:
style="border: 1px solid ; width: 371px; height: 378px;" alt=""
src="http://blogs.sun.com/arungupta/resource/images/nb68m1-jee6-ejb-create.png">
This creates a stateless session with the name "StateBeanBean" (
href="http://www.netbeans.org/issues/show_bug.cgi?id=170392">bug
#170392 for redundant "Bean" in the name).
- Simplify your managed bean by refactoring all the business
logic to the EJB as shown below:
style="text-align: left; background-color: rgb(204, 204, 255); width: 100%;"
cellpadding="2" cellspacing="2">
@Stateless
public class StateBeanBean {
@PersistenceUnit
EntityManagerFactory emf;
public List<States>
getStates() {
return
emf.createEntityManager().createNamedQuery("States.findAll").getResultList();
}
} |
and
style="text-align: left; background-color: rgb(204, 204, 255); width: 100%;"
cellpadding="2" cellspacing="2">
@ManagedBean
public class StateList {
@EJB StateBeanBean bean;
public List<States>
getStates() {
return bean.getStates();
}
}
|
In fact the EJB code can be further simplified to:
style="text-align: left; background-color: rgb(204, 204, 255); width: 100%;"
cellpadding="2" cellspacing="2">
@Stateless
public class StateBeanBean {
@PersistenceContext
style="font-weight: bold;">
EntityManager em;
public List<States>
getStates() {
return em.createNamedQuery("States.findAll").getResultList();
}
}
|
The changes are highlighted in bold.
If the application is already running then
style="font-style: italic;">Deploy-on-Save
would have automatically deployed the entire application. Otherwise
right-click on the project and select Run (default shortcut "F6").
Again, the
results can be seen at
"http://localhost:8080/HelloEclipseLink/forwardToJSF.jsp" or
"http://localhost:8080/HelloEclipseLink/faces/template-client.xhtml"
and are displayed as shown in the screenshot above.
The updated directory structure looks like:
alt=""
src="http://blogs.sun.com/arungupta/resource/images/nb68m1-jee6-ejb-dir-structure.png">
The important point to note is that our EJB is bundled in the WAR file
and no additional deployment descriptors were added or existing ones
modified to achieve that. Now, that's really clean :)
The next blog in this series will show how managed beans can be
replaced with WebBeans, err JCDI.
Also refer to other
href="http://blogs.sun.com/arungupta/tags/javaee6">Java EE 6
blog entries.
Please leave suggestions on other TOTD that
you'd like to see.
A complete archive of all the tips is available
href="http://blogs.sun.com/arungupta/tags/totd">here.
Technorati: totd
glassfish
v3
href="http://technorati.com/tags/mysql">mysql
href="http://technorati.com/tags/javaee6">javaee6
href="http://technorati.com/tags/javaserverfaces">javaserverfaces
jpa2
href="http://technorati.com/tags/ejb">ejb
href="http://technorati.com/tags/netbeans">netbeans