eclipse + JBoss 5 + EJB3开发指南(14):消息驱动Bean

xiaoxiao2026-10-08  1

本文为原创,如需转载,请注明作者和出处,谢谢! 上一篇: eclipse + JBoss 5 + EJB3开发指南(13):在Servlet中访问应用程序管制EntityManager对象 在前面的文章中给出的SessionBean的例子都是同步调用SessionBean方法的,也就是说,只有当方法中的代码都执行完,才能返回到客户端。但在某些情况下,由于SessionBean方法的执行时间比较长,这就需要异步地调用该方法,否则客户端就需要等待比较长的时间。要实现异步调用,就需要使用本要讲的消息驱动Bean。消息驱动Bean的基本原理是客户端向消息服务器发送一条消息后,消息服务器会将该消息保存在消息队列中。在这时消息服务器中的某个消费者(读取并处理消息的对象)会读取该消息,并进行处理。发送消息的客户端被称为消息生产者。 本文给出的消息驱动Bean的例子的基本功能是客户端向消息服务器发送一条消息(该消息实际上是一个实体Bean的对象实例),然后消息消费者读取这条消息后,将消息中的实体Bean持久化。实现消息驱动Bean的步骤如下: 一、实现实体Bean <!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> --> 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 DatemyDate; @Id @GeneratedValue(strategy = GenerationType.IDENTITY) public int getId() { return id; } public void setId( int id) { this .id = id; } @Column(name = " mydate " ) public DategetMyDate() { return myDate; } public void setMyDate(DatemyDate) { this .myDate = myDate; } } 二、编写消息驱动Bean 消息驱动Bean必须实现MessageListener接口,当该消息驱动Bean接收到一个消息后,EJB容器就会调用MessageListener接口的onMessage方法来理该消息。消息驱动Bean的代码如下: <!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> --> 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 EntityManagerem; @Override public void onMessage(Messagemessage) { try { if (message instanceof ObjectMessage) { ObjectMessageobjmsg = (ObjectMessage)message; DateBeandateBean = (DateBean)objmsg.getObject(); em.persist(dateBean); System.out.println( " 成功持久化DateBean对象! " ); } else { System.out.println( " 消息类型错误! " ); } } catch (Exceptione) { 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或其子目录(可以是多层子目录)中。该文件的内容如下: <!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> --> <? xmlversion="1.0"encoding="UTF-8" ?> < server > < mbean code ="org.jboss.mq.server.jmx.Queue" name ="jboss.mq.destination:service=Queue,name=MDBQueue" > < depends optional-attribute-name ="DestinationManager" > jboss.mq:service=DestinationManager </ depends > </ mbean > </ server > 要注意的是,<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 <!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> --> package service; import java.util.ArrayList; import java.util.Date; import java.util.List; import javax.annotation.Resource; import javax.ejb.Stateless; import javax.jms.Connection; import javax.jms.ConnectionFactory; import javax.jms.MessageProducer; import javax.jms.ObjectMessage; import javax.jms.Queue; import javax.jms.Session; import javax.persistence.EntityManager; import entity.DateBean; import entity.Greeting; @Stateless public class GreeterBean implements Greeter { @Resource(mappedName = " ConnectionFactory " ) private ConnectionFactorycf; @Resource(mappedName = " queue/MDBQueue " ) private Queuequeue; @Override public Stringgreet(Stringmessage) { try { DateBeandb = new DateBean(); db.setMyDate( new Date()); Connectionconnection = cf.createConnection(); Sessionsession = connection.createSession( false ,Session.AUTO_ACKNOWLEDGE); MessageProducermessageProducer = session.createProducer(queue); ObjectMessageobjectMessage = session.createObjectMessage(); objectMessage.setObject(db); messageProducer.send(objectMessage); connection.close(); System.out.println( " 成功发送消息! " ); } catch (Exceptione) { System.out.println( " 发送消息失败! " ); } return " 方法成功返回 " ; } } 在上面的代码中使用ObjectMessage对象来包装要向消息服务器发送的实体Bean的对象实例。 除了可以在SessionBean中访问消息驱动Bean外,还可以在不同的机器上通过jndi来查找并调用消息驱动Bean,代码如下: <!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> --> 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 { InitialContextctx = new InitialContext(); QueueConnectionconnection = null ; QueueSessionsession = null ; QueueConnectionFactoryfactory = (QueueConnectionFactory)ctx.lookup( " ConnectionFactory " ); connection = factory.createQueueConnection(); session = connection.createQueueSession( false ,QueueSession.AUTO_ACKNOWLEDGE); Destinationdestination = (Queue)ctx.lookup( " queue/MDBQueue " ); MessageProducermessageProducer = session.createProducer(destination); ObjectMessageobjectMessage = session.createObjectMessage(); DateBeandb = new DateBean(); db.setMyDate( new Date()); objectMessage.setObject(db); messageProducer.send(objectMessage); connection.close(); System.out.println( " 成功发送消息! " ); } } 下一篇: eclipse + JBoss 5 + EJB3开发指南(15):拦截器方法和拦截器类

国内最棒的Google Android技术社区(eoeandroid),欢迎访问! 《银河系列原创教程》发布 《Java Web开发速学宝典》出版,欢迎定购 相关资源:垃圾分类数据集及代码
转载请注明原文地址: https://www.6miu.com/read-5053797.html

最新回复(0)