在前面的文章中给出的SessionBean的例子都是同步调用SessionBean方法的,也就是说,只有当方法中的代码都执行完,才能返回到客户端。但在某些情况下,由于SessionBean方法的执行时间比较长,这就需要异步地调用该方法,否则客户端就需要等待比较长的时间。要实现异步调用,就需要使用本要讲的消息驱动Bean。消息驱动Bean的基本原理是客户端向消息服务器发送一条消息后,消息服务器会将该消息保存在消息队列中。在这时消息服务器中的某个消费者(读取并处理消息的对象)会读取该消息,并进行处理。发送消息的客户端被称为消息生产者。

创新互联建站是一家专注于成都网站设计、成都网站建设、外贸网站建设与策划设计,博山网站建设哪家好?创新互联建站做网站,专注于网站建设十年,网设计领域的专业建站公司;建站业务涵盖:博山等地区。博山做网站价格咨询:18980820575
本文给出的消息驱动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对象。读者可以\server\default\deploy目录中建立一个xxx-service.xml文件,其中xxx可以任意取值,但必须跟“-service”后缀,例如,abc-service.xml。该文件可以放在deploy或其子目录(可以是多层子目录)中。该文件的内容如下:
- < xml version="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=DestinationManagerdepends>
 - < mbean>
 - < server>
 
要注意的是,元素的name属性值中的name必须是MDBQueue,要与queue/MDBQueue中的/后面的部分一致。如果不进行上面的配置,在启动JBOSS时就会抛出如下的异常:
javax.naming.NameNotFoundException: MDBQueue not bound
也可以将元素放在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
- 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 ConnectionFactory cf;
 - @Resource(mappedName = "queue/MDBQueue")
 - private Queue queue;
 - @Override
 - public String greet(String message)
 - {
 - try
 - {
 - DateBean db = new DateBean();
 - db.setMyDate(new Date());
 - Connection connection = cf.createConnection();
 - Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
 - MessageProducer messageProducer = session.createProducer(queue);
 - ObjectMessage objectMessage = session.createObjectMessage();
 - objectMessage.setObject(db);
 - messageProducer.send(objectMessage);
 - connection.close();
 - System.out.println("成功发送消息!");
 - }
 - catch (Exception e)
 - {
 - System.out.println("发送消息失败!");
 - }
 - return "方法成功返回";
 - }
 - }
 
在上面的代码中使用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+EJB3消息驱动Bean
                
                文章URL:http://www.csdahua.cn/qtweb/news19/155969.html
            
网站建设、网络推广公司-快上网,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等
声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 快上网