在servlet中注入jms资源MDB 的最佳实践

发布于 2024-08-30 19:01:18 字数 4296 浏览 2 评论 0原文

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

场景: 我有 MDB 来监听 jms 消息并对其他一些会话 bean(无状态)进行处理。 Servlet 注入 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/[电子邮件受保护] @无效的 进入课堂 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)来处理它。 处理包括对肥皂服务的少量调用,因此完整处理时间可能为 3 秒。

谢谢。

using ejb 3.1, servlet 3.0 (glassfish server v3)

Scenario:
I have MDB that listen to jms messages and give processing to some other session bean (Stateless).
Servelet injecting jms resource.

Question 1: Why servlet can`t inject jms resources when they use static declaration ?

@Resource(mappedName = "jms/Tarturus")
private static ConnectionFactory connectionFactory;

@Resource(mappedName = "jms/StyxMDB")
private static Queue queue;


private Connection connection;

and

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

The error that I get is :

[#|2010-05-03T15:18:17.118+0300|WARNING|glassfish3.0|javax.enterprise.system.container.web.com.sun.enterprise.web|_ThreadID=35;_ThreadName=Thread-1;|StandardWrapperValve[WorkerServlet]:
PWC1382: Allocate exception for
servlet WorkerServlet
com.sun.enterprise.container.common.spi.util.InjectionException:
Error creating managed object for
class
ua.co.rufous.server.services.WorkerServiceImpl
at
com.sun.enterprise.container.common.impl.util.InjectionManagerImpl.createManagedObject(InjectionManagerImpl.java:312)
at
com.sun.enterprise.web.WebContainer.createServletInstance(WebContainer.java:709)
at
com.sun.enterprise.web.WebModule.createServletInstance(WebModule.java:1937)
at
org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1252)
Caused by:
com.sun.enterprise.container.common.spi.util.InjectionException:
Exception attempting to inject
Unresolved Message-Destination-Ref
ua.co.rufous.server.services.WorkerServiceImpl/[email protected]@null
into class
ua.co.rufous.server.services.WorkerServiceImpl
at
com.sun.enterprise.container.common.impl.util.InjectionManagerImpl._inject(InjectionManagerImpl.java:614) at
com.sun.enterprise.container.common.impl.util.InjectionManagerImpl.inject(InjectionManagerImpl.java:384)
at
com.sun.enterprise.container.common.impl.util.InjectionManagerImpl.injectInstance(InjectionManagerImpl.java:141)
at
com.sun.enterprise.container.common.impl.util.InjectionManagerImpl.injectInstance(InjectionManagerImpl.java:127)
at
com.sun.enterprise.container.common.impl.util.InjectionManagerImpl.createManagedObject(InjectionManagerImpl.java:306)
... 27 more Caused by:
com.sun.enterprise.container.common.spi.util.InjectionException:
Illegal use of static field private
static javax.jms.Queue
ua.co.rufous.server.services.WorkerServiceImpl.queue
on class that only supports
instance-based injection at
com.sun.enterprise.container.common.impl.util.InjectionManagerImpl._inject(InjectionManagerImpl.java:532) ... 31 more |#]

my 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) {

        }

    }


}

everything work good without static declaration:

@Resource(mappedName = "jms/Tarturus")
    private ConnectionFactory connectionFactory;

    @Resource(mappedName = "jms/StyxMDB")
    private Queue queue;

    private Connection connection;

Question 2:
what is the best practice for working with MDB : processing full request in onMessage() or calling another bean(Stateless bean in my case) in onMessage() method that would process it.
Processing including few calls to soap services, so the full processing time could be for a 3 seconds.

Thank you.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

追星践月 2024-09-06 19:01:18

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

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

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

Answers:
1. You cannot inject a resource into a static field. Injection into member fields occurs during object construction, static fields are not part of the object (only part of the class). In addition EJBs and servlets are threaded objects so this could possibly be dangerous to do.
2. If splitting the processing up into multiple EJB(s) makes sense do it that way, otherwise processing in onMessage() is perfectly valid.

One additional suggestion that I can give, is that you should take a look at CDI which is a new addition to the EE 6 specification and provides rich dependency injection.

Are you using an MDB to perform asynchronous operations, Servlet 3.0 has some neat asynchronous capabilities. I suggest you watch the entire presentation if you are not familiar with Servlet 3.0.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文