Spring 4.1 Конфигурация @JmsListener

Я хотел бы использовать новые аннотации и функции, представленные в Spring 4.1 для приложения, которое нуждается в прослушивании JMS.

Я внимательно прочитал примечания в сообщении Spring 4.1 JMS, но я продолжаю пропустить связь между @JmsListener и возможно, DestinationResolver и как настроить приложение, чтобы указать правильные Destination или Endpoint.

Вот рекомендуемое использование @JmsListener

@Component
public class MyService {

    @JmsListener(containerFactory = "myContainerFactory", destination = "myQueue")
    public void processOrder(String data) { ... }
}

Теперь я не могу использовать это в своем фактическом коде, потому что "myQueue" необходимо прочитать из файла конфигурации с помощью Environment.getProperty().

Я могу настроить соответствующий myContainerFactory с помощью DestinationResolver, но в основном, кажется, вы просто используете DynamicDestinationResolver, если вам не нужен JNDI для поиска очереди на сервере приложений, и вам не нужно было делать какие-либо пользовательские логика ответа. Я просто пытаюсь понять, как Spring хочет, чтобы я указывал имя очереди в параметризованной форме, используя аннотацию @JmsListener.

Далее в блоге я найду ссылку на этот конфигуратор:

@Configuration
@EnableJms
public class AppConfig implements JmsListenerConfigurer {

@Override
public void configureJmsListeners(JmsListenerEndpointRegistrar registrar) {
    registrar.setDefaultContainerFactory(defaultContainerFactory());

    SimpleJmsListenerEndpoint endpoint = new SimpleJmsListenerEndpoint();
    endpoint.setDestination("anotherQueue");
    endpoint.setMessageListener(message -> {
        // processing
    });
    registrar.registerEndpoint(endpoint);
}

Теперь это имеет некоторое значение, и я мог видеть, где это позволит мне установить Destination во время выполнения из какой-либо внешней строки, но это, похоже, противоречит использованию @JmsListener, поскольку оно, кажется, переопределяет аннотации в пользу endpoint.setMessageListener в приведенном выше коде.

Любые советы о том, как указать подходящее имя очереди с помощью @JmsListener?

Ответ 1

В конечном итоге вы можете сделать это прямо сейчас, но это немного запутанно. Вы можете установить пользовательский JmsListenerEndpointRegistry с помощью JmsListenerConfigurer

@Configuration
@EnableJms
public class AppConfig implements JmsListenerConfigurer {

    @Override
    public void configureJmsListeners(JmsListenerEndpointRegistrar registrar) {
        registrar.setEndpointRegistry(customRegistry());
    }

}

а затем переопределить метод registerListenerContainer, что-то вроде

public void registerListenerContainer(JmsListenerEndpoint endpoint, JmsListenerContainerFactory<?> factory) {
    // resolve destination according to whatever -> resolvedDestination
    ((AbstractJmsListenerEndpoint)endpoint).setDestination(resolvedDestination);
    super.registerListenerContainer(endpoint, factory);
}

Но мы могли бы сделать лучше. Пожалуйста, смотрите/голосуйте за SPR-12280

Ответ 2

Также обратите внимание, что в зависимости от варианта использования вы уже можете параметризовать использование файла свойств для среды и PropertySourcesPlaceholderConfigurer

@JmsListener(destinations = "${some.key}")

Согласно https://jira.spring.io/browse/SPR-12289

Ответ 3

Если люди используют @JmsListener с загрузкой spring, вам не нужно настраивать PropertySourcesPlaceholderConfigurer. Он выдает окно

Пример:

класс

@JmsListener(destination = "${spring.activemq.queue.name}")
    public void receiveEntityMessage(final TextMessage message) {
    // process stuff 
}
}

application.properties

spring.activemq.queue.name=some.weird.queue.name.that.does.not.exist

Spring загрузочный вывод

[26-Aug;15:07:53.475]-[INFO ]-[,]-[DefaultMes]-[o.s.j.l.DefaultMessageListenerContainer ]-[931 ]-Successfully refreshed JMS Connection 
[26-Aug;15:07:58.589]-[WARN ]-[,]-[DefaultMes]-[o.s.j.l.DefaultMessageListenerContainer ]-[880 ]-Setup of JMS message listener invoker failed for destination 'some.weird.queue.name.that.does.not.exist' - trying to recover. Cause: User user is not authorized to read from some.weird.queue.name.that.does.not.exist 
[26-Aug;15:07:59.787]-[INFO ]-[,]-[DefaultMes]-[o.s.j.l.DefaultMessageListenerContainer ]-[931 ]-Successfully refreshed JMS Connection 
[26-Aug;15:08:04.881]-[WARN ]-[,]-[DefaultMes]-[o.s.j.l.DefaultMessageListenerContainer ]-[880 ]-Setup of JMS message listener invoker failed for destination 'some.weird.queue.name.that.does.not.exist' - trying to recover. Cause: User user is not authorized to read from some.weird.queue.name.that.does.not.exist 

Это доказывает, что @JmsListener может выбирать значения свойств из application.properties без фактической настройки явного PropertySourcesPlaceholderConfigurer

Надеюсь, это поможет!