FeaturesPluginsDocs & SupportCommunityPartners

Java EE 应用程序入门

本文将详细介绍使用 EJB 3.0 技术开发企业应用程序的基础知识,而 EJB 3.0 是 Java EE 5 平台的组成部分。本文还将阐述如何通过 EJB 3.0 技术简化开发企业应用程序的流程。本文使用的是 NetBeans IDE 6.1 发行版

本文档所概括的步骤也适用于IDE的6.0版本,但是NetBeans IDE 6.1中的一些可用的选项在更早的发行版中是不可用的。

预计时间:30 分钟

教程练习

本页面的内容适用于NetBeans IDE 6.0 以及 6.1

先决条件

本文假定您在以下方面拥有基本知识和编程经验:

  • Java 编程
  • NetBeans IDE

教程所需软件

对于本教程,您需要在计算机上安装以下软件:

软件或者资源 需求版本
NetBeans IDE Web & Java EE, 版本 6.1 或者
版本 6.0
Java 开发工具包 (JDK) 版本 6 或者
版本 5
GlassFish 应用程序服务器 V2

建立企业应用程序项目

此次练习的目标是创建 NewsApp 企业应用程序项目,其中包含一个 EJB 模块和一个 web 模块。NewsApp 应用程序使用一个消息驱动的 bean 接收和处理 servlet 发送到队列的消息。该应用程序使用 servlets 发送消息给消息驱动的 bean ,以便显示消息。

创建企业应用程序

  1. 从主菜单中选择 File> New Project (Ctrl-Shift-N)。
  2. 从 Enterprise 类别中选择 Enterprise Application ,然后单击 Next 按钮。
  3. 将项目命名为 NewsApp,并将服务器设定为 Sun Java System Application Server。
  4. 将 Java EE 版本设为 Java EE 5,然后选择 Create EJB Module 和 Create Web Application Module (如果未选中)。
  5. 单击 Finish 按钮。

小结

在本练习中,我们创建了一个 Java EE 5 企业应用程序,其中包含一个 EJB 模块和一个 web 模块。

编写 EJB 模块

在本练习中,我们将在 EJB 模块中创建对象。我们将创建一个实体类,一个消息驱动 bean 和一个会话外观(Session Facade)。我们还将创建一个持久性单元,以便为容器提供管理实体,和消息驱动 bean 将使用的 Java 消息服务(Java Message Service ,JMS)资源所需的信息。

创建持久性单元

首先,我们需要创建一个持久性单元,用于定义应用程序中所使用的数据源和实体管理器。

  1. 右击 EJB 模块,然后选择 New > File/Folder 。
  2. 从 Persistence 类别中,选择 Persistence Unit ,然后单击 Next 按钮。
  3. 保持默认的 Persistence Unit 名称。
  4. 对于 Persistence Provider ,选择 TopLink(默认)
  5. 对于Data Source,选择默认数据源 jdbc/sample
  6. 检查持久性单元使用了 Java Transaction API,而且 Table Generation Strategy 被设定为 Create ,这样部署应用程序时就能基于我们的实体类创建表。
  7. 单击 Finish 按钮。
新建持久性单元向导

单击 Finish 时,IDE 将会创建 persistence.xml,并在源代码编辑器中以设计视图打开它。关闭 persistence.xml

创建 NewsEntity 实体类

在本练习中,我们将创建 NewsEntity 实体类。实体类就是一个简单的 Java 类。创建实体类时,IDE 会添加 @Entity 注释用于将类定义为实体类。创建类之后,我们将在类中创建字段,以表示要在表中保存的数据。

每个实体类都必须有一个主键。创建实体类时,IDE 会添加 @Id 注释用于声明使用哪个字段作为主键。IDE 还会添加 @GeneratedValue 注释,用于指定主 Id 的主要生成策略。

创建 NewsEntity 类的步骤如下:

  1. 在 Project 窗口在单击鼠标右键 EJB 模块,然后选择 New > File/Folder ,以便打开 New File 向导。
  2. 从 Persistence 类别中,选择 Entity Class ,然后单击 Next 按钮。
  3. 键入 NewsEntity 作为类名,键入 ejb 作为包名,让 Primary Key Type 保持为 Long。单击 Finish 按钮。

