Frage

Ich bin ziemlich neu in Java EE, so dass dies dumm sein könnte .. Bär mit mir pls: D

Ich möchte eine Stateless Session Bean in eine Message-Driven Bean injizieren. Grundsätzlich ist die MDB eine JMS-Nachricht erhält, dann wird ein Session-Bean, die Arbeit auszuführen. Der Session-Bean hält die Geschäftslogik.

Hier ist meine Session Bean:

@Stateless
public class TestBean implements TestBeanRemote {

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

Die passende Schnittstelle:

@Remote
public interface TestBeanRemote {

  public void doSomething();
}

Hier ist meine 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();
    }
}

Bisher keine Raketenwissenschaft, nicht wahr?

Leider, wenn diese auf Glassfish v3 Bereitstellung und eine Nachricht an der entsprechenden JMS-Warteschlange zu senden, erhalte ich Fehler, die nicht in der Lage ist, den Glasfischen TestBean EJB zu finden:

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]]]

Also meine Fragen sind:

  • ist dies der richtige Weg, um einen Session-Bean in einer anderen Bohne der Injektion (insbesondere eine Meldung Driven Bean)?
  • warum versagt die Namensgebung Lookup?
War es hilfreich?

Lösung 4

Ok, ich fand heraus, dass, wenn ich die Anmerkung @LocalBean auf den Session-Bean hinzufügen, es funktioniert. Was zum ...?

Andere Tipps

Könnten Sie versuchen, die Dinge so zu definieren:

@Remote
public interface TestBeanRemote {

  public void doSomething();
}

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

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

Und dann in der 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();
    }
}

Wenn diese Arbeit, ich werde versuchen, eine Erklärung zu liefern:)

Ich denke, das Problem des ersten Beispiels ist, dass Sie versuchen, die Umsetzung des EJB und nicht seine Schnittstelle zu injizieren. Die lokale no-Schnittstelle Ansicht von EJB 3.1 ist nur möglich, wenn Sie eine beliebige Schnittstelle nicht definieren, nicht einmal eine entfernte ein. So Wechsel sollte die Injektionsstelle zu folgenden ausrechnen:

 @EJB
 private TestBeanRemote testBean;

Wenn Sie Ihre Anwendung in einer nicht gruppierten Umgebung verwenden, so einzige JVM, sollten Sie darüber nachdenken, die Schnittstelle zu @Local ändern. Sobald Sie EJBs mit ihrer Remote-Schnittstelle zugreifen, werden Sie eine Menge Aufwand zu bekommen. Parameter und Rückgabewerte können nicht mehr durch Verweis zugegriffen werden, sondern von Wert, da sie immer kopiert werden (Spezifikation sagt so). Dies könnte zu performence Problemen führen, wenn sie mit komplexeren Objekten handelt.

Hofft, dass geholfen.

Es scheint, dass mein Problem zu Inversion of Control und durch meinen Mangel an Wissen und Netbeans' Vorschläge für Klassen- / Interface-Namen verursacht verwandt war.

Ich fand heraus, dass - um die die richtige Bohne und die richtige Schnittstelle zu finden - ich soll sie richtig benennen. Hier ist, was funktioniert:

@Remote
public interface Test {

  public void doSomething();
}

@Stateless
public class TestBean implements Test {

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

Und in dem MDB ich Zugang 'Test' nicht 'TestBean':

@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();
    }
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top