当前页面: 开发资料首页 → Netbeans 专题 → 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.
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:
For this tutorial you need to have the following software installed on your computer:
For the tutorial you need to register a local instance of the JBoss Application Server 4.0.4 with the IDE, as described in the first section below.
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.
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:
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 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.
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.
In this exercise we created a Java EE 5 enterprise application containing an EJB module and a web 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.
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.
When you click Finish, the IDE creates persistence.xml and opens it in the Source Editor in Design view.
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:
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:
String title; String body;
In the next step we will create 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:
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.
@MessageDriven( mappedName = "jms/NewMessage", activationConfig = { @ActivationConfigProperty( propertyName = "acknowledgeMode", propertyValue = "Auto-acknowledge"), @ActivationConfigProperty( propertyName = "destinationType", propertyValue = "javax.jms.Queue"), @ActivationConfigProperty( propertyName = "destination", propertyValue = "queue/mdb") } )
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.
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.
@PersistenceContext private EntityManager em;And it generates the following method in your code:
public void persist(Object object) { // TODO: // em.persist(object); }
public void save(Object object) { // TODO: em.persist(object); }
public void onMessage(Message message) { ObjectMessage msg = null; try { if (message instanceof ObjectMessage) { msg = (ObjectMessage) message; NewsEntity e = (NewsEntity) msg.getObject(); save(e); } } catch (JMSException e) { e.printStackTrace(); mdc.setRollbackOnly(); } catch (Throwable te) { te.printStackTrace(); } }
Next we create a session bean facade for the NewsEntity entity class. To create the session bean facade, do the following:
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.
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.
We will now create the servlets ListNews and PostMessage in our web module. These servlets will be used to read and add messages.
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.
When you click Finish, the class ListNews.java opens in the Source Editor. In the Source Editor, do the following:
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.
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>");
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.
When you click Finish, the class PostMessage.java opens in the Source Editor. In the Source Editor, do the following:
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();
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>");
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.
In this exercise, we coded two servlets that communicate with our EJB module to post and list messages.
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:
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:
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.
<!-- 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> -->
<!-- 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>
<!-- 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> -->
In this exercise we changed the database to server mode and inspected its content using the IDE's Database Explorer.
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.