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: Reza Rahman <reza_rahman_at_lycos.com>
Date: Tue, 02 Aug 2011 16:39:07 -0400

Rudiger,

It's somewhat besides the point right now, but there were a number of
questions I had about the project that were not really clear to me. Some
examples include annotation support, mapping properties, specifying
properties vs. message body, "serialization" schemes, message selectors
and so on. Really I wanted to get a better feel of the project overall
without delving through too much code.

More to the point, I think you are agreeing that if you distill your
current API a bit further, it really basically looks like EJB
@Asynchronous, @Remote or @WebService? To be specific, something along
these lines:

@Stateless
public class CustomerService {
     ...
     @JmsRemote(destination="jms/CustomerQueue")
     public void createCustomer(@JmsProperty long customerId, @JmsBody
Customer customer) {
       ...
     }
     ...
}

@Inject @JmsRemote(priority=HIGH, deliveryMode=PERSISTENT)
private CustomerService customerService;

Obviously, this would be all asynchronous calls since it's JMS. It could
also be possible to support a model whereby a return type is mapped back
to the client using reply-to/correlation ID.

As such, this is a good model for certain JMS use cases. Who knows, it
might even be a sufficient model?

The trouble is that it can't be the only high level model for JMS right
now. The fundamental issue is that because of the very high level of
abstraction it would not be able to support the very flexible features
that JMS provides today. This means that it might run the risk of being
unusable to a large number of existing JMS users.

Just consider some of the following cases. You'll see that they really
just do not fit very well to a Java RPC like model. In the least case
the API becomes quite clumsy. In the worst case, it is not possible to
implement the feature at all.

* How do I send messages to clients not written in Java (such as
AS400/mainframe clients on WebSphere MQ/MQSeries)
* How can I change the payload format at runtime?
* How do I change the destination, priority, delivery mode,
time-to-live, etc at runtime?
* How do I browse queues?
* How do I handle reply-to/correlation ID schemes that might change at
runtime?
* How do I send/receive a group of messages in the same session?
* How can I change selectors at runtime?
* How do I use temporary queues, especially with reply-to/correlation ID?
* What if I need to do some tasks between sending a JMS message and
waiting for the results of that message (a return type in our case)?
* And so on...

Now, all this being said, I do think that we could consider this once we
get a more flexible high level API in place or in a future version of
JMS if this model actually does get some more traction hopefully via
your project and it is really obvious that JMS is more flexible than it
really needs to be.

Hope this makes sense.

Cheers,
Reza


On 8/2/2011 7:35 AM, Ruediger zu Dohna wrote:
> Reza,
>
> On 08/01/2011 08:33 PM, Reza Rahman wrote:
>> Just to be clear, are you proposing this as an even higher level
>> abstraction or a replacement to what I had outlined earlier?
>
> Could be both... I'm not fixated on either... but see below.
>
>> Do you have
>> detailed documentation on this solution other than the article you sent
>> earlier?
>
> There is some documentation on the MessageApi website... but not up to
> date: http://java.net/projects/messageapi/pages/Home
>
> What information are you looking for?
>
>> As I mentioned earlier, the biggest practical issue I see with this is
>> that it reduces flexibility a bit too much...
>
> I can see your point, but it's a bit too vague to put a finger on. Can
> you give some examples? Maybe we can address it!
>
>> ... If we go
>> this route, we might want to see if that model suffices instead of
>> placing mappings on something that looks like a business logic artifact
>> but is not really a business logic artifact at all (which is basically
>> what John was saying I think). Other than some arguably semantic
>> benefit, this approach requires creating a fairly mechanical interface
>> that really has no other purpose than serving as a redundant artifact
>> for the framework...
>
> I always compare these messaging interfaces to the interfaces of EJB 3
> remote calls: EJB interfaces describe the business-semantic of a
> synchronous remote call, but in order to make it actually work, there
> has to be done quite some magic in the background, namely to hide the
> remote exceptions that the underlying RMI calls require... or even the
> complete WS-* stack! So both types of interfaces are on a very high
> level of abstraction and without the helpful magic from the container,
> they simply wouldn't work. Instead the container derives the technical
> stuff it needs from those interfaces.
>
> I can see no redundancy in this approach... OTOH there is a very
> fragile redundant know-how in a JMS client and server in how to
> package or unpack messages.
>
>> Hope this is sensible. It's a good idea that might indeed eventually be
>> broadly accepted (or not), I just don't think it's right for a standard
>> API at this point. Maybe others see this differently?...
>
> I like the saying that you should do one thing that scares you every
> day. But I also believe that people who are not afraid of anything
> will eventually kill themselves. Respecting that some things simply
> take time to get used to, I'd suggest that we continue double tracked:
> We continue to refine the required simplifications for the existing
> API, as you and others have suggested. But we add one track about how
> to shift to a better level of abstraction. Everybody should give both
> ways a close enough look (maybe even bringing it into production) to
> get a feel for it.
>
> The result may be that the latter replaces the former, will sit on top
> of it, be delayed to JMS 3.0, or even be moved out of the JMS spec. Do
> you think that's a feasible road to follow?
>
>
> Rüdiger
>
>> On 8/1/2011 5:01 AM, Ruediger zu Dohna 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
>>>
>>>
>>>
>>> -----
>>> No virus found in this message.
>>> Checked by AVG - www.avg.com
>>> Version: 10.0.1390 / Virus Database: 1518/3801 - Release Date: 07/31/11
>>>
>>>
>>
>>
>>
>
>
> -----
> No virus found in this message.
> Checked by AVG - www.avg.com
> Version: 10.0.1390 / Virus Database: 1518/3804 - Release Date: 08/01/11
>
>