ejb3: message drive bean(MDB)示例

上一篇已经知道了JMS的基本操作,今天来看一下ejb3中的一种重要bean:Message Drive Bean(mdb)

如果要不断监听一个队列中的消息,通常我们需要写一个监听程序,这需要一定的开发量,而且如果要实现高并发处理,也不易扩展,而MDB则自动实现了该功能,简单点讲,MDB的应用部署到jboss后,能自动监听目标队列,一旦有消息接收,会触发onMessage事件,开发人员可以在该事件处理中扩展自己的业务逻辑.

 

一、定义一个MDB

 1 package mdb;
 2
 3
 4
 5 import javax.ejb.ActivationConfigProperty;
 6 import javax.ejb.MessageDriven;
 7 import javax.jms.JMSException;
 8 import javax.jms.Message;
 9 import javax.jms.MessageListener;
10 import javax.jms.TextMessage;
11
12 import util.LoggerUtil;
13
14 @MessageDriven(name = "HelloWorldQueueMDB", activationConfig = {
15         @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue"),
16         @ActivationConfigProperty(propertyName = "destination", propertyValue = "jms/queue/mytest"),
17         @ActivationConfigProperty(propertyName = "acknowledgeMode", propertyValue = "Auto-acknowledge") })
18 public class HelloWorldMDB implements MessageListener {
19
20     @Override
21     public void onMessage(Message msg) {
22         TextMessage txtMsg = null;
23         try {
24             if (msg instanceof TextMessage) {
25                 txtMsg = (TextMessage) msg;
26                 String msgContent = txtMsg.getText();
27                 LoggerUtil.info("Received Message from queue: " + msgContent);
28             } else {
29                 LoggerUtil.warning("Message of wrong type: "
30                         + txtMsg.getClass().getName());
31             }
32         } catch (JMSException e) {
33             throw new RuntimeException(e);
34         }
35
36     }
37
38 }

HelloWorldMDB

注意该类上的注解,它表明了要监听哪个Queue(可以参考上一篇的内容,先在jboss中建好该queue),其它没什么特别的,把它放一个dynamic web中,打成war包部署到jboss上,为演示效果,部署后,先不启动该应用

附:pom.xml文件的内容

 1 <?xml version="1.0" encoding="UTF-8"?>
 2
 3 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 4     xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
 5     <modelVersion>4.0.0</modelVersion>
 6
 7     <groupId>cnblogs</groupId>
 8     <artifactId>helloworld-mdb</artifactId>
 9     <version>0.0.1-SNAPSHOT</version>
10     <packaging>war</packaging>
11     <name>helloworld-mdb</name>
12
13     <dependencyManagement>
14         <dependencies>
15             <dependency>
16                 <groupId>org.jboss.bom</groupId>
17                 <artifactId>jboss-javaee-6.0-with-tools</artifactId>
18                 <version>1.0.7.Final</version>
19                 <type>pom</type>
20                 <scope>import</scope>
21             </dependency>
22         </dependencies>
23     </dependencyManagement>
24
25     <dependencies>
26         <dependency>
27             <groupId>org.jboss.spec.javax.jms</groupId>
28             <artifactId>jboss-jms-api_1.1_spec</artifactId>
29             <scope>provided</scope>
30         </dependency>
31         <dependency>
32             <groupId>org.jboss.spec.javax.ejb</groupId>
33             <artifactId>jboss-ejb-api_3.1_spec</artifactId>
34             <scope>provided</scope>
35         </dependency>
36     </dependencies>
37
38 </project>

pom.xml

 

二、测试验证

a) 可以参考上一篇JMS的内容,另建一个常规的project,向该队列发送消息(注意:仅发送,不要接收,否则消息被收走了,MDB就收不到消息了)

 1 package jms;
 2
 3
 4 import java.util.Hashtable;
 5
 6 import javax.jms.Connection;
 7 import javax.jms.ConnectionFactory;
 8 import javax.jms.Destination;
 9 import javax.jms.JMSException;
