我使用JBoss 5.1的Java EE 5项目和这样的问题。我必须使用由消息内容产生的字符串对MDB中的某些EJB执行某种运行时查找。它只是MDB中使用的一种服务定位器模式。现在,由于MDB在部署之后开始消耗,我有很多NameNotFoundException
,因为隐式部署顺序在这里不能很好地运行(运行时查找)。你怎么看待这件事?是否有可能使用EJB 3.0做得很好?如果能解决问题,我也可以使用任何供应商特定的东西(JBoss 5.1)。
一些可视化情况的代码段:
@MessageDriven(mappedName="jms/Queue")
public class MessageBean implements MessageListener {
@Resource
private MessageDrivenContext mdc;
public void onMessage(Message msg) {
final String beanName = // extract somehow the bean's name from 'msg'
final Context ctx = new InitialContext();
final Object obj = ctx.lookup(beanName); // NameNotFoundException
// do something with 'obj'
}
}
答案 0 :(得分:4)
使用这四种不同方法中的一种。
使用“@EJB”注释声明EJB依赖项( EJB引用)(不要使用JNDI查找)。对于实体bean引用,必须引用实体bean home接口。容器必须确保在处理方法/消息侦听器之前注入所有依赖项:
消息驱动(mappedName = “JMS /队列”)
公共类MessageBean实现MessageListener {
@EJB private EntityBeanHomeA entityBeanHomeA;
@EJB private EntityBeanHomeB entityBeanHomeB;
@EJB private EntityBeanHomeC entityBeanHomeC;
@EJB private SessionBeanD sessionBeanD;
@Resource
private MessageDrivenContext mdc;
public void onMessage(Message msg) {
final String beanName = // extract somehow the bean's name from 'msg'
final Object obj = getDependentEJB(beanName);
// do something with 'obj'
}
private Object getDependentEJB(String beanName) {
Object result = null;
if ("EntityBeanHomeA".equals(beanName)) {
result = entityBeanHomeA;
else if ("EntityBeanHomeB".equals(beanName)) {
result = entityBeanHomeB;
else ("EntityBeanHomeC".equals(beanName)) {
result = entityBeanHomeC;
else ("SessionBeanD".equals(beanName)) {
result = sessionBeanD;
}
return result;
}
}
使用JNDI查找,但通过EJB部署描述符声明EJB依赖项。同样,容器必须确保在处理方法/消息之前确保所有依赖关系都已设置:
@MessageDriven(mappedName = “JMS /队列”) 公共类MessageBean实现MessageListener {
// as given in the original Question...
}
部署描述符:
<enterprise-beans>
<message-driven>
...
<ejb-name>MessageBean</ejb-name>
<ejb-class>com.company.pkg.MessageBean</ejb-class>
<messaging-type>javax.jms.MessageListener</messaging-type>
<message-destination-type>javax.jms.Queue</message-destination-type>
<message-destination-link>ExpenseProcessingQueue</message-destination-link>
<ejb-ref>
<description> This is a reference to an EJB 2.1 entity bean
that encapsulates access to employee records.
</description>
<ejb-ref-name>ejb/EmplRecord</ejb-ref-name>
<ejb-ref-type>Entity</ejb-ref-type>
<home>com.wombat.empl.EmployeeRecordHome</home>
<remote>com.wombat.empl.EmployeeRecord</remote>
<ejb-link>EmployeeRecord</ejb-link> <-- if in same EJB jar -->
<-- ../emp/emp.jar#EmployeeRecord if in diff EJB jar -->
</ejb-ref>
<ejb-local-ref>
<description> This is a reference to the local business interface
of an EJB 3.0 session bean that provides a payroll service.
</description>
<ejb-ref-name>ejb/Payroll</ejb-ref-name>
<local>com.aardvark.payroll.Payroll</local>
<ejb-link>Payroll</ejb-link>
</ejb-local-ref>
<ejb-local-ref>
<description> This is a reference to the local business interface of an
EJB 3.0 session bean that provides a pension plan service.
</description>
<ejb-ref-name>ejb/PensionPlan</ejb-ref-name>
<local>com.wombat.empl.PensionPlan</local>
<ejb-link>PensionPlan</ejb-link> <-- if in same EJB jar -->
</ejb-local-ref>
...
</message-driven>
...
</enterprise-beans>
使用JNDI查找但不使用@EJB注释或EJB部署声明依赖项 - 完全使用您自己的逻辑处理,而不使用容器帮助。使用延迟/错误处理。
使用JBoss专有配置来控制部署顺序:
http://texnoblog.wordpress.com/2010/09/16/depends-in-jboss/
How to order deployment of EJBs and JMS queue config in JBoss 5?
答案 1 :(得分:2)
一种方法是创建一个注入MDB的dummy-ejb,这样你的mdb就不会开始消耗,直到实际发生注入为止。
如果dummy-ejb与您打算进行动态查找的EJB捆绑在一起,那么这应该可行
我的回答here解决了类似的用例。
答案 2 :(得分:1)
我认为最好的方法是延迟MDB的部署,直到所有的EJB都启动并且运行。 这基本上是上面答案中的第4号方法。
“使用JBoss专有配置来控制部署顺序:
http://texnoblog.wordpress.com/2010/09/16/depends-in-jboss/
How to order deployment of EJBs and JMS queue config in JBoss 5?“
答案 3 :(得分:1)
你可以在查找调用周围实现一个带退避的循环。