javawildflyactivemq-artemisjava-ee-8message-listener

Why is MessageListener consuming ActiveMQ messages before a pool is ready to work on the message?


Application deployed on WildFly using Java EE javax.jms.MessageListener to consume messages from queue.

@ResourceAdapter("remote-artemis")
@MessageDriven(name = "DeliveryMDB", activationConfig = {
        @ActivationConfigProperty(propertyName = "destinationLookup", propertyValue = "delivery_inbound"),
        @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue"),
        @ActivationConfigProperty(propertyName = "acknowledgeMode", propertyValue = "Auto-acknowledge")
})
@TransactionManagement(TransactionManagementType.CONTAINER)
@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
@Pool(value="delivery-mdb-pool")

This MessageListener consumes all messages on the queue regardless of if a pool is ready to work on the message. This has multiple negative effects, such as having to wait for the application to handle all messages before shutdown is triggered (problematic because we have thousands of messages in queue). If a forced shutdown is needed then all the messages are gone. We can no longer track the number of message in queue in ActiveMQ because they are all consumed.

I expected the MessageListener to only consume a message when a pool was ready. I have tried to read the ActiveMQ documentation, but cannot find anything relevant.

Is this normal behavior?


Solution

  • As far as I can tell what you're seeing is the expected behavior. This is because the creation of sessions and receiving of messages by the JCA RA is independent of the instance pool size used by the EE container for the MDB.

    In short, the JCA RA receives the message from the broker and passes it to an instance of the MDB. If no MDB instance is available the JCA RA just waits for one to become available. If you don't want to get into this kind of situation then you should set the maxSession activation configuration property on the MDB to the same value you use for the MDB instance pool (i.e. 8 in this case).

    Also, aside from this, it is important to keep in mind that the core client used within the JCA RA will fetch a batch of messages all at once and buffer them so that it doesn't have to make a network round-trip to the broker for every single message. This is a performance optimization controlled by the consumerWindowSize activation configuration property and it impacts all core clients, not just ones in an EE context. This will also impact your use-case. If, for some reason, you want the message count in the broker to exactly reflect how many messages have been consumed and not include any buffered messages then you can set the consumerWindowSize to 0, but that will negatively impact performance, potentially severely.