On 30.06.2015, at 18:23, Nigel Deakin <nigel.deakin_at_oracle.com> wrote:
> On 17/06/2015 10:06, Rüdiger zu Dohna wrote:
>>
>> • Issue I4: It would be _very_ helpful to have more than one callback method, e.g. to receive different types of
>> messages. We would have to specify the selection algorithm, though. Annotations could be placed on the method _or_
>> the class, with the usual logic that method level annotations overwrite class level annotations.
>
> I agree in principle, but avoided it because of the extra complexity it would involve in specifying it. We already have lots of issues to consider: this would gives us many more. I'm tempted to put this to one side and come back to it a bit later in the development of JMS 2.1, purely for project management reasons, to allow us to focus on the basics.
Okay. We could specify this to be unspecified now, i.e. vendor-specific, non-portable; and later we could specify it (which might even still be in 2.1, considering the changed timeframe :)
> (We also need to come back and look at batch delivery, which we deferred from JMS 2.0 because the API was getting too complicated). I'd welcome more views on this.
>
> The EJB spec currently assumes a MDB has only a single destination (e.g. <message-driven> has a sub-element <message-destination-link>) though I suspect we can simply ignore that.
>
> I can't see anything in the JCA spec that would prevent a MDB having multiple destinations (or multiple message selectors).
>
> If a single MDB had multiple listener methods, each could have its own JMS consumer. That would be the simplest way to define the "selection algorithm" semantics.
The destination would be one differentiator for the messages. Others would be message selectors, message types, or even more. I agree: let's put this aside for the moment.
> should we allow a MDB that implements javax.jms.MessageListener to also have additional callback methods, or would this be confusing?
I don't see a reason to still inherit from MessageListener when using JMS 2.1. It's conceptually deprecated and should be removed step-by-step in all applications.
>> • Issue I11: The destination name is generally simpler than the JNDI name. It can be used to specify the destination
>> on a more abstract, business-oriented level, e.g. ‘trades’. So, objecting to your colleague, I think it would be
>> desirable to use that, yes... portable or not.
>
> Specifying a destination by anything other than JNDI name is a can of worms which I would like to keep separate from this work. You will remember we discussed this in JMS 2.0 but got rather bogged down.
>
> As things stand, destination name is not considered portable (in at least one JMS provider it includes deployment information such as the name of the JMS server). The javadocs for Session#createQueue state that this is a "provider-specific queue name" and states that "Portable applications are recommended to not use this method but instead look up an administratively-defined Queue object using JNDI." Because of this, there are no CTS tests for this method.
>
> If we can't think of anything better we could allow the existing queue and topic name to be specified,
Yes, please. The decision should be on the application developers or their architects, not on the JMS EG, should it?
> but I would rather we define a new, portable, non-JNDI name and use that instead.
That's an interesting thought! Following that direction, maybe we could use something better than strings: I'm thinking of something like CDI qualifiers.
>> • Issue I13: We can assume that the destination already exits in the container. The RA then can simply look it up to
>> see if it’s a queue or a topic. Then it would even be possible to swap one for the other without changing the
>> application. The queue topology shouldn’t be relevant for an application, should it? This is why I prefer
>> @JMSListener to @JMSQueue/TopicListener.
>
> The RA does not have any way to discover whether a Destination object is a Queue or Topic. You can't rely on using "instanceof": in a well-known JMS provider (oh, alright, I mean Weblogic), queue or topic objects implement both javax.jms.Queue and javax.jms.Topic at the same time. Which appears to me to be perfectly legal.
Ok, so it's more a question how the RA developer can use the JMS 2.1 API to find it out. I've only looked at it from the application programmers side.
> However we could certainly add a method Destination#getType if we wanted to.
That would elegantly solve the problem, wouldn't it?
> I disagree that a MDB could be swapped from a queue to a topic without changing the application. For a start, you might need to specify the subscription name and clientID. But more importantly, I think that the semantics for the two are so different that this would rarely make any sense except for trivial applications.
Even in complex applications, sometimes an application only needs, e.g., a trigger. It doesn't care about the source or the topology, it only needs to know that it has to start to (continue to) do something.
>> • Issue I14: I think it would be more consistent to have separate annotations even here.
>
> So I think you're endorsing my proposal which uses separate annotations for SubscriptionDurability, SubscriptionName and ClientId
Yes. I should have been more precise.
>> • Parameters for message body: It should be an error to have more than one method parameter for the message body,
>> i.e. the container should report and fail to load an application with MDBs that has methods with more than one
>> parameter without a @MessageHeader or @MessageProperty annotation. Annotation processors could mark this error even
>> in the IDE.
>
> Possibly, though a callback method which had multiple method parameters of different types could be used to receive JMS messages of different types.
If I need to handle several message body types, I'd rather have several methods than if statements in one method.
> I think it depends on how we handle mis-matched message bodies (for example if the callback method has a parameter of type byte[], but the message is a ObjectMessage). Currently I am proposing simply setting it to null, but I am far from sure that this is the right thing to do. I'd be interested to hear what you think about that.
>
> If we decide that a mis-matched message body needs to be treated as an error then it follows naturally that having more than one method parameter for the message body should be treated as an error, at least if they were of different type.
The code would then have to handle the case that none of the bodies it can handle was set. And what should the application do? Throw an exception? Which one?
The provider or the RA could have a generic strategy, which generally would be sending the message to a DLQ. Maybe this strategy would even be configurable, but the application would not have to be changed.
>> • Message properties: Should we make the value of the @MessageProperty annotation optional in Java 8?
>
> I think you mean that if the @MessageProperty annotation is omitted, the property name is inferred from the variable name.
I meant this:
public @interface MessageProperty {
/**
* The name of the property. Defaults to the name of the parameter, which requires to compile with the `-parameters` option.
*/
String value() default "";
}
>> Even though the default is not to include the parameter names in the class file (which I consider a bad decision, as it reduces
>> adoption, which already has effectively killed the assert keyword), it can really reduce repetition of the name.
>
> I like this in principle, though how would we then distinguish between a parameter which we want to contain the message body, and a parameter which we want to contain a message property?
like this: public void onMessage(@MessageProperty String qualityOfService, ...)
> I'm also worried that we could be making such a MDB dependent on being compiled with the special option to include the parameter names in the class file. In the real world it would mean that every MDB would end up being compiled with this option, to avoid the possibility of a runtime error. Do we really want to inflict this on users?
Yes. This is exactly the reason why I think it was a bad decision to make this compiler option optional. If the default was to include the parameter names, we wouldn't have this discussion. We would only mention that compiling would have to be done without the fictional inverse option `-noparameters`. The main use case for parameter names was exactly this: Not to have to repeat the parameter names. And now we (as well as all other EGs like JAX-RS) think about not using it :(
BTW by default the compiler already adds debug information, which includes the parameter names. That could be used as a fallback.
To me it looks like the concerns of the ME people where heard (class file size), but not those of the EE people. Maybe you should take this to the EE spec EG to find a consistent usage or non-usage of the parameter names across all EE specs. I assume that all EE 8 applications will by default be compiled with `-parameters -Xdoclint:none` (the second one is a joke :)
>> • Issue I16: I also agree with you colleague that we should consider to finally specify DLQs. They are one of the
>> fundamental messaging patterns, and official support is overdue. Routing messages that can’t be converted are just
>> one use case; they also should be usable for messages that can’t be delivered due to technical as well as application
>> problems in the consumer.
>
> As I mentioned, I think how we handle conversion errors is the biggest issue I am unsure about.
If we already have to specify DLQs in order to handle conversion errors, wouldn't it be a natural step to specify DLQs in general? As a first step, all messages that make the application throw an EJB application error (checked exception or annotated as @ApplicationException) would directly go to the DLQ. In further steps, we could specify how exceptions could be directed to specific DLQs, how retries would be handled, and probably more good things that currently are not portable.
> Does anyone know how Spring handles conversion errors? I can't see any mention of this in the docs.
I've been using Spring years ago and we had our own error message handling with resender queues with automatically increasing delays and such goodness. So as far as I recall, there was no support for that back then.
>> • Question 1: Will it be possible to use @Stereotypes for all the annotations?
>
> This is javax.enterprise.inject.Stereotype, which is part of Java EE 7.
>
> I didn't propose it, but it sounds a good idea, if there aren't any technical obstacles. I'd like to ask David Blevins about that...
David: Is there any progress in the other specs to support @Stereotype?
>> • Question 2: If the container sets method parameters to message headers and message parameters, wouldn’t it be
>> useful to have it also set method parameters to message fields of a MapMessage?
>
> I left this out for simplicity, but agree it might be nice, so long as we can define it neatly and simply. This is the kind of thing we could easily add in a later iteration of this feature.
Agreed. We should first settle on the basics. (just as a teaser: we could then also think about specifying a mapping json or yaml or xml message elements to the parameters :)
Rüdiger