jsr343-experts@jms-spec.java.net

[jsr343-experts] Re: (JMS_SPEC-33) Improving the JMS API with API simplifications, annotations and CDI

From: Ruediger zu Dohna <ruediger.dohna_at_1und1.de>
Date: Mon, 01 Aug 2011 17:50:48 +0200

John,

On 08/01/2011 12:03 PM, John D. Ament wrote:
> I assume that you are talking about something like ServiceHandlers,
> correct?
> http://docs.jboss.org/seam/3/solder/latest/reference/en-US/html/servicehandler.html
> (for those unfamiliar)
>
> As far as I know, this is slated for CDI 1.1 standardization.

ServiceHandlers are just perfect to inject into the sender. I played
around with standard CDI extensions a bit, but I had to scan all
injection points for unsatisfied dependencies and then look if I can
provide one... this was too awkward for me at that time, so I stopped.
Thanks for your pointer! Looking forward for the standardization.

> The problem though is that you need to take both producer and consumer into
> account and ensure that both sides have the same type safe fluent API.
> Otherwise, consumers will end up needing to handle XML soup or something
> similar.

Yes, but I'd say that's the same thing as with EJB calls: You agree on a
service contract, define it as an interface, and put it into an API jar
shared by both sides.

> What about using a POJO and giving it bindings that describes
> the destination it will be sent to, properties that go with it?

I don't understand...


Rüdiger

> On Mon, Aug 1, 2011 at 5:01 AM, Ruediger zu Dohna
> <ruediger.dohna_at_1und1.de <mailto:ruediger.dohna_at_1und1.de>> wrote:
>
> [I'm on the expert group by now, but not yet on the EG mailing list.
> I wanted to get this out now, so I send it on the users list... I
> hope everybody interested is on this list as well, esp. Reza and John]
>
> Hi,
>
> I agree that we should use CDI as much as possible to make JMS more
> usable. I also agree with Reza that it would be great, if this would
> be a CDI layer on top of the existing JMS APIs that would allow the
> user to get anything they need injected or even simply produce the
> message objects they want to send.
>
> *But I think we could do much more than that!*
>
> I'll need to do a bit of a round-trip to make my point clear...
> starting with the example from Nigel:
>
>
> @Resource(name="myQueue") Destination destination;
> @Resource(name="__myConnectionFactory") ConnectionFactory
> connectionFactory;
>
> private void send(String messageText) throws JMSException {
> Connection connection = connectionFactory.__createConnection();
> try {
> Session session = connection.createSession(__false,
> Session.AUTO_ACKNOWLEDGE);
> MessageProducer producer = session.createProducer(__destination);
> Message message = session.createTextMessage(__messageText);
> producer.send(message);
> } finally {
> if (connection!=null) connection.close();
> }
> }
>
> This code hides JMS from the business code that calls this method.
> But if we want to replace it completely by something the container
> provides, it has to be generic, which it is not for functional and
> non-functional reasons. I'll concentrate on the functional aspects
> first: The destination defines the semantic of the message and
> should be named accordingly. E.g. it could be a destination for
> twitter messages named TwitterDestination or a destination to delete
> customers by their id named DeleteCustomerDestination. So the method
> name should also not be "send" but e.g. "tweet" or "deleteCustomer".
>
> Adding more methods, you'd either have to add more destinations, or
> group functionality into one destination and put the desired
> operation into the message... either as a message property or into
> the message payload. I mostly prefer the latter, but you can change
> that without touching the clients of the existing method. Also the
> exact message format could change without the business code being
> affected... nice design.
>
> If the class gets too big and/or to make testing the business code
> easier, I'd refactor these JMS-methods and the resources they envy
> into a delegate... probably even extracting an interface.
>
> public interface CustomerService {
> public void createCustomer(String first, String last);
> public void deleteCustomer(String id);
> }
>
> *This* is what the business code programmer wants to see... nothing
> more. Now all the boiler plate code is in one place, and... magic
> fairy dust sparkle sound... we can get completely rid of it!
> Assuming that the exact message format, the destination name, and
> some other things are not really interesting as long as the sender
> and the receiver agree, this code can be implemented in a generic
> fashion! Convention-over-configuration.
>
> If we need to explicitly configure these things, e.g. in order to
> communicate with some legacy system, or in order to serve some
> non-functional requirements, like a QoS, priority, etc., we could
> use use CDI qualifiers:
>
> @Inject
> @DestinationName("myQueue") // required by legacy system
> @Priority(HIGH) // non-functional requirement
> CustomerService sender;
>
> This would run in Java EE as well as in Java SE with only a CDI
> container. For clients without CDI, there would have to be a factory
> method... and the non-functional aspects would have to be configured
> with a builder.
>
> There are use cases that require more control on the message
> format... stream messages come to my mind. But I consider them as
> border cases that require additional API.
>
> I think it would be a great leap forward to hide *all* of this by
> default... and when you need to specify something, add an annotation
> and let the container figure out how to obey. If the reference
> implementation only delegates to the JMS 1.1 API, all JMS
> implementations would be supported right away, while a more direct
> binding to an implementation might provide additional benefits (as
> Reza pointed out).
>
> Nigel sees the asynchronous receiver side as a separate issue, as
> the current specs force us to use MDBs. The goal IMHO would be that
> the business code would simply implement e.g. the CustomerService
> interface and not care about the message format, etc. While it could
> be possible to generate the required MDB classes on the fly, it
> would be easier if we could use the MessageListener interface, as we
> can bind those generically to any destination. But how can we have a
> single transaction for the consumption of the message and the
> business code that is called? I'm optimistic that this can be
> resolved, but I agree this would require a deeper integration into
> the container... a completely separate layer on top of JMS,
> desirable as it is, may not suffice.
>
> Is this not a good thing to aim at? But maybe I completely miss
> something. Are there any real objections, other than we might have
> to completely rewrite the spec? I believe that hiding JMS behind a
> pure business interface is a logical result from viewing
> asynchronous messaging radically from the business programmer
> perspective, but I may have lost sight of some other, elemental
> features. Please tell me, if this is so! Or should I provide more
> detail?
>
>
> Regards
> Rüdiger
>
>