网路冷眼@BlogJava

熙熙攘攘一闲人 以冷静的眼光观察技术
posts - 88, comments - 193, trackbacks - 0, articles - 28
  BlogJava :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理

EJB 3.0 Enterprise Beans(转载)

Posted on 2007-05-07 23:19 网路冷眼@BlogJava 阅读(378) 评论(0)  编辑  收藏 所属分类: Java
原文地址:http://testwww.netbeans.org/kb/55/ejb30_zh_CN.html

EJB 3.0 Enterprise Beans

本文档介绍了有关使用 EJB 3.0 技术(作为 Java EE 5 平台的一部分)开发企业应用程序的基础知识,同时说明了 EJB 3.0 技术是如何简化企业应用程序的开发过程的。本文档使用的是 NetBeans IDE 5.5 发行版本

预计持续时间:30 分钟

先决条件

本文档假定您已具备了以下技术的一些基本知识或编程经验:

  • Java 编程
  • NetBeans IDE

本教程所需的软件

在学习本教程之前,您需要在计算机中安装以下软件:

在学习本教程之前,您需要在 IDE 中注册 Sun Java System Application Server 的本地实例。

教程练习


建立企业应用程序项目

本练习的目的是:创建包含一个 EJB 模块和一个 Web 模块的 NewsApp 企业应用程序项目。NewsApp 应用程序使用消息驱动 Bean 接收和处理 Servlet 发送到队列中的消息。该应用程序使用 Servlet 将消息发送到消息驱动 Bean 并显示消息。

创建企业应用程序

  1. 从主菜单中选择“文件”>“新建项目”(Ctrl-Shift-N)。
  2. 从“企业”类别中选择“企业应用程序”,然后单击“下一步”。
  3. 将项目命名为 NewsApp,并将服务器设置为 Sun Java System Application Server。
  4. 将 J2EE 版本设置为 "Java EE 5",然后选中“创建 EJB 模块”和“创建 Web 应用程序模块”(如果未选中)。
  5. 单击“完成”。

小结

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

对 EJB 模块进行编码

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

创建持久性单元

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

  1. 右键单击 EJB 模块,然后选择“新建”>“文件/文件夹”。
  2. 从“持久性”类别中,选择“持久性单元”,然后单击“下一步”。
  3. 保留缺省的持久性单元名称。
  4. 对于持久性提供程序,请选择“TopLink(缺省)”。
  5. 对于数据源,请选择缺省的数据源 jdbc/sample
  6. 检查是否为持久性单元选中了“使用 Java 事务 API”,以及“表生成策略”是否设置为“创建”,以便在部署应用程序时创建基于实体类的表。
  7. 单击“完成”。

“新建持久性单元”向导

单击“完成”后,IDE 将创建 persistence.xml,并在源代码编辑器中将其打开。关闭 persistence.xml

创建 NewsEntity 实体类

在本练习中,我们将创建 NewsEntity 实体类。实体类是一个简单的 Java 类。在创建实体类时,IDE 会添加 @Entity 标注以将该类定义为实体类。当创建了类后,我们将在该类中创建字段以表示表中所需的数据。

每个实体类都必须具有一个主键。在创建实体类时,IDE 会添加 @Id 标注以声明要用作主键的字段。此外,IDE 还会添加 @Generated 标注以指定主 Id 的键生成策略。

要创建 NewsEntity 类,请执行以下操作:

  1. 在“项目”窗口中右键单击 EJB 模块,然后选择“新建”>“文件/文件夹”打开“新建文件”向导。
  2. 从“持久性”类别中,选择“实体类”,然后单击“下一步”。
  3. 键入 NewsEntity 作为类名,键入 ejb 作为包名,并将“主键类型”保留为 Long。单击“完成”。

单击“完成”后,将在源代码编辑器中打开实体类 NewsEntity.java。在源代码编辑器中,请执行以下操作:

  1. 将以下字段声明添加到类中:
    String title;
        String body;
  2. 在源代码编辑器中单击鼠标右键,然后选择“重构”>“封装字段”以便为每个字段生成 getter 和 setter。在“封装字段”对话框中,确保选中了字段 idtitlebody 的 getter 和 setter 复选框。
  3. 在“封装字段”对话框中单击“下一步”,然后在“输出”窗口的“重构”标签中单击“执行重构”。IDE 将为各字段添加 getter 和 setter 方法,并将字段的可视性更改为 private
  4. 保存对文件所做的更改。

