Spring DefaultMessageListenerContainer/SimpleMessageListenerContainer (JMS/AMQP) Конфигурация аннотации

Поэтому я работаю над проектом, в котором многие команды используют общие службы и следуют общей архитектуре. Одной из используемых служб является обмен сообщениями, в настоящее время JMS с ActiveMQ. Практически все команды обязаны соблюдать строгий набор правил для создания и отправки сообщений, а именно, все подписано на публикацию, а отправляемые сообщения в некоторой степени похожи на следующие:

public class WorkDTO {

   private String type;
   private String subtype;
   private String category;
   private String jsonPayload; // converted custom Java object

}

'JsonPayload' происходит из базового класса, из которого расширяются все команды, поэтому у него есть общие атрибуты.

Таким образом, в основном в JMS каждый всегда отправляет одно и то же сообщение, но на разные темы ActiveMQ. Когда сообщение (WorkDTO) отправляется через JMS, сначала оно преобразуется в объект JSON, а затем отправляется в TextMessage.

Всякий раз, когда группа желает создать подписчика для темы, она создает DefaultMessageListenerContainer и настраивает его соответствующим образом для получения сообщений (мы используем конфигурацию Spring на основе Java). По сути, каждый DefaultMessageListenerContainer, который определяет команда, практически одинаков, за исключением, возможно, пункта назначения, из которого следует получать сообщения, и обработчика сообщений.

Мне было интересно, как кто-нибудь подойдет к дальнейшему абстрагированию конфигурации обмена сообщениями с помощью аннотаций в таком случае? Это означает, что, поскольку все в значительной степени обязаны следовать одним и тем же требованиям, может быть полезно что-то вроде следующего:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Listener {

     String destination();

     boolean durable() default false;

     long receiveTimeout() default -1; // -1 use JMS default

     String defaultListenerMethod() default "handleMessage";


     // more config details here

}


@Listener(destination="PX.Foo", durable=true)
public class FooListener {

     private ObjectMapper mapper = new ObjectMapper(); // converts JSON Strings to Java Classes

     public void handleMessage(TextMessage message){

         String text = message.getText();
         WorkDTO dto = mapper.readValue(text, WorkDto.class);

         String payload = dto.getPayload();
         String type = dto.getType();
         String subType = dto.getSubType();
         String category = dto.getCategory();
     }
}

Конечно, я пропустил часть о том, как настроить DefaultMessageListenerContainer с помощью аннотации @Listener. Я начал изучать BeanFactoryPostProcessor для создания необходимых классов и добавления их в контекст приложения, но я не знаю, как все это сделать.

Причина, по которой я задаю вопрос, заключается в том, что мы переключаемся на AMQP/RabbitMQ из JMS/ActiveMQ и хотели бы еще больше абстрагировать конфигурацию обмена сообщениями с помощью аннотаций. Я знаю, что AMQP не похож на JMS, поэтому детали конфигурации будут немного отличаться. Я не верю, что мы перейдем с AMQP на что-то другое.

Здесь командам нужно только знать название места назначения и хотят ли они продлить срок действия своей подписки.

Это просто то, что пришло мне в голову совсем недавно. Есть мысли по этому поводу?

Я не хочу делать что-то слишком сложное, хотя другой альтернативой является создание вспомогательного метода, который возвращает предварительно сконфигурированный DefaultMessageListenerContainer с указанием места назначения и обработчика сообщения:

@Configuration
public class MyConfig{

    @Autowired
    private MessageConfigFactory configFactory;

    @Bean
    public DefaultMessageListenerContainer fooListenerContainer(){

         return configFactory.getListenerContainer("PX.Foo", new FooListener(), true);
    }
}

class MessageConfigFactory {

    public DefaultMessageListenerContainer getListener(String destination, Object listener, boolean durable) {

      DefaultMessageListenerContainer l = new DefaultMessageListenerContainer();
      // configuration details here

      return l;

    }
}

0 ответов

Другие вопросы по тегам