title: How can I handle JMS redelivery into my Camel Route, but still allow message deletion
body: <p>I have a Camel Route that reads from an ActiveMQ JMS Queue, does some processing, and passes the result on to a remote destination. If the communications part of this process fails, I want to retry <em>indefinitely</em> (until the destination is "up").  I can handle this by making the route <code>transacted</code> and setting up the <code>redeliveryPolicy</code>.  The redelivery is set in both Camel (via <code>camel.processor.RedeliveryPolicy</code> to reattempt the failed part of the route) and the ActiveMQConnectionFactory (via <code>org.apache.activemq.RedeliveryPolicy</code> to reattempt the entire route).</p>
  
  <p>I also have a requirement that we should be able to delete an entry from the JMS queue (which I do via an application that talks to ActiveMQ via JMX), and processing should move to the next message.</p>
  
  <p>The issue is that I can either allow message deletions (by setting the consumer to be <code>cacheLevelName=CACHE_NONE</code>), or have the connection handle retries (by setting the consumer to be <code>cacheLevelName=CACHE_CONSUMER</code>), but not both.</p>
  
  <p>Here is my current setup:</p>
  
  <pre class="lang-xml prettyprint-override"><code>&lt;bean id="jmsTransactionManager" class="org.springframework.jms.connection.JmsTransactionManager"&gt;
    &lt;property name="connectionFactory" ref="jmsConnectionFactory"/&gt;
  &lt;/bean&gt;
  
  &lt;bean id="jmsConnectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory"&gt;
    &lt;property name="brokerURL" value="${jms.brokerUrl}" /&gt;
    &lt;property name="redeliveryPolicy" ref="amqRedeliveryPolicy" /&gt;
    &lt;property name="prefetchPolicy"&gt;
      &lt;bean class="org.apache.activemq.ActiveMQPrefetchPolicy"&gt;
        &lt;property name="all" value="0"/&gt;
      &lt;/bean&gt;
    &lt;/property&gt;
  &lt;/bean&gt; 
  
  &lt;bean id="jmsConfig" class="org.apache.camel.component.jms.JmsConfiguration"&gt;
    &lt;property name="connectionFactory" ref="jmsConnectionFactory"/&gt;
    &lt;property name="transactionManager" ref="jmsTransactionManager"/&gt;
    &lt;property name="transacted" value="true"/&gt;
    &lt;property name="concurrentConsumers" value="1"/&gt;
  &lt;/bean&gt;
  
  &lt;bean id="jms" class="org.apache.camel.component.jms.JmsComponent" &gt;
    &lt;property name="configuration" ref="jmsConfig" /&gt;
  &lt;/bean&gt;
  
  &lt;!-- Redelivery Policy for ActiveMQ (the Broker), so it will perform retries of the entire route --&gt;
  &lt;bean id="amqRedeliveryPolicy" class="org.apache.activemq.RedeliveryPolicy"&gt;
    &lt;property name="initialRedeliveryDelay" value="5000" /&gt;
    &lt;property name="redeliveryDelay" value="5000" /&gt;
    &lt;property name="maximumRedeliveries" value="-1" /&gt;
    &lt;property name="queue" value="&gt;" /&gt;
  &lt;/bean&gt;
  
  &lt;!-- Redelivery Policy for Camel Internal, so it will retry from the part of the exchange that's failed in case of comms issues --&gt;
  &lt;bean id="redeliveryProfile" class="org.apache.camel.processor.RedeliveryPolicy"&gt;
    &lt;property name="maximumRedeliveries" value="2"/&gt;
    &lt;property name="redeliveryDelay" value="500"/&gt;
  &lt;/bean&gt;
  
  &lt;bean id="PROPAGATION_REQUIRED" class="org.apache.camel.spring.spi.SpringTransactionPolicy"&gt;
    &lt;constructor-arg&gt;
      &lt;bean class="org.springframework.transaction.support.TransactionTemplate"&gt;
        &lt;property name="transactionManager" ref="jmsTransactionManager"/&gt;
      &lt;/bean&gt;
    &lt;/constructor-arg&gt;
  &lt;/bean&gt;
  
  &lt;camel:camelContext id="testContext"&gt;
    &lt;camel:routeBuilder ref="transactedRoute" /&gt;
  &lt;/camel:camelContext&gt;
  </code></pre>
  
  <p>With a very simple route:</p>
  
  <pre class="lang-java prettyprint-override"><code>@Component
  public class TransactedRoute extends SpringRouteBuilder {
    @Override
    public void configure() {
      onException(Exception.class) // we would handle comms exceptions here
        .redeliveryPolicyRef("redeliveryProfile")
        .rollback();
  
      from("jms:queue:myqueue?cacheLevelName=CACHE_CONSUMER")
        .transacted("PROPAGATION_REQUIRED")
        .bean(Bean1.class)
        .to(DESTINATION); // this could throw a comms exception
    }
  }
  </code></pre>
  
  <p>With this setup, the route reads from <code>jms:queue:myqueue</code>, and in the case of a Comms exception, Camel internally retries the route from <code>to</code> part twice (<code>redeliveryProfile</code>). Then after a 5-second delay the message is sent through the entire route again (<code>amqRedeliveryPolicy</code>). This continues until I stop the test.</p>
  
  <p>However, if I delete the message from ActiveMQ, it continues to be processed by the route, despite it no longer being in the queue.</p>
  
  <p>If I change the consumer to be:</p>
  
  <pre><code>from("jms:queue:myqueue?cacheLevelName=CACHE_NONE")
  </code></pre>
  
  <p>I can now delete the message from ActiveMQ and the route stops processing it... but <code>amqRedeliveryPolicy</code> is ignored, the message is retried immediately (no 5-second delay) and after 6 attempts (the default for AMQ) it is put into the Dead Letter Queue.</p>
  
  <p>So, is there a way to achieve both by modifying my configuration?</p>
  
  <p>Or have I completely missed the point somewhere along the lines?</p>