在接下来的步骤中,我们将创建 NewMessage 消息驱动 Bean。

创建 NewMessage 消息驱动 Bean

现在我们将在 EJB 模块中创建 NewMessage 消息驱动 Bean。我们将使用“新建消息驱动 Bean”向导来创建 Bean 和所需的 JMS 资源。

要创建 NewMessage 消息驱动 Bean,请执行以下操作:

  1. 在“项目”窗口中右键单击 EJB 模块,然后选择“新建”>“文件/文件夹”以打开“新建文件”向导。
  2. 从“企业”类别中,选择“消息驱动 Bean”,然后单击“下一步”。
  3. 键入 NewMessage 作为类名。
  4. 从“包”下拉列表中选择 "ejb"。
  5. 选择“队列”作为目标类型,然后单击“完成”。

单击“完成”后,将在源代码编辑器中打开新建的消息驱动 Bean 类 NewMessage.java。您可以看到该类具有以下标注:

@MessageDriven(mappedName = "jms/NewMessage")

此标注向容器说明:该组件是一个消息驱动 Bean 并且该 Bean 使用 JMS 资源。当 IDE 生成类时,将从类 (NewMessage.java) 名称派生资源的映射名 (jms/NewMessage)。JMS 资源被映射到目标的 JNDI 名称,Bean 从该目标中接收消息。“新建消息驱动 Bean”向导已为我们创建了 JMS 资源。通过 EJB 3.0 API,我们可以从 Bean 类中查找 JNDI 名称空间中的对象,这样就不需要配置部署描述符来指定 JMS 资源了。

