Part 2 of these series articles describe how to coding on MDB with EJB3.
MDB is the MVP(most valuable player) both in previous EJB version
and EJB3. Although coding with MDB is simple in EJB2.x, EJB3 make it
much more friendly to you. Let's get to the point.
Following is what you should know before write the first MDB in EJB3:
- MDB is just a POJO which must implement javax.jms.MessageListener directly or indirectly.
- MDB can not extends from another MDB. This should be fine, because each MDB should has its own destination or queue.
- Do not throw runtime exception which will cause the instance of this MDB to be destroyed.
- One no argument construct method like session bean does.
1 package com.ramon.expejb3.session.impl;
2
3 import javax.annotation.PostConstruct;
4 import javax.annotation.PreDestroy;
5 import javax.annotation.Resource;
6 import javax.ejb.ActivationConfigProperty;
7 import javax.ejb.MessageDriven;
8 import javax.jms.JMSException;
9 import javax.jms.Message;
10 import javax.jms.MessageListener;
11 import javax.jms.Queue;
12 import javax.jms.QueueConnection;
13 import javax.jms.QueueConnectionFactory;
14 import javax.jms.QueueSender;
15 import javax.jms.QueueSession;
16 import javax.jms.Session;
17 import javax.jms.TextMessage;
18
19 @MessageDriven(
20 name = "greetingSender",
21 activationConfig = {
22 @ActivationConfigProperty(propertyName="destinationType", propertyValue="javax.jms.Queue"),
23 @ActivationConfigProperty(propertyName="destination", propertyValue="queue/ramonQueue")
24 }
25 )
26 public class GreetingSenderMDB implements MessageListener {
27
28 @Resource(mappedName="java:/XAConnectionFactory")
29 private QueueConnectionFactory qconFactory;
30
31 @Resource(mappedName="queue/ramonRecoderQueue")
32 private Queue queue;
33
34 private QueueConnection qcon;
35
36 private QueueSession qsession;
37
38 private QueueSender qsender;
39
40 private TextMessage msg;
41
42 @PostConstruct
43 public void init() {
44 try {
45 qcon = qconFactory.createQueueConnection();
46 qsession = qcon.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
47 qsender = qsession.createSender(queue);
48 msg = qsession.createTextMessage();
49 qcon.start();
50 System.out.println(this.getClass() + " init done.");
51 } catch (JMSException e) {
52 // TODO Auto-generated catch block
53 e.printStackTrace();
54 }
55 }
56
57 private void send(String message) throws JMSException {
58 msg.setText(message);
59 qsender.send(msg);
60 }
61
62 public void onMessage(Message arg0) {
63 TextMessage txt = (TextMessage)arg0;
64 try {
65 System.out.println("Message '" + txt.getText() + "' has been received.");
66 send(txt.getText());
67 System.out.println(">>> Record msg for '" + txt.getText() + "' has been sent out.");
68 } catch (JMSException e) {
69 // TODO Auto-generated catch block
70 e.printStackTrace();
71 }
72 }
73
74 @PreDestroy
75 public void gc() {
76 try {
77 qcon.close();
78 System.out.println("GC for " + this.getClass() + ".");
79 } catch (JMSException e) {
80 // TODO Auto-generated catch block
81 e.printStackTrace();
82 }
83 }
84
85 }
86
2
3 import javax.annotation.PostConstruct;
4 import javax.annotation.PreDestroy;
5 import javax.annotation.Resource;
6 import javax.ejb.ActivationConfigProperty;
7 import javax.ejb.MessageDriven;
8 import javax.jms.JMSException;
9 import javax.jms.Message;
10 import javax.jms.MessageListener;
11 import javax.jms.Queue;
12 import javax.jms.QueueConnection;
13 import javax.jms.QueueConnectionFactory;
14 import javax.jms.QueueSender;
15 import javax.jms.QueueSession;
16 import javax.jms.Session;
17 import javax.jms.TextMessage;
18
19 @MessageDriven(
20 name = "greetingSender",
21 activationConfig = {
22 @ActivationConfigProperty(propertyName="destinationType", propertyValue="javax.jms.Queue"),
23 @ActivationConfigProperty(propertyName="destination", propertyValue="queue/ramonQueue")
24 }
25 )
26 public class GreetingSenderMDB implements MessageListener {
27
28 @Resource(mappedName="java:/XAConnectionFactory")
29 private QueueConnectionFactory qconFactory;
30
31 @Resource(mappedName="queue/ramonRecoderQueue")
32 private Queue queue;
33
34 private QueueConnection qcon;
35
36 private QueueSession qsession;
37
38 private QueueSender qsender;
39
40 private TextMessage msg;
41
42 @PostConstruct
43 public void init() {
44 try {
45 qcon = qconFactory.createQueueConnection();
46 qsession = qcon.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
47 qsender = qsession.createSender(queue);
48 msg = qsession.createTextMessage();
49 qcon.start();
50 System.out.println(this.getClass() + " init done.");
51 } catch (JMSException e) {
52 // TODO Auto-generated catch block
53 e.printStackTrace();
54 }
55 }
56
57 private void send(String message) throws JMSException {
58 msg.setText(message);
59 qsender.send(msg);
60 }
61
62 public void onMessage(Message arg0) {
63 TextMessage txt = (TextMessage)arg0;
64 try {
65 System.out.println("Message '" + txt.getText() + "' has been received.");
66 send(txt.getText());
67 System.out.println(">>> Record msg for '" + txt.getText() + "' has been sent out.");
68 } catch (JMSException e) {
69 // TODO Auto-generated catch block
70 e.printStackTrace();
71 }
72 }
73
74 @PreDestroy
75 public void gc() {
76 try {
77 qcon.close();
78 System.out.println("GC for " + this.getClass() + ".");
79 } catch (JMSException e) {
80 // TODO Auto-generated catch block
81 e.printStackTrace();
82 }
83 }
84
85 }
86
This is a smiple example, we use @MessageDriven to make this POJO a EJB3 MDB, the "destinationType" attribute make this MDB register itself to a JMS queue not a topic, the "destination" attribute tell the MDB where to listen for the queue, it's a jndi name of the queue you specified in your container. Other part of this code is also self-explanation, you should just focus on how to implement the MessageListener interface -- the onMessage() method.
For our example, the logic in onMessage() is simple, described as follow:
1. Receive message from client invocation.
2. Create a new message according to received message and then send it out to another JMS queue.
Let's see the source code:
1 public void onMessage(Message arg0) {
2 TextMessage txt = (TextMessage)arg0;
3 try {
4 System.out.println("Message '" + txt.getText() + "' has been received.");
5 send(txt.getText());
6 System.out.println(">>> Record msg for '" + txt.getText() + "' has been sent out.");
7 } catch (JMSException e) {
8 // TODO Auto-generated catch block
9 e.printStackTrace();
10 }
11 }
Yup, it's simple, just like the ordinary JMS listener
implementation. Let's see how does the send() method in the line 5 get
the ConnectionFactory and Queue object and then send message to another
queue. EJB3 give us an anotation named "Resource", with this anotation
container can inject resource such as DataSourceConnectionFactory,
JMSConnectionFactory... into our bean instance, we use this anotation
to inject JMSConnectionFactory and JMSQueue, see the code snatch:2 TextMessage txt = (TextMessage)arg0;
3 try {
4 System.out.println("Message '" + txt.getText() + "' has been received.");
5 send(txt.getText());
6 System.out.println(">>> Record msg for '" + txt.getText() + "' has been sent out.");
7 } catch (JMSException e) {
8 // TODO Auto-generated catch block
9 e.printStackTrace();
10 }
11 }
1 @Resource(mappedName="java:/XAConnectionFactory")
2 private QueueConnectionFactory qconFactory;
3
4 @Resource(mappedName="queue/ramonRecoderQueue")
5 private Queue queue;
2 private QueueConnectionFactory qconFactory;
3
4 @Resource(mappedName="queue/ramonRecoderQueue")
5 private Queue queue;
With this anotation we can remove the boring JNDI lookup code, that's really great, because I always copy and paste for JNDI lookup code:) What important is that you should use the "mappedName" attribute instead of the "name" attribute when you want to lookup some JNDI, because the "name" attribute always triger an "env" prefix before the actual JNDI name you specified.
Other part of this code is simple, so I just paste the code here, GreetingRecordMDB.java:
1 package com.ramon.expejb3.session.impl;
2
3 import javax.ejb.ActivationConfigProperty;
4 import javax.ejb.MessageDriven;
5 import javax.jms.JMSException;
6 import javax.jms.Message;
7 import javax.jms.MessageListener;
8 import javax.jms.TextMessage;
9
10 @MessageDriven(
11 name = "greetingRecoder",
12 activationConfig = {
13 @ActivationConfigProperty(propertyName="destinationType", propertyValue="javax.jms.Queue"),
14 @ActivationConfigProperty(propertyName="destination", propertyValue="queue/ramonRecoderQueue")
15 }
16 )
17 public class GreetingRecordMDB implements MessageListener {
18
19 public void onMessage(Message arg0) {
20 TextMessage msg = (TextMessage)arg0;
21 try {
22 String name = msg.getText();
23 System.out.println(name + "has been recorded.");
24 } catch (JMSException e) {
25 // TODO Auto-generated catch block
26 e.printStackTrace();
27 }
28 }
29
30 }
31
The client side code GreetingSenderMDBTest.java:2
3 import javax.ejb.ActivationConfigProperty;
4 import javax.ejb.MessageDriven;
5 import javax.jms.JMSException;
6 import javax.jms.Message;
7 import javax.jms.MessageListener;
8 import javax.jms.TextMessage;
9
10 @MessageDriven(
11 name = "greetingRecoder",
12 activationConfig = {
13 @ActivationConfigProperty(propertyName="destinationType", propertyValue="javax.jms.Queue"),
14 @ActivationConfigProperty(propertyName="destination", propertyValue="queue/ramonRecoderQueue")
15 }
16 )
17 public class GreetingRecordMDB implements MessageListener {
18
19 public void onMessage(Message arg0) {
20 TextMessage msg = (TextMessage)arg0;
21 try {
22 String name = msg.getText();
23 System.out.println(name + "has been recorded.");
24 } catch (JMSException e) {
25 // TODO Auto-generated catch block
26 e.printStackTrace();
27 }
28 }
29
30 }
31
1 package com.ramon.expejb3.session.impl;
2
3 import javax.jms.JMSException;
4 import javax.jms.Queue;
5 import javax.jms.QueueConnection;
6 import javax.jms.QueueConnectionFactory;
7 import javax.jms.QueueSender;
8 import javax.jms.QueueSession;
9 import javax.jms.Session;
10 import javax.jms.TextMessage;
11 import javax.naming.Context;
12
13 import com.ramon.expejb3.session.ExpEJB3BaseTestCase;
14
15 public class GreetingSenderMDBTest extends ExpEJB3BaseTestCase {
16
17 private QueueConnectionFactory qconFactory;
18 private QueueConnection qcon;
19 private QueueSession qsession;
20 private QueueSender qsender;
21 private Queue queue;
22 private TextMessage msg;
23
24 @Override
25 protected void setUp() throws Exception {
26 // TODO Auto-generated method stub
27 super.setUp();
28 Context ctx = this.getContext();
29 qconFactory = (QueueConnectionFactory) ctx
30 .lookup("java:/XAConnectionFactory");
31 qcon = qconFactory.createQueueConnection();
32 qsession = qcon.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
33 queue = (Queue) ctx.lookup("queue/ramonQueue");
34 qsender = qsession.createSender(queue);
35 msg = qsession.createTextMessage();
36 qcon.start();
37 }
38
39 public void send(String message) throws JMSException {
40 msg.setText(message);
41 qsender.send(msg);
42 }
43
44 public void close() throws JMSException {
45 qcon.close();
46 }
47
48 @Override
49 protected void tearDown() throws Exception {
50 // TODO Auto-generated method stub
51 super.tearDown();
52 }
53
54 public void testOnMessage() {
55 try {
56 for (int i = 0; i < 5; i++) {
57 String msg = "Ramon " + i;
58 send(msg);
59 System.out.println("send msg: " + msg);
60 }
61 send("end");
62 } catch (JMSException e) {
63 // TODO Auto-generated catch block
64 e.printStackTrace();
65 } finally {
66 try {
67 close();
68 } catch (JMSException e) {
69 // TODO Auto-generated catch block
70 e.printStackTrace();
71 }
72 }
73 }
74
75 }
76
2
3 import javax.jms.JMSException;
4 import javax.jms.Queue;
5 import javax.jms.QueueConnection;
6 import javax.jms.QueueConnectionFactory;
7 import javax.jms.QueueSender;
8 import javax.jms.QueueSession;
9 import javax.jms.Session;
10 import javax.jms.TextMessage;
11 import javax.naming.Context;
12
13 import com.ramon.expejb3.session.ExpEJB3BaseTestCase;
14
15 public class GreetingSenderMDBTest extends ExpEJB3BaseTestCase {
16
17 private QueueConnectionFactory qconFactory;
18 private QueueConnection qcon;
19 private QueueSession qsession;
20 private QueueSender qsender;
21 private Queue queue;
22 private TextMessage msg;
23
24 @Override
25 protected void setUp() throws Exception {
26 // TODO Auto-generated method stub
27 super.setUp();
28 Context ctx = this.getContext();
29 qconFactory = (QueueConnectionFactory) ctx
30 .lookup("java:/XAConnectionFactory");
31 qcon = qconFactory.createQueueConnection();
32 qsession = qcon.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
33 queue = (Queue) ctx.lookup("queue/ramonQueue");
34 qsender = qsession.createSender(queue);
35 msg = qsession.createTextMessage();
36 qcon.start();
37 }
38
39 public void send(String message) throws JMSException {
40 msg.setText(message);
41 qsender.send(msg);
42 }
43
44 public void close() throws JMSException {
45 qcon.close();
46 }
47
48 @Override
49 protected void tearDown() throws Exception {
50 // TODO Auto-generated method stub
51 super.tearDown();
52 }
53
54 public void testOnMessage() {
55 try {
56 for (int i = 0; i < 5; i++) {
57 String msg = "Ramon " + i;
58 send(msg);
59 System.out.println("send msg: " + msg);
60 }
61 send("end");
62 } catch (JMSException e) {
63 // TODO Auto-generated catch block
64 e.printStackTrace();
65 } finally {
66 try {
67 close();
68 } catch (JMSException e) {
69 // TODO Auto-generated catch block
70 e.printStackTrace();
71 }
72 }
73 }
74
75 }
76
The JMS configuration snatch in file "jbossmq-destinations-service.xml" of Jboss server:
1 <mbean code="org.jboss.mq.server.jmx.Queue"
2 name="jboss.mq.destination:service=Queue,name=ramonQueue">
3 <depends optional-attribute-name="DestinationManager">jboss.mq:service=DestinationManager</depends>
4 <depends optional-attribute-name="SecurityManager">jboss.mq:service=SecurityManager</depends>
5 <attribute name="MessageCounterHistoryDayLimit">-1</attribute>
6 <attribute name="SecurityConf">
7 <security>
8 <role name="guest" read="true" write="true"/>
9 <role name="publisher" read="true" write="true" create="false"/>
10 <role name="noacc" read="false" write="false" create="false"/>
11 </security>
12 </attribute>
13 </mbean>
14
15 <mbean code="org.jboss.mq.server.jmx.Queue"
16 name="jboss.mq.destination:service=Queue,name=ramonRecoderQueue">
17 <depends optional-attribute-name="DestinationManager">jboss.mq:service=DestinationManager</depends>
18 <depends optional-attribute-name="SecurityManager">jboss.mq:service=SecurityManager</depends>
19 <attribute name="MessageCounterHistoryDayLimit">-1</attribute>
20 <attribute name="SecurityConf">
21 <security>
22 <role name="guest" read="true" write="true"/>
23 <role name="publisher" read="true" write="true" create="false"/>
24 <role name="noacc" read="false" write="false" create="false"/>
25 </security>
26 </attribute>
27 </mbean>
2 name="jboss.mq.destination:service=Queue,name=ramonQueue">
3 <depends optional-attribute-name="DestinationManager">jboss.mq:service=DestinationManager</depends>
4 <depends optional-attribute-name="SecurityManager">jboss.mq:service=SecurityManager</depends>
5 <attribute name="MessageCounterHistoryDayLimit">-1</attribute>
6 <attribute name="SecurityConf">
7 <security>
8 <role name="guest" read="true" write="true"/>
9 <role name="publisher" read="true" write="true" create="false"/>
10 <role name="noacc" read="false" write="false" create="false"/>
11 </security>
12 </attribute>
13 </mbean>
14
15 <mbean code="org.jboss.mq.server.jmx.Queue"
16 name="jboss.mq.destination:service=Queue,name=ramonRecoderQueue">
17 <depends optional-attribute-name="DestinationManager">jboss.mq:service=DestinationManager</depends>
18 <depends optional-attribute-name="SecurityManager">jboss.mq:service=SecurityManager</depends>
19 <attribute name="MessageCounterHistoryDayLimit">-1</attribute>
20 <attribute name="SecurityConf">
21 <security>
22 <role name="guest" read="true" write="true"/>
23 <role name="publisher" read="true" write="true" create="false"/>
24 <role name="noacc" read="false" write="false" create="false"/>
25 </security>
26 </attribute>
27 </mbean>
相关推荐
在本文中,我们将深入探讨如何使用Eclipse IDE与JBoss应用程序服务器(版本7.x)来开发和部署一个基于EJB 3.x的简单企业级Java应用程序。EJB(Enterprise JavaBeans)是Java平台上的核心组件,它提供了一种标准的...
在JBoss 7及以上版本中,对EJB的配置过程相较于之前的版本有所变化,主要涉及到两个关键的配置文件:`jboss-ejb3.xml`和`ejb-jar.xml`。 `ejb-jar.xml`文件是EJB模块的标准配置文件,遵循Java EE规范。在这个文件中...
罗时飞精通EJB3.0.part01.rar罗时飞精通EJB3.0.part01.rar罗时飞精通EJB3.0.part01.rar罗时飞精通EJB3.0.part01.rar
中文版EXPERT-ONE-ON-ONE-J2EE-DEVELOPMENT-WITHOUT-EJB.part2.rar
中文版EXPERT-ONE-ON-ONE-J2EE-DEVELOPMENT-WITHOUT-EJB.part3.rar
javax.ejb.DependsOn.class javax.ejb.DuplicateKeyException.class javax.ejb.EJB.class javax.ejb.EJBAccessException.class javax.ejb.EJBContext.class javax.ejb.EJBException.class javax.ejb.EJBHome.class ...
标题中的“J2EE Jboss Ejb With Eclipse 2003.rar”表明这是一个关于使用Eclipse集成开发环境(IDE)在JBoss应用服务器上开发Java Enterprise Edition (J2EE) 的Enterprise JavaBeans (EJB) 的教程或资料包。...
javax.ejb.AccessLocalException.class javax.ejb.CreateException.class javax.ejb.DuplicateKeyException.class javax.ejb.EJBContext.class javax.ejb.EJBException.class javax.ejb.EJBHome.class javax.ejb....
ejb3 and jboss 多本合一(three) Using @Service annotation in eclipse JBoss中文文档.pdf JBOSS使用指南.doc JBOSS架构分析.doc JBOSS对EJB3_0的扩展 jbossgs4x.pdf JBoss-EJB3.0实例教程.pdf JBoss.in.Action....
美河制作.中文版EXPERT.ONE.ON.ONE.J2EE.DEVELOPMENT.WITHOUT.EJB.part01.rar美河制作.中文版EXPERT.ONE.ON.ONE.J2EE.DEVELOPMENT.WITHOUT.EJB.part01.rar
经典JAVA EE企业应用实战 基于WEBLOGIC JBOSS的JSF+EJB 3+JPA整合开发.part2
H:\q\罗时飞精通EJB3.0.part08.rarH:\q\罗时飞精通EJB3.0.part08.rarH:\q\罗时飞精通EJB3.0.part08.rar
javax.ejb.DependsOn.class javax.ejb.DuplicateKeyException.class javax.ejb.EJB.class javax.ejb.EJBAccessException.class javax.ejb.EJBContext.class javax.ejb.EJBException.class javax.ejb.EJBHome.class ...
H:\q\罗时飞精通EJB3.0.part09.rarH:\q\罗时飞精通EJB3.0.part09.rar
jboss-ejb3-client.jar
H:\q\罗时飞精通EJB3.0.part02.rarH:\q\罗时飞精通EJB3.0.part02.rar
H:\q\罗时飞精通EJB3.0.part06.rarH:\q\罗时飞精通EJB3.0.part06.rarH:\q\罗时飞精通EJB3.0.part06.rar
H:\q\罗时飞精通EJB3.0.part07.rarH:\q\罗时飞精通EJB3.0.part07.rarH:\q\罗时飞精通EJB3.0.part07.rar
H:\q\罗时飞精通EJB3.0.part05.rarH:\q\罗时飞精通EJB3.0.part05.rar
2. **EJB 3.0**:JBoss 4.0.5.GA实现了EJB 3.0规范,简化了Enterprise JavaBeans的开发,通过注解(Annotation)可以轻松地声明bean的属性,无需XML配置文件,提高了开发效率。 3. **JPA**:这一版本引入了JPA作为...