ejb3: message drive bean(MDB)示例

简介: 上一篇已经知道了JMS的基本操作,今天来看一下ejb3中的一种重要bean:Message Drive Bean(mdb) 如果要不断监听一个队列中的消息,通常我们需要写一个监听程序,这需要一定的开发量,而且如果要实现高并发处理,也不易扩展,而MDB则自动实现了该功能,简单点讲,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

目录
相关文章
|
6月前
r2dbc的repository注入失败
r2dbc的repository注入失败
69 0
|
XML Java 程序员
Spring启动报错--class path resource [Beans.xml] cannot be opened because it does not exist
程序员不是在去生产bug的路上,那就是在去解决bug的路上。🤣🤣🤣🤣
240 1
|
消息中间件 Java RocketMQ
【Java】Error creating bean with name ‘functionBindingRegistrar‘ defined in class path resource的一种解决方式
【Java】Error creating bean with name ‘functionBindingRegistrar‘ defined in class path resource的一种解决方式
139 0
|
Java Spring
使用feign调用的时候出现Could not autowire. No beans of ‘Api2UserFegin‘ type found报错
使用feign调用的时候出现Could not autowire. No beans of ‘Api2UserFegin‘ type found报错
312 0
|
XML SQL Java
Mybatis报错:There is no getter for property named ‘xxxx‘ in ‘class xxxx
Mybatis报错:There is no getter for property named ‘xxxx‘ in ‘class xxxx
245 0
|
Java Spring
Field roomService in edu.hpu.controller.GuestController required a bean of type 'edu.hpu.service.Roo
Field roomService in edu.hpu.controller.GuestController required a bean of type 'edu.hpu.service.Roo
125 0
|
数据库 容器
Entity Framework Core(3)-配置DbContext
设计时 DbContext 配置 EF Core 设计时工具如迁移需要能够发现和创建的工作实例DbContext以收集有关应用程序的实体类型以及它们如何映射到数据库架构的详细信息的类型。 此过程可以为自动,只要该工具可以轻松地创建DbContext,会将其配置同样到它如何将配置在运行时的方式。
962 0
|
Java Spring
class path resource [spring/applicationContext.xml] cannot be opened because it does not exist
1.查看路径有没有写错    2.编辑器认为你的文件不是 source folders(原文件),需要你手动将文件改过来
4346 0
|
Java 数据库连接
hibernate提示Unknown entity: :xxx
错误提示: org.hibernate.MappingException: Unknown entity: org.dao.po.Role at org.hibernate.internal.SessionFactoryImpl.
2209 0