Eclipse+JBoss+EJB3消息驱动Bean

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

本文给出的消息驱动Bean的例子的基本功能是客户端向消息服务器发送一条消息(该消息实际上是一个实体Bean的对象实例),然后消息消费者读取这条消息后,将消息中的实体Bean持久化。实现消息驱动Bean的步骤如下:

一、实现实体Bean

 
 
  1. package entity;  
  2.  
  3. import java.io.Serializable;  
  4. import java.util.Date;  
  5. import javax.persistence.Column;  
  6. import javax.persistence.Entity;  
  7. import javax.persistence.GeneratedValue;  
  8. import javax.persistence.GenerationType;  
  9. import javax.persistence.Id;  
  10. import javax.persistence.Table;  
  11.  
  12. @Entity 
  13. @Table(name="t_date")  
  14. public class DateBean implements Serializable  
  15. {  
  16.     private int id;  
  17.     private Date myDate;  
  18.     @Id 
  19.     @GeneratedValue(strategy=GenerationType.IDENTITY)  
  20.     public int getId()  
  21.     {  
  22.         return id;  
  23.     }  
  24.       
  25.     public void setId(int id)  
  26.     {  
  27.         this.id = id;  
  28.     }  
  29.     @Column(name="mydate")  
  30.     public Date getMyDate()  
  31.     {  
  32.         return myDate;  
  33.     }  
  34.     public void setMyDate(Date myDate)  
  35.     {  
  36.         this.myDate = myDate;  
  37.     }  
  38.       
  39. }  

二、编写消息驱动Bean

消息驱动Bean必须实现MessageListener接口,当该消息驱动Bean接收到一个消息后,EJB容器就会调用MessageListener接口的onMessage方法来理该消息。消息驱动Bean的代码如下:

 
 
  1. package service;  
  2.  
  3. import javax.ejb.ActivationConfigProperty;  
  4. import javax.ejb.EJBException;  
  5. import javax.ejb.MessageDriven;  
  6. import javax.jms.Message;  
  7. import javax.jms.MessageListener;  
  8. import javax.jms.ObjectMessage;  
  9. import javax.persistence.EntityManager;  
  10. import javax.persistence.PersistenceContext;  
  11. import entity.DateBean;  
  12.  
  13. @MessageDriven( activationConfig =  {          
  14.         @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue"),  
  15.         @ActivationConfigProperty(propertyName = "destination", propertyValue = "queue/MDBQueue")  
  16.       })  
  17. public class DateMessageBean implements MessageListener  
  18. {  
  19.     @PersistenceContext(unitName = "myentity1")  
  20.     private EntityManager em;  
  21.  
  22.     @Override 
  23.     public void onMessage(Message message)  
  24.     {  
  25.         try 
  26.         {  
  27.             if(message instanceof ObjectMessage)  
  28.             {  
  29.  
  30.                 ObjectMessage objmsg = (ObjectMessage) message;  
  31.                 DateBean dateBean = (DateBean) objmsg.getObject();  
  32.                 em.persist(dateBean);  
  33.                 System.out.println("成功持久化DateBean对象!");  
  34.             }  
  35.             else 
  36.             {  
  37.                 System.out.println("消息类型错误!");  
  38.             }  
  39.         }  
  40.         catch (Exception e)  
  41.         {  
  42.             throw new EJBException(e);  
  43.         }  
  44.  
  45.     }  
  46.  
  47. }  

消息驱动Bean需要使用@MessageDriven进行注释。要注意的是destination属性的值是queue/MDBQueue。JBoss不会自已建立一个Queue对象,因此,需要手工来配置Queue对象。读者可以\server\default\deploy目录中建立一个xxx-service.xml文件,其中xxx可以任意取值,但必须跟“-service”后缀,例如,abc-service.xml。该文件可以放在deploy或其子目录(可以是多层子目录)中。该文件的内容如下:

 
 
  1. < xml version="1.0" encoding="UTF-8"?> 
  2. < server> 
  3.   < mbean code="org.jboss.mq.server.jmx.Queue" name="jboss.mq.destination:service=Queue,name=MDBQueue"> 
  4.     < depends optional-attribute-name="DestinationManager">jboss.mq:service=DestinationManagerdepends> 
  5.   < mbean> 
  6. < server> 
  7.      