EJB 3.0 规范允许您使用标注将资源直接引入类中。现在,我们准备使用标注将 MessageDrivenContext 资源引入类中,然后注入 PersistenceContext 资源,EntityManager API 将使用该资源来管理持久性实体实例。我们要在源代码编辑器中将标注添加到类中。

  1. 通过在类中添加以下带标注的字段(以粗体显示),将 MessageDrivenContext 资源注入到类中:
    public class NewMessage implements MessageListener {
        @Resource
        private MessageDrivenContext mdc;
  2. 在代码中单击鼠标右键,然后从弹出式菜单中选择“持久性”>“使用实体管理器”,将实体管理器引入类中。
    这会在源代码中添加以下标注:
    @PersistenceContext
        private EntityManager em;
    并在代码中生成以下方法:
    public void persist(Object object) {
        // TODO:
        // em.persist(object);
        }
  3. 按如下所示修改 persist 方法:
    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 组合键生成所有必要的 import 语句。在生成 import 语句时,我们需要确保导入 jmsjavax.annotation.Resource; 库。
  6. 保存该文件。

创建会话 Bean

接下来,我们将为 NewsEntity 实体类创建一个会话 Facade。要创建会话 Facade,请执行以下操作:

  1. 右键单击 EJB 模块,然后选择“新建”>“文件/文件夹”。
  2. 从“持久性”类别中,选择“实体类的会话 Bean”,然后单击“下一步”。
  3. 从可用的实体类列表中,选择 "NewsEntity",单击“添加”,然后单击“下一步”。
  4. 检查是否将包设置为 ejb 以及是否选中了创建本地接口。
  5. 单击“完成”。

单击“完成”后,将创建会话 Facade 类 NewsEntityFacade.java,并在源代码编辑器中将其打开。IDE 还将创建本地接口 NewsEntityFacadeLocal.java

EJB 3.0 技术通过减少所需的代码量来简化会话 Bean 的创建。您可以看到,标注 @Stateless 用于将类声明为无态会话 Bean 组件,并且该类不再需要实现 javax.ejb.SessionBean 的语句。此外,代码也更为简洁了,因为利用 EJB 3.0 技术,业务方法不再需要使用代码来声明其抛出了所检查到的异常。

您会看到,在创建会话 Facade 时,PersistenceContext 资源已直接注入到会话 Bean 组件中。

小结

在本练习中,我们已对 EJB 模块中的实体类和消息驱动 Bean 进行了编码,然后为实体类创建了会话 Facade。此外,我们还创建了应用程序使用的 JMS 资源。

对 Web 模块进行编码

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

创建 ListNews Servlet

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

  1. 右键单击 Web 模块项目,然后选择“新建”> "Servlet"。
  2. 键入 ListNews 作为类名。
  3. 输入 web 作为包名,然后单击“完成”。

单击“完成”后,将在源代码编辑器中打开类 ListNews.java。在源代码编辑器中,请执行以下操作:

  1. 在源代码中,单击鼠标右键,然后选择“企业资源”>“调用 Enterprise Bean”。
  2. 在“调用 Enterprise Bean”对话框中,选择 "NewsEntityFacade",然后单击“确定”。单击“确定”后,将使用 @EJB 标注在 Servlet 中注入实体 Bean 资源。
  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 组合键为类生成所有必要的 import 语句。在生成 import 语句时,我们希望从 util 包中导入类。
  5. 保存对文件所做的更改。

创建 PostMessage Servlet

在本练习中,我们将创建用于传递消息的 PostMessage Servlet。我们将使用标注将所创建的 JMS 资源直接注入 Servlet 中,并且指定变量名称及其映射到的名称。然后,添加用于发送 JMS 消息的代码,以及用于在 HTML 表单中添加消息的代码。

  1. 右键单击 Web 模块项目,然后选择“新建”> "Servlet"。
  2. 键入 PostMessage 作为类名。
  3. 输入 web 作为包名,然后单击“完成”。

单击“完成”后,将在源代码编辑器中打开类 PostMessage.java。在源代码编辑器中,请执行以下操作:

  1. 通过添加下面以粗体显示的字段声明,使用标注来注入 ConnectionFactoryQueue 资源:
    public class PostMessage extends HttpServlet {
        @Resource(mappedName="jms/NewMessageFactory")
        private  ConnectionFactory connectionFactory;
        @Resource(mappedName="jms/NewMessage")
        private  Queue queue;
  2. 现在,通过将下面以粗体显示的代码添加到 processRequest 方法中,添加用于发送 JMS 消息的代码:
    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 组合键为类生成所有必要的 import 语句。在选择 ConnectionConnectionFactorySessionQueue 的 import 语句时,将导入 java.jms 库。
  5. 保存对文件所做的更改。

运行项目

现在可以运行项目了。在运行项目时,我们希望浏览器打开包含 ListNews Servlet 的页面。可以通过在企业应用程序的“属性”对话框中指定该页的 URL 来实现这一目的。该 URL 是应用程序的上下文路径的相对 URL。输入相对 URL 后,可以从“项目”窗口中生成、部署并运行应用程序。

要设置相对 URL 并运行应用程序,请执行以下操作:

  1. 在“项目”窗口中,右键单击 "NewsApp" 企业应用程序节点,然后从弹出式菜单中选择“属性”。
  2. 在“类别”窗格中选择“运行”。
  3. 在“相对 URL”文本字段中,键入 /ListNews。
  4. 单击“确定”。
  5. 在“项目”窗口中,右键单击 "NewsApp" 企业应用程序节点,然后选择“运行项目”。

运行项目时,将在浏览器中打开 ListNews Servlet,该 Servlet 用于显示数据库中的消息列表。如果您是第一次运行项目,则数据库为空,但是您可以单击“添加消息”来添加消息。

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 的“运行环境”中,展开“服务器”节点以确认 Sun Java System Application Server 正在运行。"Sun Java System Application Server" 节点旁边的小绿色箭头表示服务器正在运行。
  2. 右键单击 "Sun Java System Application Server" 节点,然后选择“查看管理控制台”以在浏览器中打开登录窗口。
  3. 登录到 Sun Java System Application Server。缺省的用户名为 admin,口令为 adminadmin
  4. 在浏览器的管理控制台中,依次展开左框架中的“资源”节点和“JMS 资源”节点。
  5. 在左框架中单击“连接工厂”和“目标资源”链接以检查是否在服务器中注册了这些资源,并在必要时修改这些资源。如果这些资源不存在,您可以在管理控制台中创建这些资源。

您需要确保将 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 5.5 开发 Java EE 应用程序的更多信息,请参见以下资源:

您可以在 Java EE 5 教程中找到有关使用 EJB 3.0 Enterprise Beans 的详细信息。

要发送意见和建议、获得支持以及随时了解 NetBeans IDE Java EE 开发功能的最新开发情况,请加入 nbj2ee 邮件列表


只有注册用户登录后才能发表评论。


网站导航: