jsr343-experts@jms-spec.java.net

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

From: John D. Ament <john.d.ament_at_gmail.com>
Date: Mon, 1 Aug 2011 06:03:01 -0400

Rudiger,

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. 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. What
about using a POJO and giving it bindings that describes the destination it
will be sent to, properties that go with it?

John

On Mon, Aug 1, 2011 at 5:01 AM, Ruediger zu Dohna
<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
>
>