热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

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

本文为原创,如需转载,请注明作者和出处,谢谢!在前面的文章中给出的SessionBean的例子都是同步调用SessionBe

本文为原创,如需转载,请注明作者和出处,谢谢!

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

一、实现实体Bean


Code:
  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.       


二、编写消息驱动Bean

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


Code:
  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.   


    消息驱动Bean需要使用

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


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

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

javax.naming.NameNotFoundException: MDBQueue not bound

    也可以将元素放在deploy目录中的其他以-service.xml结尾的文件中。
    如果不设置destination属性的值&#xff0c;在启动JBoss是会抛出如下的异常&#xff1a;

org.jboss.deployers.spi.DeploymentException: Required config property RequiredConfigPropertyMetaData&#64;174098f[name&#61;destination descriptions&#61;[DescriptionMetaData&#64;4ca30b[language&#61;zh]]] for messagingType &#39;javax.jms.MessageListener&#39; not found in activation config [ActivationConfigProperty(destinationType&#61;javax.jms.Queue), ActivationConfigProperty(connectionFactoryJndiName&#61;MyQueueConnectionFactory), ActivationConfigProperty(destinationName&#61;MyRequestQueue)] ra&#61;jboss.jca:service&#61;RARDeployment,name&#61;&#39;jms-ra.rar&#39;
... ...
 

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


Code:
  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. &#64;Stateless  
  19. public class GreeterBean implements Greeter  
  20. {  
  21.     &#64;Resource(mappedName &#61; "ConnectionFactory")  
  22.     private ConnectionFactory cf;  
  23.     &#64;Resource(mappedName &#61; "queue/MDBQueue")  
  24.     private Queue queue;  
  25.   
  26.     &#64;Override  
  27.     public String greet(String message)  
  28.     {  
  29.         try  
  30.         {  
  31.             DateBean db &#61; new DateBean();  
  32.             db.setMyDate(new Date());  
  33.             Connection connection &#61; cf.createConnection();  
  34.             Session session &#61; connection.createSession(false, Session.AUTO_ACKNOWLEDGE);  
  35.             MessageProducer messageProducer &#61; session.createProducer(queue);  
  36.             ObjectMessage objectMessage &#61; session.createObjectMessage();  
  37.             objectMessage.setObject(db);  
  38.             messageProducer.send(objectMessage);  
  39.             connection.close();  
  40.             System.out.println("成功发送消息&#xff01;");  
  41.         }  
  42.         catch (Exception e)  
  43.         {  
  44.             System.out.println("发送消息失败&#xff01;");  
  45.         }  
  46.   
  47.         return "方法成功返回";  
  48.   
  49.     }  



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

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


Code:
  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 &#61; new InitialContext();  
  24.         QueueConnection connection &#61; null;  
  25.         QueueSession session &#61; null;  
  26.         QueueConnectionFactory factory &#61; (QueueConnectionFactory) ctx.lookup("ConnectionFactory");  
  27.         connection &#61; factory.createQueueConnection();  
  28.         session &#61; connection.createQueueSession(false, QueueSession.AUTO_ACKNOWLEDGE);  
  29.         Destination destination &#61; (Queue) ctx.lookup("queue/MDBQueue");  
  30.         MessageProducer messageProducer &#61; session.createProducer(destination);  
  31.         ObjectMessage objectMessage &#61; session.createObjectMessage();  
  32.         DateBean db &#61; new DateBean();  
  33.         db.setMyDate(new Date());  
  34.         objectMessage.setObject(db);  
  35.         messageProducer.send(objectMessage);  
  36.         connection.close();  
  37.         System.out.println("成功发送消息&#xff01;");  
  38.     }  
  39. }  


