Search code examples
spring-bootazureservicebusspring-jmsspring-amqp

spring-jms selector doesn't work with servicebus


I'm using spring-jms with azure's servicebus. I'm trying to use selector to distinguish between message types, but I can't get it working. This is my code.

@Component
@Slf4j
public class MessageTestRunner implements CommandLineRunner {

    private static final String QUEUE_NAME = "lva-test-queue";
    private static final String PING_SELECTOR = "selector = 'PING'";
    private static final String PONG_SELECTOR = "selector = 'PONG'";

    private static final String SB_SCHEDULED_ENQUEUE_HEADER = "x-opt-scheduled-enqueue-time";


    private final JmsTemplate jmsTemplate;

    public MessageTestRunner(JmsTemplate jmsTemplate) {
        this.jmsTemplate = jmsTemplate;
    }

    @Override
    public void run(String... args) throws Exception {
        jmsTemplate.convertAndSend(QUEUE_NAME, ping(), m -> {
            m.setStringProperty("selector", "PING");
            return m;
        });
        jmsTemplate.convertAndSend(QUEUE_NAME, pong(), m -> {
            m.setStringProperty("selector", "PONG");
            return m;
        });
    }

    private PingMessage ping() {
        final PingMessage msg = new PingMessage();
        msg.setAt(ZonedDateTime.now());
        return msg;
    }

    private PongMessage pong() {
        final PongMessage msg = new PongMessage();
        msg.setAt(ZonedDateTime.now());
        return msg;
    }


    @JmsListener(destination = QUEUE_NAME, selector = PING_SELECTOR, containerFactory = JMS_FACTORY_NAME)
    public void handle(PingMessage message) {
        log.debug("Handling ping message [{}]", message);
    }

    @JmsListener(destination = QUEUE_NAME, selector = PONG_SELECTOR, containerFactory = JMS_FACTORY_NAME)
    public void handle(PongMessage message) {
        log.debug("Handling pong message [{}]", message);
    }

}

and this is the exception which I get

org.springframework.jms.listener.adapter.ListenerExecutionFailedException: Listener method could not be invoked with incoming message
Endpoint handler details:
Method [public void com.example.MessageTestRunner.handle(com.example.data.model.PingMessage)]
Bean [com.example.MessageTestRunner@7aae1170]
; nested exception is org.springframework.messaging.converter.MessageConversionException: Cannot convert from [com.example.data.model.PongMessage] to [com.example.data.model.PingMessage] for org.springframework.jms.listener.adapter.AbstractAdaptableMessageListener$MessagingMessageConverterAdapter$LazyResolutionMessage@72eb85b7, failedMessage=org.springframework.jms.listener.adapter.AbstractAdaptableMessageListener$MessagingMessageConverterAdapter$LazyResolutionMessage@72eb85b7
    at org.springframework.jms.listener.adapter.MessagingMessageListenerAdapter.invokeHandler(MessagingMessageListenerAdapter.java:118) ~[spring-jms-5.3.10.jar:5.3.10]
    at org.springframework.jms.listener.adapter.MessagingMessageListenerAdapter.onMessage(MessagingMessageListenerAdapter.java:77) ~[spring-jms-5.3.10.jar:5.3.10]
    at org.springframework.jms.listener.AbstractMessageListenerContainer.doInvokeListener(AbstractMessageListenerContainer.java:736) ~[spring-jms-5.3.10.jar:5.3.10]
    at org.springframework.jms.listener.AbstractMessageListenerContainer.invokeListener(AbstractMessageListenerContainer.java:696) ~[spring-jms-5.3.10.jar:5.3.10]
    at org.springframework.jms.listener.AbstractMessageListenerContainer.doExecuteListener(AbstractMessageListenerContainer.java:674) ~[spring-jms-5.3.10.jar:5.3.10]
    at org.springframework.jms.listener.AbstractPollingMessageListenerContainer.doReceiveAndExecute(AbstractPollingMessageListenerContainer.java:318) ~[spring-jms-5.3.10.jar:5.3.10]
    at org.springframework.jms.listener.AbstractPollingMessageListenerContainer.receiveAndExecute(AbstractPollingMessageListenerContainer.java:257) ~[spring-jms-5.3.10.jar:5.3.10]

Is there some configuration/... which should I change to enable selector?

EDIT: The problem seems to be when I disable sending of PONG message, then PONG handler is receiving also PING messages and I can see the error in logs. However I would expect that PING message is never sent to PONG handler as there is selector that won't allow that.

EDIT2: Seems like selector is supported only in service bus premium tier which supports JMS 2.0 (link)


Solution

  • So the issue is with service bus itself. We are using service bus in standard tier which doesn't support selector. More details here and here