0

I have a question about Message Driven Beans (MDB). Is there a way to generate these only at runtime? I want to provide a way in my backend to start or stop receiving messages. It should be controlled via a configuration entry in the database. When starting WildFly, it should also first check whether the MDBs can be started.

Is it Java EE compliant to do without an MDB and create the listeners manually?

I am currently using the following code

@MessageDriven(name = "MyMDB", activationConfig = {
        @ActivationConfigProperty(propertyName = "maxSession", propertyValue = "2"),
        @ActivationConfigProperty(propertyName = "destination", propertyValue = "java:/jms/queue/Test"),
        @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue"),
        @ActivationConfigProperty(propertyName = "acknowledgeMode", propertyValue = "Auto-acknowledge")})
public class JmsConsumer implements MessageListener {

    @Override
    public void onMessage(final Message msg) {

        if (msg instanceof TextMessage) {
            try {
                final String text = ((TextMessage) msg).getText();

                System.out.println("message: " + text + " (" + msg.getJMSRedelivered() + ")");

            } catch (final JMSException e) {
                e.printStackTrace();
            }
        }
    }
}

Would this code also conform to Java EE?

@Singleton
@LocalBean
public class QueueWorkerManager {
    private InitialContext initialContext = null;
    private QueueConnectionFactory queueConnectionFactory = null;
    private Queue queue = null;
    private QueueConnection queueConnection = null;
    private QueueSession queueSession = null;
    private MessageConsumer consumer = null;

    @PostConstruct
    public void init() {
        try {
            this.initialContext = new InitialContext();
            this.queueConnectionFactory = (QueueConnectionFactory) initialContext
                    .lookup("java:/ConnectionFactory");

            this.queue = (Queue) initialContext.lookup(MyQueueSender.WORKER_QUEUE);
            this.queueConnection = queueConnectionFactory.createQueueConnection();
            this.queueSession = queueConnection.createQueueSession(false, Session.CLIENT_ACKNOWLEDGE);

            this.consumer = queueSession.createConsumer(this.queue);
            this.consumer.setMessageListener(new ConsumerMessageListener());

            this.queueConnection.start();
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    @PreDestroy
    public void destroy() {
        this.stopConsumer(this.consumer;
        if(this.consumer != null) {
            try {
                this.consumer.close();
            } catch (JMSException e) {
            }
            this.consumer = null;
        }

        if(this.queueSession != null) {
            try {
                this.queueSession.close();
            } catch (JMSException e) {
            }
            this.queueSession = null;
        }

        if(this.queueConnection != null) {
            try {
                this.queueConnection.close();
            } catch (JMSException e) {
            }
            this.queueConnection = null;
        }
    }
}

public class ConsumerMessageListener implements MessageListener {

    @Override
    public void onMessage(Message message) {
        TextMessage textMessage = (TextMessage) message;
        try {
             System.out.println("message: " + textMessage.getText() + " (" + msg.getJMSRedelivered() + ")");
            message.acknowledge();
        } catch (JMSException | InterruptedException e) {          
            e.printStackTrace();
        }
    }

}
Net_Hans
  • 115
  • 12
  • What about pausing the queues ? https://activemq.apache.org/components/artemis/documentation/latest/management.html The QueueControl can pause and resume the underlying queue. When a queue is paused, it will receive messages but will not deliver them. When it's resumed, it'll begin delivering the queued messages, if any. – ehsavoie Apr 30 '20 at 12:16
  • I have read through the described option. Unfortunately, a complete interruption in message delivery is not my goal. I am looking for a way to deactivate individual MDBs instances. I can identify the instances using the MDB name or the class name. – Net_Hans May 03 '20 at 08:16

1 Answers1

1

I would suggest you to

  • add a @DeliveryActive(false/true) annotation to your MDB in order to boot it in the desired initial state
  • Use JMX or JBoss CLI to programatically change the value of the active attribute of your MDB

Everything is explained here: https://docs.wildfly.org/16/Developer_Guide.html#Message_Driven_Beans_Controlled_Delivery

Good luck

TacheDeChoco
  • 3,683
  • 1
  • 14
  • 17
  • thanks for the help, if I can implement the JMX connection in the program, it would be a nice solution. – Net_Hans May 06 '20 at 06:36