EJB 2.0 消息 驱动 bean
在使用 J2EE 1.3 和 EJB 2.0 时,消息驱动 bean(MDB)只能起到相当有限的作用。它们让应用程序异步地接收传递 JMS 目标的消息。而 MDB 需要实现 javax.jms.MessageListener,如清单 1 所示:
清单 1. javax.jms.MessageListener 接口
1
public
interface
MessageListener {
2
void
onMessage(Message message);
3
}
MDB 还需要实现 MessageDrivenBean 接口。结果,典型的类看起来可能类似清单 2 中的 ExampleMdb :
清单 2. 示例 EJB 2.0 MDB
1
public
class
ExampleMdb
implements
MessageDrivenBean, MessageListener {
2
public
void
ejbCreate()
throws
CreateException { ... }
3
public
void
ejbRemove() { ... }
4
public
void
setMessageDrivenContext(MessageDrivenContext ctx) { ... }
5
public
void
onMessage(Message message) {
6
if
(msg
instanceof
TextMessage) {
7
String text
=
((TextMessage) message).getText();
8
InitialContext context
=
new
InitialContext();
9
ExampleHome home
=
(ExampleHome)context.lookup(
"
java:comp/env/ejb/Example
"
);
10
Example bean
=
home.create();
11
bean.operation(text);
12
}
13
}
14
}
如果像清单 2 那样遵照 EJB 2.0 规范的建议,那么 onMessage 方法负责对消息的内容进行解包,然后调用其他 EJB 执行实际的业务逻辑。
但是别误会 —— EJB 2.0 MDB 当然有它们的好处。对于初学者来说,因为 MDB 不是由客户机调用的,所以不需要编写 home、remote 或 local 接口。而且 —— 最主要的一个好处就是,多个实例可以并行操作。在没有 MDB 时,应用程序可能已经确定了一个异步接收消息的目标,但是由于没有将工作复制到另外一个线程中的能力,所以应用程序须先处理第一个消息才能处理下一个消息。
就像其他 EJB 那样,MDB 能够使用 bean 托管事务或者容器托管事务。后者对 MDB 有一些扭曲。首先,只允许使用两个事务属性:Required 和 NotSupported。这是完全合理的。因为没有客户机调用 MDB,没有需要继承的事务,所以要做的就是能够指出 bean 是否应当在事务中运行。第二,也是更重要的,如果指定了事务属性 Required,那么传递到 MDB 的消息就作为消息的一部分接收。如果有什么事情出错,事务将回滚,那么消息将被重新放在目标上,再次进行处理。
正如在清单 3 中可以看到的,MDB 只用于 JMS 的这个事实也反映在部署描述符中:
清单 3. EJB 2.0 部署描述符
1
<
ejb-jar
>
2
<
enterprise-beans
>
3
<
message-driven
>
4
<
ejb-name
>
Example MDB
</
ejb-name
>
5
<
ejb-class
>
example.ExampleMDB
</
ejb-class
>
6
<
transaction-type
>
Bean
</
transaction-type
>
7
<
acknowledge-mode
>
Auto-acknowledge
</
acknowledge-mode
>
8
<
message-driven-destination
>
9
<
destination-type
>
javax.jms.Topic
</
destination-type
>
10
<
subscription-durability
>
Durable
</
subscription-durability
>
11
</
message-driven-destination
>
12
<
message-selector
>
13
JMSType = 'car' AND color = 'red'
14
</
message-selector
>
15
</
message-driven
>
16
</
enterprise-beans
>
17
</
ejb-jar
>
18
在清单 3 中可以看到,部署描述符中的一些元素对应着 JMS 概念中的应答模式、订阅、持久性和消息选择器。另外一个元素给出了消息目标的类型,它必须是 javax.jms.Queue 或者是 javax.jms.Topic。