users@jms-spec.java.net

[jms-spec users] Re: JMS_SPEC-134: Declarative Annotation Based JMS Listeners

From: Nigel Deakin <nigel.deakin_at_oracle.com>
Date: Thu, 27 Aug 2015 17:45:02 +0100

On 27/08/2015 16:11, Clebert Suconic wrote:
>
> On Thu, Aug 27, 2015 at 10:37 AM, Nigel Deakin <nigel.deakin_at_oracle.com <mailto:nigel.deakin_at_oracle.com>> wrote:
>
> Hi Clebert,
>
> We should definitely discuss how the JMS 2.0 proposals proposals for batch delivery (since deferred) might work with
> the new-style MDBs and listener beans.
>
> As you know, MDB users can turn off XA transactions using the @TransactionManagement annotation, and can remove the
> number of network round-trips using an acknowledgement mode of DUPS_OK. Why is this not sufficient?
>
>
> Because users want to have the messages and their Database operations in transaction.
> I have seen this pattern since my days of consultant.
>
> This goes beyond my JBoss. I'm not concerned about any specific usecase from JBoss, but from what I see from users doing
> on day by day with their messaging systems.
>
> DupsOK is ok, but that doesn't guarantee the semantic these users have.
>
>
> Or do you have a specific need to have XA transactions that cover multiple messages?
>
>
>
> From what I see, EE users will want to have async messages, but will need transactions.. the easiest way to do XA
> Transactions between JMS and Databases are through EE... for that reason, users are *over-using* MDBs... and XA transaction
>
> And that's limiting any improvements done by any messaging provider.
>
> A few handful users will write standalone application to batch things properly...
>
>
> So, I think we really should propose a way to batch things through MDBs. At least these users would take full advantage
> of asynchronous message systems and still do transactions.
>

OK, thanks. So the user *does* want XA transactions. They just don't want every single message to be in a separate
transaction.

As you will of course remember, you proposed "batch delivery" for JMS 2.0. This was a way of passing an array (or
whatever) of messages in the same onMessage() call.

(Incidentally, another approach might be to provide a mechanism for grouping multiple container-managed transaction MDB
onMessage() calls together under a single transaction. I know Weblogic has a proprietary feature like this, others may too.)

I went back to look at the ideas we discussed for batch message delivery. This was back in December 2011! The basic idea
was to have a new BatchMessageListener interface, which defined a method onMessages.

   public interface BatchMessageListener {
     void onMessages(Message[] messages);
   }

During that discussion we decided that the application needed to be able to specify maxBatchSize and batchTimeout:

* maxBatchSize - The maximum batch size that should be used. Must be greater than zero.

* batchTimeout - The batch timeout in milliseconds. A value of zero means no timeout is required The JMS provider may
override the specified timeout with a shorter value.

Now it's JMS 2.1, and we're discussing my proposals that JMS MDBs don't need to implement a fixed interface and can
define their own callback methods.

I've already proposed that a callback method could be defined with two parameters, the first of which was a TextMessage,
and the second was the JMSCorrelationID of that message.

@JMSListener(lookup="java:global/Trades", type=JMSListener.Type.QUEUE)
public void processTrade(TextMessage tradeMessage, @MessageHeader(Header.JMSCorrelationID) String correlationId){
   ...
}

An obvious extension would be to allow these parameters to be arrays:

@JMSListener(lookup="java:global/Trades", type=JMSListener.Type.QUEUE)
public void processTrades(TextMessage[] tradeMessages, @MessageHeader(Header.JMSCorrelationID) String[] correlationIds){
   ...
}

We'd need to define some new annotations to allow maxBatchSize and batchTimeout to be specified. Perhaps:

@BatchConfig(maxBatchSize=100, batchTimeout=10000);
@JMSListener(lookup="java:global/Trades", type=JMSListener.Type.QUEUE)
public void processTrades(TextMessage[] tradeMessages, @MessageHeader(Header.JMSCorrelationID) String[] correlationIds){
...
}

No doubt there are other possibilities, and I know arrays are a bit old-fashioned, but I hope this gives an idea.

Is this on the right track, Clebert? If so I'll write this up in a bit more detail.

Nigel