Как добавить задержку в JmsMessage для Artemis Broker в исходящем адаптере Spring Integration

#spring-integration #activemq-artemis

#spring-интеграция #activemq-artemis

Вопрос:

У меня есть адаптер исходящего канала jms. Я хотел бы отправить сообщение моему брокеру Apache Artemis и добавить задержку.

 <int-jms:outbound-channel-adapter connection-factory="scheduledConnectionFactory" channel="tnpScheduledOutboundChannel" destination="tnpScheduledQueue" />
  

Мой java-код, который добавляет заголовок к сообщению spring integration, выглядит следующим образом:

  return MessageBuilder.withPayload(sdpInfo).setHeader("_AMQ_SCHED_DELIVERY",sdpInfo.getDelay()).build();
  

Заголовок добавляется как заголовок spring integration. Но его не улавливает JMS, т.е. потребитель очереди видит его мгновенно.

Нужно ли мне добавлять какой-то JmsHeaderMapper? Может кто-нибудь указать на какую-нибудь документацию или пример.

Обновить

Это сообщение, полученное при отладке в JmsSendingMessageHandler.

 ActiveMQMessage[null]:PERSISTENT/ClientMessageImpl[messageID=0, durable=true, address=null,userID=null,properties=TypedProperties[sequenceNumber=4,file_status=0,sequenceSize=0,_AMQ_SCHED_DELIVERY=14685858,timestamp=1605707114145,correlationId=4d6fa6c8-fdcb-d69b-cd60-d260264545f5]]
  

Если я использую непосредственно в активаторе JmsTemplate

 public void sendDelayMessage(SdpInfoTemplate<?> message, long deliveryDelay, String queue) {
        jmsTemplateDelay.setDeliveryDelay(deliveryDelay);
        jmsTemplateDelay.setDeliveryMode(DeliveryMode.PERSISTENT);
        jmsTemplateDelay.convertAndSend("sdp-file-tnp-scheduled-dimitris-test", message, m -> {
            m.setLongProperty("_AMQ_SCHED_DELIVERY", deliveryDelay);
            m.setStringProperty("TRANSACTION_ID",message.getTransactionId());
            return m;
        });
  

Ключевая часть jmsTemplateDelay.setDeliveryDelay(deliveryDelay);

Это будет запланировано, если я не установлю это, оно будет проигнорировано, и сторона потребителя немедленно получит сообщение

Ответ №1:

DefaultJmsHeaderMapper Используется по JmsSendingMessageHandler умолчанию. Он сопоставляет все заголовки jmsMessage.setObjectProperty(propertyName, value); , если значения находятся в поддерживаемых типах:

 private static final List<Class<?>> SUPPORTED_PROPERTY_TYPES = Arrays.asList(new Class<?>[] {
        Boolean.class, Byte.class, Double.class, Float.class
  

Или вы потеряете свой заголовок где-то посередине…

Обновить

Извините, но вы нас путаете. Ваш _AMQ_SCHED_DELIVERY ineed присутствует как свойство в этом последнем сообщении JMS. Когда вы говорите об setDeliveryDelay() этом, это совершенно другая история.

Что вы можете сделать, это что-то вроде расширения для DynamicJmsTemplate . Переопределите его getDeliveryDelay() и возьмите требуемое значение из ThreadLocal заполняемого вами перед отправкой сообщения на него <int-jms:outbound-channel-adapter> .

Это то, что мы определенно можем добавить в упомянутый DynamicJmsTemplate и DynamicJmsTemplateProperties для решения JmsSendingMessageHandler . Но на данный момент обходной путь реализует только вашу собственную ThreadLocal переменную для этой deliveryDelay опции.

Комментарии:

1. Я обновил свой ответ, похоже, я не теряю свой заголовок. Кроме того, если я использую jmsTemlpate напрямую, а я этого не jmsTemplateDelay.setDeliveryDelay(deliveryDelay); делаю, сообщение отправляется немедленно

2. Смотрите ОБНОВЛЕНИЕ в моем ответе.

3. Расчет времени в миллисекундах был неправильным, я передавал только разницу, нет необходимости добавлять setDeliveryDelay, который сводится к _AMQ_SCHED_DELIVERY самому себе