eclipse + JBoss 5 + EJB3开发指南(14):消息驱动Bean
来源:互联网 发布:因网络而犯罪的案例 编辑:程序博客网 时间:2024/04/26 05:24
本文为原创,如需转载,请注明作者和出处,谢谢!
在前面的文章中给出的SessionBean的例子都是同步调用SessionBean方法的,也就是说,只有当方法中的代码都执行完,才能返回到客户 端。但在某些情况下,由于SessionBean方法的执行时间比较长,这就需要异步地调用该方法,否则客户端就需要等待比较长的时间。要实现异步调用, 就需要使用本要讲的消息驱动Bean。消息驱动Bean的基本原理是客户端向消息服务器发送一条消息后,消息服务器会将该消息保存在消息队列中。在这时消 息服务器中的某个消费者(读取并处理消息的对象)会读取该消息,并进行处理。发送消息的客户端被称为消息生产者。
本文给出的消息驱动Bean的例子的基本功能是客户端向消息服务器发送一条消息(该消息实际上是一个实体Bean的对象实例),然后消息消费者读取这条消息后,将消息中的实体Bean持久化。实现消息驱动Bean的步骤如下:
一、实现实体Bean
- package entity;
- import java.io.Serializable;
- import java.util.Date;
- import javax.persistence.Column;
- import javax.persistence.Entity;
- import javax.persistence.GeneratedValue;
- import javax.persistence.GenerationType;
- import javax.persistence.Id;
- import javax.persistence.Table;
- @Entity
- @Table(name="t_date")
- public class DateBean implements Serializable
- {
- private int id;
- private Date myDate;
- @Id
- @GeneratedValue(strategy=GenerationType.IDENTITY)
- public int getId()
- {
- return id;
- }
- public void setId(int id)
- {
- this.id = id;
- }
- @Column(name="mydate")
- public Date getMyDate()
- {
- return myDate;
- }
- public void setMyDate(Date myDate)
- {
- this.myDate = myDate;
- }
- }
二、编写消息驱动Bean
消息驱动Bean必须实现MessageListener接口,当该消息驱动Bean接收到一个消息后,EJB容器就会调用MessageListener接口的onMessage方法来理该消息。消息驱动Bean的代码如下:
- package service;
- import javax.ejb.ActivationConfigProperty;
- import javax.ejb.EJBException;
- import javax.ejb.MessageDriven;
- import javax.jms.Message;
- import javax.jms.MessageListener;
- import javax.jms.ObjectMessage;
- import javax.persistence.EntityManager;
- import javax.persistence.PersistenceContext;
- import entity.DateBean;
- @MessageDriven( activationConfig = {
- @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue"),
- @ActivationConfigProperty(propertyName = "destination", propertyValue = "queue/MDBQueue")
- })
- public class DateMessageBean implements MessageListener
- {
- @PersistenceContext(unitName = "myentity1")
- private EntityManager em;
- @Override
- public void onMessage(Message message)
- {
- try
- {
- if(message instanceof ObjectMessage)
- {
- ObjectMessage objmsg = (ObjectMessage) message;
- DateBean dateBean = (DateBean) objmsg.getObject();
- em.persist(dateBean);
- System.out.println("成功持久化DateBean对象!");
- }
- else
- {
- System.out.println("消息类型错误!");
- }
- }
- catch (Exception e)
- {
- throw new EJBException(e);
- }
- }
- }
消息驱动Bean需要使用
@MessageDriven进行注释。要注意的是destination属性的值是queue/MDBQueue。 JBoss不会自已建立一个Queue对象,因此,需要手工来配置Queue对象。读者可以<JBoss5.x安装目录>/server/ default/deploy目录中建立一个xxx-service.xml文件,其中xxx可以任意取值,但必须跟“-service”后缀,例如, abc-service.xml。该文件可以放在deploy或其子目录(可以是多层子目录)中。该文件的内容如下:
要注意的是,<mbean>元素的name属性值中的name必须是MDBQueue,要与queue/MDBQueue中的/后面的部分一致。如果不进行上面的配置,在启动JBOSS时就会抛出如下的异常:
javax.naming.NameNotFoundException: MDBQueue not bound
也可以将<mbean>元素放在deploy目录中的其他以-service.xml结尾的文件中。
如果不设置destination属性的值,在启动JBoss是会抛出如下的异常:
org.jboss.deployers.spi.DeploymentException: Required config property RequiredConfigPropertyMetaData@174098f[name=destination descriptions=[DescriptionMetaData@4ca30b[language=zh]]] for messagingType 'javax.jms.MessageListener' not found in activation config [ActivationConfigProperty(destinationType=javax.jms.Queue), ActivationConfigProperty(connectionFactoryJndiName=MyQueueConnectionFactory), ActivationConfigProperty(destinationName=MyRequestQueue)] ra=jboss.jca:service=RARDeployment,name='jms-ra.rar'
... ...
三、编写调用消息驱动Bean的SessionBean
在上面的代码中使用ObjectMessage对象来包装要向消息服务器发送的实体Bean的对象实例。
除了可以在SessionBean中访问消息驱动Bean外,还可以在不同的机器上通过jndi来查找并调用消息驱动Bean,代码如下::
- package test;
- import java.util.Date;
- import javax.ejb.EJB;
- import javax.jms.Destination;
- import javax.jms.MessageProducer;
- import javax.jms.ObjectMessage;
- import javax.jms.Queue;
- import javax.jms.QueueConnection;
- import javax.jms.QueueConnectionFactory;
- import javax.jms.QueueSession;
- import javax.jms.TextMessage;
- import javax.naming.InitialContext;
- import entity.DateBean;
- import service.Greeter;
- public class Client
- {
- public static void main(String[] args) throws Exception
- {
- InitialContext ctx = new InitialContext();
- QueueConnection connection = null;
- QueueSession session = null;
- QueueConnectionFactory factory = (QueueConnectionFactory) ctx.lookup("ConnectionFactory");
- connection = factory.createQueueConnection();
- session = connection.createQueueSession(false, QueueSession.AUTO_ACKNOWLEDGE);
- Destination destination = (Queue) ctx.lookup("queue/MDBQueue");
- MessageProducer messageProducer = session.createProducer(destination);
- ObjectMessage objectMessage = session.createObjectMessage();
- DateBean db = new DateBean();
- db.setMyDate(new Date());
- objectMessage.setObject(db);
- messageProducer.send(objectMessage);
- connection.close();
- System.out.println("成功发送消息!");
- }
- }
- eclipse + JBoss 5 + EJB3开发指南(14):消息驱动Bean
- eclipse + JBoss 5 + EJB3开发指南(14):消息驱动Bean
- Eclipse+JBoss+EJB3消息驱动Bean
- EJB3.0开发指南:消息驱动Bean
- EJB3.0开发指南:消息驱动Bean
- eclipse + JBoss 5 + EJB3开发指南(5):使用配置文件发布Session Bean
- eclipse + JBoss 5 + EJB3开发指南(11):实体Bean的连接策略(JOINED Strategy)
- eclipse + JBoss 5 + EJB3开发指南(6):编写第一个实体Bean程序
- eclipse + JBoss 5 + EJB3开发指南(4):Session Bean中的注释方法
- eclipse + JBoss 5 + EJB3开发指南(3):使用Session Bean的本地接口
- eclipse + JBoss 5 + EJB3开发指南(3):使用Session Bean的本地接口
- eclipse + JBoss 5 + EJB3开发指南(4):Session Bean中的注释方法
- eclipse + JBoss 5 + EJB3开发指南(6):编写第一个实体Bean程序
- eclipse + JBoss 5 + EJB3开发指南(7):实现Entity Bean的一对一(on
- eclipse + JBoss 5 + EJB3开发指南(8):实现Entity Bean的一对多(on
- eclipse + JBoss 5 + EJB3开发指南(9):实现Entity Bean的多对多(ma
- eclipse + JBoss 5 + EJB3开发指南(11):实体Bean的连接策略
- eclipse + JBoss 5 + EJB3开发指南(9):实现Entity Bean的多对多(many-to-many)映射
- 超越
- C的试验田-指向数组的指针练习,并对数组内的字母大小转化
- 汇编语言
- 必须超越
- [C/C++] 头文件一览
- eclipse + JBoss 5 + EJB3开发指南(14):消息驱动Bean
- C++中将字符串作为参数传递,应采用什么类型变量
- 面向对象三大特性
- [转]IT精英,必须掌握的命令行
- 类的三大成员
- 先精而后广
- .NET 知识体系结构图
- 找的Eclipse快捷键
- 从学习中体验快乐