jsr343-experts@jms-spec.java.net

[jsr343-experts] Re: [jms-spec users] Re: (JMS_SPEC-36) Allow messages to be delivered asynchronously in batches

From: Nigel Deakin <nigel.deakin_at_oracle.com>
Date: Tue, 20 Mar 2012 09:50:54 +0000

On 20/03/2012 00:47, Reza Rahman wrote:
> I hate to be the spoilsport, but how about just adding setBatchSize() to the context/session/connection and leave it
> be for now (sort of like the batch size concept in ORM tools like Hibernate)? It would basically be a mode-switch of
> the existing APIs to start doing things in batches under the hood. I know, it does not have the syntactic sugar, but
> it would meet the need for performance optimization (provided that's the key motivation for this feature)...
Please elaborate. I don't see what that would achieve without an API to pass the batch to the application in one go.

It may be worth me repeating Clebert's original proposal (from the top of this thread on 26 July 2011):

I'm proposing this because it's a common problem among message
processing. When you have an event, you are forced to make a
transaction for each message you receive.

Users would be able to do optimizations like this:

public void onmessage(Message[] messages)
{
      Money ammount = new SomePseudoObjectMoney(); // whatever you wnat here

      for (Message msg : messages)
      {
           ammount.add(msg.getWhateverNumberProperty());
      }

      // you didn't need to make 100 updates here, a single update was fine!
      // and a single commit also.
      database.update(ammount);
}

It would be nice to have this as part of the spec, instead of being a
proprietary extension.

More views please. This is the first time anyone has objected to this feature (no-one objected to it being in the Early
Draft).

Clebert - would you like to join this discussion?

Nigel


>
> On 3/16/2012 8:46 AM, Nigel Deakin wrote:
>> There have been some interesting discussions going on since last September over in the EJB EG about how MDBs could be
>> made more general so they didn't need to implement MessageListener. It's worth going back and reading the "MDB
>> Improvements" thread. However, as John notes, this looks like something that they will be deferring until Java EE 8.
>>
>> (Perhaps that's just as well given that we still haven't completed defining the annotations for injecting
>> MessagingContexts)
>>
>> Here in JMS 2.0, the proposals below for message batching don't just apply to MDBs. They apply to Java SE
>> applications as well. Even though we might want to support the use of CDI features when using JMS in a Java SE
>> environment I think it unlikely that we would want to make it mandatory - at least as long as CDI is not part of Java
>> SE. We certainly don't want to make new features such as message batching dependent on it. So we would still need to
>> extend the existing "old-fashioned" async delivery API to support message batching.
>>
>> In addition, if we adopt the proposal for BatchMessage below then message batching would also be made available to
>> synchronous consumers, and also perhaps when sending messages (if others join Rob in supporting this).
>>
>> Nevertheless, EG members need to consider whether adopting either proposal for message batching at this stage would
>> prejudice any future simplifications along the lines Reza suggested.
>>
>> More comments would be welcome. Please indicate your preferences
>>
>> Question 1:
>>
>> A. We should keep the async batch message delivery feature using the BatchMessageListener API proposed in the Early
>> Draft
>> B. We should keep the async batch message delivery feature but use the BatchMessage API proposed below (Nigel, Rob)
>> C. We should remove the async batch message delivery feature from JMS 2.0 and consider it again for Java EE 8. (Reza)
>>
>> Question 2:
>>
>> If option (B) is chosen, should we allow BatchMessages to be used by producer applications to send messages more
>> efficiently? (Such BatchMessages would be broken into their constituent messages before they are added to the
>> destination)
>>
>> Y (Rob)
>> N
>> Not sure: (Nigel)
>>
>> Question 3:
>>
>> if option (B) is chosen, should we extend it to support sync batch delivery as well as async?
>>
>> Y (Nigel, Rob)
>> N:
>> Not sure:
>>
>> Thanks,
>>
>> Nigel
>>
>> On 16/03/2012 01:53, John D. Ament wrote:
>>> Not sure if it has been seen by all members of this EG, but the EJB EG came back with a response from the platform
>>> team. it looks like no changes to JCA are included in EE7, and changes to JCA would be required to make these happen.
>>>
>>> On Thu, Mar 15, 2012 at 2:35 PM, Reza Rahman <reza_rahman_at_lycos.com <mailto:reza_rahman_at_lycos.com>> wrote:
>>>
>>> I'd prefer we table this until the outdated interface-based MDB/JMS message listener paradigm can be updated to
>>> something modern/CDI-based/POJO-centric that supports something like this:
>>>
>>> @JmsListens
>>> @JmsQueue("someQueue")
>>> @JmsBatchSize(10)
>>> public void processMessages (Message[] messages)
>>>
>>>
>>> On 3/13/2012 3:02 PM, Nigel Deakin wrote:
>>>
>>> I'd like to resurrect our discussion on batch delivery.
>>> This is http://java.net/jira/browse/JMS_SPEC-36
>>>
>>> As I mentioned earlier, and explicitly wrote in section A.2. "Unresolved issues in the JMS 2.0 Early Draft",
>>> I'm concerned that the API for batch delivery is rather more complicated than it needs to be. Here is what I
>>> wrote:
>>>
>>> "The proposed API involves a new BatchMessageListener interface. This has necessitated the addition of two
>>> new methods on MessageConsumer and five additional methods on MessagingContext.
>>>
>>> "In addition, since a MessageConsumer can only have a single listener it has been necessary to explain how a
>>> call to setBatchBatchListener would override a previous call to setMessageListener. This is complicated and
>>> potentially confusing.
>>>
>>> "One alternative way to allow messages to be delivered in batches might be to invent a new message type, a
>>> BatchMessage, which would contain an ordered collection of normal Message objects. This would allow batches
>>> of messages to be delivered to a normal MessageListener and so remove the need for a separate
>>> BatchMessageListener interface. It would also allow batch delivery to synchronous consumers."
>>>
>>> Another advantage of replacing BatchMessageListener with BatchMessage is that it would avoid the need to
>>> extend resource adapters and MDB code to support the new listener interface.
>>>
>>> I'd now like to take this new idea further. The main change is that we would drop the new
>>> BatchMessageListener interface with its method onMessages(Message[] messages). Instead the existing
>>> MessageListener interface would be used with its existing method onMessage(Message message). When the JMS
>>> server wants to deliver a batch of messages to the consumer it would create a new type of message, a
>>> javax.jms.BatchMessage, load it up with a batch-worth of messages, and then deliver it to the
>>> MessageListener in the usual way.
>>>
>>> I've sketched out below what the new API might look like. Before I work this through in detail, I'd like to
>>> invite feedback on various points of principle:
>>>
>>> ==================================================================================
>>>
>>> QUESTIONS
>>>
>>> 1. Which is better, using a BatchMessageListener or allowing the server to create BatchMessage objects?
>>>
>>> 2. I'm currently suggesting that BatchMessage objects would never be created by the application, They would
>>> simply be a convenient container object that the JMS provider could use when delivering batches of messages.
>>> However we could if we wanted allow the producer client to create them and use them to send batches of
>>> messages to the server, which would then break them down into their constituent messages before adding to
>>> the destination. Would this have any benefit?
>>>
>>> 3. Should we take advantage of BatchMessage objects to allow the server to deliver messages in batches to a
>>> synchronous consumer?
>>>
>>> ==================================================================================
>>>
>>> SUMMARY OF PROPOSAL
>>>
>>> THE NEW BatchMessage CLASS
>>>
>>> /** An <CODE>BatchMessage</CODE> object is a special type of message which can be
>>> * created by the JMS provider and used to deliver an ordered batch of ordinary
>>> * messages to a consumer. It inherits from the <CODE>Message</CODE> interface
>>> * and adds methods to allow the individual messages to be extracted.
>>> *
>>> * Note that this message type is created by the JMS provider, not by
>>> * the application, and therefore only provides public methods to
>>> * extract messages, not to set them.
>>> *
>>> * @see javax.jms.ObjectMessage
>>> * @see javax.jms.BytesMessage
>>> * @see javax.jms.MapMessage
>>> * @see javax.jms.Message
>>> * @see javax.jms.StreamMessage
>>> * @see javax.jms.TextMessage
>>> */
>>>
>>> public interface BatchMessage extends Message {
>>>
>>> /**
>>> * returns the number of messages in this BatchMessage
>>> *
>>> * @return the number of messages in this BatchMessage
>>> *
>>> * @throws JMSException if the JMS provider fails to get the size due to some internal error
>>> */
>>> int size() throws JMSException;
>>>
>>> /**
>>> * returns the Message at the specified position in the batch
>>> * @param index index of the Messagr to return
>>> *
>>> * @return the Message at the specified position in the batch
>>> *
>>> * @throws JMSException if the JMS provider fails to get the Message due to some internal error
>>> */
>>> Message get(int index) throws JMSException;
>>> }
>>>
>>> NEW METHODS ON Session FOR CREATING A MESSAGE CONSUMER
>>>
>>> In addition, two new methods on Session would be needed to allow the batch size and timeout when creating a
>>> MessageConsumer:
>>>
>>> MessageConsumer createConsumer(Destination destination, String messageSelector, boolean NoLocal, int
>>> maxBatchSize, long batchTimeout)
>>>
>>> MessageConsumer createDurableConsumer(Topic topic, String name, String messageSelector, boolean noLocal,
>>> int maxBatchSize, long batchTimeout)
>>>
>>> NEW METHODS ON MessagingContext FOR SETTING A MESSAGE LISTENER
>>>
>>> We would need similar new methods on MessagingContext. You will remember that this currently offers methods
>>> to set the message listener directly, five for MessageListener and five for BatchMessageListener, making ten
>>> in total.
>>>
>>> We would drop the latter five, and add two new methods methods (one for queues and non-durable subscriptions
>>> and one for durable subscriptions) to allow batch size and timeout to be supplied, making seven in total:
>>>
>>> setMessageListener(Destination destination, String messageSelector, boolean noLocal, int maxBatchSize, long
>>> batchTimeout, MessageListener listener)
>>>
>>> setMessageListener(Topic topic, String subscriptionName, String messageSelector, boolean noLocal, int
>>> maxBatchSize, long batchTimeout, MessageListener listener)
>>>
>>> NEW METHODS ON MessagingContext FOR CREATING A SYNC MESSAGE CONSUMER
>>>
>>> If we wanted to extend this feature to synchronous consumers we would also add two new methods for creating
>>> a SyncMessageConsumer (one for queues and non-durable subscriptions and one for durable subscriptions):
>>>
>>> SyncMessageConsumer createSyncConsumer(Destination destination, String messageSelector, boolean noLocal, int
>>> maxBatchSize, long batchTimeout)
>>>
>>> SyncMessageConsumer createSyncDurableConsumer(Topic topic, String name, String messageSelector, boolean
>>> noLocal, int maxBatchSize, long batchTimeout)
>>>
>>> ==================================================================================
>>>
>>> I hope this is clear! If not, please let me know.
>>>
>>> Nigel
>>>
>>>
>>>
>>> -----
>>> No virus found in this message.
>>> Checked by AVG - www.avg.com <http://www.avg.com>
>>> Version: 2012.0.1913 / Virus Database: 2114/4872 - Release Date: 03/15/12
>>>
>>>
>>>
>>>
>> No virus found in this message.
>> Checked by AVG - www.avg.com <http://www.avg.com>
>> Version: 2012.0.1913 / Virus Database: 2114/4873 - Release Date: 03/15/12
>>
>