站内搜索: 请输入搜索关键词

当前页面: 开发资料首页Netbeans 专题EJB 3.0 Enterprise Beans for the JBoss Application Server

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.

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)
  • JBoss Application Server 4.0.4 (download)

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.

Tutorial Exercises


Setting Up the JBoss Application Server

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:

  1. Download the NetBeans IDE 5.5 Beta 2 + JBoss Application Server 4.0.4 Bundle Installer here.
  2. Use the NetBeans IDE 5.5 Beta 2 and JBoss Application Server Bundle Installation Instructions.
  3. 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.

  1. In the IDE, open the Runtime window (Ctrl-5).
  2. Right-click the Servers node and choose Add Server...
  3. In the Add Server Instance wizard, select JBoss Application Server 4 from the Server drop-down. Click Next.
  4. In the Server Location page, browse to the installation directory of the JBoss Application Server. Click Next.
  5. In the Instance Properties page, select a domain from the Domain drop-down. Click Finish.

Exploring the JBoss Application Server in the IDE

  1. In the Runtime window, expand the Servers node. Notice that there is a new node for the JBoss Application Server.
  2. Right-click the JBoss Application Server node. Notice the menu items that are available for working with the server from within the IDE.
  3. 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.
  4. 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:

    node's contextual menu

  5. 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.
  6. 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

  1. Choose File > New Project (Ctrl-Shift-N). Select Enterprise Application from the Enterprise category.
  2. Name the project NewsApp, set the server to JBoss Application Server 4.
  3. 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:

    new enterprise wizard

  4. Click Finish. The Projects window should now show you the following:

    new projects wizard

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.

  1. Right-click the EJB module and choose New > File/Folder.
  2. From the Persistence category, select Persistence Unit and click Next.
  3. Keep the default Persistence Unit Name.
  4. For the Persistence Provider, choose Hibernate (default).
  5. 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).
  6. 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:

    Hibernate and The New Persistence Unit wizard

  7. 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:

  1. Right-click the EJB module in the Projects window and choose New > File/Folder to open the New File wizard.
  2. From the Persistence category, select Entity Class and click Next.
  3. 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:

new projects wizard

In the Source Editor, do the following:

  1. Add the following field declarations to the class:
    String title;
    String body;
  2. 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.
  3. 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:

  1. Right-click the EJB module in the Projects window and choose New > File/Folder to open the New File wizard.
  2. From the Enterprise category, select Message-Driven Bean and click Next.
  3. Leave NewMessage unchanged for the class name.
  4. Select ejb from the Package drop-down list, if not selected by default.
  5. 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:

new projects wizard

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.

  1. Replace the generated @MessageDriven annotation with the following:

    @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.

  2. 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.

  3. 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);
    }
  4. 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);
    }
  5. Modify the onMessage method by adding the following highlighted code to the body:
    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();
        }
    }
  6. Press Alt-Shift-F to generate any necessary import statements. When generating the import statements, we want to import the jms libraries.
  7. 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:

  1. Right-click the EJB module and choose New > File/Folder.
  2. From the Persistence category, select Session Beans for Entity Classes and click Next.
  3. From the list of available entity classes, select NewsEntity and click Add and then click Next.
  4. Check that the Package is set to ejb and that a local interface will be created.
  5. 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.

  1. Right-click the web module project and choose New > Servlet.
  2. Type ListNews for the Class Name.
  3. 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:

  1. Right-click in the source code and select Enterprise Resources > Call Enterprise Bean.
  2. 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.

  3. 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>");
  4. 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.
  5. 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.

  1. Right-click the web module project and choose New > Servlet.
  2. Type PostMessage for the Class Name.
  3. 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:

  1. 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();
  2. 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>");
  3. 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.
  4. 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:

  1. In the Projects window, right-click the NewsApp enterprise application node and select Properties in the pop-up menu.
  2. Select Run in the Categories pane.
  3. In the Relative URL textfield, type /ListNews.
  4. Click OK.
  5. 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:

The ListNews Servlet page

Then you add a message with the PostMessage servlet:

The PostNews Servlet page

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 2ndListNews Servlet page

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:

The ListNews Servlet page

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

  1. Outside the IDE, go to the JBoss Appliation Server installation directory and open the \server\default\deploy\hsqldb-ds.xml file.
  2. 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>
    -->
  3. 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>
  4. 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>
    -->
  5. Save the file.

Using the Database Explorer

  1. In the IDE, go to the Runtime window and restart the JBoss Application Server.
  2. Expand the Databases node in the Runtime window, right-click the Drivers node, and choose New Driver.
  3. 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.
  4. Right-click the new HSQLDB driver node and select Connect Using.
  5. Set the Database URL to jdbc:hsqldb:hsql://localhost:1701 and the user name to sa. Leave the password blank. Click OK.
  6. Select PUBLIC from the drop-down. Click OK.
  7. 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:

    db1

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.


↑返回目录
前一篇: Developing for the SavaJe Mobile Platform
后一篇: EJB 3.0 Enterprise Beans