12

我有使用 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'
    }
}
4

4 回答 4

4

使用这四种不同方法中的一种。

  1. 使用“@EJB”注释声明 EJB 依赖项(EJB 引用)(不要使用 JNDI 查找)。对于实体 bean 的引用,必须引用实体 bean 的 home 接口。容器必须确保在处理方法/消息侦听器之前注入所有依赖项:

    MessageDriven(mappedName="jms/Queue")
    公共类 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;
    }
    

    }

  2. 使用 JNDI 查找,但通过 EJB 部署描述符声明 EJB 依赖项。同样,容器必须确保在处理方法/消息之前设置所有依赖项:

    @MessageDriven(mappedName="jms/Queue") 公共类 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>
    
  3. 使用 JNDI 查找,但不使用 @EJB 注释或 EJB 部署声明依赖关系 - 完全使用您自己的逻辑处理,无需容器帮助。使用延迟/错误处理。

  4. 使用 JBoss 专有配置来控制部署顺序:

    http://texnoblog.wordpress.com/2010/09/16/depends-in-jboss/

    如何在 JBoss 5 中订购 EJB 和 JMS 队列配置的部署?

于 2013-02-22T15:58:09.067 回答
2

一种方法是创建一个注入到 MDB 中的 dummy-ejb,这样在注入实际发生之前,您的 mdb 不会开始消耗。

如果 dummy-ejb 与您打算对其进行动态查找的 EJB 捆绑在一起,这应该可以工作

在这里的回答解决了一个类似的用例。

于 2013-02-22T07:53:18.250 回答
1

我认为最好的方法是延迟 MDB 的部署,直到所有 EJB 都启动并运行。这基本上是上述答案中的方法 4。

“使用 JBoss 专有配置来控制部署顺序:

http://texnoblog.wordpress.com/2010/09/16/depends-in-jboss/

如何在 JBoss 5 中订购 EJB 和 JMS 队列配置的部署?"

于 2013-02-23T02:42:32.230 回答
1

您可以在查找调用周围实现一个带有回退的循环。

于 2013-02-23T03:26:53.727 回答