单击 Finish 时,实体类 NewsEntity.java 就会在源代码编辑器中打开。在源代码编辑器中,完成以下步骤:

  1. 给类添加以下字段声明:
    private String title;
    private String body;
  2. 在源代码编辑器中单击鼠标右键,然后选择 Insert Code ,同时选择 Getter and Setter 为每个字段生成 getter 和 setter 程序。
  3. 在 Generate Getters and Setters 对话框中,选择 bodytitle 字段,然后单击 Generate 按钮。
  4. 保存修改。
Generate Getters and Setters对话框

在下一步中,我们将创建 NewMessage 消息驱动 bean。

创建 NewMessage 消息驱动 Bean

现在,我们将在我们的 EJB 模块中创建 NewMessage 消息驱动。我们将使用 New Message-Driven Bean 向导来创建 bean 和必要的 JMS 资源。

创建 NewMessage 消息驱动 bean 的步骤如下:

  1. 在 Projects 窗口在单击鼠标右键 EJB 模块,然后选择 New > File/Folder ,可以打开 New File 向导。
  2. 从 Enterprise 类别中,选择 Message-Driven Beans ,然后单击 Next 按钮。
  3. 键入 NewMessage 作为类名。
  4. 从 Package 下拉列表中选择 ejb
  5. 单击 Add 打开 Add Message Destination 对话框。
  6. 在 Add Message Destination 对话框中,键入 jms/NewMessage,然后 选择 Queue 作为目标类型。单击 OK 。
  7. 确保项目目的地正确,然后单击 Finish 按钮。
New Message-Driven Bean向导

单击 Finish 时,新的消息驱动 bean 类 NewMessage.java 就会在源代码编辑器中打开。您可以看到 @MessageDriven 注释和配置属性已经添加到类中。

@MessageDriven(mappedName = "jms/NewMessage", activationConfig =  {
        @ActivationConfigProperty(propertyName = "acknowledgeMode", propertyValue = "Auto-acknowledge"),
        @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue")
    })

这段注释告诉容器,组件是消息驱动 bean 和 bean 使用的 JMS 资源。当 IDE 生成类时,资源的 Mapped Name (jms/NewMessage) 来自类名 (NewMessage.java)。JMS 资源被映射为 bean 接收消息所在目的地的 JNDI 名称。 New Message-Driven Bean 向导已经把 JMS 资源的信息添加到了 sun-resources.xml中。EJB 3.0 API 支持在 bean 类的 JNDI 命名空间中查找对象,这样我们就不需要配置部署描述符就可以指定 JMS 资源。

EJB 3.0 规范允许我们使用注释直接在一个类中引入资源。现在,我们将使用注释将 MessageDrivenContext 资源引入到我们的类中,然后注入 将被 EntityManager API 使用的 PersistenceContext 资源,以便管理持久性实体实例。我们将在 源代码编辑器中给类添加注释。

  1. MessageDrivenContext 资源注入到类中,方法是添加以下带注释的字段(以黑体表示)到类中:
    public class NewMessage implements MessageListener {
    @Resource
    private MessageDrivenContext mdc;
  2. 在类中引入实体管理器,方法是在代码在单击鼠标右键,然后从弹出式菜单中选择 Persistence > Use Entity Manager 。这将在源代码中添加如下注释:
    @PersistenceContext
    private EntityManager em;
    并在代码中生成如下方法:
    public void persist(Object object) {
        em.persist(object);
    }
  3. 修改 persist 方法,将名称 save。方法应该像如下所示:
    public void save(Object object) {
        em.persist(object);
    }
  4. 修改 onMessage 方法,方法是在方法体中加入如下内容:
        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();
        }
  5. 按下 Alt-Shift-F 组合键,生成所有必需的导入语句。注意: 生成导入语句时,我们需要确保导入 jmsjavax.annotation.Resource
  6. 保存文件。

创建会话 Bean

接下来,我们将为 NewsEntity 实体类创建会话外观。创建会话外观的步骤如下:

  1. 右击 EJB 模块,然后选择 New > File/Folder 。
  2. 从 Persistence 类别中,选择 Session Beans for Entity Classes ,然后单击 Next 按钮。
  3. 从可用实体类的列表中,选择 ejb.NewsEntity 并单击 Add ,然后单击 Next 按钮。
  4. 确定将 Package 设置为 ejb 并且已创建本地接口。
  5. 单击 Finish 按钮。

