Search in sources :

Example 1 with ActiveMQDuplicateIdException

use of org.apache.activemq.artemis.api.core.ActiveMQDuplicateIdException in project activemq-artemis by apache.

the class AsynchronousFailoverTest method doTestTransactional.

private void doTestTransactional(final TestRunner runner) throws Throwable {
    // For duplication detection
    int executionId = 0;
    while (!runner.isFailed()) {
        ClientSession session = null;
        executionId++;
        log.info("#test doTestTransactional starting now. Execution " + executionId);
        try {
            boolean retry = false;
            final int numMessages = 1000;
            session = sf.createSession(false, false);
            listener = new CountDownSessionFailureListener(session);
            session.addFailureListener(listener);
            do {
                try {
                    ClientProducer producer = session.createProducer(FailoverTestBase.ADDRESS);
                    for (int i = 0; i < numMessages; i++) {
                        ClientMessage message = session.createMessage(true);
                        message.getBodyBuffer().writeString("message" + i);
                        message.putIntProperty("counter", i);
                        message.putStringProperty(Message.HDR_DUPLICATE_DETECTION_ID, new SimpleString("id:" + i + ",exec:" + executionId));
                        addPayload(message);
                        if (log.isDebugEnabled()) {
                            log.debug("Sending message " + message);
                        }
                        producer.send(message);
                    }
                    log.debug("Sending commit");
                    session.commit();
                    retry = false;
                } catch (ActiveMQDuplicateIdException die) {
                    logAndSystemOut("#test duplicate id rejected on sending");
                    break;
                } catch (ActiveMQTransactionRolledBackException trbe) {
                    log.info("#test transaction rollback retrying on sending");
                    // OK
                    retry = true;
                } catch (ActiveMQUnBlockedException ube) {
                    log.info("#test transaction rollback retrying on sending");
                    // OK
                    retry = true;
                } catch (ActiveMQTransactionOutcomeUnknownException toue) {
                    log.info("#test transaction rollback retrying on sending");
                    // OK
                    retry = true;
                } catch (ActiveMQException e) {
                    log.info("#test Exception " + e, e);
                    throw e;
                }
            } while (retry);
            logAndSystemOut("#test Finished sending, starting consumption now");
            boolean blocked = false;
            retry = false;
            ClientConsumer consumer = null;
            do {
                ArrayList<Integer> msgs = new ArrayList<>();
                try {
                    if (consumer == null) {
                        consumer = session.createConsumer(FailoverTestBase.ADDRESS);
                        session.start();
                    }
                    for (int i = 0; i < numMessages; i++) {
                        if (log.isDebugEnabled()) {
                            log.debug("Consumer receiving message " + i);
                        }
                        ClientMessage message = consumer.receive(10000);
                        if (message == null) {
                            break;
                        }
                        if (log.isDebugEnabled()) {
                            log.debug("Received message " + message);
                        }
                        int count = message.getIntProperty("counter");
                        if (count != i) {
                            log.warn("count was received out of order, " + count + "!=" + i);
                        }
                        msgs.add(count);
                        message.acknowledge();
                    }
                    log.info("#test commit");
                    try {
                        session.commit();
                    } catch (ActiveMQTransactionRolledBackException trbe) {
                        // we know the tx has been rolled back so we just consume again
                        retry = true;
                        continue;
                    } catch (ActiveMQException e) {
                        // This could eventually happen
                        // We will get rid of this when we implement 2 phase commit on failover
                        log.warn("exception during commit, it will be ignored for now" + e.getMessage(), e);
                    }
                    try {
                        if (blocked) {
                            assertTrue("msgs.size is expected to be 0 or " + numMessages + " but it was " + msgs.size(), msgs.size() == 0 || msgs.size() == numMessages);
                        } else {
                            assertTrue("msgs.size is expected to be " + numMessages + " but it was " + msgs.size(), msgs.size() == numMessages);
                        }
                    } catch (Throwable e) {
                        log.info(threadDump("Thread dump, messagesReceived = " + msgs.size()));
                        logAndSystemOut(e.getMessage() + " messages received");
                        for (Integer msg : msgs) {
                            logAndSystemOut(msg.toString());
                        }
                        throw e;
                    }
                    int i = 0;
                    for (Integer msg : msgs) {
                        assertEquals(i++, (int) msg);
                    }
                    retry = false;
                    blocked = false;
                } catch (ActiveMQTransactionRolledBackException trbe) {
                    logAndSystemOut("Transaction rolled back with " + msgs.size(), trbe);
                    // TODO: https://jira.jboss.org/jira/browse/HORNETQ-369
                    // ATM RolledBack exception is being called with the transaction is committed.
                    // the test will fail if you remove this next line
                    blocked = true;
                    retry = true;
                } catch (ActiveMQTransactionOutcomeUnknownException tou) {
                    logAndSystemOut("Transaction rolled back with " + msgs.size(), tou);
                    // TODO: https://jira.jboss.org/jira/browse/HORNETQ-369
                    // ATM RolledBack exception is being called with the transaction is committed.
                    // the test will fail if you remove this next line
                    blocked = true;
                    retry = true;
                } catch (ActiveMQUnBlockedException ube) {
                    logAndSystemOut("Unblocked with " + msgs.size(), ube);
                    // TODO: https://jira.jboss.org/jira/browse/HORNETQ-369
                    // This part of the test is never being called.
                    blocked = true;
                    retry = true;
                } catch (ActiveMQException e) {
                    logAndSystemOut(e.getMessage(), e);
                    throw e;
                }
            } while (retry);
        } finally {
            if (session != null) {
                session.close();
            }
        }
        listener = null;
    }
}
Also used : ActiveMQTransactionOutcomeUnknownException(org.apache.activemq.artemis.api.core.ActiveMQTransactionOutcomeUnknownException) ArrayList(java.util.ArrayList) SimpleString(org.apache.activemq.artemis.api.core.SimpleString) ClientMessage(org.apache.activemq.artemis.api.core.client.ClientMessage) CountDownSessionFailureListener(org.apache.activemq.artemis.tests.util.CountDownSessionFailureListener) ActiveMQUnBlockedException(org.apache.activemq.artemis.api.core.ActiveMQUnBlockedException) ActiveMQException(org.apache.activemq.artemis.api.core.ActiveMQException) ActiveMQTransactionRolledBackException(org.apache.activemq.artemis.api.core.ActiveMQTransactionRolledBackException) ClientSession(org.apache.activemq.artemis.api.core.client.ClientSession) ActiveMQDuplicateIdException(org.apache.activemq.artemis.api.core.ActiveMQDuplicateIdException) ClientConsumer(org.apache.activemq.artemis.api.core.client.ClientConsumer) ClientProducer(org.apache.activemq.artemis.api.core.client.ClientProducer)

