Спорадическая автоматическая проводка в Spring JMS Message Listener

Я пытаюсь реализовать очередь для запуска заданий через Spring Batch. Очередь получает сообщения для заданий. Обрабатывает содержимое и запускает задание. Все работает так, как ожидалось, примерно в 50% случаев, и я не могу сказать, почему.

Вот код:

public class Listener implements MessageListener {
private static final Logger log = LoggerFactory.getLogger(Listener.class);


@Resource(name = "job")
Job job;

@Resource
JobLauncher jobLauncher;
/**
 * Method called when message is sent to Queue. Reads messages in FIFO
 * @param message Message pulled from Queue
 */
@Override
public void onMessage(Message message) {

    log.info("Message received");
    try {
        String jobName = message.getJMSCorrelationID();

        if (jobName.equals("job")) {
            launchJob(message);
        }
    } catch (JMSException e) {
        log.error("Error with queued message: " + message.toString());
    }

Похоже, что иногда @Resource не инициализируются. Если я отлаживаю, я замечаю, что примерно в половине случаев они нулевые, а в другой половине времени они правильно подключены. Правильное сканирование закодировано в XML-файлах контекста.

Вот конфигурация очереди:

<!--  Embedded ActiveMQ Broker -->
<amq:broker id="broker" useJmx="false" persistent="false" >
    <amq:transportConnectors>
        <amq:transportConnector uri="tcp://localhost:0" />
    </amq:transportConnectors>
</amq:broker>

<!--  ActiveMQ Destination  -->
<amq:queue id="destination" physicalName="org" />

<!-- JMS ConnectionFactory to use, configuring the embedded broker using XML -->
<amq:connectionFactory id="jmsFactory" brokerURL="vm://localhost" />

<!-- JMS Producer Configuration -->
<bean id="jmsProducerConnectionFactory"
      class="org.springframework.jms.connection.SingleConnectionFactory"
      depends-on="broker"
      p:targetConnectionFactory-ref="jmsFactory" />

<bean id="localQueueTemplate" class="org.springframework.jms.core.JmsTemplate"
      p:connectionFactory-ref="jmsProducerConnectionFactory"
      p:defaultDestination-ref="destination" />

<!--JMS Consumer Configuration-->
<bean id="jmsConsumerConnectionFactory"
      class="org.springframework.jms.connection.SingleConnectionFactory"
      depends-on="broker"
      p:targetConnectionFactory-ref="jmsFactory" />

<jms:listener-container container-type="default"
                        connection-factory="jmsConsumerConnectionFactory"
                        acknowledge="auto"
                        >
    <jms:listener destination="org" ref="Queue" />
</jms:listener-container>

<bean id="Queue" class="org.Listener" />

Я нашел другие ТАК, что может быть так. По-видимому, существуют проблемы с созданием bean-компонентов в слушателях из-за различного образа жизни контекста bean-компонентов Listeners по сравнению со стандартными Spring Beans. См. здесь. Однако решения на самом деле нет. И единственное предложенное решение, которое я не могу реализовать, используя пространство имен jms:.

РЕДАКТИРОВАТЬ:

Я переместил некоторые контексты конфигурации. Я переместил Listener в его собственный файл контекста. Теперь @Resources инициализируются ровно один раз. Первое отправленное сообщение будет правильно запускать задание. Кажется, что каждое последующее сообщение имеет нулевую программу запуска и задание.

РЕДАКТИРОВАТЬ 2:

Я переместил конфигурацию очереди в контекстный файл за пределами общего. Кажется, это решило проблему.

Судя по отладчику, создается несколько экземпляров Listener. Некоторые правильно подключаются, а некоторые нет. Похоже, это связано с порядком создания экземпляров. Перемещение контекста, скорее всего, означает, что bean-компоненты доступны при создании прослушивателя.

Таким образом, кажется, что мне просто нужно добавить зависимость к компоненту Queue, чтобы он «зависел» от задания и средства запуска задания. Я попробую и, надеюсь, отчитаюсь.

РЕДАКТИРОВАТЬ 3:

Похоже, что "зависит от" не работает должным образом. Я выбрал решение перемещения логики очереди в другой контекст конфигурации. Этот контекст импортирует все ресурсы для задания. Каждый созданный объект (по какой-то причине их два) правильно подключен.

РЕДАКТИРОВАТЬ 4:

Проблема была вызвана многократными загрузками файла контекста. В качестве примера здесь была проблема, расположенная в файле web.xml.

    <servlet>
      <servlet-name>Job1 Controller</servlet-name>
      <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>controller-context.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>Job1 Controller</servlet-name>
    <url-pattern>/Job1/</url-pattern>
  </servlet-mapping>
  <servlet>
    <servlet-name>Job2 Controller</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>controller-context.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>Job2 Controller</servlet-name>
    <url-pattern>/Job2/</url-pattern>
  </servlet-mapping>

person Cameron Bauer    schedule 04.09.2014    source источник
comment
То, что вы описываете, не имеет смысла; упомянутый вопрос совершенно не связан (речь идет о жизненном цикле, вызывающем нетерпеливое создание экземпляра DMLC). каждое последующее сообщение... - невозможно - один и тот же экземпляр прослушивателя используется для всех сообщений, поэтому один из них подключен, он имеет одинаковые зависимости для каждого сообщения. Я предлагаю вам включить ведение журнала DEBUG для org.springframework - он выдает обильные сообщения о проводке.   -  person Gary Russell    schedule 04.09.2014
comment
@GaryRussell На основе отладчика создается несколько экземпляров прослушивателей. Я вернулся к конфигурации 50%. Похоже, что по умолчанию есть 3 объекта слушателя. 2 подключены правильно. 1 нет. Я предполагаю, что это означает, что среди различных файлов контекста создается несколько bean-компонентов.   -  person Cameron Bauer    schedule 04.09.2014
comment
@GaryRussell Похоже, мне что-то удалось, переместив конфигурацию в другой файл контекста. Я не могу определить, почему создается несколько объектов прослушивателя, но, судя по отладке, их как минимум два. Однако после перемещения все объекты подключаются правильно.   -  person Cameron Bauer    schedule 04.09.2014
comment
Журнал DEBUG должен показать вам, почему вы получаете несколько экземпляров.   -  person Gary Russell    schedule 04.09.2014
comment
@GaryRussell Операторы отладки менее чем полезны. Существует ровно два экземпляра создания экземпляра bean-компонента «Очередь». Кажется, что каждый компонент, определенный в пространстве имен ams и jms, получает ровно два экземпляра. Среди всех файлов контекста существует только одна конфигурация очереди. Сообщают ли файлы отладки, почему был создан экземпляр определенного компонента?   -  person Cameron Bauer    schedule 04.09.2014
comment
У вас не может быть двух экземпляров одного и того же имени компонента в одном контексте — выигрывает определение второго компонента. Это означает, что у вас есть bean-компонент, объявленный в нескольких контекстах. Далее в журнале вы должны увидеть, какие файлы анализируются. Это веб-приложение? Распространенной ошибкой является загрузка одного и того же контекста в корневом контексте (ContextLoadedListener), а также в контексте сервлета.   -  person Gary Russell    schedule 04.09.2014
comment
@GaryRussell Это не так. Контекст загружается только в одном месте.   -  person Cameron Bauer    schedule 05.09.2014
comment
Как я сказал; невозможно получить 2 экземпляра с одинаковым именем компонента. Значит что-то не так в вашем анализе.   -  person Gary Russell    schedule 05.09.2014
comment
@GaryRussell Есть ли в файлах журнала какие-либо указания на то, почему или что инициализирует определенные компоненты? Например, из какого файла контекста он вызывается? Я могу заверить вас, что в каждом файле контекста в проекте есть только один экземпляр вышеуказанной конфигурации.   -  person Cameron Bauer    schedule 05.09.2014
comment
@GaryRussell Могут ли эти два экземпляра иметь какое-либо отношение к возможностям динамического масштабирования DMLC? Из того, что я прочитал, контейнер прослушивателя инициализирует столько одновременных прослушивателей, сколько ему разрешено иметь как минимум. Однако также кажется, что по умолчанию будет 1 для DMLC.   -  person Cameron Bauer    schedule 05.09.2014
comment
@GaryRussell Похоже, ты был прав. Мы загружаем контекст дважды. Я не знал, но в нашем web.xml мы создаем два набора контроллеров, используя одни и те же файлы контекста. Извините, если я показался немного отчужденным, но я совсем новичок в Spring. Спасибо за помощь. Извините, я также не мог переместить это в чат. Нет респ.   -  person Cameron Bauer    schedule 05.09.2014