Внедрение ресурса jms в сервлет и лучшая практика для MDB - PullRequest
2 голосов
/ 03 мая 2010

с использованием ejb 3.1, сервлет 3.0 (glassfish server 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 = резьбовых 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.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 / очередь @ java.lang.String @ нуль в класс 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 статический 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 (), который будет обрабатывать его. Обработка включает несколько обращений к мыльным службам, поэтому полное время обработки может составлять 3 секунды.

Спасибо.

1 Ответ

6 голосов
/ 03 мая 2010

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

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

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

...