Example 2 with ActiveMQDuplicateIdException

use of org.apache.activemq.artemis.api.core.ActiveMQDuplicateIdException in project activemq-artemis by apache.

the class DuplicateDetectionTest method testPersistTransactional.

@Test
public void testPersistTransactional() throws Exception {
    ClientSession session = sf.createSession(false, false, false);
    session.start();
    final SimpleString queueName = new SimpleString("DuplicateDetectionTestQueue");
    session.createQueue(queueName, queueName, null, false);
    ClientProducer producer = session.createProducer(queueName);
    ClientConsumer consumer = session.createConsumer(queueName);
    ClientMessage message = createMessage(session, 1);
    SimpleString dupID = new SimpleString("abcdefg");
    message.putBytesProperty(Message.HDR_DUPLICATE_DETECTION_ID, dupID.getData());
    producer.send(message);
    session.commit();
    ClientMessage message2 = consumer.receive(1000);
    message2.acknowledge();
    session.commit();
    Assert.assertEquals(1, message2.getObjectProperty(propKey));
    message = createMessage(session, 2);
    SimpleString dupID2 = new SimpleString("hijklmnopqr");
    message.putBytesProperty(Message.HDR_DUPLICATE_DETECTION_ID, dupID2.getData());
    producer.send(message);
    session.commit();
    message2 = consumer.receive(1000);
    message2.acknowledge();
    session.commit();
    Assert.assertEquals(2, message2.getObjectProperty(propKey));
    session.close();
    sf.close();
    server.stop();
    waitForServerToStop(server);
    server.start();
    sf = createSessionFactory(locator);
    session = sf.createSession(false, false, false);
    session.start();
    session.createQueue(queueName, queueName, null, false);
    producer = session.createProducer(queueName);
    consumer = session.createConsumer(queueName);
    message = createMessage(session, 1);
    message.putBytesProperty(Message.HDR_DUPLICATE_DETECTION_ID, dupID.getData());
    producer.send(message);
    try {
        session.commit();
    } catch (ActiveMQDuplicateIdException die) {
        session.rollback();
    } catch (ActiveMQException e) {
        fail("Invalid Exception type:" + e.getType());
    }
    message2 = consumer.receiveImmediate();
    Assert.assertNull(message2);
    message = createMessage(session, 2);
    message.putBytesProperty(Message.HDR_DUPLICATE_DETECTION_ID, dupID2.getData());
    producer.send(message);
    try {
        session.commit();
    } catch (ActiveMQDuplicateIdException die) {
        session.rollback();
    } catch (ActiveMQException e) {
        fail("Invalid Exception type:" + e.getType());
    }
    message2 = consumer.receiveImmediate();
    Assert.assertNull(message2);
}
Also used : ActiveMQException(org.apache.activemq.artemis.api.core.ActiveMQException) ClientSession(org.apache.activemq.artemis.api.core.client.ClientSession) ActiveMQDuplicateIdException(org.apache.activemq.artemis.api.core.ActiveMQDuplicateIdException) SimpleString(org.apache.activemq.artemis.api.core.SimpleString) ClientMessage(org.apache.activemq.artemis.api.core.client.ClientMessage) ClientConsumer(org.apache.activemq.artemis.api.core.client.ClientConsumer) ClientProducer(org.apache.activemq.artemis.api.core.client.ClientProducer) Test(org.junit.Test)

