/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.activemq.artemis.jms.tests;
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.DeliveryMode;
import javax.jms.Message;
import javax.jms.MessageConsumer;
import javax.jms.MessageListener;
import javax.jms.MessageProducer;
import javax.jms.Session;
import javax.jms.TextMessage;
import javax.jms.TopicConnection;
import javax.jms.TopicPublisher;
import javax.jms.TopicSession;
import javax.jms.TopicSubscriber;
import java.util.concurrent.CountDownLatch;
import org.apache.activemq.artemis.jms.tests.util.ProxyAssertSupport;
import org.junit.Assert;
import org.junit.Test;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
public class AcknowledgementTest extends JMSTestCase {
/**
* Topics shouldn't hold on to messages if there are no subscribers
*/
@Test
public void testPersistentMessagesForTopicDropped() throws Exception {
TopicConnection topicConn = createTopicConnection();
TopicSession sess = topicConn.createTopicSession(true, 0);
TopicPublisher pub = sess.createPublisher(ActiveMQServerTestCase.topic1);
pub.setDeliveryMode(DeliveryMode.PERSISTENT);
Message m = sess.createTextMessage("testing123");
pub.publish(m);
sess.commit();
topicConn.close();
checkEmpty(ActiveMQServerTestCase.topic1);
}
/**
* Topics shouldn't hold on to messages when the non-durable subscribers close
*/
@Test
public void testPersistentMessagesForTopicDropped2() throws Exception {
TopicConnection topicConn = createTopicConnection();
topicConn.start();
TopicSession sess = topicConn.createTopicSession(true, 0);
TopicPublisher pub = sess.createPublisher(ActiveMQServerTestCase.topic1);
TopicSubscriber sub = sess.createSubscriber(ActiveMQServerTestCase.topic1);
pub.setDeliveryMode(DeliveryMode.PERSISTENT);
Message m = sess.createTextMessage("testing123");
pub.publish(m);
sess.commit();
// receive but rollback
TextMessage m2 = (TextMessage) sub.receive(3000);
ProxyAssertSupport.assertNotNull(m2);
ProxyAssertSupport.assertEquals("testing123", m2.getText());
sess.rollback();
topicConn.close();
checkEmpty(ActiveMQServerTestCase.topic1);
}
@Test
public void testRollbackRecover() throws Exception {
TopicConnection topicConn = createTopicConnection();
TopicSession sess = topicConn.createTopicSession(true, 0);
TopicPublisher pub = sess.createPublisher(ActiveMQServerTestCase.topic1);
TopicSubscriber cons = sess.createSubscriber(ActiveMQServerTestCase.topic1);
topicConn.start();
Message m = sess.createTextMessage("testing123");
pub.publish(m);
sess.commit();
TextMessage m2 = (TextMessage) cons.receive(3000);
ProxyAssertSupport.assertNotNull(m2);
ProxyAssertSupport.assertEquals("testing123", m2.getText());
sess.rollback();
m2 = (TextMessage) cons.receive(3000);
ProxyAssertSupport.assertNotNull(m2);
ProxyAssertSupport.assertEquals("testing123", m2.getText());
topicConn.close();
topicConn = createTopicConnection();
topicConn.start();
// test 2
TopicSession newsess = topicConn.createTopicSession(true, 0);
TopicPublisher newpub = newsess.createPublisher(ActiveMQServerTestCase.topic1);
TopicSubscriber newcons = newsess.createSubscriber(ActiveMQServerTestCase.topic1);
Message m3 = newsess.createTextMessage("testing456");
newpub.publish(m3);
newsess.commit();
TextMessage m4 = (TextMessage) newcons.receive(3000);
ProxyAssertSupport.assertNotNull(m4);
ProxyAssertSupport.assertEquals("testing456", m4.getText());
newsess.commit();
newpub.publish(m3);
newsess.commit();
TextMessage m5 = (TextMessage) newcons.receive(3000);
ProxyAssertSupport.assertNotNull(m5);
ProxyAssertSupport.assertEquals("testing456", m5.getText());
newsess.rollback();
TextMessage m6 = (TextMessage) newcons.receive(3000);
ProxyAssertSupport.assertNotNull(m6);
ProxyAssertSupport.assertEquals("testing456", m6.getText());
newsess.commit();
}
@Test
public void testTransactionalAcknowledgement() throws Exception {
Connection conn = createConnection();
Session producerSess = conn.createSession(true, Session.SESSION_TRANSACTED);
MessageProducer producer = producerSess.createProducer(queue1);
Session consumerSess = conn.createSession(true, Session.SESSION_TRANSACTED);
MessageConsumer consumer = consumerSess.createConsumer(queue1);
conn.start();
final int NUM_MESSAGES = 20;
// Send some messages
for (int i = 0; i < NUM_MESSAGES; i++) {
Message m = producerSess.createMessage();
producer.send(m);
}
assertRemainingMessages(0);
producerSess.rollback();
// Send some messages
for (int i = 0; i < NUM_MESSAGES; i++) {
Message m = producerSess.createMessage();
producer.send(m);
}
assertRemainingMessages(0);
producerSess.commit();
assertRemainingMessages(NUM_MESSAGES);
int count = 0;
while (true) {
Message m = consumer.receive(200);
if (m == null) {
break;
}
count++;
}
assertRemainingMessages(NUM_MESSAGES);
ProxyAssertSupport.assertEquals(count, NUM_MESSAGES);
consumerSess.rollback();
assertRemainingMessages(NUM_MESSAGES);
int i = 0;
for (; i < NUM_MESSAGES; i++) {
consumer.receive();
}
assertRemainingMessages(NUM_MESSAGES);
// if I don't receive enough messages, the test will timeout
consumerSess.commit();
assertRemainingMessages(0);
checkEmpty(queue1);
}
/**
* Send some messages, don't acknowledge them and verify that they are re-sent on recovery.
*/
@Test
public void testClientAcknowledgeNoAcknowledgement() throws Exception {
Connection conn = createConnection();
Session producerSess = conn.createSession(false, Session.CLIENT_ACKNOWLEDGE);
MessageProducer producer = producerSess.createProducer(queue1);
Session consumerSess = conn.createSession(false, Session.CLIENT_ACKNOWLEDGE);
MessageConsumer consumer = consumerSess.createConsumer(queue1);
conn.start();
final int NUM_MESSAGES = 20;
// Send some messages
for (int i = 0; i < NUM_MESSAGES; i++) {
Message m = producerSess.createMessage();
producer.send(m);
}
assertRemainingMessages(NUM_MESSAGES);
log.trace("Sent messages");
int count = 0;
while (true) {
Message m = consumer.receive(1000);
if (m == null) {
break;
}
count++;
}
assertRemainingMessages(NUM_MESSAGES);
log.trace("Received " + count + " messages");
ProxyAssertSupport.assertEquals(count, NUM_MESSAGES);
consumerSess.recover();
assertRemainingMessages(NUM_MESSAGES);
log.trace("Session recover called");
Message m = null;
int i = 0;
for (; i < NUM_MESSAGES; i++) {
m = consumer.receive();
log.trace("Received message " + i);
}
assertRemainingMessages(NUM_MESSAGES);
// if I don't receive enough messages, the test will timeout
log.trace("Received " + i + " messages after recover");
m.acknowledge();
assertRemainingMessages(0);
// make sure I don't receive anything else
checkEmpty(queue1);
conn.close();
}
/**
* Send some messages, acknowledge them individually and verify they are not resent after recovery.
*/
@Test
public void testIndividualClientAcknowledge() throws Exception {
Connection conn = createConnection();
Session producerSess = conn.createSession(false, Session.CLIENT_ACKNOWLEDGE);
MessageProducer producer = producerSess.createProducer(queue1);
Session consumerSess = conn.createSession(false, Session.CLIENT_ACKNOWLEDGE);
MessageConsumer consumer = consumerSess.createConsumer(queue1);
conn.start();
final int NUM_MESSAGES = 20;
for (int i = 0; i < NUM_MESSAGES; i++) {
Message m = producerSess.createMessage();
producer.send(m);
}
assertRemainingMessages(NUM_MESSAGES);
for (int i = 0; i < NUM_MESSAGES; i++) {
Message m = consumer.receive(200);
ProxyAssertSupport.assertNotNull(m);
assertRemainingMessages(NUM_MESSAGES - i);
m.acknowledge();
assertRemainingMessages(NUM_MESSAGES - (i + 1));
}
assertRemainingMessages(0);
consumerSess.recover();
Message m = consumer.receive(200);
ProxyAssertSupport.assertNull(m);
}
/**
* Send some messages, acknowledge them once after all have been received verify they are not resent after recovery
*/
@Test
public void testBulkClientAcknowledge() throws Exception {
Connection conn = createConnection();
Session producerSess = conn.createSession(false, Session.CLIENT_ACKNOWLEDGE);
MessageProducer producer = producerSess.createProducer(queue1);
Session consumerSess = conn.createSession(false, Session.CLIENT_ACKNOWLEDGE);
MessageConsumer consumer = consumerSess.createConsumer(queue1);
conn.start();
final int NUM_MESSAGES = 20;
// Send some messages
for (int i = 0; i < NUM_MESSAGES; i++) {
Message m = producerSess.createMessage();
producer.send(m);
}
assertRemainingMessages(NUM_MESSAGES);
log.trace("Sent messages");
Message m = null;
int count = 0;
for (int i = 0; i < NUM_MESSAGES; i++) {
m = consumer.receive(200);
if (m == null) {
break;
}
count++;
}
assertRemainingMessages(NUM_MESSAGES);
ProxyAssertSupport.assertNotNull(m);
m.acknowledge();
assertRemainingMessages(0);
log.trace("Received " + count + " messages");
ProxyAssertSupport.assertEquals(count, NUM_MESSAGES);
consumerSess.recover();
log.trace("Session recover called");
m = consumer.receive(200);
log.trace("Message is:" + m);
ProxyAssertSupport.assertNull(m);
}
/**
* Send some messages, acknowledge some of them, and verify that the others are resent after delivery
*/
@Test
public void testPartialClientAcknowledge() throws Exception {
Connection conn = null;
try {
conn = createConnection();
Session producerSess = conn.createSession(false, Session.CLIENT_ACKNOWLEDGE);
MessageProducer producer = producerSess.createProducer(queue1);
Session consumerSess = conn.createSession(false, Session.CLIENT_ACKNOWLEDGE);
MessageConsumer consumer = consumerSess.createConsumer(queue1);
conn.start();
final int NUM_MESSAGES = 20;
final int ACKED_MESSAGES = 11;
// Send some messages
for (int i = 0; i < NUM_MESSAGES; i++) {
Message m = producerSess.createMessage();
producer.send(m);
}
assertRemainingMessages(NUM_MESSAGES);
log.trace("Sent messages");
int count = 0;
Message m = null;
for (int i = 0; i < NUM_MESSAGES; i++) {
m = consumer.receive(200);
if (m == null) {
break;
}
if (count == ACKED_MESSAGES - 1) {
m.acknowledge();
}
count++;
}
assertRemainingMessages(NUM_MESSAGES - ACKED_MESSAGES);
ProxyAssertSupport.assertNotNull(m);
log.trace("Received " + count + " messages");
ProxyAssertSupport.assertEquals(count, NUM_MESSAGES);
consumerSess.recover();
log.trace("Session recover called");
count = 0;
while (true) {
m = consumer.receive(200);
if (m == null) {
break;
}
count++;
}
ProxyAssertSupport.assertEquals(NUM_MESSAGES - ACKED_MESSAGES, count);
} finally {
if (conn != null) {
conn.close();
}
removeAllMessages(queue1.getQueueName(), true);
}
}
/*
* Send some messages, consume them and verify the messages are not sent upon recovery
*/
@Test
public void testAutoAcknowledge() throws Exception {
Connection conn = createConnection();
Session producerSess = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
MessageProducer producer = producerSess.createProducer(queue1);
Session consumerSess = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
MessageConsumer consumer = consumerSess.createConsumer(queue1);
conn.start();
final int NUM_MESSAGES = 20;
// Send some messages
for (int i = 0; i < NUM_MESSAGES; i++) {
Message m = producerSess.createMessage();
producer.send(m);
}
assertRemainingMessages(NUM_MESSAGES);
int count = 0;
Message m = null;
for (int i = 0; i < NUM_MESSAGES; i++) {
assertRemainingMessages(NUM_MESSAGES - i);
m = consumer.receive(200);
assertRemainingMessages(NUM_MESSAGES - (i + 1));
if (m == null) {
break;
}
count++;
}
assertRemainingMessages(0);
ProxyAssertSupport.assertNotNull(m);
log.trace("Received " + count + " messages");
ProxyAssertSupport.assertEquals(count, NUM_MESSAGES);
consumerSess.recover();
log.trace("Session recover called");
m = consumer.receive(200);
log.trace("Message is:" + m);
ProxyAssertSupport.assertNull(m);
// Thread.sleep(3000000);
}
@Test
public void testDupsOKAcknowledgeQueue() throws Exception {
Connection conn = createConnection();
Session producerSess = conn.createSession(false, Session.DUPS_OK_ACKNOWLEDGE);
MessageProducer producer = producerSess.createProducer(queue1);
Session consumerSess = conn.createSession(false, Session.DUPS_OK_ACKNOWLEDGE);
MessageConsumer consumer = consumerSess.createConsumer(queue1);
conn.start();
final int NUM_MESSAGES = 20;
// Send some messages
for (int i = 0; i < NUM_MESSAGES; i++) {
Message m = producerSess.createMessage();
producer.send(m);
}
assertRemainingMessages(NUM_MESSAGES);
int count = 0;
Message m = null;
for (int i = 0; i < NUM_MESSAGES; i++) {
m = consumer.receive(200);
if (m == null) {
break;
}
count++;
}
assertRemainingMessages(NUM_MESSAGES);
ProxyAssertSupport.assertNotNull(m);
log.trace("Received " + count + " messages");
ProxyAssertSupport.assertEquals(count, NUM_MESSAGES);
consumerSess.recover();
log.trace("Session recover called");
m = consumer.receive(200);
log.trace("Message is:" + m);
ProxyAssertSupport.assertNull(m);
conn.close();
assertRemainingMessages(0);
}
@Test
public void testDupsOKAcknowledgeTopic() throws Exception {
final int BATCH_SIZE = 10;
deployConnectionFactory(null, "MyConnectionFactory2", -1, -1, -1, -1, false, false, BATCH_SIZE, true, "mycf");
Connection conn = null;
try {
ConnectionFactory myCF = (ConnectionFactory) ic.lookup("/mycf");
conn = myCF.createConnection();
Session producerSess = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
MessageProducer producer = producerSess.createProducer(ActiveMQServerTestCase.topic1);
Session consumerSess = conn.createSession(false, Session.DUPS_OK_ACKNOWLEDGE);
MessageConsumer consumer = consumerSess.createConsumer(ActiveMQServerTestCase.topic1);
conn.start();
// Send some messages
for (int i = 0; i < 19; i++) {
Message m = producerSess.createMessage();
producer.send(m);
}
log.trace("Sent messages");
Message m = null;
for (int i = 0; i < 19; i++) {
m = consumer.receive(200);
ProxyAssertSupport.assertNotNull(m);
}
consumerSess.close();
} finally {
if (conn != null) {
conn.close();
}
ActiveMQServerTestCase.undeployConnectionFactory("MyConnectionFactory2");
}
}
/*
* Send some messages, consume them and verify the messages are not sent upon recovery
*/
@Test
public void testLazyAcknowledge() throws Exception {
Connection conn = createConnection();
Session producerSess = conn.createSession(false, Session.DUPS_OK_ACKNOWLEDGE);
MessageProducer producer = producerSess.createProducer(queue1);
Session consumerSess = conn.createSession(false, Session.DUPS_OK_ACKNOWLEDGE);
MessageConsumer consumer = consumerSess.createConsumer(queue1);
conn.start();
final int NUM_MESSAGES = 20;
// Send some messages
for (int i = 0; i < NUM_MESSAGES; i++) {
Message m = producerSess.createMessage();
producer.send(m);
}
assertRemainingMessages(NUM_MESSAGES);
log.trace("Sent messages");
int count = 0;
Message m = null;
for (int i = 0; i < NUM_MESSAGES; i++) {
m = consumer.receive(200);
if (m == null) {
break;
}
count++;
}
ProxyAssertSupport.assertNotNull(m);
assertRemainingMessages(NUM_MESSAGES);
log.trace("Received " + count + " messages");
ProxyAssertSupport.assertEquals(count, NUM_MESSAGES);
consumerSess.recover();
log.trace("Session recover called");
m = consumer.receive(200);
log.trace("Message is:" + m);
ProxyAssertSupport.assertNull(m);
conn.close();
assertRemainingMessages(0);
}
@Test
public void testMessageListenerAutoAck() throws Exception {
Connection conn = createConnection();
Session sessSend = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
MessageProducer prod = sessSend.createProducer(queue1);
log.trace("Sending messages");
TextMessage tm1 = sessSend.createTextMessage("a");
TextMessage tm2 = sessSend.createTextMessage("b");
TextMessage tm3 = sessSend.createTextMessage("c");
prod.send(tm1);
prod.send(tm2);
prod.send(tm3);
log.trace("Sent messages");
sessSend.close();
assertRemainingMessages(3);
conn.start();
Session sessReceive = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
log.trace("Creating consumer");
MessageConsumer cons = sessReceive.createConsumer(queue1);
log.trace("Created consumer");
MessageListenerAutoAck listener = new MessageListenerAutoAck(sessReceive);
log.trace("Setting message listener");
cons.setMessageListener(listener);
log.trace("Set message listener");
listener.waitForMessages();
Thread.sleep(500);
assertRemainingMessages(0);
ProxyAssertSupport.assertFalse(listener.failed);
}
/*
* This test will: - Send two messages over a producer - Receive one message over a consumer - Call Recover - Receive
* the second message - The queue should be empty after that Note: testMessageListenerAutoAck will test a similar
* case using MessageListeners
*/
@Test
public void testRecoverAutoACK() throws Exception {
Connection conn = createConnection();
Session s = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
MessageProducer p = s.createProducer(queue1);
p.setDeliveryMode(DeliveryMode.PERSISTENT);
Message m = s.createTextMessage("one");
p.send(m);
m = s.createTextMessage("two");
p.send(m);
conn.close();
conn = null;
assertRemainingMessages(2);
conn = createConnection();
conn.start();
Session session = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
MessageConsumer consumer = session.createConsumer(queue1);
TextMessage messageReceived = (TextMessage) consumer.receive(1000);
ProxyAssertSupport.assertNotNull(messageReceived);
ProxyAssertSupport.assertEquals("one", messageReceived.getText());
session.recover();
messageReceived = (TextMessage) consumer.receive(1000);
ProxyAssertSupport.assertEquals("two", messageReceived.getText());
messageReceived = (TextMessage) consumer.receiveNoWait();
if (messageReceived != null) {
System.out.println("Message received " + messageReceived.getText());
}
Assert.assertNull(messageReceived);
consumer.close();
// I can't call xasession.close for this test as JCA layer would cache the session
// So.. keep this close commented!
// xasession.close();
assertRemainingMessages(0);
}
@Test
public void testMessageListenerDupsOK() throws Exception {
Connection conn = createConnection();
Session sessSend = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
MessageProducer prod = sessSend.createProducer(queue1);
log.trace("Sending messages");
TextMessage tm1 = sessSend.createTextMessage("a");
TextMessage tm2 = sessSend.createTextMessage("b");
TextMessage tm3 = sessSend.createTextMessage("c");
prod.send(tm1);
prod.send(tm2);
prod.send(tm3);
log.trace("Sent messages");
sessSend.close();
assertRemainingMessages(3);
conn.start();
Session sessReceive = conn.createSession(false, Session.DUPS_OK_ACKNOWLEDGE);
log.trace("Creating consumer");
MessageConsumer cons = sessReceive.createConsumer(queue1);
log.trace("Created consumer");
MessageListenerDupsOK listener = new MessageListenerDupsOK(sessReceive);
log.trace("Setting message listener");
cons.setMessageListener(listener);
log.trace("Set message listener");
listener.waitForMessages();
cons.close();
assertRemainingMessages(0);
ProxyAssertSupport.assertFalse(listener.failed);
}
@Test
public void testMessageListenerClientAck() throws Exception {
Connection conn = createConnection();
Session sessSend = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
MessageProducer prod = sessSend.createProducer(queue1);
TextMessage tm1 = sessSend.createTextMessage("a");
TextMessage tm2 = sessSend.createTextMessage("b");
TextMessage tm3 = sessSend.createTextMessage("c");
prod.send(tm1);
prod.send(tm2);
prod.send(tm3);
sessSend.close();
assertRemainingMessages(3);
conn.start();
Session sessReceive = conn.createSession(false, Session.CLIENT_ACKNOWLEDGE);
MessageConsumer cons = sessReceive.createConsumer(queue1);
MessageListenerClientAck listener = new MessageListenerClientAck(sessReceive);
cons.setMessageListener(listener);
listener.waitForMessages();
Thread.sleep(500);
assertRemainingMessages(0);
conn.close();
ProxyAssertSupport.assertFalse(listener.failed);
}
@Test
public void testMessageListenerTransactionalAck() throws Exception {
Connection conn = createConnection();
Session sessSend = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
MessageProducer prod = sessSend.createProducer(queue1);
TextMessage tm1 = sessSend.createTextMessage("a");
TextMessage tm2 = sessSend.createTextMessage("b");
TextMessage tm3 = sessSend.createTextMessage("c");
prod.send(tm1);
prod.send(tm2);
prod.send(tm3);
sessSend.close();
assertRemainingMessages(3);
conn.start();
Session sessReceive = conn.createSession(true, Session.SESSION_TRANSACTED);
MessageConsumer cons = sessReceive.createConsumer(queue1);
MessageListenerTransactionalAck listener = new MessageListenerTransactionalAck(sessReceive);
cons.setMessageListener(listener);
listener.waitForMessages();
Thread.sleep(500);
assertRemainingMessages(0);
conn.close();
ProxyAssertSupport.assertFalse(listener.failed);
}
// Package protected ---------------------------------------------
// Protected -----------------------------------------------------
// Private -------------------------------------------------------
// Inner classes -------------------------------------------------
private abstract class LatchListener implements MessageListener {
protected CountDownLatch latch = new CountDownLatch(1);
protected Session sess;
protected int count = 0;
boolean failed;
LatchListener(final Session sess) {
this.sess = sess;
}
public void waitForMessages() throws InterruptedException {
ProxyAssertSupport.assertTrue("failed to receive all messages", latch.await(2000, MILLISECONDS));
}
@Override
public abstract void onMessage(Message m);
}
private class MessageListenerAutoAck extends LatchListener {
MessageListenerAutoAck(final Session sess) {
super(sess);
}
@Override
public void onMessage(final Message m) {
try {
count++;
TextMessage tm = (TextMessage) m;
// Receive first three messages then recover() session
// Only last message should be redelivered
if (count == 1) {
assertRemainingMessages(3);
if (!"a".equals(tm.getText())) {
failed = true;
latch.countDown();
}
}
if (count == 2) {
assertRemainingMessages(2);
if (!"b".equals(tm.getText())) {
failed = true;
latch.countDown();
}
}
if (count == 3) {
assertRemainingMessages(1);
if (!"c".equals(tm.getText())) {
failed = true;
latch.countDown();
}
sess.recover();
}
if (count == 4) {
assertRemainingMessages(1);
if (!"c".equals(tm.getText())) {
failed = true;
latch.countDown();
}
latch.countDown();
}
} catch (Exception e) {
failed = true;
latch.countDown();
}
}
}
private class MessageListenerDupsOK extends LatchListener {
MessageListenerDupsOK(final Session sess) {
super(sess);
}
@Override
public void onMessage(final Message m) {
try {
count++;
TextMessage tm = (TextMessage) m;
// Receive first three messages then recover() session
// Only last message should be redelivered
if (count == 1) {
assertRemainingMessages(3);
if (!"a".equals(tm.getText())) {
failed = true;
latch.countDown();
}
}
if (count == 2) {
assertRemainingMessages(3);
if (!"b".equals(tm.getText())) {
failed = true;
latch.countDown();
}
}
if (count == 3) {
assertRemainingMessages(3);
if (!"c".equals(tm.getText())) {
failed = true;
latch.countDown();
}
sess.recover();
}
if (count == 4) {
// Recover forces an ack, so there will be only one left
assertRemainingMessages(1);
if (!"c".equals(tm.getText())) {
failed = true;
latch.countDown();
}
latch.countDown();
}
} catch (Exception e) {
failed = true;
latch.countDown();
}
}
}
private class MessageListenerClientAck extends LatchListener {
MessageListenerClientAck(final Session sess) {
super(sess);
}
@Override
public void onMessage(final Message m) {
try {
count++;
TextMessage tm = (TextMessage) m;
if (count == 1) {
assertRemainingMessages(3);
if (!"a".equals(tm.getText())) {
log.trace("Expected a but got " + tm.getText());
failed = true;
latch.countDown();
}
}
if (count == 2) {
assertRemainingMessages(3);
if (!"b".equals(tm.getText())) {
log.trace("Expected b but got " + tm.getText());
failed = true;
latch.countDown();
}
}
if (count == 3) {
assertRemainingMessages(3);
if (!"c".equals(tm.getText())) {
log.trace("Expected c but got " + tm.getText());
failed = true;
latch.countDown();
}
log.trace("calling recover");
sess.recover();
}
if (count == 4) {
assertRemainingMessages(3);
if (!"a".equals(tm.getText())) {
log.trace("Expected a but got " + tm.getText());
failed = true;
latch.countDown();
}
log.trace("*** calling acknowledge");
tm.acknowledge();
assertRemainingMessages(2);
log.trace("calling recover");
sess.recover();
}
if (count == 5) {
assertRemainingMessages(2);
if (!"b".equals(tm.getText())) {
log.trace("Expected b but got " + tm.getText());
failed = true;
latch.countDown();
}
log.trace("calling recover");
sess.recover();
}
if (count == 6) {
assertRemainingMessages(2);
if (!"b".equals(tm.getText())) {
log.trace("Expected b but got " + tm.getText());
failed = true;
latch.countDown();
}
}
if (count == 7) {
assertRemainingMessages(2);
if (!"c".equals(tm.getText())) {
log.trace("Expected c but got " + tm.getText());
failed = true;
latch.countDown();
}
tm.acknowledge();
assertRemainingMessages(0);
latch.countDown();
}
} catch (Exception e) {
log.error("Caught exception", e);
failed = true;
latch.countDown();
}
}
}
private class MessageListenerTransactionalAck extends LatchListener {
MessageListenerTransactionalAck(final Session sess) {
super(sess);
}
@Override
public void onMessage(final Message m) {
try {
count++;
TextMessage tm = (TextMessage) m;
if (count == 1) {
assertRemainingMessages(3);
if (!"a".equals(tm.getText())) {
failed = true;
latch.countDown();
}
}
if (count == 2) {
assertRemainingMessages(3);
if (!"b".equals(tm.getText())) {
failed = true;
latch.countDown();
}
}
if (count == 3) {
assertRemainingMessages(3);
if (!"c".equals(tm.getText())) {
failed = true;
latch.countDown();
}
log.trace("Rollback");
sess.rollback();
}
if (count == 4) {
assertRemainingMessages(3);
if (!"a".equals(tm.getText())) {
failed = true;
latch.countDown();
}
}
if (count == 5) {
assertRemainingMessages(3);
if (!"b".equals(tm.getText())) {
failed = true;
latch.countDown();
}
log.trace("commit");
sess.commit();
assertRemainingMessages(1);
}
if (count == 6) {
assertRemainingMessages(1);
if (!"c".equals(tm.getText())) {
failed = true;
latch.countDown();
}
log.trace("recover");
sess.rollback();
}
if (count == 7) {
assertRemainingMessages(1);
if (!"c".equals(tm.getText())) {
failed = true;
latch.countDown();
}
log.trace("Commit");
sess.commit();
assertRemainingMessages(0);
latch.countDown();
}
} catch (Exception e) {
// log.error(e);
failed = true;
latch.countDown();
}
}
}
@Test
public void testTransactionalIgnoreACK() throws Exception {
Connection conn = createConnection();
Session producerSess = conn.createSession(true, Session.SESSION_TRANSACTED);
MessageProducer producer = producerSess.createProducer(queue1);
Session consumerSess = conn.createSession(true, Session.SESSION_TRANSACTED);
MessageConsumer consumer = consumerSess.createConsumer(queue1);
conn.start();
final int NUM_MESSAGES = 20;
// Send some messages
for (int i = 0; i < NUM_MESSAGES; i++) {
Message m = producerSess.createMessage();
m.acknowledge(); // This is invalid but should be ignored accordingly to the javadoc
producer.send(m);
}
assertRemainingMessages(0);
producerSess.rollback();
// Send some messages
for (int i = 0; i < NUM_MESSAGES; i++) {
Message m = producerSess.createMessage();
m.acknowledge(); // / should be ignored
producer.send(m);
}
assertRemainingMessages(0);
producerSess.commit();
assertRemainingMessages(NUM_MESSAGES);
int count = 0;
while (true) {
Message m = consumer.receive(200);
if (m == null) {
break;
}
m.acknowledge();
count++;
}
assertRemainingMessages(NUM_MESSAGES);
ProxyAssertSupport.assertEquals(count, NUM_MESSAGES);
consumerSess.rollback();
assertRemainingMessages(NUM_MESSAGES);
int i = 0;
for (; i < NUM_MESSAGES; i++) {
consumer.receive();
}
assertRemainingMessages(NUM_MESSAGES);
// if I don't receive enough messages, the test will timeout
consumerSess.commit();
assertRemainingMessages(0);
checkEmpty(queue1);
}
}