|
for a managed case, the XA case was made the general case. a close is deferred if in any transaction.
Added your test case with the prefetch workaround: http://svn.apache.org/viewvc/activemq/trunk/activemq-core/src/test/java/org/apache/activemq/bugs/RawRollbackTests.java?view=markup
The issue is the consumer.close call in the receiveAndConvert. The close occurs in a transaction and the close is deferred till the transaction completes. The default prefetch value of 100 ensures that the consumer will have both messages queued up for dispatch. The undispatched are only redispatched afer the close. But we don't know if the messages are to be acked till the transaction completes. Thus the additional prefetched "bar" message is not available to a second consumer. Thanks for the update. I tried (as previously indicated) the prefetch hint and it didn't change anything. If I understand the comment correctly maybe you misunderstood the test case: it doesn't fail because "bar" is unavailable to a second consumer - in fact it is, as the assertion assertEquals(2, list.size()) in the test method shows.
It fails because neither "foo" nor "bar" is available to any consumer whatsoever, after the rollback has occurred. The transaction has certainly completed by the time the test fails (thecomment seems to imply the opposite, but maybe I misunderstood). It still fails for you, right? (I only ran it against 5.2.0.) so the test (your test) I committed to trunk works. It uses &jms.prefetchPolicy.all=0
With out the prefetch=0 config, the assertion fails for me with list.size() == 1 The workaround is to only deliver messages on demand, when receive is called, prefetch=0 gives this. Your failure is not the same as mine (in 5.2.0). I am failing in the @After, and it sounds like you are failing (before the fetch size hint) in @Test.
I will try it when a new snapshot appears. The Apache snapshots repo has a latest version in mid April; any news on that, or am I looking in the wrong place? The original test (with or without the fech size) still fails with 5.2.0 and passes with 5.1.0. It also fails if I use a single consumer to consume all messages in a Session. So I'd be interested to know what broke in the meantime there. 5.1.0 seems correct as far as the JMS spec goes. The nightly snapshot is available at https://repository.apache.org/content/repositories/snapshots/org/apache/activemq/apache-activemq/5.3-SNAPSHOT/
I think the key change (on trunk) relates to consumer.close when there is a transaction. The close is deferred to a synchronisation afterCompletion so the effect of the close is not visible till the transaction completes. From what i can see, the test depends on the visibility of predispatched messages before the transaction completes. Can you provide your test variant that uses a single consumer so I can include it? yea, I think that is a bug with 5.2.0. All is good on trunk now though. I committed that shared test to protect against regression, thanks. Are you happy to see this issue closed?
Not abundantly happy, really, no. I think it's a regression from 5.1.0, and hiding behind the strict letter of the law regarding the specification is a weak position to take. Even if prefetch is a proprietary feature, having to set it to a non-default value to get a system to behave as expected makes it very hard for users to guess or understand what is happening. Also, prefetch is a good feature that I probably want to use, so switching it off just to get messages redelivered to another consumer in the same process seems like it must be a workaround for a bug.
resolving as per dave's comment, current snapshot has a fix.
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
This is an interesting test case. The change of behavior is around consumer.close() and transactions. When in a transaction, the close is deferred till the transaction completes, so with a prefetch > 0, messages dispatched to that consumer will not be available till the transaction commits.
I think your test case will work with a prefetch of 0, connectionFactory.setBrokerURL("vm://localhost?async=false&waitForStart=5000&jms.prefetchPolicy.all=0");