users@jms-spec.java.net

[jms-spec users] Re: JMS_SPEC-116: Make Message Poisoning Handling a priority?

From: David Heffelfinger <dheffelfinger_at_gmail.com>
Date: Wed, 12 Aug 2015 19:48:04 -0400

It would be nice if the spec defined what to do with poison messages.
Perhaps they could be configured with an annotation at the class or
callback method level.

I'm having a hard time coming up with a good annotation name, but something
like this

@BadMessageManagement(numRetries="5", action="give-up")

or

@BadMessageManagement(numRetries="3", action="dead-letter-queue",
queueName="jms/deadLetter")

In the first case the MDB would stop trying to process the message after 5
retries and just give up.

In the second case the MDB would stop trying to process the message and
send it to a dead letter queue.

If the annotation is not defined, then the MDB could defer to the app
server vendor specific message poisoning handling.

Just some rough ideas, feel free to chip in.

David

On Wed, Aug 12, 2015 at 9:56 AM, Nigel Deakin <nigel.deakin_at_oracle.com>
wrote:

>
> On 12/08/2015 00:50, David Heffelfinger wrote:
>
> New guy here, apologies if I'm breaking any rules, if this is the case
> please let me know.
>
> Welcome! Comments like this are just fine (and a meaningful subject line
> like you have used is helpful too, especially when they reference the JIRA
> issue under discussion)
>
> (As a general point, you may see me respond to comments by trying to
> redirect discussions to an existing issue, or subdivide an issue into
> separate aspects. That's just me trying to organise discussions into
> manageable parts, or reducing the dependency between one set of changes and
> another set of changes.)
>
>
> In any case, I read Nigel's "More flexible JMS MDBs (Version 2)" document
> at https://java.net/projects/jms-spec/pages/JMSListener2 and have some
> comments.
>
> I like a lot of the ideas that have been suggested.
>
> That's good to hear!
>
>
> Most of the ideas suggested will result in a better, easier to use APIs,
> which is great, however, the following particular suggestions addresses
> what, in my experience, is one of the biggest pain points when using MDB's:
>
> "The JMS provider should detect repeated attempts to redeliver the same
> message to a MDB. Such messages may either be
> discarded or delivered to a provider-specific dead message queue. (Note
> that this not completely new to JMS: JMS 2.1
> section 8.7 refers to a JMS provider "giving up" after a message has been
> redelivered a certain number of times)."
>
> I am actually working on a project right now that uses JMS extensively,
> and "JMS Message Poisoning" has been a problem
> that has been not that easy to solve. Essentially if there is an exception
> when handling a message, the message is put
> back in the queue then immediately consumed again by the same MDB, again
> the exception is thrown, the message goes back
> in the queue, essentially in an infinite loop. It would be great if the
> spec provided a standard, easily configurable way to deal with this
> situation. If I may, I think it would be nice that this particular
> suggestion does not "fall through the cracks" (i.e. make it a high
> priority).
>
> In terms of managing our work on JMS 2.1 there are two aspects to this.
>
> *1. Poison messages generally*
>
> The first aspect is defining how "poison messages" should be handled in
> JMS and Java EE generally. This is a frequently-requested feature. I looked
> to see whether we had a JIRA issue logged for this, and came across
> JMS_SPEC-72 <https://java.net/jira/browse/JMS_SPEC-72> which seems to
> cover the general case.
>
> This was one of the issues mentioned when I originally proposed JSR 368
> (see https://www.jcp.org/en/jsr/detail?id=368, which mentions redelivery
> behaviour), so it's definitely on the roadmap for JMS 2.1. I suspect this
> might be quite difficult, since (as Vaquar mentioned) each application has
> different needs, and also because several JMS vendors and Java EE app
> servers currently provide their own features to handle redelivery
> (redelivery delay, redelivery limits, dead message queues etc) and it will
> be a challenge to define standard behaviour without undermining or breaking
> these existing features.
>
> *2. Poison messages with new-style JMS MDBs*
>
> The other aspect is addressing the specific requirements of the current
> new JMS MDB proposals. (That's issue JMS_SPEC-116
> <https://java.net/jira/browse/JMS_SPEC-116>, with detailed proposals at
> JMSListener2 <https://java.net/projects/jms-spec/pages/JMSListener2>).
>
> The reason that the current MDB proposals mention "poison message"
> handling is that they introduce two new use cases which are not currently
> possible. (If it were not for these two cases there would be no need for
> the current proposals to mention redelivery at all.)
>
> 2a. If a user-defined callback method throws a checked exception (the
> existing onMessage method is not allowed to throw a checked exception, but
> I am proposing that a user-defined callback method is allowed to do so)
>
> 2b. If a message cannot be delivered because the user-defined callback
> method has parameters which cannot be set (e.g. if the callback message is
> handleMessage(String text), but the message is a BytesMessage).
>
> *Suggested approach*
>
> We should have discussions on both, but I see the priority as being (2),
> defining how the new MDB cases 2a and 2b should be handled. I would like to
> avoid the new MDB proposals becoming dependent on solving the general case
> (1).
>
> Currently, the JMS spec is fairly vague on how "poison messages" are
> handled. Despite that, vendors have managed to implement JMS MDBs (and Java
> SE MessageListeners), adding their own extra features on top.
>
> My suggestion is that we continue this approach for the new-style MDBs:
> use a wording that allows vendors to handle these new cases in a similar
> way to how they do now. This would then allow us to finish defining the MDB
> improvements without getting too side-tracked into the issue of poison
> message handling.
>
> *For exceptions thrown by user-defined MDB callback methods* *(case 2a)*
>
> The current proposal is:
>
> "Callback methods will be allowed to declare and throw exceptions.
> Exceptions thrown by the callback method (including unchecked exceptions
> thrown by the onMessage method of a MessageListener) will be handled by the
> EJB container as defined in the EJB 3.2 specification section 9.3.4
> "Exceptions thrown from Message-Driven Bean Message Listener methods". This
> defines whether or not any transaction in progress is committed or rolled
> back, depending on whether or not the exception is a "system exception" or
> an "application exception", whether or not the application exception is
> specified as causing rollback, and whether or not the application has
> called setRollbackOnly. It also defines whether or not the MDB instance is
> discarded. If the transaction is rolled back, or a transaction is not being
> used, then the message will be redelivered." (Paragraph 1)
>
> "The JMS provider should detect repeated attempts to redeliver the same
> message to a MDB. Such messages may either be discarded or delivered to a
> provider-specific dead message queue. " (Paragraph 2)
>
> Paragraph 1 is mostly a repeat of what the EJB spec already says, so
> doesn't add anything new. Hidden in that is the requirement that if the
> exception is an "application exception" (and checked exceptions are
> application exceptions by default) then the transaction will be *committed
> *unless the exception is explicitly annotated as causing rollback. This
> may be surprising: do we want to change this?
>
> Paragraph 2 goes rather further than the existing spec, which doesn't
> mention automatically sending messages to dead message queues. The closest
> thing I can find is this sentence in JMS 2.0 section 8.7 which refers to
> the auto-ack case only:
>
> "The number of times a JMS provider will redeliver the same message before
> giving up is provider-dependent. The JMSRedelivered message header field
> will be set, and the JMSXDeliveryCount message property incremented, for a
> message redelivered under these circumstances."
>
> I'm tempted to change Paragraph 2, to drop the reference to discarding the
> message, or to dead message queues, and replace it with the sentence
> above. When/if we get around to defining poison message handling more
> completely we can extend this. What do people think about this?
>
> *If a message cannot be delivered because the user-defined callback method
> has parameters which cannot be set (Case 2b)*
>
> This is a different case since it does not involve the MDB throwing an
> exception. Instead, this is an error condition detected within the
> application server or resource adapter before the MDB has been called, and
> possibly before any transaction has been started. So this is a new case
> that needs to be defined.
>
> The current proposal is:
>
> "If any of the parameters of the callback method cannot be set because
> they have an incompatible type then callback method will not be invoked.
> Such messages may either be discarded or delivered to a provider-specific
> dead message queue. "
>
> I wonder whether we should again drop the reference to discarding the
> message, or to dead message queues, and instead refer to the JMS provider
> making repeated attempts to deliver the message before "giving up".
>
> In this case, a second attempt to deliver the message to the same MDB
> would fail for exactly the same reason. It would only succeed if the
> application was changed and restarted, or if (in the case of a queue) it
> was delivered to some different MDB or consumer.
>
> We should also define whether or not "repeated attempts to deliver the
> message" counts as redelivery (meaning JMSRedelivered must be set). Since
> the application hasn't actually seen the message before, it isn't really
> redelivery. My inclination is to state that JMSRedelivered does not have
> to be set (and JMSXDeliveryCount does not have to be incremented), but to
> repeat that setting JMSRedelivered in this case (and incrementing
> JMSXDeliveryCount) is not considered an error.
>
> Any other views?
>
> Nigel
>
>
>
>
>
>
>


-- 
http://ensode.net - A Guide to Java, Linux and Other Technology Topics
My Books: http://www.packtpub.com/authors/profiles/david-heffelfinger
My Video Training:
http://www.packtpub.com/java-ee-development-with-netbeans-7/video
Follow me on Twitter: https://twitter.com/ensode