Question

Je suis assez nouveau pour Java EE, alors cela pourrait être stupide .. ours avec moi pls: D

Je voudrais injecter un bean session sans état dans un bean géré par message. Fondamentalement, le MDB reçoit un message JMS, puis utilise un bean de session pour effectuer le travail. La fève de la session détient la logique métier.

Voici ma session Bean:

@Stateless
public class TestBean implements TestBeanRemote {

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

L'interface d'adaptation:

@Remote
public interface TestBeanRemote {

  public void doSomething();
}

Voici mon 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();
    }
}

Jusqu'à présent, pas la science de fusée, droit?

Malheureusement, lors du déploiement de cette GlassFish v3, et envoyer un message à la file d'attente JMS appropriée, je reçois des erreurs que GlassFish est incapable de localiser le 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]]]

Alors mes questions sont:

  • est-ce la bonne façon d'injecter un bean session dans un autre haricot (en particulier un haricot géré par message)?
  • pourquoi la recherche de nom échoue?
Était-ce utile?

La solution 4

Ok, je trouve que si j'ajoute l'annotation @LocalBean à la fève de session, cela fonctionne. Qu'est-ce que ...?

Autres conseils

Pouvez-vous essayer de définir les choses comme ceci:

@Remote
public interface TestBeanRemote {

  public void doSomething();
}

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

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

Et puis dans le 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();
    }
}

Si ce travail, je vais essayer de fournir une explication:)

Je pense que le problème de l'exemple premier est que vous essayez d'injecter la mise en œuvre de l'EJB et non son interface. La vue sans interface locale de 3.1 EJB est seulement possible si vous ne définissez pas d'interface, pas même une seule télécommande. Donc changer le point d'injection à ce qui suit devrait fonctionner:

 @EJB
 private TestBeanRemote testBean;

Si vous utilisez votre application dans un environnement non cluster, si seule machine virtuelle Java, vous devriez penser à changer l'interface @Local. Dès que vous accédez à l'aide de leur interface EJBs à distance, vous obtenez beaucoup de frais généraux. Les paramètres et les valeurs de retour ne peuvent pas être consultés par référence plus, mais en valeur, car ils sont toujours copiés (spécification le dit). Cela pourrait conduire à des problèmes de performence lorsqu'ils traitent avec des objets plus complexes.

Espère qui a aidé.

Il semble que mon problème était lié à l'inversion de contrôle et causé par mon manque de connaissances et les suggestions de Netbeans pour les noms de classe / d'interface.

J'ai découvert que - afin de trouver la fève à droite et l'interface droite - je les nommer correctement. Voici ce qui fonctionne:

@Remote
public interface Test {

  public void doSomething();
}

@Stateless
public class TestBean implements Test {

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

Et dans le MDB-je accéder à 'Test' pas '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();
    }
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top