Example 3 with ActiveMQDuplicateIdException

use of org.apache.activemq.artemis.api.core.ActiveMQDuplicateIdException in project activemq-artemis by apache.

the class DuplicateDetectionTest method testEntireTransactionRejected.

/*
    * Entire transaction should be rejected on duplicate detection
    * Even if not all entries have dupl id header
    */
@Test
public void testEntireTransactionRejected() throws Exception {
    ClientSession session = sf.createSession(false, false, false);
    session.start();
    final SimpleString queueName = new SimpleString("DuplicateDetectionTestQueue");
    final SimpleString queue2 = new SimpleString("queue2");
    session.createQueue(queueName, queueName, null, false);
    session.createQueue(queue2, queue2, null, false);
    ClientProducer producer = session.createProducer(queueName);
    ClientMessage message = createMessage(session, 0);
    SimpleString dupID = new SimpleString("abcdefg");
    message.putBytesProperty(Message.HDR_DUPLICATE_DETECTION_ID, dupID.getData());
    producer.send(message);
    ClientMessage message2 = createMessage(session, 0);
    ClientProducer producer2 = session.createProducer(queue2);
    producer2.send(message2);
    session.commit();
    session.close();
    session = sf.createSession(false, false, false);
    session.start();
    ClientConsumer consumer2 = session.createConsumer(queue2);
    producer = session.createProducer(queueName);
    message = createMessage(session, 1);
    message.putBytesProperty(Message.HDR_DUPLICATE_DETECTION_ID, dupID.getData());
    producer.send(message);
    message = createMessage(session, 2);
    producer.send(message);
    message = createMessage(session, 3);
    producer.send(message);
    message = createMessage(session, 4);
    producer.send(message);
    message = consumer2.receive(5000);
    assertNotNull(message);
    message.acknowledge();
    try {
        session.commit();
    } catch (ActiveMQDuplicateIdException die) {
        session.rollback();
    } catch (ActiveMQException e) {
        fail("Invalid Exception type:" + e.getType());
    }
    ClientConsumer consumer = session.createConsumer(queueName);
    message = consumer.receive(250);
    Assert.assertEquals(0, message.getObjectProperty(propKey));
    message = consumer.receiveImmediate();
    Assert.assertNull(message);
    message = consumer2.receive(5000);
    assertNotNull(message);
    message.acknowledge();
    session.commit();
}
Also used : ActiveMQException(org.apache.activemq.artemis.api.core.ActiveMQException) ClientSession(org.apache.activemq.artemis.api.core.client.ClientSession) ActiveMQDuplicateIdException(org.apache.activemq.artemis.api.core.ActiveMQDuplicateIdException) SimpleString(org.apache.activemq.artemis.api.core.SimpleString) ClientMessage(org.apache.activemq.artemis.api.core.client.ClientMessage) ClientConsumer(org.apache.activemq.artemis.api.core.client.ClientConsumer) ClientProducer(org.apache.activemq.artemis.api.core.client.ClientProducer) Test(org.junit.Test)

