2

使用 ejb 3.1、servlet 3.0(glassfish 服务器 v3)

场景:我有侦听 jms 消息并将处理交给其他会话 bean(无状态)的 MDB。Servelet 注入 jms 资源。

问题一:为什么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 WorkerServlet com.sun.enterprise.container.common.spi.util.InjectionException 分配异常:在 com.sun 为类 ua.co.rufous.server.services.WorkerServiceImpl 创建托管对象时出错。 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) at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1252) 原因:com.sun.enterprise.container.common.spi.util。InjectionException:尝试将 Unresolved Message-Destination-Ref ua.co.rufous.server.services.WorkerServiceImpl/queue@java.lang.String@null 注入 com.sun 的类 ua.co.rufous.server.services.WorkerServiceImpl 的异常.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:在仅支持基于实例的注入的类上非法使用静态字段 private static 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)来处理它。处理包括对肥皂服务的少量调用,因此完整处理时间可能为 3 秒。

谢谢你。

4

1 回答 1

6

答案:
1. 不能将资源注入静态字段。在对象构造期间注入成员字段,静态字段不是对象的一部分(只是类的一部分)。此外,EJB 和 servlet 是线程对象,因此这样做可能很危险。
2. 如果将处理分成多个 EJB(s) 是有意义的,那么这样做是有意义的,否则 onMessage() 中的处理是完全有效的。

我可以给出的另一个建议是,您应该看看CDI,它是 EE 6 规范的新增内容,并提供了丰富的依赖注入。

您是否使用 MDB 执行异步操作,Servlet 3.0 具有一些简洁的异步功能。如果您不熟悉 Servlet 3.0,我建议您观看整个演示文稿。

于 2010-05-03T12:53:07.480 回答