单击 Finish 按钮后,IDE 将会创建会话外观类 NewsEntityFacade.java,而且该类会在源代码编辑器中打开。IDE 还会创建本地接口 NewsEntityFacadeLocal.java

EJB 3.0 技术简化了会话 bean 的创建过程,因为它减少了所需代码的数量。您可以看到,注释 @Stateless 用于把类声明为无状态的会话 bean,而类不再需要一条语句来实现 javax.ejb.SessionBean。代码也要清晰很多,因为借助 EJB 3.0 技术,业务方法不再需要代码来声明它们抛出了未经检查的异常。

您可以看到,创建会话外观时,PersistenceContext 资源被直接注入了会话 bean 组件中。

小结

在本练习中,我们为 EJB 模块中的一个实体类和一个消息驱动编写了代码。我们还创建了我们的应用程序将会使用的 JMS 资源。

编写 Web 模块

现在,我们将在 web 模块中创建 servlets ListNewsPostMessage。这些 servlets 将用于读取和添加消息。

创建 ListNews Servlet

在本练习中,我们将创建一个用于显示数据的简单 servlet。我们将使用注释从我们的 servlet 中调用实体。

  1. 右击 web 模块项目,然后选择 New > Servlet 。
  2. 键入 ListNews 作为类名。
  3. 输入 web 作为包名,然后单击 Finish 按钮。

单击 Finish 按钮后,类 ListNews.java 就会在源代码编辑器中打开。在源代码编辑器中,执行以下步骤:

  1. 在源代码在单击鼠标右键,然后选择 Enterprise Resources > Call Enterprise Bean 。
  2. 在 Call Enterprise Bean 对话框中,选择 NewsEntityFacade 然后单击 OK 按钮。单击 OK 按钮后,实体 bean 源代码就会通过使用 @EJB 注释注入到 servlet 中。
  3. processRequest 方法中,去掉代码的注释,并在方法体中添加以下用黑体表示的行:
    out.println("<h1>Servlet ListNews at " + request.getContextPath () + "</h1>");
    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. 按下 Alt-Shift-F 组合键,便可为类生成所有必需的导入语句。生成导入语句时,我们需要 导入 java.util
  5. 保存对文件所做的修改。

创建 PostMessage Servlet

在本练习中,我们将创建用于发布消息的 PostMessage servlet。我们将使用注释把我们创建的 JMS 资源直接注入到 servlet中,用于指定变量名和它映射到的名称。接着,我们将添加用于发送 JMS 消息的代码,以及用于添加消息的 HTML 窗体的代码。

  1. 右击 web 模块项目,然后选择 New > Servlet 。
  2. 键入 PostMessage 作为类名。
  3. 输入 web 作为包名,然后单击 Finish 按钮。