推荐阅读
  • Imtryingtofigureoutawaytogeneratetorrentfilesfromabucket,usingtheAWSSDKforGo.我正 ... [详细]
  • 本文介绍了如何使用C#制作Java+Mysql+Tomcat环境安装程序,实现一键式安装。通过将JDK、Mysql、Tomcat三者制作成一个安装包,解决了客户在安装软件时的复杂配置和繁琐问题,便于管理软件版本和系统集成。具体步骤包括配置JDK环境变量和安装Mysql服务,其中使用了MySQL Server 5.5社区版和my.ini文件。安装方法为通过命令行将目录转到mysql的bin目录下,执行mysqld --install MySQL5命令。 ... [详细]
  • Hibernate延迟加载深入分析-集合属性的延迟加载策略
    本文深入分析了Hibernate延迟加载的机制,特别是集合属性的延迟加载策略。通过延迟加载,可以降低系统的内存开销,提高Hibernate的运行性能。对于集合属性,推荐使用延迟加载策略,即在系统需要使用集合属性时才从数据库装载关联的数据,避免一次加载所有集合属性导致性能下降。 ... [详细]
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • Java序列化对象传给PHP的方法及原理解析
    本文介绍了Java序列化对象传给PHP的方法及原理,包括Java对象传递的方式、序列化的方式、PHP中的序列化用法介绍、Java是否能反序列化PHP的数据、Java序列化的原理以及解决Java序列化中的问题。同时还解释了序列化的概念和作用,以及代码执行序列化所需要的权限。最后指出,序列化会将对象实例的所有字段都进行序列化,使得数据能够被表示为实例的序列化数据,但只有能够解释该格式的代码才能够确定数据的内容。 ... [详细]
  • 开发笔记:加密&json&StringIO模块&BytesIO模块
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了加密&json&StringIO模块&BytesIO模块相关的知识,希望对你有一定的参考价值。一、加密加密 ... [详细]
  • 目录实现效果:实现环境实现方法一:基本思路主要代码JavaScript代码总结方法二主要代码总结方法三基本思路主要代码JavaScriptHTML总结实 ... [详细]
  • 如何使用Java获取服务器硬件信息和磁盘负载率
    本文介绍了使用Java编程语言获取服务器硬件信息和磁盘负载率的方法。首先在远程服务器上搭建一个支持服务端语言的HTTP服务,并获取服务器的磁盘信息,并将结果输出。然后在本地使用JS编写一个AJAX脚本,远程请求服务端的程序,得到结果并展示给用户。其中还介绍了如何提取硬盘序列号的方法。 ... [详细]
  • Java容器中的compareto方法排序原理解析
    本文从源码解析Java容器中的compareto方法的排序原理,讲解了在使用数组存储数据时的限制以及存储效率的问题。同时提到了Redis的五大数据结构和list、set等知识点,回忆了作者大学时代的Java学习经历。文章以作者做的思维导图作为目录,展示了整个讲解过程。 ... [详细]
  • LeetCode笔记:剑指Offer 41. 数据流中的中位数(Java、堆、优先队列、知识点)
    本文介绍了LeetCode剑指Offer 41题的解题思路和代码实现,主要涉及了Java中的优先队列和堆排序的知识点。优先队列是Queue接口的实现,可以对其中的元素进行排序,采用小顶堆的方式进行排序。本文还介绍了Java中queue的offer、poll、add、remove、element、peek等方法的区别和用法。 ... [详细]
  • 本文介绍了OC学习笔记中的@property和@synthesize,包括属性的定义和合成的使用方法。通过示例代码详细讲解了@property和@synthesize的作用和用法。 ... [详细]
  • ZSI.generate.Wsdl2PythonError: unsupported local simpleType restriction ... [详细]
  • 本文介绍了一款名为TimeSelector的Android日期时间选择器,采用了Material Design风格,可以在Android Studio中通过gradle添加依赖来使用,也可以在Eclipse中下载源码使用。文章详细介绍了TimeSelector的构造方法和参数说明,以及如何使用回调函数来处理选取时间后的操作。同时还提供了示例代码和可选的起始时间和结束时间设置。 ... [详细]
  • GreenDAO快速入门
    前言之前在自己做项目的时候,用到了GreenDAO数据库,其实对于数据库辅助工具库从OrmLite,到litePal再到GreenDAO,总是在不停的切换,但是没有真正去了解他们的 ... [详细]
  • Servlet多用户登录时HttpSession会话信息覆盖问题的解决方案
    本文讨论了在Servlet多用户登录时可能出现的HttpSession会话信息覆盖问题,并提供了解决方案。通过分析JSESSIONID的作用机制和编码方式,我们可以得出每个HttpSession对象都是通过客户端发送的唯一JSESSIONID来识别的,因此无需担心会话信息被覆盖的问题。需要注意的是,本文讨论的是多个客户端级别上的多用户登录,而非同一个浏览器级别上的多用户登录。 ... [详细]
author-avatar
花长好月常圆人长久
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有