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

これら 4 つの異なるアプローチのいずれかを使用します。

  1. 「@EJB」アノテーションを使用してEJB 依存関係 ( EJB 参照) を宣言します (JNDI ルックアップを使用しないでください)。エンティティ Bean の参照については、エンティティ Bean のホーム インターフェイスを参照する必要があります。コンテナーは、メソッド/メッセージ リスナーが処理される前に、すべての依存関係が注入されていることを確認する必要があります。

    MessageDriven(mappedName="jms/Queue")
    public class 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") public class 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

1 つの方法は、MDB に注入するダミー ejb を作成することです。この方法では、その注入が実際に行われるまで、mdb は消費を開始しません。

動的ルックアップを行う予定の EJB にダミーの ejb がバンドルされている場合、これは機能するはずです。

ここでの私の答えは、同様のユースケースを解決します。

于 2013-02-22T07:53:18.250 に答える
1

ルックアップ呼び出しの前後にバックオフを使用してループを実装できます。

于 2013-02-23T03:26:53.727 に答える