单击 Finish 按钮后,类 PostMessage.java 就会在源代码编辑器中打开。在源代码编辑器中,完成以下步骤:

  1. 使用注释把 ConnectionFactoryQueue 资源注入,方法是添加如下字段声明(以黑体表示):
    public class PostMessage extends HttpServlet {
        @Resource(mappedName="jms/NewMessageFactory")
        private  ConnectionFactory connectionFactory;
        @Resource(mappedName="jms/NewMessage")
        private  Queue queue;
  2. 现在,我们添加用于发送 JMS 消息的代码,方法是在 processRequest 方法中添加以下用黑体表示的代码:
    response.setContentType("text/html;charset=UTF-8");
    // Add the following code to send the JMS message
    String title=request.getParameter("title");
    String body=request.getParameter("body");
    if ((title!=null) && (body!=null)) {
        try {
            Connection connection = connectionFactory.createConnection();
            Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
            MessageProducer messageProducer = session.createProducer(queue);
            ObjectMessage message = session.createObjectMessage();
            // here we create 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();
        }
    }
    PrintWriter out = response.getWriter();
                        
  3. 现在,对于用于打印 HTML 和添加消息 web 窗体的代码,我们去掉其注释。在 processRequest 方法中添加如下以黑体表示的代码行:
    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>");
                    
  4. 按下 Alt-Shift-F 可以为类生成所有必需的导入语句。注意:ConnectionConnectionFactorySessionQueue 选择要导入的库时,确保已经导入了 java.jms
  5. 保存对文件所做的修改。

运行项目

现在,我们可以运行刚才创建的项目。运行项目时,我们想让浏览器打开带有 ListNews servlet 的页面。为此,我们需要在 Enterprise Application 的 Properties 对话框中指定 URL。此 URL 相对于我们应用程序的上下文路径。输入相对 URL 之后,我们就可以从 Projects 窗口中编译、部署和运行我们的应用程序了。

设定相对 URL 和运行我们的应用程序的步骤如下:

  1. 在 Projects 窗口中,右击 NewsApp enterprise application 节点,然后在弹出菜单中选择 Properties 。
  2. 在 Categories 窗格中选择 Run 。
  3. 在 Relative URL 文本框中,键入 /ListNews。
  4. 单击 OK 按钮。
  5. 在 Projects 窗口中,右击 NewsApp enterprise application 节点,然后选择 Run Project 。

运行项目时,ListNews servlet 就会在浏览器中打开,并显示数据库中消息的一个列表。首次运行项目时,数据库是空的,但您可以单击 Add Message 添加一条消息。

ListNews Servlet 页面

使用 PostMessage servlet 添加一条消息时,该消息将被发送给消息驱动 bean,以便写入持久性存储器,而 ListNews servlet 将被调用以显示数据库中的消息。ListNews 从数据库中获得的消息列表通常还没有包含新消息,因为我们的消息服务是异步的。

故障排除

创建项目时可能会遇到以下一些问题。

JMS 资源的问题

使用向导创建 JMS 资源时,您可能会在输出窗口中看到如下服务器错误消息:

[com.sun.enterprise.connectors.ConnectorRuntimeException:
                    JMS resource not created : jms/Queue]
                

这条消息大概是指出,JMS 资源没有创建或没有注册到应用服务器。您可以使用 Sun Java System Application Server 的管理控制台来检查、创建和编辑 JMS 资源。

打开管理控制台的步骤如下:

  1. 在 IDE 的运行时中展开 Servers 节点,确定 Sun Java System Application Server 正在运行。位于 Sun Java System Application Server 节点旁边的一个小小的绿色箭头指示服务器正在运行中。
  2. 右击 Sun Java System Application Server 节点,然后选择 View Admin Console ,可以在浏览器中打开登陆窗口。
  3. 登陆到 Sun Java System Application Server 中。默认的用户名和密码是 adminadminadmin
  4. 在浏览器的管理控制台中,展开画面左侧的 Resources 节点 和 JMS Resources 节点。
  5. 单击画面左侧的 Connection Factories 和 Destination Resources 链接,检查资源是否已经注册到服务器,如果有必要可以修改资源。如果资源不存在,您可以在管理控制台中创建它们。

您需要确保 PostMessage servlet 中的 JMS 连接工厂资源被映射为了已注册到 Sun Java System Application Server 的 JMS 连接工厂资源的正确 JNDI 名称。

以下资源应该注册到 Sun Java System Application Server 中:

  • 拥有 JNDI 名称 jms/NewMessage 和类型 javax.jms.Queue 的一个目的地资源。
  • 拥有 JNDI 名称 jms/NewMessageFactory 和类型 javax.jms.QueueConnectionFactory 的一个连接工厂资源。


参考资料

要了解使用 NetBeans IDE 6.0 开发 Java EE 应用程序的更多信息,请参考以下资源:

Java EE 5 教程 中,您可以找到有关 EJB 3.0 Enterprise Beans 使用方法的更多信息。

要发送意见和建议,获得支持,了解 NetBeans IDE Java EE 开发特性的最新发展,请加入 nbj2ee 邮件列表

Bookmark this page

del.icio.us furl simpy slashdot technorati digg
Companion
Projects:
MySQL Database Server   Open JDK: an Open SourceJDK   GlassFish Community: an Open Source Application Server    Mobile & Embedded Community    Open Solaris   java.net - The Source for Java Technology Collaboration   Virtual Box - full virtualizer  Open ESB - The Open Enterprise Service Bus Powered by