简体   繁体   中英

JMSListener - dynamic selector

I currently have a JMSListener as shown below. It uses a selector of a value in a properties file. This works fine.

 @JmsListener(destination = "myQueueDest",
     selector = MyHeaders.SELECTOR_KEY + " = '${myapp.selector_val}'")
 private void consumeData(MyCustomObj mycustomObj) { }

I have a need now to use a dynamic selector with a value in memory, rather than the spring property. Is there a way to use JMSListener (or some other listener mechnaism) to do a selection off the ActiveMQ queue?

Update:

It may be possible to assign an ID to my @JMSListener , and then retrieve it from my JmsListenerEndpointRegistry bean. Get the listener container by ID, cast it to DefaultMessageListenerContainer , and call setMessageSelector() , although I'm not entirely sure if this will work yet.

This requires setting my DefaultJmsListenerContainerFactory bean to have the cache level of CACHE_SESSION .

But this doesn't seem to work, as the listener picks up all messages, regardless of what I set the message selector to be.

JMS specification says the selection string must be provided while creating a consumer. So the answer is NO. Consumer must be closed and recreated with a different selection string to receive messages that match a different selection criteria.

If using JMS API is not a must for your project, then you could explore using Active MQ's native APIs. I am sure the API will have a way to specify a different selection string every time a receive is called. IBM MQ's native API provides such a functionality.

As stated in one of the comments:

the javadoc for setMessageSelector says it can be set at runtime. http://docs.spring.io/spring-framework/docs/2.5.x/api/org/springframework/jms/listener/AbstractMessageListenerContainer.html#setMessageSelector(java.lang.String)

This example explains how to setup at startup but doing it dynamically should be possible with a few more tricks:

@EnableJms
@Configuration
public class JmsConfiguration {

    @Value("${my.int.param:100}")
    private int config;

    @Bean
    public MessageConverter messageConverter() {
        final MappingJackson2MessageConverter converter = new MappingJackson2MessageConverter();
        converter.setTargetType(MessageType.TEXT);
        converter.setTypeIdPropertyName("_type");
        return converter;
    }

    @Bean
    public JmsListenerContainerFactory<?> specialQueueListenerFactory() {
        final String selector = "foo > " + config;
        final DefaultJmsListenerContainerFactory factory = new CustomJmsListenerContainerFactory(selector);
        factory.setMessageConverter(messageConverter());
        return factory;
    }
}

And the CustomJmsListenerContainerFactory

public class CustomJmsListenerContainerFactory extends DefaultJmsListenerContainerFactory {

    private final String selector;

    public CustomJmsListenerContainerFactory(String jmsSelector) {
        this.selector = jmsSelector;
    }

    @Override
    public DefaultMessageListenerContainer createListenerContainer(JmsListenerEndpoint endpoint) {
        final DefaultMessageListenerContainer instance = super.createListenerContainer(endpoint);
        instance.setMessageSelector(selector);
        return instance;
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM