如何将会话 Bean 注入消息驱动 Bean?
-
20-09-2019 - |
题
我对 Java EE 相当陌生,所以这可能很愚蠢。请耐心等待:D
我想将无状态会话 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 v3 并向相应的 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)的正确方法吗?
- 为什么命名查找失败?
解决方案 4
好的,我发现如果我将注释 @LocalBean 添加到会话 bean 中,它就可以工作。什么……?
其他提示
你能尝试定义这样的事情:
@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();
}
}
如果这有效,我会尽力提供解释:)
我认为第一个示例的问题是您试图注入 EJB 的实现而不是其接口。如果您不定义任何接口(甚至远程接口),则 EJB 3.1 的本地无接口视图才可能实现。因此,将注入点更改为以下内容应该可以解决问题:
@EJB
private TestBeanRemote testBean;
如果您在非集群环境(即单个 JVM)中使用应用程序,您应该考虑将接口更改为 @Local。一旦您使用远程接口访问 EJB,就会产生大量开销。参数和返回值不能再通过引用访问,而是通过值访问,因为它们总是被复制(规范是这么说的)。在处理更复杂的对象时,这可能会导致性能问题。
希望有帮助。
看来我的问题与控制反转有关,并且是由于我缺乏知识和 Netbeans 对类/接口名称的建议而引起的。
我发现 - 为了找到正确的 bean 和正确的接口 - 我应该正确命名它们。这是有效的:
@Remote
public interface Test {
public void doSomething();
}
@Stateless
public class TestBean implements Test {
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
private Test testBean;
public TestController() {
}
public void onMessage(Message message) {
testBean.doSomething();
}
}
不隶属于 StackOverflow