要注意的是,元素的name属性值中的name必须是MDBQueue,要与queue/MDBQueue中的/后面的部分一致。如果不进行上面的配置,在启动JBOSS时就会抛出如下的异常:

javax.naming.NameNotFoundException: MDBQueue not bound

也可以将元素放在deploy目录中的其他以-service.xml结尾的文件中。

如果不设置destination属性的值,在启动JBoss是会抛出如下的异常:

 
 
  1. 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' 
  2. ... ... 

三、编写调用消息驱动Bean的SessionBean

 
 
  1. package service;  
  2.  
  3. import java.util.ArrayList;  
  4. import java.util.Date;  
  5. import java.util.List;  
  6. import javax.annotation.Resource;  
  7. import javax.ejb.Stateless;  
  8. import javax.jms.Connection;  
  9. import javax.jms.ConnectionFactory;  
  10. import javax.jms.MessageProducer;  
  11. import javax.jms.ObjectMessage;  
  12. import javax.jms.Queue;  
  13. import javax.jms.Session;  
  14. import javax.persistence.EntityManager;  
  15. import entity.DateBean;  
  16. import entity.Greeting;  
  17.  
  18. @Stateless 
  19. public class GreeterBean implements Greeter  
  20. {  
  21.     @Resource(mappedName = "ConnectionFactory")  
  22.     private ConnectionFactory cf;  
  23.     @Resource(mappedName = "queue/MDBQueue")  
  24.     private Queue queue;  
  25.  
  26.     @Override 
  27.     public String greet(String message)  
  28.     {  
  29.         try 
  30.         {  
  31.             DateBean db = new DateBean();  
  32.             db.setMyDate(new Date());  
  33.             Connection connection = cf.createConnection();  
  34.             Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);  
  35.             MessageProducer messageProducer = session.createProducer(queue);  
  36.             ObjectMessage objectMessage = session.createObjectMessage();  
  37.             objectMessage.setObject(db);  
  38.             messageProducer.send(objectMessage);  
  39.             connection.close();  
  40.             System.out.println("成功发送消息!");  
  41.         }  
  42.         catch (Exception e)  
  43.         {  
  44.             System.out.println("发送消息失败!");  
  45.         }  
  46.  
  47.         return "方法成功返回";  
  48.  
  49.     }  
  50. }  

在上面的代码中使用ObjectMessage对象来包装要向消息服务器发送的实体Bean的对象实例。

除了可以在SessionBean中访问消息驱动Bean外,还可以在不同的机器上通过jndi来查找并调用消息驱动Bean,代码如下:

 
 
  1. package test;  
  2.  
  3. import java.util.Date;  
  4. import javax.ejb.EJB;  
  5. import javax.jms.Destination;  
  6. import javax.jms.MessageProducer;  
  7. import javax.jms.ObjectMessage;  
  8. import javax.jms.Queue;  
  9. import javax.jms.QueueConnection;  
  10. import javax.jms.QueueConnectionFactory;  
  11. import javax.jms.QueueSession;  
  12. import javax.jms.TextMessage;  
  13. import javax.naming.InitialContext;  
  14. import entity.DateBean;  
  15.  
  16. import service.Greeter;  
  17.  
  18. public class Client  
  19. {  
  20.  
  21.     public static void main(String[] args) throws Exception  
  22.     {  
  23.         InitialContext ctx = new InitialContext();  
  24.         QueueConnection connection = null;  
  25.         QueueSession session = null;  
  26.         QueueConnectionFactory factory = (QueueConnectionFactory) ctx.lookup("ConnectionFactory");  
  27.         connection = factory.createQueueConnection();  
  28.         session = connection.createQueueSession(false, QueueSession.AUTO_ACKNOWLEDGE);  
  29.         Destination destination = (Queue) ctx.lookup("queue/MDBQueue");  
  30.         MessageProducer messageProducer = session.createProducer(destination);  
  31.         ObjectMessage objectMessage = session.createObjectMessage();  
  32.         DateBean db = new DateBean();  
  33.         db.setMyDate(new Date());  
  34.         objectMessage.setObject(db);  
  35.         messageProducer.send(objectMessage);  
  36.         connection.close();  
  37.         System.out.println("成功发送消息!");  
  38.     }  
  39. }  

    Eclipse+JBoss+EJB3消息驱动Bean

1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 、4下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合;、下载 4使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合;、 4下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值