Example 4 with ActiveMQDuplicateIdException

use of org.apache.activemq.artemis.api.core.ActiveMQDuplicateIdException in project activemq-artemis by apache.

the class PostOfficeImpl method checkDuplicateID.

private boolean checkDuplicateID(final Message message, final RoutingContext context, boolean rejectDuplicates, AtomicBoolean startedTX) throws Exception {
    // Check the DuplicateCache for the Bridge first
    Object bridgeDup = message.removeExtraBytesProperty(Message.HDR_BRIDGE_DUPLICATE_ID);
    if (bridgeDup != null) {
        // if the message is being sent from the bridge, we just ignore the duplicate id, and use the internal one
        byte[] bridgeDupBytes = (byte[]) bridgeDup;
        DuplicateIDCache cacheBridge = getDuplicateIDCache(BRIDGE_CACHE_STR.concat(context.getAddress(message).toString()));
        if (context.getTransaction() == null) {
            context.setTransaction(new TransactionImpl(storageManager));
            startedTX.set(true);
        }
        if (!cacheBridge.atomicVerify(bridgeDupBytes, context.getTransaction())) {
            context.getTransaction().rollback();
            startedTX.set(false);
            message.decrementRefCount();
            return false;
        }
    } else {
        // if used BridgeDuplicate, it's not going to use the regular duplicate
        // since this will would break redistribution (re-setting the duplicateId)
        byte[] duplicateIDBytes = message.getDuplicateIDBytes();
        DuplicateIDCache cache = null;
        boolean isDuplicate = false;
        if (duplicateIDBytes != null) {
            cache = getDuplicateIDCache(context.getAddress(message));
            isDuplicate = cache.contains(duplicateIDBytes);
            if (rejectDuplicates && isDuplicate) {
                ActiveMQServerLogger.LOGGER.duplicateMessageDetected(message);
                String warnMessage = "Duplicate message detected - message will not be routed. Message information:" + message.toString();
                if (context.getTransaction() != null) {
                    context.getTransaction().markAsRollbackOnly(new ActiveMQDuplicateIdException(warnMessage));
                }
                message.decrementRefCount();
                return false;
            }
        }
        if (cache != null && !isDuplicate) {
            if (context.getTransaction() == null) {
                // We need to store the duplicate id atomically with the message storage, so we need to create a tx for this
                context.setTransaction(new TransactionImpl(storageManager));
                startedTX.set(true);
            }
            cache.addToCache(duplicateIDBytes, context.getTransaction(), false);
        }
    }
    return true;
}
Also used : DuplicateIDCache(org.apache.activemq.artemis.core.postoffice.DuplicateIDCache) ActiveMQDuplicateIdException(org.apache.activemq.artemis.api.core.ActiveMQDuplicateIdException) TransactionImpl(org.apache.activemq.artemis.core.transaction.impl.TransactionImpl) SimpleString(org.apache.activemq.artemis.api.core.SimpleString)

Example 5 with ActiveMQDuplicateIdException

use of org.apache.activemq.artemis.api.core.ActiveMQDuplicateIdException in project activemq-artemis by apache.

the class FailoverTest method testCommitOccurredUnblockedAndResendNoDuplicates.

