Внедрение ресурса jms в сервлет и лучшие практики для MDB

с использованием ejb 3.1, сервлета 3.0 (сервер Glassfish v3)

Сценарий: у меня есть MDB, который прослушивает сообщения jms и передает обработку другому компоненту сеанса (без сохранения состояния). Сервлет вводит ресурс jms.

Вопрос 1: Почему сервлет не может внедрять ресурсы 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: назначить исключение для сервлета WorkerServlet 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.enterManagedObject. 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: незаконное использование статического поля 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 () или вызов другого bean-компонента (bean-компонента без сохранения состояния в моем случае) в методе onMessage (), который бы его обработал. Обработка включает несколько обращений к службам мыла, поэтому полное время обработки может составлять 3 секунды.

Спасибо.


person kislo_metal    schedule 03.05.2010    source источник


Ответы (1)


Ответы:
1. Вы не можете внедрить ресурс в статическое поле. Внедрение в поля-члены происходит во время создания объекта, статические поля не являются частью объекта (только частью класса). Вдобавок EJB и сервлеты представляют собой многопоточные объекты, поэтому это может быть опасно.
2. Если имеет смысл разделить обработку на несколько EJB (ов), сделайте это таким образом, иначе обработка в onMessage () будет вполне допустимой.

Еще одно предложение, которое я могу дать, заключается в том, что вам следует взглянуть на CDI, который является новым дополнением к спецификации EE 6 и обеспечивает широкое внедрение зависимостей.

Если вы используете MDB для выполнения асинхронных операций, Servlet 3.0 имеет некоторые изящные асинхронные возможности. Я предлагаю вам просмотреть всю презентацию, если вы не знакомы с Servlet 3.0.

person Justin    schedule 03.05.2010
comment
Мой сервлет на самом деле является сервлетом GWT, поэтому мне нужно будет проверить, совместим ли GWT с асинхронным методом Servlet 3.0. На самом деле gwt имеет its own GWT.runAsync() method, havent заглянуть внутрь, но если он, естественно, поддерживает тот же метод async, что и сервлет 3.0, или если он работает с помощью методов async сервлета 3.0. - person kislo_metal; 03.05.2010
comment
Хорошо, похоже, в моем случае я мог бы справиться со всем, что мне нужно, без MDB. Насчет GWT.runAsync () - другое. Отличная презентация, спасибо! - person kislo_metal; 03.05.2010