10 import javax.jms.MessageConsumer;
11 import javax.jms.MessageProducer;
12 import javax.jms.Session;
13 import javax.jms.TextMessage;
14 import javax.naming.Context;
15 import javax.naming.InitialContext;
16 import javax.naming.NamingException;
17
18 public class App {
19
20     public static void main(String[] args) throws NamingException, JMSException {
21
22         final String lOOKUP_CONNECTION_FACTORY_NAME = "lookup.connectionfactory.name";
23         final String lOOKUP_DESTINATION_NAME = "lookup.destination.name";
24
25         ConnectionFactory connectionFactory = null;
26         Connection connection = null;
27         Session session = null;
28         MessageProducer producer = null;
29         MessageConsumer consumer = null;
30         Destination destination = null;
31         TextMessage message = null;
32         Context context = null;
33
34         try {
35             // 创建上下文(默认会从应用的classpath下加载jndi.properties做为环境参数)
36             context = new InitialContext();
37
38             // 把环境参数取出来,后面会用到
39             Hashtable<String, String> env = (Hashtable<String, String>) context
40                     .getEnvironment();
41
42             // 查找连接工厂
43             connectionFactory = (ConnectionFactory) context.lookup(env
44                     .get(lOOKUP_CONNECTION_FACTORY_NAME));
45
46             // 查找目标队列
47             destination = (Destination) context.lookup(env
48                     .get(lOOKUP_DESTINATION_NAME));
49
50             // 创建连接
51             connection = connectionFactory.createConnection(
52                     env.get(Context.SECURITY_PRINCIPAL),
53                     env.get(Context.SECURITY_CREDENTIALS));
54
55             // 创建会话
56             session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
57
58             // 创建生产者(即发送者)
59             producer = session.createProducer(destination);
60
61             // 创建消费者(即接收者)
62             consumer = session.createConsumer(destination);
63
64             // 开始连接
65             connection.start();
66
67             // 发送消息
68
69             message = session.createTextMessage("HELLO,I AM GLAD TO SEE YOU!");
70
71             producer.send(message);
72
73             System.out.println("发送成功!");
74
75
76
77         } catch (NamingException e) {
78             e.printStackTrace();
79         } catch (JMSException e) {
80             e.printStackTrace();
81         } finally {
82             // 释放资源
83             if (context != null) {
84                 context.close();
85             }
86
87             if (connection != null) {
88                 connection.close();
89             }
90
91         }
92     }
93
94 }

Send Message

b) 然后在jboss中,再把该应用启用起来,观察console窗口的输出:

 

三、xml方式配置MDB

刚才我们是用注解方式来配置MDB的,这种方式不需要xml配置文件,十分方便,但是也有缺点,配置与代码紧耦合,如果以后要修改queue名称,就得改代码,重新编译,所以jboss也提供了xml配置方式

方法:在META-INF(非web项目)或WEB-INF(web项目)放置一个名为jboss-ejb3.xml(这是固定名称,不要修改!)

内容参考下面这样:

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <jboss:ejb-jar xmlns:jboss="http://www.jboss.com/xml/ns/javaee"
 3     xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 4     xmlns:c="urn:clustering:1.0"
 5     xsi:schemaLocation="http://www.jboss.com/xml/ns/javaee http://www.jboss.org/j2ee/schema/jboss-ejb3-2_0.xsd http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/ejb-jar_3_1.xsd"
 6     version="3.1" impl-version="2.0">
 7     <enterprise-beans>
 8         <message-driven>
 9             <ejb-name>HelloWorldQueueMDB</ejb-name>
10             <ejb-class>mdb.HelloWorldMDB</ejb-class>
11             <activation-config>
12                 <activation-config-property>
13                     <activation-config-property-name>destinationType</activation-config-property-name>
14                     <activation-config-property-value>javax.jms.Queue</activation-config-property-value>
15                 </activation-config-property>
16                 <activation-config-property>
17                     <activation-config-property-name>destination</activation-config-property-name>
18                     <activation-config-property-value>jms/queue/mytest</activation-config-property-value>
19                 </activation-config-property>
20                 <activation-config-property>
21                     <activation-config-property-name>acknowledgeMode</activation-config-property-name>
22                     <activation-config-property-value>Auto-acknowledge</activation-config-property-value>
23                 </activation-config-property>
24             </activation-config>
25         </message-driven>
26     </enterprise-beans>
27     <assembly-descriptor>
28         <c:clustering>
29             <ejb-name>DDBasedClusteredSFSB</ejb-name>
30             <c:clustered>true</c:clustered>
31         </c:clustering>
32     </assembly-descriptor>
33 </jboss:ejb-jar>

jboss-ejb3.xml

然后把HelloWorldQueueMDB类上的那一堆注解全注释掉,再跑下,顺利的话,也同样可以接收消息

示例源代码下载:mdb-sample.zip

时间: 2024-09-14 11:18:31

