English 中文(简体)
How to inject a Session Bean into a Message Driven Bean?
原标题:

I m reasonably new to Java EE, so this might be stupid.. bear with me pls :D

I would like to inject a stateless session bean into a message-driven bean. Basically, the MDB gets a JMS message, then uses a session bean to perform the work. The session bean holds the business logic.

Here s my Session Bean:

@Stateless
public class TestBean implements TestBeanRemote {

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

The matching interface:

@Remote
public interface TestBeanRemote {

  public void doSomething();
}

Here s my 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();
    }
}

So far, not rocket science, right?

Unfortunately, when deploying this to glassfish v3, and sending a message to the appropriate JMS Queue, I get errors that glassfish is unable to locate the 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]]]

So my questions are:

  • is this the correct way of injecting a session bean into another bean (particularly a message driven bean)?
  • why is the naming lookup failing?
最佳回答

Ok, I found out that if I add the annotation @LocalBean to the session bean, it works. What the ...?

问题回答

Could you try to define things like this:

@Remote
public interface TestBeanRemote {

  public void doSomething();
}

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

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

And then in the 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();
    }
}

If this work, I ll try to provide an explanation :)

I think the problem of the very first example is that you are trying to inject the implementation of the EJB and not its interface. The local no-interface view of EJB 3.1 is just possible if you do not define any interface, not even a remote one. So changing the injection point to the following should work out:

 @EJB
 private TestBeanRemote testBean;

If you are using your application within a non clustered environment, so single JVM, you should think about changing the interface to @Local. As soon as you are accessing EJBs using their remote interface, you are getting a lot of overhead. Parameters and return values can not be accessed by reference anymore, but by value, as they are always copied (specification says so). This might lead to performence issues when dealing with more complex objects.

Hoped that helped.

It seems that my problem was related to Inversion of Control and caused by my lack of knowledge and Netbeans suggestions for Class/Interface names.

I found out that - in order to find the the right bean and the right interface - I should name them properly. Here s what works:

@Remote
public interface Test {

  public void doSomething();
}

@Stateless
public class TestBean implements Test {

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

And in the MDB I access Test not 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();
    }
}




相关问题
Force clear EJB3 cache in Glassfish

I have application written in Java that is using EJB3 + Toplink. I m using Glassfish as my app. server. Sometimes the data that has been cached is old and I need to clear my cache manually. I know ...

Which Maven GlassFish plugin to use?

I ve been trying to integrate deploying java .war s in GlassFish V3 through Maven. While I have found a few plugins, none of them look to be very active: Maven Glassfish Plugin Eskato s Wordpress ...

is it good to catch error in DAO?

public boolean checkInd() { int dis_ind = 2; HashMap parmMap = new HashMap(); //line below can generate errors getSqlMapClientTemplate().queryForList("authentication.checkInd", parmMap)...

Turn off TRACE in GlassFish v2

I need to turn off TRACE to help close XST security vulnerabilities. I ve been looking, nothing obvious so far. Any help?

Glassfish in a production environment?

Do you use Glassfish 2 or v3 in a production environment? Do you find it robust? Have you ever been able to find a complete set of documentation? What do you do when you find that Glassfish ignores ...

热门标签