Pregunta

Soy bastante nuevo a Java EE, por lo que este podría ser estúpidos .. oso conmigo pls: D

Me gustaría inyectar un bean de sesión sin estado en un bean controlado por mensajes. Básicamente, el MDB recibe un mensaje JMS, a continuación, utiliza un bean de sesión para realizar el trabajo. El bean de sesión mantiene la lógica de negocio.

Aquí está mi bean de sesión:

@Stateless
public class TestBean implements TestBeanRemote {

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

La interfaz de juego:

@Remote
public interface TestBeanRemote {

  public void doSomething();
}

Aquí está mi 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();
    }
}

Hasta el momento, no es ciencia de cohetes, ¿verdad?

Por desgracia, al implementar esta a GlassFish v3, y enviando un mensaje a la adecuada cola JMS, consigo errores que GlassFish es incapaz de localizar el 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]]]

Así que mis preguntas son:

  • Es esta la forma correcta de inyectar un bean de sesión en otro bean (particularmente un grano controlado por mensajes)?
  • ¿Por qué está fallando la búsqueda de nombres?
¿Fue útil?

Solución 4

Bueno, he encontrado que si añado los @LocalBean de anotación para el bean de sesión, funciona. ¿Qué ...?

Otros consejos

Podría tratar de definir las cosas como esto:

@Remote
public interface TestBeanRemote {

  public void doSomething();
}

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

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

Y luego, en el 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 este trabajo, voy a tratar de dar una explicación:)

Creo que el problema del primer ejemplo es que usted está tratando de inyectar la implementación del EJB y no su interfaz. La vista sin interfaz local del EJB 3.1 es sólo posible si no se define ninguna interfaz, ni siquiera un solo mando a distancia. Por lo que cambiar el punto de inyección a la siguiente debería funcionar:

 @EJB
 private TestBeanRemote testBean;

Si está utilizando su aplicación dentro de un entorno no agrupado, por lo única JVM, debe pensar en cambiar la interfaz a @Local. Tan pronto como se está accediendo a los EJB utilizando su interfaz remota, que está recibiendo un montón de gastos generales. Los parámetros y valores de retorno no se puede acceder por referencia ya, pero por valor, ya que siempre se copian (especificación dice así). Esto podría conducir a problemas de performence cuando se trata de objetos más complejos.

espera que ayudó.

Parece que mi problema estaba relacionado con Inversión de Control y causada por mi falta de conocimientos y sugerencias de Netbeans' para los nombres / interfaz de clase.

descubrí que - con el fin de encontrar el grano de la derecha y la interfaz de la derecha - Debería nombrarlos correctamente. Esto es lo que funciona:

@Remote
public interface Test {

  public void doSomething();
}

@Stateless
public class TestBean implements Test {

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

Y en el MDB accedo 'Test' no '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();
    }
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top