ejb3: message drive bean(MDB)示例的相关文章

jboss EAP 6.2 + Message Drive Bean(MDB) 整合IBM Webshpere MQ 7.5

上一篇我们知道了消息驱动Bean的基本用法,实际大型分布式企业应用中,往往会采用高性能的商业Queue产品,比如IBM Webshpere MQ(目前最新版本是7.5 ),下面讲解下如何在Jboss EAP 6.2 版本上整合Webshpere MQ 7.5   一.修改jboss的standalone-full.xml a) 添加IBM的resource-adapters 找到<subsystem xmlns="urn:jboss:domain:resource-adapters:1.1

Jboss Ejb3.0 Statefull Bean

这个例子结合了j2se5.0的generis新特性,可以先看下我写的J2se5.0 generis新特性   ShoppingCart.java package org.jboss.tutorial.stateful.bean; import javax.ejb.Remote; import javax.ejb.Remove; import java.util.HashMap; @Remote public interface ShoppingCart {    void buy(String

Jboss Ejb3.0 Entity Bean

   Order.java package org.jboss.tutorial.entity.bean;   import javax.persistence.CascadeType; import javax.persistence.Entity; import javax.persistence.FetchType; import javax.persistence.GeneratorType; import javax.persistence.Id; import javax.persi

spring动态bean注册示例分享_JSP编程

1.在一些特殊的场景中需要动态向spring注册bean2.spring版本2.5.6 复制代码 代码如下: public class ServiceServiceImpl implements ServiceService, ApplicationContextAware {  @Override public void setApplicationContext(org.springframework.context.ApplicationContext applicationContext

EJB(Enterprise Java Bean)概述

一,什么情况下需要企业Bean            企业Bean运行在EJB容器中.企业Bean实际上就是一个封装了业务逻辑的Java类.            需要使用EJB的N个理由:               1,分布式!分布式对象之间的相互协作,完成特定的业务功能.分布式对象之间应实现分布透明性(或位置透明性).即在客户端代码中无需指定分布式对象的位置(通过配置来解决).               2,分布式对象之间的事务支持(RMI不支持事务).               3,

一步一步学EJB3.0(四):实体Bean开发

EJB3.0实体Bean开发是是很简单的,主要就是学习标注的使用, 现在EJB3实体Bean是纯粹的POJO.实际 上这表达了和Hibernate持久化实体对象同样的概念.它们的映射都通过JDK5.0注解来定义(EJB3规范已经 定义了对应的XML描述语法).注解分为两个部分,分别是逻辑映射注解和物理映射注解,通过逻辑映射注解 可以描述对象模型,类之间的关系等等,而物理映射注解则描述了物理的schema,表,列,索引等等. 这些标注都封装在javax.persistence包下,如果是使用Hib

Weblogic10 + EJB3入门教程(1):编写第一个无状态会话Bean(Stateless Session Bean)

本文为原创,如需转载,请注明作者和出处,谢谢!     在本文主要介绍如何来开发一个Stateless Session Bean,并在未安装WebLogic10的机器上访问Session Bean.开发EJB3 Stateless Session Bean要比开发EJB2 Stateless Session Bean容易得多,只需要几个注释就可以搞定.读者可按如下的步骤来开发和调用EJB3 Stateless Session Bean: 第1步:编写远程接口     每一个Session Bea

eclipse + JBoss 5 + EJB3开发指南(10):通过继承实体Bean,将单个表映射成多个表(单表策略,SINGLE_TABLE)

本文为原创,如需转载,请注明作者和出处,谢谢! 上一篇:eclipse + JBoss 5 + EJB3开发指南(9):实现Entity Bean的多对多(many-to-many)映射     如果以前使用过EJB1.x或EJB2.x的实体Bean,会发现无法通过继承实体Bean将单个表分成多表.而在EJB3中,我们很容易实现这个功能.先看看图1所示的表结构和记录. 图1   t_accounts表的结构和记录 在t_accounts表中,有一个account_type字段.这个字段是一个长度

EJB3.0入门经典

1.什么是EJB?Enterprise JavaBeans(EJB)定义了3种企业Bean:会话Bean(Session Bean).实体Bean(Entity Bean)和消息驱动Bean(Message Driven Bean) 2.支持EJB的容器有哪些?Jboss(4.2x以上版本).Glassfish.WebLogic(10以上版本).Sun Application Server(9.0以上版本).Oracle Application Server(10g以上版本)和我们国内的Apus