4

I have recently discovered message selectors

@ActivationConfigProperty(
        propertyName="messageSelector",
        propertyValue="Fragile IS TRUE")

My Question is: How can I make the selector dynamic at runtime?

Lets say a consumer decided they wanted only messages with the property "Fragile IS FALSE"

Could the consumer change the selector somehow without redeploying the MDB?

Note: I am using Glassfish v2.1

Fionnuala
  • 90,370
  • 7
  • 114
  • 152
mainstringargs
  • 13,563
  • 35
  • 109
  • 174
  • I think one option could be to get all messages in an MDB and use a programmatic filter based on some configuration loaded from the database. – muasif80 Dec 23 '17 at 12:25
  • I'have asked something similar, see https://stackoverflow.com/questions/48868136/dynamically-change-jmsselector# but doesn't fit exactly your question. – pikimota Mar 02 '18 at 14:38

2 Answers2

5

To my knowledge, this is not possible. There may be implementations that will allow it via some custom server hooks, but it would be implementation dependent. For one, it requires a change to the deployment descriptor, which is not read after the EAR is deployed.

Robin
  • 24,062
  • 5
  • 49
  • 58
  • 1
    This is irritating. And if you want to be compliant, you can't use setMessageListener to get asynchronous messages. I'm trying to build a JMS test app and it's infuriating. :-/ – Chris K Jun 22 '12 at 14:45
  • Message-driven beans are meant to be simple to use and not flexible. If you need flexibility and modify the selector at runtime, you can consume messages programmatically. When you need to change the selector, you would close the existing consumer and create a new consumer with a new selector. – OndroMih Mar 19 '22 at 09:19
1

JMS (Jakarta Messaging) is designed to provide simple means to do simple things and more complicated things to do more complicated but less frequently needed things. Message-driven beans are an example of the first case. To do some dynamic reconfiguration, you need to stop using MDBs and start consuming messages using the programmatic API, using an injected JMSContext and topic or queue. For example:

    @Inject
    private JMSContext context;
    
    @Resource(lookup="jms/queue/thumbnail")
    Queue thumbnailQueue;

    JMSConsumer connectListener(String messageSelector) {
        JMSConsumer consumer = context.createConsumer(logTopic, messageSelector);
        consumer.setMessageListener(message -> {
            // process message
        });
        return consumer;
    }

You can call connectListener during startup, e.g. in a CDI bean:

public void start(@Observes @Initialized(ApplicationScoped.class) Object startEvent) {
    connectListener("Fragile IS TRUE");
}

Then you can easily reconfigure it by closing the returned consumer and creating it again with a new selector string:

consumer.close();
consumer = connectListener("Fragile IS FALSE");
OndroMih
  • 7,280
  • 1
  • 26
  • 44