使用ejb 3.1,servlet 3.0(glassfish服务器v3)
场景:
我有MDB来监听jms消息,并处理其他会话bean(无状态)。
Servelet注入jms资源。
问题1:为什么servlet在使用静态声明时不能注入jms资源?
@Resource(mappedName = "jms/Tarturus")
private static ConnectionFactory connectionFactory;
@Resource(mappedName = "jms/StyxMDB")
private static Queue queue;
private Connection connection;
和
@PostConstruct
public void postConstruct() {
try {
connection = connectionFactory.createConnection();
} catch (JMSException e) {
e.printStackTrace();
}
}
@PreDestroy
public void preDestroy() {
try {
connection.close();
} catch (JMSException e) {
e.printStackTrace();
}
}
我得到的错误是:
[#| 2010-05-03T15:18:17.118 + 0300 |警告| glassfish3.0 | javax.enterprise.system.container.web.com.sun.enterprise.web | _ThreadID = 35; _ThreadName = Thread-1; | StandardWrapperValve [WorkerServlet]:
PWC1382:为以下项分配异常
Servlet工人Servlet
com.sun.enterprise.container.common.spi.util.InjectionException:
为以下对象创建托管对象时出错
类
ua.co.rufous.server.services.WorkerServiceImpl
在
com.sun.enterprise.container.common.impl.util.InjectionManagerImpl.createManagedObject(InjectionManagerImpl.java:312)
在
com.sun.enterprise.web.WebContainer.createServletInstance(WebContainer.java:709)
在
com.sun.enterprise.web.WebModule.createServletInstance(WebModule.java:1937)
在
org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1252)
造成原因:
com.sun.enterprise.container.common.spi.util.InjectionException:
尝试注入异常
未解决的消息目标引用
ua.co.rufous.server.services.WorkerServiceImpl / queue @ java.lang.String @ null
上课
ua.co.rufous.server.services.WorkerServiceImpl
在
com.sun.enterprise.container.common.impl.util.InjectionManagerImpl._inject(InjectionManagerImpl.java:614)在
com.sun.enterprise.container.common.impl.util.InjectionManagerImpl.inject(InjectionManagerImpl.java:384)
在
com.sun.enterprise.container.common.impl.util.InjectionManagerImpl.injectInstance(InjectionManagerImpl.java:141)
在
com.sun.enterprise.container.common.impl.util.InjectionManagerImpl.injectInstance(InjectionManagerImpl.java:127)
在
com.sun.enterprise.container.common.impl.util.InjectionManagerImpl.createManagedObject(InjectionManagerImpl.java:306)
... 27更多原因:
com.sun.enterprise.container.common.spi.util.InjectionException:
非法使用静态私有字段
静态javax.jms.Queue
ua.co.rufous.server.services.WorkerServiceImpl.queue
在仅支持的课程上
基于实例的注入
com.sun.enterprise.container.common.impl.util.InjectionManagerImpl._inject(InjectionManagerImpl.java:532)... 31更多|#]
我的MDB:
/**
* asadmin commands
* asadmin create-jms-resource --restype javax.jms.ConnectionFactory jms/Tarturus
* asadmin create-jms-resource --restype javax.jms.Queue jms/StyxMDB
* asadmin list-jms-resources
*/
@MessageDriven(mappedName = "jms/StyxMDB", activationConfig =
{
@ActivationConfigProperty(propertyName = "connectionFactoryJndiName", propertyValue = "jms/Tarturus"),
@ActivationConfigProperty(propertyName = "acknowledgeMode", propertyValue = "Auto-acknowledge"),
@ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue")
})
public class StyxMDB implements MessageListener {
@EJB
private ActivationProcessingLocal aProcessing;
public StyxMDB() {
}
public void onMessage(Message message) {
try {
TextMessage msg = (TextMessage) message;
String hash = msg.getText();
GluttonyLogger.getInstance().writeInfoLog("geted jms message hash = " + hash);
} catch (JMSException e) {
}
}
}
没有静态声明,一切都会很好:
@Resource(mappedName = "jms/Tarturus")
private ConnectionFactory connectionFactory;
@Resource(mappedName = "jms/StyxMDB")
private Queue queue;
private Connection connection;
问题2:
使用MDB的最佳实践是什么:在onMessage()中处理完整请求,或者在将处理该请求的onMessage()方法中调用另一个bean(在我的情况下为无状态bean)。
处理过程几乎不包含对Soap服务的调用,因此整个处理时间可能为3秒。
谢谢。
最佳答案
答案:
1.您不能将资源注入静态字段。注入成员字段是在对象构造期间发生的,静态字段不是对象的一部分(仅是类的一部分)。另外,EJB和servlet是线程对象,因此这样做可能很危险。
2.如果将处理分成多个EJB是有意义的,请这样做,否则onMessage()中的处理是完全有效的。
我可以提出的另一个建议是,您应该看一下CDI,它是EE 6规范的新增功能,并提供了丰富的依赖项注入。
在使用MDB执行异步操作时,Servlet 3.0具有一些简洁的异步capabilities。如果您不熟悉Servlet 3.0,建议您观看整个演示文稿。