Как слушать динамические места назначения с помощью Spring Boot? - PullRequest
1 голос
/ 20 мая 2019

У нас есть приложение, использующее Spring Boot и его средство JMS. Во время выполнения у нас есть разные производители, которые подключаются к сети и сообщают нашему приложению название темы или очереди для прослушивания. Прямо сейчас у нас есть:

@JmsListener(destination = "helloworld.q")
public void receive(String message) {
  LOGGER.info("received message='{}'", message);
}

, который работает, когда мы отправляем сообщение в тему helloworld.q. Проблема в том, что мы не будем знать, каким будет название темы до времени выполнения, а JmsListener, похоже, хочет иметь постоянное выражение.

Производители сообщений подключатся к нашему экземпляру ActiveMQ и передадут сообщение, сообщающее нам, что нам нужно начать слушать их темы, такие как «Васаби», «Белая бумага», «Спутник-майор», «BigBoosters» и т. Д. чтобы знать во время выполнения, какие темы нам нужно начать слушать.

Я прочитал документацию Spring, которая объясняет, как слушать темы / очереди во время выполнения (вроде):

@Configuration
@EnableJms
public class ReceiverConfig implements JmsListenerConfigurer {

  @Override
  public void configureJmsListeners(JmsListenerEndpointRegistrar registrar) {
    SimpleJmsListenerEndpoint endpoint = new SimpleJmsListenerEndpoint();
    endpoint.setId("myJmsEndpoint");
    endpoint.setDestination("anotherQueue");
    endpoint.setMessageListener(message -> {
        // processing
    });
    registrar.registerEndpoint(endpoint);
  }

  // other methods...
}

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

Мы используем Spring 2. x .

1 Ответ

2 голосов
/ 20 мая 2019

Вы можете использовать заполнитель свойства для имени пункта назначения

@SpringBootApplication
public class So56226984Application {

    public static void main(String[] args) {
        SpringApplication.run(So56226984Application.class, args);
    }

    @JmsListener(destination = "${foo.bar}")
    public void listen(String in) {
        System.out.println(in);
    }

    @Bean
    public ApplicationRunner runner(JmsTemplate template) {
        return args -> template.convertAndSend("baz", "qux");
    }

}

Затем установите свойство, например, в application.yml для приложения Spring Boot или в свойстве командной строки при запуске JVM

-Dfoo.bar=baz

EDIT

Вы можете сделать компонент-слушатель прототипом и настроить свойство среды.

@SpringBootApplication
public class So56226984Application {

    public static void main(String[] args) {
        SpringApplication.run(So56226984Application.class, args).close();
    }

    @Bean
    public ApplicationRunner runner(JmsTemplate template, JmsListenerEndpointRegistry registry,
            ConfigurableApplicationContext context) {

        return args -> {
            Scanner scanner = new Scanner(System.in);
            String queue = scanner.nextLine();
            Properties props = new Properties();
            context.getEnvironment().getPropertySources().addLast(new PropertiesPropertySource("queues", props));
            while (!"quit".equals(queue)) {
                System.out.println("Adding " + queue);
                props.put("queue.name", queue);
                context.getBean("listener", Listener.class);
                template.convertAndSend(queue, "qux sent to " +  queue);
                System.out.println("There are now " + registry.getListenerContainers().size() + " containers");
                queue = scanner.nextLine();
            }
            scanner.close();
        };
    }

    @Bean
    @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
    public Listener listener() {
        return new Listener();
    }

    public static class Listener {

        @JmsListener(destination = "${queue.name}")
        public void listen(String in) {
            System.out.println(in);
        }

    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...