编写 EJB 模块
在文中,我们将在 EJB 模块中创建对象。我们将创建一个实体类,一个消息驱动 bean 和一个会话外观(Session Facade)。我们还将创建一个持久性单元,以便为容器提供管理实体,和消息驱动 bean 将使用的 Java 消息服务(Java Message Service ,JMS)资源所需的信息。
创建持久性单元
首先,我们需要创建一个持久性单元,用于定义应用程序中所使用的数据源和实体管理器。
- 右击 EJB 模块,然后选择 New > File/Folder 。
- 从 Persistence 类别中,选择 Persistence Unit ,然后单击 Next 按钮。
- 保持默认的 Persistence Unit 名称。
- 对于 Persistence Provider ,选择 TopLink(默认)。
- 对于Data Source,选择默认数据源 jdbc/sample。
- 检查持久性单元使用了 Java Transaction API,而且 Table Generation Strategy 被设定为 Create ,这样部署应用程序时就能基于我们的实体类创建表。
- 单击 Finish 按钮。
单击 Finish 时,IDE 将会创建 persistence.xml,并在源代码编辑器中以设计视图打开它。关闭 persistence.xml。
创建 NewsEntity 实体类
在本练习中,我们将创建 NewsEntity 实体类。实体类就是一个简单的 Java 类。创建实体类时,IDE 会添加 @Entity 注释用于将类定义为实体类。创建类之后,我们将在类中创建字段,以表示要在表中保存的数据。
每个实体类都必须有一个主键。创建实体类时,IDE 会添加 @Id 注释用于声明使用哪个字段作为主键。IDE 还会添加 @GeneratedValue 注释,用于指定主 Id 的主要生成策略。
创建 NewsEntity 类的步骤如下:
- 在 Project 窗口在单击鼠标右键 EJB 模块,然后选择 New > File/Folder ,以便打开 New File 向导。
- 从 Persistence 类别中,选择 Entity Class ,然后单击 Next 按钮。
- 键入 NewsEntity 作为类名,键入 ejb 作为包名,让 Primary Key Type 保持为 Long。单击 Finish 按钮。
单击 Finish 时,实体类 NewsEntity.java 就会在源代码编辑器中打开。在源代码编辑器中,完成以下步骤:
- 给类添加以下字段声明:
private String title;
private String body; - 在源代码编辑器中单击鼠标右键,然后选择 Insert Code ,同时选择 Getter and Setter 为每个字段生成 getter 和 setter 程序。
- 在 Generate Getters and Setters 对话框中,选择 body 和 title 字段,然后单击 Generate 按钮。
- 保存修改。
在下一步中,我们将创建 NewMessage 消息驱动 bean。
创建 NewMessage 消息驱动 Bean
现在,我们将在我们的 EJB 模块中创建 NewMessage 消息驱动。我们将使用 New Message-Driven Bean 向导来创建 bean 和必要的 JMS 资源。
创建 NewMessage 消息驱动 bean 的步骤如下:
- 在 Projects 窗口在单击鼠标右键 EJB 模块,然后选择 New > File/Folder ,可以打开 New File 向导。
- 从 Enterprise 类别中,选择 Message-Driven Beans ,然后单击 Next 按钮。
- 键入 NewMessage 作为类名。
- 从 Package 下拉列表中选择 ejb。
- 单击 Add 打开 Add Message Destination 对话框。
- 在 Add Message Destination 对话框中,键入 jms/NewMessage,然后 选择 Queue 作为目标类型。单击 OK 。
- 确保项目目的地正确,然后单击 Finish 按钮。
单击 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 资源,以便管理持久性实体实例。我们将在 源代码编辑器中给类添加注释。
- 将 MessageDrivenContext 资源注入到类中,方法是添加以下带注释的字段(以黑体表示)到类中:
public class NewMessage implements MessageListener {
@Resource
private MessageDrivenContext mdc; - 在类中引入实体管理器,方法是在代码在单击鼠标右键,然后从弹出式菜单中选择 Persistence > Use Entity Manager 。这将在源代码中添加如下注释:
@PersistenceContext
并在代码中生成如下方法:
private EntityManager em;public void persist(Object object) {
em.persist(object);
} - 修改 persist 方法,将名称 save。方法应该像如下所示:
public void save(Object object) {
em.persist(object);
} - 修改 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();
} - 按下 Alt-Shift-F 组合键,生成所有必需的导入语句。注意: 生成导入语句时,我们需要确保导入 jms 和 javax.annotation.Resource 库。
- 保存文件。
创建会话 Bean
接下来,我们将为 NewsEntity 实体类创建会话外观。创建会话外观的步骤如下:
- 右击 EJB 模块,然后选择 New > File/Folder 。
- 从 Persistence 类别中,选择 Session Beans for Entity Classes ,然后单击 Next 按钮。
- 从可用实体类的列表中,选择 ejb.NewsEntity 并单击 Add ,然后单击 Next 按钮。
- 确定将 Package 设置为 ejb 并且已创建本地接口。
- 单击 Finish 按钮。
单击 Finish 按钮后,IDE 将会创建会话外观类 NewsEntityFacade.java,而且该类会在源代码编辑器中打开。IDE 还会创建本地接口 NewsEntityFacadeLocal.java。
EJB 3.0 技术简化了会话 bean 的创建过程,因为它减少了所需代码的数量。您可以看到,注释 @Stateless 用于把类声明为无状态的会话 bean,而类不再需要一条语句来实现 javax.ejb.SessionBean。代码也要清晰很多,因为借助 EJB 3.0 技术,业务方法不再需要代码来声明它们抛出了未经检查的异常。
您可以看到,创建会话外观时,PersistenceContext 资源被直接注入了会话 bean 组件中。
小结
在本练习中,我们为 EJB 模块中的一个实体类和一个消息驱动编写了代码。我们还创建了我们的应用程序将会使用的 JMS 资源。