locator.setBlockOnNonDurableSend(true);
locator.setBlockOnDurableSend(true);
locator.setReconnectAttempts(-1);
locator.setBlockOnAcknowledge(true);
final ClientSessionFactoryInternal sf = createSessionFactoryAndWaitForTopology(locator, 2);
final ClientSession session = createSession(sf, false, false);
session.createQueue(FailoverTestBase.ADDRESS, FailoverTestBase.ADDRESS, null, true);
final int numMessages = 100;
ClientProducer producer = session.createProducer(FailoverTestBase.ADDRESS);
String txID = "my-tx-id";
for (int i = 0; i < numMessages; i++)
{
ClientMessage message = session.createMessage(true);
if (i == 0)
{
// Only need to add it on one message per tx
message.putStringProperty(Message.HDR_DUPLICATE_DETECTION_ID, new SimpleString(txID));
}
setBody(i, message);
message.putIntProperty("counter", i);
producer.send(message);
}
class Committer extends Thread
{
DelayInterceptor2 interceptor = new DelayInterceptor2();
@Override
public void run()
{
try
{
sf.getServerLocator().addInterceptor(interceptor);
session.commit();
}
catch (HornetQException e)
{
if (e.getCode() == HornetQException.TRANSACTION_ROLLED_BACK)
{
// Ok - now we retry the commit after removing the interceptor
sf.getServerLocator().removeInterceptor(interceptor);
try
{
session.commit();
failed = false;
}
catch (HornetQException e2)
{
}
}
}
}
volatile boolean failed = true;
}
Committer committer = new Committer();
// Commit will occur, but response will never get back, connetion is failed, and commit should be unblocked
// with transaction rolled back
committer.start();
// Wait for the commit to occur and the response to be discarded
assertTrue(committer.interceptor.await());
Thread.sleep(500);
crash(session);
committer.join();
Assert.assertFalse(committer.failed);
session.close();
ClientSession session2 = createSession(sf, false, false);
producer = session2.createProducer(FailoverTestBase.ADDRESS);
// We now try and resend the messages since we get a transaction rolled back exception
// but the commit actually succeeded, duplicate detection should kick in and prevent dups
for (int i = 0; i < numMessages; i++)
{
ClientMessage message = session2.createMessage(true);
if (i == 0)
{
// Only need to add it on one message per tx
message.putStringProperty(Message.HDR_DUPLICATE_DETECTION_ID, new SimpleString(txID));
}
setBody(i, message);
message.putIntProperty("counter", i);
producer.send(message);
}
try
{
session2.commit();
}
catch (HornetQException e)
{
assertEquals(HornetQException.DUPLICATE_ID_REJECTED, e.getCode());
}
ClientConsumer consumer = session2.createConsumer(FailoverTestBase.ADDRESS);
session2.start();
for (int i = 0; i < numMessages; i++)
{
ClientMessage message = consumer.receive(1000);
Assert.assertNotNull(message);
assertMessageBody(i, message);
Assert.assertEquals(i, message.getIntProperty("counter").intValue());
message.acknowledge();
}
ClientMessage message = consumer.receiveImmediate();
Assert.assertNull(message);
session2.close();
sf.close();
Assert.assertEquals(0, sf.numSessions());
Assert.assertEquals(0, sf.numConnections());
}