@Test(timeout = 120000)
public void testCommitOccurredUnblockedAndResendNoDuplicates() throws Exception {
    locator.setBlockOnNonDurableSend(true).setBlockOnDurableSend(true).setReconnectAttempts(300).setRetryInterval(100).setBlockOnAcknowledge(true);
    sf = createSessionFactoryAndWaitForTopology(locator, 2);
    final ClientSession session = createSession(sf, false, false);
    session.createQueue(FailoverTestBase.ADDRESS, RoutingType.MULTICAST, FailoverTestBase.ADDRESS, null, true);
    ClientProducer producer = session.createProducer(FailoverTestBase.ADDRESS);
    String txID = "my-tx-id";
    for (int i = 0; i < NUM_MESSAGES; 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().addIncomingInterceptor(interceptor);
                session.commit();
            } catch (ActiveMQTransactionRolledBackException trbe) {
                // Ok - now we retry the commit after removing the interceptor
                sf.getServerLocator().removeIncomingInterceptor(interceptor);
                try {
                    session.commit();
                    failed = false;
                } catch (ActiveMQException e2) {
                    throw new RuntimeException(e2);
                }
            } catch (ActiveMQTransactionOutcomeUnknownException toue) {
                // Ok - now we retry the commit after removing the interceptor
                sf.getServerLocator().removeIncomingInterceptor(interceptor);
                try {
                    session.commit();
                    failed = false;
                } catch (ActiveMQException e2) {
                    throw new RuntimeException(e2);
                }
            } catch (ActiveMQException e) {
            // ignore
            }
        }

        volatile boolean failed = true;
    }
    Committer committer = new Committer();
    // Commit will occur, but response will never get back, connection 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
    Assert.assertTrue(committer.interceptor.await());
    crash(session);
    committer.join();
    Assert.assertFalse("second attempt succeed?", committer.failed);
    session.close();
    ClientSession session2 = createSession(sf, false, false);
    producer = session2.createProducer(FailoverTestBase.ADDRESS);
    for (int i = 0; i < NUM_MESSAGES; 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();
        Assert.fail("expecting DUPLICATE_ID_REJECTED exception");
    } catch (ActiveMQDuplicateIdException dide) {
    // ok
    } catch (ActiveMQException e) {
        Assert.fail("Invalid Exception type:" + e.getType());
    }
    ClientConsumer consumer = session2.createConsumer(FailoverTestBase.ADDRESS);
    session2.start();
    receiveMessages(consumer);
    ClientMessage message = consumer.receiveImmediate();
    Assert.assertNull(message);
}
Also used : ActiveMQTransactionOutcomeUnknownException(org.apache.activemq.artemis.api.core.ActiveMQTransactionOutcomeUnknownException) SimpleString(org.apache.activemq.artemis.api.core.SimpleString) SimpleString(org.apache.activemq.artemis.api.core.SimpleString) ClientMessage(org.apache.activemq.artemis.api.core.client.ClientMessage) ActiveMQException(org.apache.activemq.artemis.api.core.ActiveMQException) ActiveMQTransactionRolledBackException(org.apache.activemq.artemis.api.core.ActiveMQTransactionRolledBackException) ClientSession(org.apache.activemq.artemis.api.core.client.ClientSession) ActiveMQDuplicateIdException(org.apache.activemq.artemis.api.core.ActiveMQDuplicateIdException) ClientConsumer(org.apache.activemq.artemis.api.core.client.ClientConsumer) ClientProducer(org.apache.activemq.artemis.api.core.client.ClientProducer) Test(org.junit.Test)

Aggregations

ActiveMQDuplicateIdException (org.apache.activemq.artemis.api.core.ActiveMQDuplicateIdException)5 SimpleString (org.apache.activemq.artemis.api.core.SimpleString)5 ActiveMQException (org.apache.activemq.artemis.api.core.ActiveMQException)4 ClientConsumer (org.apache.activemq.artemis.api.core.client.ClientConsumer)4 ClientMessage (org.apache.activemq.artemis.api.core.client.ClientMessage)4 ClientProducer (org.apache.activemq.artemis.api.core.client.ClientProducer)4 ClientSession (org.apache.activemq.artemis.api.core.client.ClientSession)4 Test (org.junit.Test)3 ActiveMQTransactionOutcomeUnknownException (org.apache.activemq.artemis.api.core.ActiveMQTransactionOutcomeUnknownException)2 ActiveMQTransactionRolledBackException (org.apache.activemq.artemis.api.core.ActiveMQTransactionRolledBackException)2 ArrayList (java.util.ArrayList)1 ActiveMQUnBlockedException (org.apache.activemq.artemis.api.core.ActiveMQUnBlockedException)1 DuplicateIDCache (org.apache.activemq.artemis.core.postoffice.DuplicateIDCache)1 TransactionImpl (org.apache.activemq.artemis.core.transaction.impl.TransactionImpl)1 CountDownSessionFailureListener (org.apache.activemq.artemis.tests.util.CountDownSessionFailureListener)1