jsr343-experts@jms-spec.java.net

[jsr343-experts] Re: [jms-spec users] Re: JMS Support for DI

From: Reza Rahman <reza_rahman_at_lycos.com>
Date: Thu, 10 Nov 2011 08:50:02 -0500

If the Seam JMS style solution is a no-go, this might be the only way to
go forward. I think it should be explored seriously.

On 11/10/2011 6:39 AM, Nigel Deakin wrote:
> On 10/11/2011 00:45, Clebert Suconic wrote:
>> Thanks Bruce.. I was a bit doubtful it was a good idea at first.. but
>> later I talked to some other people and more
>> people seem to like the idea.
>
> It's good to continue this discussion.
>
>>
>> What I just thought also was adding the idea of a context.
>>
>> in 90% of the cases I have seen, users are always creating a consumer
>> within a single Session. (because you have also
>> the requirement of a session per thread, per the spec).
>
> I'm not sure I follow. A Consumer is always tied to a single Session.
> Do you mean that users are always creating one Consumer per Session?
>
>>
>> In case you need more objects as part of the same context
>> (request/response case maybe), you could do this:
>>
>> Consumer sameContextProducer = producer.getContext().createConsumer();
>>
>> On this case both objects would be part of the same context. a commit
>> call on either consumer.
>>
>> This would be the same idea as the Session. If people don't like the
>> name..fine.. we can keep the name of Session here..
>> but I guess you get the idea.
>
> Are you thinking of the responder code, which receives the request
> message and sends the reply message? I agree that you might want to
> perform both steps in the same transaction, which means the same
> session (you could achieve this with two sessions in an XA
> transaction, but that may be less efficient).
>
> By suggesting a "context" object you seem to be re-inventing the
> Session, so I don't see the benefit.
>
> Perhaps we should start by reviewing which API classes we are trying
> to merge or eliminate.
>
> 1. Merge Connection and Session
>
> This is straightforward for Java EE applications, since you can have
> only one session per connection anyway.
>
> We could replace:
>
> Connection connection = connectionFactory.createConnection();
> Session session =
> connection.createSession(false,Session.AUTO_ACKNOWLEDGE);
>
> with:
>
> NewConnection newConnection =
> connectionFactory.createConnection(false,Session.AUTO_ACKNOWLEDGE);
>
> But this would be a restriction for Java SE applications since we
> would be preventing the application making use of the same Connection
> from multiple threads at the same time. We would have to think
> carefully whether we want to define an API for Java EE use only.
>
> 2. Merge Session and Producer
>
> This looks straightforward, at least in theory. I think we could replace
>
> // inject connectionFactory and queue in the usual way
>
> Connection connection = connectionFactory.createConnection();
> Session session =
> connection.createSession(false,Session.AUTO_ACKNOWLEDGE);
> MessageProducer messageProducer = session.createProducer(queue);
> TextMessage textMessage = session.createTextMessage(payload);
> messageProducer.send(queue,textMessage,DeliveryMode.PERSISTENT,0,0);
>
> with:
>
> NewConnection newConnection =
> connectionFactory.createConnection(false,Session.AUTO_ACKNOWLEDGE);
> TextMessage textMessage = newConnection .createTextMessage(payload);
> newConnection.send(queue,textMessage,DeliveryMode.PERSISTENT,0,0);
>
> (with a simpler variants that used the default delivery mode, priority
> and timeToLive)
>
> There would be no problem using the same NewConnection to send
> messages to multiple destinations, so long as the NewConnection was
> only used by one thread at a time.
>
> 3. Merge Session and Async Consumer.
>
> The API to this looks relatively straightforward, since we could
> specify all the former MessageConsumer's state to the
> setMessageListener() method:
>
> NewConnection newConnection =
> connectionFactory.createConnection(false,Session.AUTO_ACKNOWLEDGE);
> newConnection.setMessageListener(queue,messageListener,messageSelector,noLocal);
>
>
> Note
>
> (a) Existing Java EE restrictions on creating async consumers would
> mean this would not be permitted in Java EE applications anyway
>
> (b) that existing JMS threading restrictions means that once you did
> this you couldn't use the newConnection to send messages.
>
> 4. Merge Session and Sync Consumer
>
> The obvious way to combine these would be to specify all the former
> MessageConsumer's state on the receive() method:
>
> NewConnection newConnection =
> connectionFactory.createConnection(false,Session.AUTO_ACKNOWLEDGE);
> Message someMessage =
> newConnection.receive(queue,messageListener,messageSelector,noLocal,timeout);
>
> However this would prevent implementations enhancing performance by
> creating state on the server to improve the performance when
> delivering multiple messages to the same consumer, or caching messages
> on the MessageConsumer prior to the call to receive(). I think this
> would be a big drawback.
>
> One possible solution might be to require the application to "express
> its interest" in consuming messages before it called receive().
> Something like:
>
> NewConnection newConnection =
> connectionFactory.createConnection(false,Session.AUTO_ACKNOWLEDGE);
> newConnection.startReceiving(queue,messageListener,messageSelector,noLocal,timeout);
>
> Message someMessage1 =
> newConnection.receive(queue,messageListener,messageSelector,noLocal,timeout);
> Message someMessage2 =
> newConnection.receive(queue,messageListener,messageSelector,noLocal,timeout);
> Message someMessage3 =
> newConnection.receive(queue,messageListener,messageSelector,noLocal,timeout);
> newConnection.endReceiving(queue,messageListener,messageSelector,noLocal,timeout);
>
>
> However I'm not sure that would represent an improvement: if you
> didn't know about JMS and looked at the above code you would
> immediately want to replace it with:
>
> NewConnection newConnection =
> connectionFactory.createConnection(false,Session.AUTO_ACKNOWLEDGE);
> NewConsumer newConsumer =
> newConnection.startReceiving(queue,messageListener,messageSelector,noLocal);
> Message someMessage1 = newConsumer.receive(timeout);
> Message someMessage2 = newConsumer.receive(timeout);
> Message someMessage3 = newConsumer.receive(timeout);
> newConsumer.close()
>
> ...which is almost exactly what we have now.
>
> 5. Eliminating javax.jms.Message when sending messages
>
> We've discussed this before. It would certainly be possible to create
> convenience methods for use when the user wanted to send a
> TextMessage, ObjectMessage and perhaps the other types, and the user
> did not want to set any message properties:
>
> Replace:
>
> TextMessage textMessage = newConnection.createTextMessage(payload);
>
> newConnection.send(queue,textMessage,DeliveryMode.PERSISTENT,0,0);
>
> With:
>
>
> newConnection.send(payload,queue,textMessage,DeliveryMode.PERSISTENT,0,0);
>
> (I'm not sure whether offering this for BytesMessage, MapMessage and
> StreamMessage would prevent vendor optimisations for large messages.)
>
> Since message properties are a very important part of JMS, users would
> still need to be able to create Message objects. I suppose we could
> consider adding the message properties to the send() call, but I don't
> think this would represent a simplification since the user would still
> need to create an intermediate Map or Properties object (or even a new
> MessageProperties object).
>
>
> newConnection.send(payload,messageProperties,queue,textMessage,DeliveryMode.PERSISTENT,0,0);
>
> 6. Eliminating javax.jms.Message when receiving messages
>
> I'm much less convinced that we can eliminate the Message object when
> consuming messages.
>
> For the sync case, we could invent:
>
> newConsumer.receiveText(timeout);
>
> but this would be one of 15 new methods needed to handle all the five
> message types and the three variants of receive().
>
> This also raises the question of what should this method do if the
> next message is not a TextMessage. Should it throw a
> ClassCastException? Should this method add an implicit message
> selector that only received TextMessages? I think this may be
> introducing more complexities than it removes.
>
> For the async case, we would need to invent
>
> onMessage(String payload);
>
> and four other callbacks. Similarly, I don't think this is making
> things simpler for applications.
>
> 7. Conclusions
>
> So here is what I think may be possible:
>
> a. Merging Session and Connection (easy for Java EE, a major
> restriction for Java SE)
> b. Removing the need to create a MessageProducer for anything
> c. Removing the need to create a MessageConsumer when using a
> MessageListener (Java SE only)
>
> This would leave us with the need to create a MessageConsumer when
> using receive().
>
> In addition to all this, we could offer convenience methods which
> avoided the need to create a Message when sending messages, but this
> would only be useful in limited cases, and applications would still
> need to handle Message objects when receiving messages.
>
> Note: The above is just a brainstorm, not a carefully worked out
> proposal. Depending on comments, I might attempt such a proposal in
> the future.
>
> Thoughts?
>
> Nigel
>
>
>>
>>
>> This would need to be done on a new package as we would need the
>> current stuff backward compatible.
>
> Indeed. We'd probably want to use new interface names as well. I used
> NewConnection above to illustrate this, but I'm not suggesting this
> would be a suitable name. We could perhaps use a completely new word
> such as JMSContext or JMSHandle.
>
> Nigel
>
>
> -----
> No virus found in this message.
> Checked by AVG - www.avg.com
> Version: 2012.0.1869 / Virus Database: 2092/4607 - Release Date: 11/09/11
>
>