5

私はかなりJava EEに慣れていないので、これはばかげているかもしれません..我慢してください:D

ステートレス セッション Bean をメッセージ駆動型 Bean に注入したいと考えています。基本的に、MDB は JMS メッセージを取得し、セッション Bean を使用して作業を実行します。セッション Bean は、ビジネス ロジックを保持します。

これが私のセッション Bean です。

@Stateless
public class TestBean implements TestBeanRemote {

  public void doSomething() {
    // business logic goes here
  }
}

一致するインターフェース:

@Remote
public interface TestBeanRemote {

  public void doSomething();
}

ここに私のMDBがあります:

@MessageDriven(mappedName = "jms/mvs.TestController", activationConfig =  {
@ActivationConfigProperty(propertyName = "acknowledgeMode", propertyValue = "Auto-acknowledge"),
@ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue")
    })
public class TestController implements MessageListener {

 @EJB
 private TestBean testBean;

    public TestController() {
    }

    public void onMessage(Message message) {
      testBean.doSomething();
    }
}

これまでのところ、ロケット科学ではありませんよね?

残念ながら、これを Glassfish v3 にデプロイし、適切な JMS キューにメッセージを送信すると、glassfish が TestBean EJB を見つけられないというエラーが発生します。

java.lang.IllegalStateException: Exception attempting to inject Remote ejb-ref name=mvs.test.TestController/testBean,Remote 3.x interface =mvs.test.TestBean,ejb-link=null,lookup=null,mappedName=,jndi-name=mvs.test.TestBean,refType=Session into class mvs.test.TestController
Caused by: com.sun.enterprise.container.common.spi.util.InjectionException: Exception attempting to inject Remote ejb-ref name=mvs.test.TestController/testBean,Remote 3.x interface =mvs.test.TestBean,ejb-link=null,lookup=null,mappedName=,jndi-name=mvs.test.TestBean,refType=Session into class mvs.test.TestController
Caused by: javax.naming.NamingException: Lookup failed for 'java:comp/env/mvs.test.TestController/testBean' in SerialContext  [Root exception is javax.naming.NamingException: Exception resolving Ejb for 'Remote ejb-ref name=mvs.test.TestController/testBean,Remote 3.x interface =mvs.test.TestBean,ejb-link=null,lookup=null,mappedName=,jndi-name=mvs.test.TestBean,refType=Session' .  Actual (possibly internal) Remote JNDI name used for lookup is 'mvs.test.TestBean#mvs.test.TestBean' [Root exception is javax.naming.NamingException: Lookup failed for 'mvs.test.TestBean#mvs.test.TestBean' in SerialContext  [Root exception is javax.naming.NameNotFoundException: mvs.test.TestBean#mvs.test.TestBean not found]]]

だから私の質問は:

  • これは、セッション Bean を別の Bean (特にメッセージ駆動型 Bean) に注入する正しい方法ですか?
  • 名前の参照が失敗するのはなぜですか?
4

4 に答える 4

6

次のようなものを定義してみてください:

@Remote
public interface TestBeanRemote {

  public void doSomething();
}

@Stateless(name="TestBeanRemote")
public class TestBean implements TestBeanRemote {

  public void doSomething() {
    // business logic goes here
  }
}

そして、MDB で:

@MessageDriven(mappedName = "jms/mvs.TestController", activationConfig =  {
@ActivationConfigProperty(propertyName = "acknowledgeMode", propertyValue = "Auto-acknowledge"),
@ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue")
    })
public class TestController implements MessageListener {

    @EJB(beanName="TestBeanRemote")
    private TestBeanRemote testBean;

    public TestController() {
    }

    public void onMessage(Message message) {
      testBean.doSomething();
    }
}

これが機能する場合は、説明を提供しようとします:)

于 2010-03-18T06:23:21.113 に答える
6

最初の例の問題は、EJB のインターフェースではなく実装を注入しようとしていることだと思います。EJB 3.1 のローカルの非インターフェース ビューは、リモート インターフェースでさえもインターフェースを定義しない場合にのみ可能です。したがって、注入ポイントを次のように変更するとうまくいくはずです。

 @EJB
 private TestBeanRemote testBean;

アプリケーションをクラスタ化されていない環境 (単一の JVM) で使用している場合は、インターフェースを @Local に変更することを検討する必要があります。リモート インターフェイスを使用して EJB にアクセスするとすぐに、大量のオーバーヘッドが発生します。パラメータと戻り値は、参照ではアクセスできなくなりましたが、常にコピーされるため、値でアクセスできます (仕様はそう言っています)。これにより、より複雑なオブジェクトを処理するときにパフォーマンスの問題が発生する可能性があります。

それが助けになることを願った。

于 2012-01-28T07:37:59.780 に答える
4

私の問題は制御の反転に関連していたようで、私の知識不足とクラス/インターフェース名に関する Netbeans の提案が原因でした。

適切な Bean と適切なインターフェイスを見つけるには、適切な名前を付ける必要があることがわかりました。機能するものは次のとおりです。

@Remote
public interface Test {

  public void doSomething();
}

@Stateless
public class TestBean implements Test {

  public void doSomething() {
    // business logic goes here
  }
}

MDB では、 「TestBean」ではなく「Test」にアクセスします。

@MessageDriven(mappedName = "jms/mvs.TestController", activationConfig =  {
@ActivationConfigProperty(propertyName = "acknowledgeMode", propertyValue = "Auto-acknowledge"),
@ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue")
    })
public class TestController implements MessageListener {

    @EJB
    private Test testBean;

    public TestController() {
    }

    public void onMessage(Message message) {
      testBean.doSomething();
    }
}
于 2010-03-18T07:40:02.100 に答える
3

わかりました。@LocalBean アノテーションをセッション Bean に追加すると、機能することがわかりました。なに…?

于 2010-03-17T19:19:09.070 に答える