EJB 3.0 Enterprise Beans for the JBoss Application Server
This document takes you through the basics of developing an enterprise application
using EJB 3.0 technology, which is part of the Java EE 5 platform.
This document shows how the EJB 3.0 technology can simplify the process of developing
enterprise applications.
The application is developed in NetBeans IDE 5.5 Beta 2 and deployed to JBoss Application Server 4.0.4.
Please note that JBoss Application Server 4.0.4, even with its EJB 3.0
support, is not a fully compatible Java EE 5 application server.
Expected duration: 45 minutes
Prerequisites
This document does not assume anything about your knowledge or skills. It would be
helpful, but is absolutely not a requirement, to have some basic knowledge of
the following technologies:
Java Programming
NetBeans IDE
JBoss Application Server
Software Needed for the Tutorial
For this tutorial you need to have the following software installed on your computer:
NetBeans IDE 5.5 (download) or NetBeans IDE 5.5 daily build.
(To download a daily build, go to the development build download page, set 5.5 as the release version and Daily as the build type.
Java Standard Development Kit (JDK) version 5.0 (download)
The goal of this exercise is to correctly set up the server and inspect
some of its important files. You will also be introduced to the JBoss Application
Server node in the Runtime window.
Installing the JBoss Application Server
The NetBeans IDE 5.5 Beta 2 and JBoss Application Server Bundle
includes a version of the JBoss Application Server
that is tailored to your needs as an EJB 3 developer.
To get started, do the following:
Download the NetBeans IDE 5.5 Beta 2 + JBoss Application Server 4.0.4 Bundle Installer
here.
After you have completed the installation instructions, let's first have a look in the JBoss installation directory. There are two
files that are going to be very useful to us. So, go to the JBoss installation directory,
and then look at the following files:
server\default\deploy\jbossweb-tomcat55.sar\server.xml. In this file,
notice that the HTTP/1.1 Connector is set to 8080. This is the server's port
number. The IDE does not provide a facility
for you to change the default port number. If you want to change the default port number,
you must do so manually in this file. If you have already registered the server with the IDE
when you change the default port number, you must remove the server in the IDE and then
register it afresh.
server\default\deploy\hsqldb-ds.xml. This file defines the data source
that we will be using in our application. Notice that the JNDI name is "DefaultDS"
and that the specified prefix is "java:/". We will need to refer to this data
source later, when we create our persistence unit. We will also need to work with this
file later, at the end of the tutorial, to switch the HSQL database from embedded (in-process)
mode to server mode. Once we have done that, we will be able to inspect the database
from inside the IDE's Database Explorer.
Registering the JBoss Application Server with the IDE
If you installed the JBoss Application Server from the NetBeans IDE 5.5 Beta 2 and JBoss Application Server Bundle,
the JBoss Application Server is automatically registered in the IDE.
If you did not install the NetBeans IDE 5.5 Beta 2 and JBoss Application Server Bundle, but obtained the JBoss
Application Server separately, you need to register the server in the IDE.
In the IDE, open the Runtime window (Ctrl-5).
Right-click the Servers node and choose Add Server...
In the Add Server Instance wizard, select JBoss Application Server 4 from the Server drop-down. Click Next.
In the Server Location page, browse to the installation directory of the JBoss Application Server. Click Next.
In the Instance Properties page, select a domain from the Domain drop-down. Click Finish.
Exploring the JBoss Application Server in the IDE
In the Runtime window, expand the Servers node. Notice that there is a new node for
the JBoss Application Server.
Right-click the JBoss Application Server node. Notice the menu items that are
available for working with the server from within the IDE.
When you deploy an application to
the server, the server starts automatically. However, you can choose Start to
start the
server manually. Do so now.
Notice the server output in the Output window at the bottom of the IDE. After starting
the server, you can restart or stop it, as well as access a variety of other features, as shown
below:
You can now inspect the nodes that appear after the server starts. After the server starts,
a node appears for each application deployed to the server. For example, you
can right-click a node and choose Undeploy to undeploy it without needing to go into your
filesystem.
Now stop the server so that, when you run the application at the end of
the tutorial, you can see how it is started automatically at deployment.
Summary
In this exercise we made sure to install the correct JBoss Application Server installation type.
Then we registered it with the IDE and explored the nodes that the IDE creates
to help you work with the JBoss Application Server.
Setting Up the Enterprise Application Project
The goal of this exercise is to create the NewsApp enterprise application project
containing an EJB module and a web module.
The NewsApp application uses a message-driven bean to receive and process messages
sent to the queue by a servlet.
The application uses servlets to send messages to the message-driven bean and to display messages.
Creating an Enterprise Application
Choose File > New Project (Ctrl-Shift-N).
Select Enterprise Application from the Enterprise category.
Name the project NewsApp, set the server to JBoss Application Server 4.
Make sure the J2EE Version is set to Java EE 5, and select Create EJB Module and Create Web Application Module, if unselected.
The wizard should now look as follows:
Click Finish. The Projects window should now show you the following:
Summary
In this exercise we created a Java EE 5 enterprise application containing an EJB module and a web module.
Coding the EJB Module
In this exercise we will create the objects in the EJB module.
We will create an entity class, a message-driven bean and a session bean facade.
We also will create a persistence unit to provide the container with information for managing our entities, and
the Java Message Service (JMS) resources that our message-driven bean will use.
Creating a Persistence Unit
First we create a persistence unit that defines the data source and entity manager used in our application. Here, we
use the New Persistence Unit wizard to create a persistence unit, but we could also create it when we use the New Entity Class
wizard in the next section.
Right-click the EJB module and choose New > File/Folder.
From the Persistence category, select Persistence Unit and click Next.
Keep the default Persistence Unit Name.
For the Persistence Provider, choose Hibernate (default).
For the Data Source, choose the default data source DefaultDS, but
prepend java:/ (as stated in the hsqldb-ds.xml file that we examined at the
start of this tutorial).
Check that the persistence unit is using the Java Transaction API
and that the Table Generation Strategy is set to Create
so that the tables based on our entity classes are created when the application is deployed, as shown below:
Click Finish.
When you click Finish, the IDE creates persistence.xml and opens it in
the Source Editor in Design view.
Creating the NewsEntity Entity Class
In this exercise we will create the NewsEntity entity class.
An entity class is a simple Java class.
When you create the entity class, the IDE adds the @Entity annotation to define the class as an entity class.
After we create the class, we will create fields in the class to represent the data that we want in our table.
Each entity class must have a primary key.
When you create the entity class, the IDE adds the @Id annotation to declare which field to use as the primary key.
The IDE also adds the @Generated annotation to specify the key generation strategy for the primary Id.
To create the NewsEntity class, do the following:
Right-click the EJB module in the Projects window and choose New > File/Folder to open the New File wizard.
From the Persistence category, select Entity Class and click Next.
Type NewsEntity for the class name, type ejb for the
package, and leave the Primary Key Type as Long. Click Finish.
When you click Finish, the entity class NewsEntity.java opens in the Source Editor.
In the Projects window, you should now see the following:
In the Source Editor, do the following:
Add the following field declarations to the class:
String title;
String body;
Right-click within the body of the class in the Source Editor and choose Refactor > Encapsulate Fields to generate getters and setters for each of the fields.
In the Encapsulate Fields dialog box, make sure that getter and setter checkboxes are selected for the fields id, title and body.
Click Next in the Encapsulate Fields dialog box and then click Do Refactoring in the Refactoring tab of the Output window.
The IDE adds the getter and setter methods for the fields and changes the visibility of the fields to private. The
IDE also automatically saves your changes to the file.
In the next step we will create the NewMessage message-driven bean.
Creating the NewMessage Message-Driven Bean
Now we will create the NewMessage message-driven bean in our EJB module.
We will use the New Message-Driven Bean wizard to create the bean.
To create the NewMessage message-driven bean, do the following:
Right-click the EJB module in the Projects window and choose New > File/Folder to open the New File wizard.
From the Enterprise category, select Message-Driven Bean and click Next.
Leave NewMessage unchanged for the class name.
Select ejb from the Package drop-down list, if not selected by default.
Leave Queue selected as the Destination Type and click Finish.
When you click Finish, the new message-driven bean class NewMessage.java opens in the Source Editor.
In the Projects window, you should see the new node that has been added:
In the Source Editor, you can see that the class has a long annotation, which starts as follows:
@MessageDriven(mappedName = "jms/NewMessage")
This annotation tells the container that the component is a message-driven bean and the name of the JMS resource used by the bean.
When the IDE generates the class, the Mapped Name of the resource (jms/NewMessage) is derived from the name of the class (NewMessage.java).
The JMS resource is mapped to the JNDI name of the destination from which the bean receives messages.
The JBoss Application Server comes with a set of data sources, which are very easy
to use from within your own application. As discussed at the start of this tutorial,
we will use the hsqldb-ds.xml file, which contains our JMS resources.
The EJB 3.0 API enables us to look up objects in the JNDI namespace from within the bean class
so that we do not need to configure deployment descriptors to specify the JMS resources.
With the Java EE 5 specification, we can use annotations to introduce resources directly into a class.
We will now use annotations to introduce the MessageDrivenContext resource into our class, and then inject
the PersistenceContext resource which will be used by the EntityManager API to manage the persistent entity instances.
We will add the annotations to the class in the Source Editor.
Replace the generated @MessageDriven annotation with the following:
In the above, the only change is the addition of the final property, "destination",
and its value "queue/mdb". This sets "queue/mdb" as the JNDI name for looking up the queue.
Inject the MessageDrivenContext resource into the class by adding the following
annotated field (in bold) to the class:
public class NewMessage implements MessageListener {
@Resource
private MessageDrivenContext mdc;
When prompted to generate any necessary import statements,
note that we want javax.annotation.Resource and javax.ejb.MessageDrivenContext.
Introduce the entity manager into the class by right-clicking in the code and
selecting Persistence > Use Entity Manager from the pop-up menu. This
adds the following annotation to your source code:
@PersistenceContext
private EntityManager em;
And it generates the following method in your code:
public void persist(Object object) {
// TODO:
// em.persist(object);
}
Change the name of the persist method
to save and then remove the comments to enable the generated code:
public void save(Object object) {
// TODO:
em.persist(object);
}
Modify the onMessage method by adding the following
highlighted code to the body:
Press Alt-Shift-F to generate any necessary import statements.
When generating the import statements, we want to import the jms libraries.
Save the file.
Creating the Session Bean
Next we create a session bean facade for the NewsEntity entity class.
To create the session bean facade, do the following:
Right-click the EJB module and choose New > File/Folder.
From the Persistence category, select Session Beans for Entity Classes and click Next.
From the list of available entity classes, select NewsEntity and click Add and then click Next.
Check that the Package is set to ejb and that a local interface will be created.
Click Finish.
When you click Finish, the session bean facade class NewsEntityFacade.java is created
and opens in the Source Editor. The IDE also creates the local interface NewsEntityFacadeLocal.java.
EJB 3.0 technology simplifies the creation of session beans by reducing the amount of required code.
You can see that the annotation @Stateless is used to
declare the class as a stateless session bean component and that the class no longer needs a statement implementing
javax.ejb.SessionBean.
The code is also much cleaner because with EJB 3.0 technology the business methods no longer need to have code declaring they throw checked exceptions.
You can see that the PersistenceContext resource was injected directly into the session bean component
when we created the session bean facade.
Summary
In this exercise, we coded an entity class and a message-driven bean in the EJB module.
We then created a session bean facade for the entity class.
We also created the JMS resources that will be used by our application.
Coding the Web Module
We will now create the servlets ListNews and PostMessage in our web module.
These servlets will be used to read and add messages.
Creating the ListNews Servlet
In this exercise we will create a simple servlet for displaying our data.
We will use JNDI to call the session bean facade bean from our servlet.
Right-click the web module project and choose New > Servlet.
Type ListNews for the Class Name.
Enter web for the Package name and click Finish.
When you click Finish, the class ListNews.java opens in the Source Editor.
In the Source Editor, do the following:
Right-click in the source code and select Enterprise Resources > Call Enterprise Bean.
In the Call Enterprise Bean dialog box, select NewsEntityFacade and click OK.
When you click OK, the following method is added to the bottom of the file:
private ejb.NewsEntityFacadeLocal lookupNewsEntityFacade() {
try {
javax.naming.Context c = new javax.naming.InitialContext();
return (ejb.NewsEntityFacadeLocal) c.lookup("java:comp/env/ejb/NewsEntityFacade");
}
catch(javax.naming.NamingException ne) {
java.util.logging.Logger.getLogger(getClass().
getName()).log(java.util.logging.Level.SEVERE,"exception caught" ,ne);
throw new RuntimeException(ne);
}
}
This lookup method is generated because JBoss Application Server 4.0.4 is not
fully Java EE 5 compatible. Once JBoss is fully Java EE 5 compatible, an @EJB annotation
will be generated instead. In the meantime, change the lookup
from java:comp/env/ejb/NewsEntityFacade to NewsApp/NewsEntityFacade/local.
Uncomment the code in the processRequest method and modify it
by adding the following lines in bold to the body of the method:
out.println("<h1>Servlet ListNews at " + request.getContextPath () + "</h1>");
NewsEntityFacadeLocal newsEntityFacade = (NewsEntityFacadeLocal) lookupNewsEntityFacade();
List news = newsEntityFacade.findAll();
for (Iterator it = news.iterator(); it.hasNext();) {
NewsEntity elem = (NewsEntity) it.next();
out.println(" <b>"+elem.getTitle()+" </b><br />");
out.println(elem.getBody()+"<br /> ");
}
out.println("<a href='PostMessage'>Add new message</a>");
out.println("</body>");
Press Alt-Shift-F to generate any necessary import statements for the class.
When generating the import statements, we want to import classes from the util package.
Save the changes to the file.
Creating the PostMessage Servlet
In this exercise we will create the PostMessage servlet that will be used to post messages.
We will use JNDI lookups to access the JMS resources we created.
We will then add the code to send the JMS message and the code for the
HTML form for adding a message.
Right-click the web module project and choose New > Servlet.
Type PostMessage for the Class Name.
Enter web for the Package name and click Finish.
When you click Finish, the class PostMessage.java opens in the Source Editor.
In the Source Editor, do the following:
We send the JMS messages by adding the following code in bold to the processRequest method:
response.setContentType("text/html;charset=UTF-8");
String title=request.getParameter("title");
String body=request.getParameter("body");
if ((title!=null) && (body!=null)) {
Queue queue = null;
QueueConnection connection = null;
QueueSession session = null;
MessageProducer messageProducer = null;
try {
InitialContext ctx = new InitialContext();
queue = (Queue) ctx.lookup("queue/mdb");
QueueConnectionFactory factory =
(QueueConnectionFactory) ctx.lookup("ConnectionFactory");
connection = factory.createQueueConnection();
session = connection.createQueueSession(false,
QueueSession.AUTO_ACKNOWLEDGE);
messageProducer = session.createProducer(queue);
ObjectMessage message = session.createObjectMessage();
// here we create a NewsEntity, that will be sent in JMS message
NewsEntity e = new NewsEntity();
e.setTitle(title);
e.setBody(body);
message.setObject(e);
messageProducer.send(message);
messageProducer.close();
connection.close();
response.sendRedirect("ListNews");
} catch (JMSException ex) {
ex.printStackTrace();
} catch (NamingException ex) {
ex.printStackTrace();
}
}
PrintWriter out = response.getWriter();
Next, we uncomment the code to print the HTML and add the web form for adding a message.
Add the following lines in bold to the processRequest method
out.println("Servlet PostMessage at " + request.getContextPath() + "</h1>");
// Add the following code to add the form to the web page:
out.println("<form>");
out.println("Title: <input type='text' name='title'><br/>");
out.println("Message: <textarea name='body'></textarea><br/>");
out.println("<input type='submit'><br/>");
out.println("</form>");
out.println("</body>");
Press Alt-Shift-F to generate any necessary import statements for the class.
When selecting the import statements for Connection, ConnectionFactory, Session and
Queue, import the javax.jms libraries.
Save your changes to the file.
Finishing Up
JBoss automatically adds session beans to the JNDI namespace,
therefore remove the ejb-local-ref section from the web.xml file. This file is
found in the web module's WEB-INF folder, which is within the Web Pages node. Note that removing
the ejb-local-ref section is allowed by the JBoss Application Server, but results
in the application not being Java EE 5 compatible.
In addition, since we are using the default data source (in hsqldb-ds.xml)
that comes with the JBoss application server, we do not need the jboss-ds.xml file
that was generated in our EJB module.
You can remove the jboss-ds.xml from the EJB module's Server Resources node.
Right-click it
and choose Delete.
Summary
In this exercise, we coded two servlets that communicate with our EJB module
to post and list messages.
Running the Project
We can now run our project.
When we run the project, we want our browser to open to the page with the ListNews servlet.
We do this by specifying the URL in the Project Properties dialog box for our Enterprise Application.
The URL is relative to the context path for our application.
After we enter the relative URL, we can build, deploy and run our application from the Projects window.
To set the relative URL and run our application, do the following:
In the Projects window, right-click the NewsApp enterprise application node and select Properties in the pop-up menu.
Select Run in the Categories pane.
In the Relative URL textfield, type /ListNews.
Click OK.
In the Projects window, right click the NewsApp enterprise application node and choose Run Project.
When you run the project, the ListNews servlet opens in your browser and displays a list of the messages in the database.
When you first run the project, the database is empty, but you can click Add New Message to add a message:
Then you add a message with the PostMessage servlet:
Next, the message is sent to the
message-driven bean for writing to persistent storage, and the ListNews servlet is called to display the messages in the database:
The list of messages in the database retrieved by ListNews often does not yet contain the new message because
our message service is asynchronous. Also, you should use the "Refresh" button, if you see no messages displayed.
Each new message is printed below previously entered messages:
Note that because of issue 82173, you must change
the value in the persistence.xml from "create" to "update" on subsequent deployments of the application,
to avoid having the database overwritten.
Inspecting the Database
By default, the HSQL database runs in embedded (in-process) mode.
In order to use the IDE's Database Explorer to inspect the database,
we need to switch the database to server mode, as described below.
Switching to Server Mode
Outside the IDE, go to the JBoss Appliation Server installation
directory and open the \server\default\deploy\hsqldb-ds.xml file.
Uncomment the connection-url to be used
for server mode and comment out the section used for in-process persistent db mode:
<!-- For server mode db, allowing other processes to use hsqldb over tcp.-->
This requires the org.jboss.jdbc.HypersonicDatabase mbean.
<connection-url>jdbc:hsqldb:hsql://${jboss.bind.address}:1701</connection-url>
<!-- For in-process persistent db, saved when jboss stops.
The org.jboss.jdbc.HypersonicDatabase mbean is required for proper db shutdown
<connection-url>jdbc:hsqldb:${jboss.server.data.dir}${/}hypersonic${/}localDB</connection-url>
-->
Comment the depends element used for in-process mode and uncomment the depends
element used for server mode:
<!-- When using in-process (standalone) mode
<depends>jboss:service=Hypersonic,database=localDB</depends> -->
<!-- Uncomment when using hsqldb in server mode -->
<depends>jboss:service=Hypersonic</depends>
Comment the mbean element used for in-process mode and uncomment the mbean
element used for server mode:
<!-- Uncomment if you want hsqldb accessed over tcp (server mode)-->
<mbean code="org.jboss.jdbc.HypersonicDatabase"
name="jboss:service=Hypersonic">
<attribute name="Port">1701</attribute>
<attribute name="BindAddress">${jboss.bind.address}</attribute>
<attribute name="Silent">true</attribute>
<attribute name="Database">default</attribute>
<attribute name="Trace">false</attribute>
<attribute name="No_system_exit">true</attribute>
</mbean>
<!-- For hsqldb accessed from jboss only, in-process (standalone) mode
<mbean code="org.jboss.jdbc.HypersonicDatabase"
name="jboss:service=Hypersonic,database=localDB">
<attribute name="Database">localDB</attribute>
<attribute name="InProcessMode">true</attribute>
</mbean>
-->
Save the file.
Using the Database Explorer
In the IDE, go to the Runtime window and restart the JBoss Application Server.
Expand the Databases node in the Runtime window, right-click the Drivers node,
and choose New Driver.
In the New JDBC Driver dialog box, click Add and browse to the JBoss Application Server's
/server/default/lib directory and select hsqldb.jar. The IDE automatically
locates the driver class, org.hsqldb.jdbcDriver, and suggests a name, HSQLDB. Click OK.
Right-click the new HSQLDB driver node and select Connect Using.
Set the Database URL to jdbc:hsqldb:hsql://localhost:1701 and the user name to sa.
Leave the password blank. Click OK.
Select PUBLIC from the drop-down. Click OK.
A new node appears below the HSQLDB driver node. Expand it. Expand the Tables node.
Right-click the NEWSENTITY node and choose View Data. You should now see the following:
Summary
In this exercise we changed the database to server mode and inspected its content using
the IDE's Database Explorer.
Next Steps
To send comments and suggestions, get support, and keep informed on the latest
developments on the NetBeans IDE J2EE development features, join the
mailing list.