2010-03-17 52 views
5

我对Java EE是比较新的,所以这可能是愚蠢的。请耐心等待我请求:D如何将会话Bean注入消息驱动Bean?

我想将无状态会话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的第三版,并且将消息发送到相应的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)的正确方法吗?
  • 为什么命名查找失败?

回答

3

好的,我发现如果我将注释@LocalBean添加到会话bean中,它就可以工作。什么......?

+0

我现在有点远了。 @LocalBean标识没有接口的bean。所以这不是我想要的,即使它有效:D – Hank 2010-03-18 07:34:47

+0

您应该使用“@EJB private TestBeanRemote testBean;” – Dagvadorj 2013-04-13 11:23:53

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

如果这个工作,我会尽力提供一个解释:)

+0

对不起,不幸的是,这也不起作用。我想我会跟着我发现的IoC。不管怎么说,还是要谢谢你! – Hank 2010-03-18 07:46:00

+0

@Hank怪异的,我理解它应该。我很困惑... – 2010-03-18 07:58:53

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这个”:

@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(); 
    } 
} 
+0

你能否在你的关于命名约定的发现上添加任何参考? – 2010-03-18 08:05:29

+1

试试这里:http://java.sun.com/blueprints/code/namingconventions.html – Hank 2010-03-18 08:34:24

+0

好吧,我现在开始越来越明白这一点。我的上面的例子是正确的,如果接口是@Local。 当我注入一个会话bean的东西,我注射。然后容器试图找到实现类( Bean)以及相应的接口(对于@Local使用: Local,对于@Remote使用:远程)。 所以这个问题不是JNDI,它不符合命名约定! – Hank 2010-03-18 08:47:15

6

我觉得第一个例子的问题是,你正在试图注入EJB的实现而不是它的接口。如果您没有定义任何接口,即使是远程接口,EJB 3.1的本地无接口视图也是可能的。因此,改变注入点以下应该制定出:

@EJB 
private TestBeanRemote testBean; 

如果您正在使用非群集环境中的应用程序,因此单个JVM,你应该考虑改变接口@Local。只要使用远程接口访问EJB,就会产生很大的开销。参数和返回值不能通过引用进行访问,而是按值进行访问,因为它们总是被复制(规范如此说明)。处理更复杂的对象时,这可能会导致性能问题。

希望有所帮助。