You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by da...@apache.org on 2009/04/17 11:33:01 UTC

svn commit: r765920 - in /camel/trunk: camel-core/src/main/java/org/apache/camel/builder/ camel-core/src/main/java/org/apache/camel/model/ camel-core/src/main/java/org/apache/camel/processor/ camel-core/src/test/java/org/apache/camel/processor/ compone...

Author: davsclaus
Date: Fri Apr 17 09:32:59 2009
New Revision: 765920

URL: http://svn.apache.org/viewvc?rev=765920&view=rev
Log:
CAMEL-1475: Polished the transacted error handler a bit so it works in conjunction with stream interceptor. 

Added:
    camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/interceptor/MixedPropagationTransactedTest.java
      - copied, changed from r765844, camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/interceptor/TransactionalClientDataSourceTransactedTest.java
    camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/interceptor/TransactionalClientDataSourceMixedTransactedTest.java
      - copied, changed from r765211, camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/interceptor/TransactionalClientDataSourceNotTransactedTest.java
    camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/interceptor/TransactionalClientDataSourceTransactedWithChoiceTest.java
      - copied, changed from r765844, camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/interceptor/TransactionalClientDataSourceTransactedTest.java
    camel/trunk/components/camel-spring/src/test/resources/org/apache/camel/spring/interceptor/mixedPropagationTransactedTest.xml
      - copied, changed from r765844, camel/trunk/components/camel-spring/src/test/resources/org/apache/camel/spring/interceptor/transactionalClientDataSource.xml
Modified:
    camel/trunk/camel-core/src/main/java/org/apache/camel/builder/DeadLetterChannelBuilder.java
    camel/trunk/camel-core/src/main/java/org/apache/camel/builder/DefaultErrorHandlerBuilder.java
    camel/trunk/camel-core/src/main/java/org/apache/camel/builder/ErrorHandlerBuilder.java
    camel/trunk/camel-core/src/main/java/org/apache/camel/builder/ErrorHandlerBuilderRef.java
    camel/trunk/camel-core/src/main/java/org/apache/camel/builder/ErrorHandlerBuilderSupport.java
    camel/trunk/camel-core/src/main/java/org/apache/camel/builder/LoggingErrorHandlerBuilder.java
    camel/trunk/camel-core/src/main/java/org/apache/camel/builder/NoErrorHandlerBuilder.java
    camel/trunk/camel-core/src/main/java/org/apache/camel/model/TransactedDefinition.java
    camel/trunk/camel-core/src/main/java/org/apache/camel/processor/DeadLetterChannel.java
    camel/trunk/camel-core/src/main/java/org/apache/camel/processor/DefaultErrorHandler.java
    camel/trunk/camel-core/src/main/java/org/apache/camel/processor/ErrorHandlerSupport.java
    camel/trunk/camel-core/src/main/java/org/apache/camel/processor/LoggingErrorHandler.java
    camel/trunk/camel-core/src/test/java/org/apache/camel/processor/ErrorHandlerSupportTest.java
    camel/trunk/components/camel-jms/src/test/java/org/apache/camel/component/jms/TransactedJmsRouteTest.java
    camel/trunk/components/camel-jms/src/test/java/org/apache/camel/component/jms/tx/QueueToProcessorTransactionTest.java
    camel/trunk/components/camel-jms/src/test/java/org/apache/camel/component/jms/tx/QueueToQueueRequestReplyTransactionTest.java
    camel/trunk/components/camel-jms/src/test/java/org/apache/camel/component/jms/tx/QueueToQueueTransactionTest.java
    camel/trunk/components/camel-spring/src/main/java/org/apache/camel/spring/SpringRouteBuilder.java
    camel/trunk/components/camel-spring/src/main/java/org/apache/camel/spring/spi/SpringTransactionPolicy.java
    camel/trunk/components/camel-spring/src/main/java/org/apache/camel/spring/spi/TransactedRuntimeCamelException.java
    camel/trunk/components/camel-spring/src/main/java/org/apache/camel/spring/spi/TransactionErrorHandler.java
    camel/trunk/components/camel-spring/src/main/java/org/apache/camel/spring/spi/TransactionErrorHandlerBuilder.java
    camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/config/DummyErrorHandlerBuilder.java
    camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/interceptor/TransactionalClientDataSourceNotTransactedTest.java
    camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/interceptor/TransactionalClientDataSourceTest.java
    camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/interceptor/TransactionalClientDataSourceWithOnExceptionTest.java
    camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/interceptor/TransactionalClientWithRollbackTest.java
    camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/interceptor/route/DataSourceSpringRouteBuilder.java

Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/builder/DeadLetterChannelBuilder.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/builder/DeadLetterChannelBuilder.java?rev=765920&r1=765919&r2=765920&view=diff
==============================================================================
--- camel/trunk/camel-core/src/main/java/org/apache/camel/builder/DeadLetterChannelBuilder.java (original)
+++ camel/trunk/camel-core/src/main/java/org/apache/camel/builder/DeadLetterChannelBuilder.java Fri Apr 17 09:32:59 2009
@@ -40,7 +40,7 @@
  * @version $Revision$
  */
 public class DeadLetterChannelBuilder extends ErrorHandlerBuilderSupport {
-    private Logger logger = DeadLetterChannel.createDefaultLogger();
+    private Logger logger = new Logger(LogFactory.getLog(DeadLetterChannel.class), LoggingLevel.ERROR);
     private ExceptionPolicyStrategy exceptionPolicyStrategy = ErrorHandlerSupport.createDefaultExceptionPolicyStrategy();
     private RedeliveryPolicy redeliveryPolicy = new RedeliveryPolicy();
     private Processor onRedelivery;
@@ -81,6 +81,10 @@
         return answer;
     }
 
+    public boolean supportTransacted() {
+        return false;
+    }
+
     // Builder methods
     // -------------------------------------------------------------------------
     public DeadLetterChannelBuilder backOffMultiplier(double backOffMultiplier) {

Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/builder/DefaultErrorHandlerBuilder.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/builder/DefaultErrorHandlerBuilder.java?rev=765920&r1=765919&r2=765920&view=diff
==============================================================================
--- camel/trunk/camel-core/src/main/java/org/apache/camel/builder/DefaultErrorHandlerBuilder.java (original)
+++ camel/trunk/camel-core/src/main/java/org/apache/camel/builder/DefaultErrorHandlerBuilder.java Fri Apr 17 09:32:59 2009
@@ -27,6 +27,10 @@
  */
 public class DefaultErrorHandlerBuilder extends ErrorHandlerBuilderSupport {
 
+    public boolean supportTransacted() {
+        return false;
+    }
+
     public Processor createErrorHandler(RouteContext routeContext, Processor processor) {
         DefaultErrorHandler answer = new DefaultErrorHandler(processor, getExceptionPolicyStrategy());
         configure(answer);

Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/builder/ErrorHandlerBuilder.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/builder/ErrorHandlerBuilder.java?rev=765920&r1=765919&r2=765920&view=diff
==============================================================================
--- camel/trunk/camel-core/src/main/java/org/apache/camel/builder/ErrorHandlerBuilder.java (original)
+++ camel/trunk/camel-core/src/main/java/org/apache/camel/builder/ErrorHandlerBuilder.java Fri Apr 17 09:32:59 2009
@@ -20,6 +20,7 @@
 
 import org.apache.camel.Processor;
 import org.apache.camel.model.OnExceptionDefinition;
+import org.apache.camel.processor.ErrorHandler;
 import org.apache.camel.processor.exceptionpolicy.ExceptionPolicyStrategy;
 import org.apache.camel.spi.RouteContext;
 
@@ -71,4 +72,16 @@
      * @param exceptionPolicyStrategy  the exception policy strategy
      */
     void setExceptionPolicyStrategy(ExceptionPolicyStrategy exceptionPolicyStrategy);
+
+    /**
+     * Whether this error handler supports transacted exchanges.
+     */
+    boolean supportTransacted();
+
+    /**
+     * Configures the other error handler based on this error handler.
+     *
+     * @param handler the other error handler
+     */
+    void configure(ErrorHandler handler);
 }

Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/builder/ErrorHandlerBuilderRef.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/builder/ErrorHandlerBuilderRef.java?rev=765920&r1=765919&r2=765920&view=diff
==============================================================================
--- camel/trunk/camel-core/src/main/java/org/apache/camel/builder/ErrorHandlerBuilderRef.java (original)
+++ camel/trunk/camel-core/src/main/java/org/apache/camel/builder/ErrorHandlerBuilderRef.java Fri Apr 17 09:32:59 2009
@@ -32,6 +32,7 @@
     public static final String DEFAULT_ERROR_HANDLER_BUILDER = "CamelDefaultErrorHandlerBuilder";
     private final String ref;
     private ErrorHandlerBuilder handler;
+    private boolean supportTransacted;
 
     public ErrorHandlerBuilderRef(String ref) {
         this.ref = ref;
@@ -65,6 +66,10 @@
         return !DEFAULT_ERROR_HANDLER_BUILDER.equals(getRef());
     }
 
+    public boolean supportTransacted() {
+        return supportTransacted;
+    }
+
     public ErrorHandlerBuilder lookupErrorHandlerBuilder(RouteContext routeContext) {
         if (handler == null) {
             // if the ref is the default then the we do not have any explicit error handler configured
@@ -95,6 +100,10 @@
             }
 
             ObjectHelper.notNull(handler, "error handler '" + ref + "'");
+
+            // configure if the handler support transacted
+            supportTransacted = handler.supportTransacted();
+
             List<OnExceptionDefinition> list = getErrorHandlers();
             for (OnExceptionDefinition exceptionType : list) {
                 handler.addErrorHandlers(exceptionType);

Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/builder/ErrorHandlerBuilderSupport.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/builder/ErrorHandlerBuilderSupport.java?rev=765920&r1=765919&r2=765920&view=diff
==============================================================================
--- camel/trunk/camel-core/src/main/java/org/apache/camel/builder/ErrorHandlerBuilderSupport.java (original)
+++ camel/trunk/camel-core/src/main/java/org/apache/camel/builder/ErrorHandlerBuilderSupport.java Fri Apr 17 09:32:59 2009
@@ -20,6 +20,7 @@
 import java.util.List;
 
 import org.apache.camel.model.OnExceptionDefinition;
+import org.apache.camel.processor.ErrorHandler;
 import org.apache.camel.processor.ErrorHandlerSupport;
 import org.apache.camel.processor.exceptionpolicy.ExceptionPolicyStrategy;
 
@@ -39,9 +40,13 @@
         }
     }
 
-    public void configure(ErrorHandlerSupport handler) {
-        for (OnExceptionDefinition exception : exceptions) {
-            handler.addExceptionPolicy(exception);
+    public void configure(ErrorHandler handler) {
+        if (handler instanceof ErrorHandlerSupport) {
+            ErrorHandlerSupport handlerSupport = (ErrorHandlerSupport) handler;
+
+            for (OnExceptionDefinition exception : exceptions) {
+                handlerSupport.addExceptionPolicy(exception);
+            }
         }
     }
 

Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/builder/LoggingErrorHandlerBuilder.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/builder/LoggingErrorHandlerBuilder.java?rev=765920&r1=765919&r2=765920&view=diff
==============================================================================
--- camel/trunk/camel-core/src/main/java/org/apache/camel/builder/LoggingErrorHandlerBuilder.java (original)
+++ camel/trunk/camel-core/src/main/java/org/apache/camel/builder/LoggingErrorHandlerBuilder.java Fri Apr 17 09:32:59 2009
@@ -45,6 +45,10 @@
         this.level = level;
     }
 
+    public boolean supportTransacted() {
+        return false;
+    }
+
     public Processor createErrorHandler(final RouteContext routeContext, final Processor processor) {
         LoggingErrorHandler handler = new LoggingErrorHandler(processor, log, level);
         configure(handler);

Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/builder/NoErrorHandlerBuilder.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/builder/NoErrorHandlerBuilder.java?rev=765920&r1=765919&r2=765920&view=diff
==============================================================================
--- camel/trunk/camel-core/src/main/java/org/apache/camel/builder/NoErrorHandlerBuilder.java (original)
+++ camel/trunk/camel-core/src/main/java/org/apache/camel/builder/NoErrorHandlerBuilder.java Fri Apr 17 09:32:59 2009
@@ -33,4 +33,8 @@
     public Processor createErrorHandler(RouteContext routeContext, Processor processor) {
         return processor;
     }
+
+    public boolean supportTransacted() {
+        return false;
+    }
 }

Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/model/TransactedDefinition.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/model/TransactedDefinition.java?rev=765920&r1=765919&r2=765920&view=diff
==============================================================================
--- camel/trunk/camel-core/src/main/java/org/apache/camel/model/TransactedDefinition.java (original)
+++ camel/trunk/camel-core/src/main/java/org/apache/camel/model/TransactedDefinition.java Fri Apr 17 09:32:59 2009
@@ -148,15 +148,16 @@
 
     @SuppressWarnings("unchecked")
     protected static Policy doResolvePolicy(RouteContext routeContext, String ref, Class<? extends Policy> type) {
-        Policy answer = null;
-
-        // try ref first
+        // explicit ref given so lookup by it
         if (ObjectHelper.isNotEmpty(ref)) {
-            answer = routeContext.lookup(ref, Policy.class);
+            return routeContext.lookup(ref, Policy.class);
         }
 
+        // no explicit reference given from user so we can use some convention over configuration here
+
         // try to lookup by scoped type
-        if (answer == null && type != null) {
+        Policy answer = null;
+        if (type != null) {
             // try find by type, note that this method is not supported by all registry
             Map types = routeContext.lookupByType(type);
             if (types.size() == 1) {
@@ -169,12 +170,12 @@
         }
 
         // for transacted routing try the default REQUIRED name
-        if (answer == null && type == TransactedPolicy.class) {
+        if (type == TransactedPolicy.class) {
             // still not found try with the default name PROPAGATION_REQUIRED
             answer = routeContext.lookup(PROPAGATION_REQUIRED, TransactedPolicy.class);
         }
 
-        // no policy then try lookup the platform transaction manager and use it as policy
+        // still no policy found then try lookup the platform transaction manager and use it as policy
         if (answer == null && type == TransactedPolicy.class) {
             Class tmClazz = routeContext.getCamelContext().getClassResolver().resolveClass("org.springframework.transaction.PlatformTransactionManager");
             if (tmClazz != null) {

Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/processor/DeadLetterChannel.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/processor/DeadLetterChannel.java?rev=765920&r1=765919&r2=765920&view=diff
==============================================================================
--- camel/trunk/camel-core/src/main/java/org/apache/camel/processor/DeadLetterChannel.java (original)
+++ camel/trunk/camel-core/src/main/java/org/apache/camel/processor/DeadLetterChannel.java Fri Apr 17 09:32:59 2009
@@ -34,8 +34,6 @@
 import org.apache.camel.util.ExchangeHelper;
 import org.apache.camel.util.MessageHelper;
 import org.apache.camel.util.ServiceHelper;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
 
 /**
  * Implements a <a
@@ -46,7 +44,6 @@
  * @version $Revision$
  */
 public class DeadLetterChannel extends ErrorHandlerSupport implements AsyncProcessor {
-    private static final transient Log LOG = LogFactory.getLog(DeadLetterChannel.class);
 
     // we can use a single shared static timer for async redeliveries
     private static final Timer REDELIVER_TIMER = new Timer("Camel DeadLetterChannel Redeliver Timer", true);
@@ -128,33 +125,33 @@
         setExceptionPolicy(exceptionPolicyStrategy);
     }
 
-    public static Logger createDefaultLogger() {
-        return new Logger(LOG, LoggingLevel.ERROR);
-    }
-
     @Override
     public String toString() {
         return "DeadLetterChannel[" + output + ", " + (deadLetterUri != null ? deadLetterUri : deadLetter) + "]";
     }
 
+    public boolean supportTransacted() {
+        return false;
+    }
+
     public void process(Exchange exchange) throws Exception {
         AsyncProcessorHelper.process(this, exchange);
     }
 
     public boolean process(Exchange exchange, final AsyncCallback callback) {
-        return process(exchange, callback, new RedeliveryData());
+        return processErrorHandler(exchange, callback, new RedeliveryData());
     }
 
     /**
-     * Processes the exchange using decorated with this dead letter channel.
+     * Processes the exchange decorated with this dead letter channel.
      */
-    protected boolean process(final Exchange exchange, final AsyncCallback callback, final RedeliveryData data) {
+    protected boolean processErrorHandler(final Exchange exchange, final AsyncCallback callback, final RedeliveryData data) {
 
         while (true) {
             // we can't keep retrying if the route is being shutdown.
             if (!isRunAllowed()) {
-                if (LOG.isDebugEnabled()) {
-                    LOG.debug("Rejected execution as we are not started for exchange: " + exchange);
+                if (log.isDebugEnabled()) {
+                    log.debug("Rejected execution as we are not started for exchange: " + exchange);
                 }
                 if (exchange.getException() == null) {
                     exchange.setException(new RejectedExecutionException());
@@ -163,12 +160,11 @@
                 return data.sync;
             }
 
-            // if the exchange is transacted then let the underlying system handle the redelivery etc.
-            // this DeadLetterChannel is only for non transacted exchanges
-            // TODO: Should be possible to remove with Claus got the TX error handler sorted
-            if (exchange.isTransacted() && exchange.getException() != null) {
-                if (LOG.isDebugEnabled()) {
-                    LOG.debug("This is a transacted exchange, bypassing this DeadLetterChannel: " + this + " for exchange: " + exchange);
+            // do not handle transacted exchanges that failed as this error handler does not support it
+            if (exchange.isTransacted() && !supportTransacted() && exchange.getException() != null) {
+                if (log.isDebugEnabled()) {
+                    log.debug("This error handler does not support transacted exchanges."
+                        + " Bypassing this error handler: " + this + " for exchangeId: " + exchange.getExchangeId());
                 }
                 return data.sync;
             }
@@ -192,7 +188,7 @@
                 try {
                     data.redeliveryDelay = data.currentRedeliveryPolicy.sleep(data.redeliveryDelay, data.redeliveryCounter);
                 } catch (InterruptedException e) {
-                    LOG.debug("Sleep interrupted, are we stopping? " + (isStopping() || isStopped()));
+                    log.debug("Sleep interrupted, are we stopping? " + (isStopping() || isStopped()));
                     // continue from top
                     continue;
                 }
@@ -243,15 +239,15 @@
             return;
         }
 
-        // if the exchange is transacted then let the underlying system handle the redelivery etc.
-        // this DeadLetterChannel is only for non transacted exchanges
-        if (exchange.isTransacted() && exchange.getException() != null) {
-            if (LOG.isDebugEnabled()) {
-                LOG.debug("This is a transacted exchange, bypassing this DeadLetterChannel: " + this + " for exchange: " + exchange);
+        // do not handle transacted exchanges that failed as this error handler does not support it
+        if (exchange.isTransacted() && !supportTransacted() && exchange.getException() != null) {
+            if (log.isDebugEnabled()) {
+                log.debug("This error handler does not support transacted exchanges."
+                    + " Bypassing this error handler: " + this + " for exchangeId: " + exchange.getExchangeId());
             }
             return;
         }
-        
+
         // did previous processing caused an exception?
         if (exchange.getException() != null) {
             handleException(exchange, data);
@@ -312,7 +308,7 @@
     }
 
     /**
-     * Sets the logger strategy; which {@link Log} to use and which
+     * Sets the logger strategy; which {@link com.sun.tools.javac.util.Log} to use and which
      * {@link LoggingLevel} to use
      */
     public void setLogger(Logger logger) {
@@ -377,14 +373,14 @@
             return;
         }
 
-        if (LOG.isTraceEnabled()) {
-            LOG.trace("RedeliveryProcessor " + data.onRedeliveryProcessor + " is processing Exchange: " + exchange + " before its redelivered");
+        if (log.isTraceEnabled()) {
+            log.trace("RedeliveryProcessor " + data.onRedeliveryProcessor + " is processing Exchange: " + exchange + " before its redelivered");
         }
 
         AsyncProcessor afp = AsyncProcessorTypeConverter.convert(data.onRedeliveryProcessor);
         afp.process(exchange, new AsyncCallback() {
             public void done(boolean sync) {
-                LOG.trace("Redelivery processor done");
+                log.trace("Redelivery processor done");
                 // do NOT call done on callback as this is the redelivery processor that
                 // is done. we should not mark the entire exchange as done.
             }
@@ -405,7 +401,7 @@
         AsyncProcessor afp = AsyncProcessorTypeConverter.convert(data.failureProcessor);
         boolean sync = afp.process(exchange, new AsyncCallback() {
             public void done(boolean sync) {
-                LOG.trace("Fault processor done");
+                log.trace("Fault processor done");
                 prepareExchangeForFailure(exchange, data.handledPredicate);
                 callback.done(data.sync);
             }
@@ -420,14 +416,14 @@
 
     private void prepareExchangeForFailure(Exchange exchange, Predicate handledPredicate) {
         if (handledPredicate == null || !handledPredicate.matches(exchange)) {
-            if (LOG.isDebugEnabled()) {
-                LOG.debug("This exchange is not handled so its marked as failed: " + exchange);
+            if (log.isDebugEnabled()) {
+                log.debug("This exchange is not handled so its marked as failed: " + exchange);
             }
             // exception not handled, put exception back in the exchange
             exchange.setException(exchange.getProperty(Exchange.EXCEPTION_CAUGHT, Exception.class));
         } else {
-            if (LOG.isDebugEnabled()) {
-                LOG.debug("This exchange is handled so its marked as not failed: " + exchange);
+            if (log.isDebugEnabled()) {
+                log.debug("This exchange is handled so its marked as not failed: " + exchange);
             }
             exchange.setProperty(Exchange.EXCEPTION_HANDLED, Boolean.TRUE);
         }

Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/processor/DefaultErrorHandler.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/processor/DefaultErrorHandler.java?rev=765920&r1=765919&r2=765920&view=diff
==============================================================================
--- camel/trunk/camel-core/src/main/java/org/apache/camel/processor/DefaultErrorHandler.java (original)
+++ camel/trunk/camel-core/src/main/java/org/apache/camel/processor/DefaultErrorHandler.java Fri Apr 17 09:32:59 2009
@@ -28,8 +28,6 @@
 import org.apache.camel.util.ExchangeHelper;
 import org.apache.camel.util.MessageHelper;
 import org.apache.camel.util.ServiceHelper;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
 
 /**
  * Default error handler
@@ -37,18 +35,20 @@
  * @version $Revision$
  */
 public class DefaultErrorHandler extends ErrorHandlerSupport implements AsyncProcessor {
-
-    private static final transient Log LOG = LogFactory.getLog(DefaultErrorHandler.class);
-    private AsyncProcessor outputAsync;
+    private AsyncProcessor output;
 
     public DefaultErrorHandler(Processor output, ExceptionPolicyStrategy exceptionPolicyStrategy) {
-        this.outputAsync = AsyncProcessorTypeConverter.convert(output);
+        this.output = AsyncProcessorTypeConverter.convert(output);
         setExceptionPolicy(exceptionPolicyStrategy);
     }
 
     @Override
     public String toString() {
-        return "DefaultErrorHandler[" + outputAsync + "]";
+        return "DefaultErrorHandler[" + output + "]";
+    }
+
+    public boolean supportTransacted() {
+        return false;
     }
 
     public void process(Exchange exchange) throws Exception {
@@ -56,12 +56,22 @@
     }
 
     public boolean process(final Exchange exchange, final AsyncCallback callback) {
-        return outputAsync.process(exchange, new AsyncCallback() {
+        return output.process(exchange, new AsyncCallback() {
             public void done(boolean sync) {
-                if (exchange.getException() != null && !ExchangeHelper.isFailureHandled(exchange)) {
-                    handleException(exchange);
+
+                // do not handle transacted exchanges as this error handler does not support it
+                boolean handle = true;
+                if (exchange.isTransacted() && !supportTransacted()) {
+                    handle = false;
+                    if (log.isDebugEnabled()) {
+                        log.debug("This error handler does not support transacted exchanges."
+                            + " Bypassing this error handler: " + this + " for exchangeId: " + exchange.getExchangeId());
+                    }
                 }
 
+                if (handle && exchange.getException() != null && !ExchangeHelper.isFailureHandled(exchange)) {
+                    handleException(exchange);
+                }
                 callback.done(sync);
             }
         });
@@ -79,11 +89,11 @@
             Predicate handledPredicate = exceptionPolicy.getHandledPolicy();
 
             Processor processor = exceptionPolicy.getErrorHandler();
+            prepareExchangeBeforeOnException(exchange);
             if (processor != null) {
-                prepareExchangeBeforeOnException(exchange);
                 deliverToFaultProcessor(exchange, processor);
-                prepareExchangeAfterOnException(exchange, handledPredicate);
             }
+            prepareExchangeAfterOnException(exchange, handledPredicate);
         }
     }
 
@@ -102,24 +112,22 @@
 
     private boolean deliverToFaultProcessor(final Exchange exchange, final Processor failureProcessor) {
         AsyncProcessor afp = AsyncProcessorTypeConverter.convert(failureProcessor);
-        boolean sync = afp.process(exchange, new AsyncCallback() {
+        return afp.process(exchange, new AsyncCallback() {
             public void done(boolean sync) {
             }
         });
-
-        return sync;
     }
 
     private void prepareExchangeAfterOnException(Exchange exchange, Predicate handledPredicate) {
         if (handledPredicate == null || !handledPredicate.matches(exchange)) {
-            if (LOG.isDebugEnabled()) {
-                LOG.debug("This exchange is not handled so its marked as failed: " + exchange);
+            if (log.isDebugEnabled()) {
+                log.debug("This exchange is not handled so its marked as failed: " + exchange);
             }
             // exception not handled, put exception back in the exchange
             exchange.setException(exchange.getProperty(Exchange.EXCEPTION_CAUGHT, Exception.class));
         } else {
-            if (LOG.isDebugEnabled()) {
-                LOG.debug("This exchange is handled so its marked as not failed: " + exchange);
+            if (log.isDebugEnabled()) {
+                log.debug("This exchange is handled so its marked as not failed: " + exchange);
             }
             exchange.setProperty(Exchange.EXCEPTION_HANDLED, Boolean.TRUE);
         }
@@ -129,15 +137,15 @@
      * Returns the output processor
      */
     public Processor getOutput() {
-        return outputAsync;
+        return output;
     }
 
     protected void doStart() throws Exception {
-        ServiceHelper.startServices(outputAsync);
+        ServiceHelper.startServices(output);
     }
 
     protected void doStop() throws Exception {
-        ServiceHelper.stopServices(outputAsync);
+        ServiceHelper.stopServices(output);
     }
 
 }

Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/processor/ErrorHandlerSupport.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/processor/ErrorHandlerSupport.java?rev=765920&r1=765919&r2=765920&view=diff
==============================================================================
--- camel/trunk/camel-core/src/main/java/org/apache/camel/processor/ErrorHandlerSupport.java (original)
+++ camel/trunk/camel-core/src/main/java/org/apache/camel/processor/ErrorHandlerSupport.java Fri Apr 17 09:32:59 2009
@@ -27,6 +27,8 @@
 import org.apache.camel.processor.exceptionpolicy.DefaultExceptionPolicyStrategy;
 import org.apache.camel.processor.exceptionpolicy.ExceptionPolicyKey;
 import org.apache.camel.processor.exceptionpolicy.ExceptionPolicyStrategy;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
 
 /**
  * Support class for {@link ErrorHandler} implementations.
@@ -34,6 +36,9 @@
  * @version $Revision$
  */
 public abstract class ErrorHandlerSupport extends ServiceSupport implements ErrorHandler {
+
+    protected final transient Log log = LogFactory.getLog(getClass());
+
     private final Map<ExceptionPolicyKey, OnExceptionDefinition> exceptionPolicies = new LinkedHashMap<ExceptionPolicyKey, OnExceptionDefinition>();
     private ExceptionPolicyStrategy exceptionPolicy = createDefaultExceptionPolicyStrategy();
 
@@ -94,4 +99,9 @@
         return new DefaultExceptionPolicyStrategy();
     }
 
+    /**
+     * Whether this error handler supports transacted exchanges or not.
+     */
+    public abstract boolean supportTransacted();
+
 }

Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/processor/LoggingErrorHandler.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/processor/LoggingErrorHandler.java?rev=765920&r1=765919&r2=765920&view=diff
==============================================================================
--- camel/trunk/camel-core/src/main/java/org/apache/camel/processor/LoggingErrorHandler.java (original)
+++ camel/trunk/camel-core/src/main/java/org/apache/camel/processor/LoggingErrorHandler.java Fri Apr 17 09:32:59 2009
@@ -48,6 +48,10 @@
         return "LoggingErrorHandler[" + output + "]";
     }
 
+    public boolean supportTransacted() {
+        return false;
+    }
+
     public void process(Exchange exchange) throws Exception {
         Throwable error = null;
         try {
@@ -129,13 +133,12 @@
             }
             break;
         default:
-            log.error("Unknown level: " + level + " when trying to log exchange: " + logMessage(exchange, e),
-                      e);
+            log.error("Unknown level: " + level + " when trying to log exchange: " + logMessage(exchange, e), e);
         }
     }
 
     protected Object logMessage(Exchange exchange, Throwable e) {
-        return e + " while processing exchange: " + exchange;
+        return e.getMessage() + " while processing exchange: " + exchange;
     }
 
     protected void doStart() throws Exception {

Modified: camel/trunk/camel-core/src/test/java/org/apache/camel/processor/ErrorHandlerSupportTest.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/test/java/org/apache/camel/processor/ErrorHandlerSupportTest.java?rev=765920&r1=765919&r2=765920&view=diff
==============================================================================
--- camel/trunk/camel-core/src/test/java/org/apache/camel/processor/ErrorHandlerSupportTest.java (original)
+++ camel/trunk/camel-core/src/test/java/org/apache/camel/processor/ErrorHandlerSupportTest.java Fri Apr 17 09:32:59 2009
@@ -87,6 +87,10 @@
         protected void doStop() throws Exception {
         }
 
+        public boolean supportTransacted() {
+            return false;
+        }
+
         public void process(Exchange exchange) throws Exception {
         }
     }

Modified: camel/trunk/components/camel-jms/src/test/java/org/apache/camel/component/jms/TransactedJmsRouteTest.java
URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-jms/src/test/java/org/apache/camel/component/jms/TransactedJmsRouteTest.java?rev=765920&r1=765919&r2=765920&view=diff
==============================================================================
--- camel/trunk/components/camel-jms/src/test/java/org/apache/camel/component/jms/TransactedJmsRouteTest.java (original)
+++ camel/trunk/components/camel-jms/src/test/java/org/apache/camel/component/jms/TransactedJmsRouteTest.java Fri Apr 17 09:32:59 2009
@@ -62,9 +62,9 @@
         return new SpringRouteBuilder() {
             public void configure() {
 
-                SpringTransactionPolicy requried = new SpringTransactionPolicy(bean(TransactionTemplate.class, "PROPAGATION_REQUIRED"));
-                SpringTransactionPolicy notsupported = new SpringTransactionPolicy(bean(TransactionTemplate.class, "PROPAGATION_NOT_SUPPORTED"));
-                SpringTransactionPolicy requirenew = new SpringTransactionPolicy(bean(TransactionTemplate.class, "PROPAGATION_REQUIRES_NEW"));
+                SpringTransactionPolicy requried = new SpringTransactionPolicy(bean("PROPAGATION_REQUIRED", TransactionTemplate.class));
+                SpringTransactionPolicy notsupported = new SpringTransactionPolicy(bean("PROPAGATION_NOT_SUPPORTED", TransactionTemplate.class));
+                SpringTransactionPolicy requirenew = new SpringTransactionPolicy(bean("PROPAGATION_REQUIRES_NEW", TransactionTemplate.class));
 
                 Policy rollback = new Policy() {
                     public Processor wrap(RouteContext routeContext, Processor processor) {
@@ -214,8 +214,6 @@
 
     /**
      * This test seems to be fail every other run.
-     *
-     * @throws Exception
      */
     public void disabledtestSenarioF() throws Exception {
         String expected = getName() + ": " + System.currentTimeMillis();
@@ -250,7 +248,7 @@
         assertIsSatisfied(assertTimeoutSeconds, TimeUnit.SECONDS, mockEndpointA, mockEndpointB);
     }
 
-    public void xxxtestSenarioC() throws Exception {
+    public void disabledtestSenarioC() throws Exception {
         String expected = getName() + ": " + System.currentTimeMillis();
         mockEndpointA.expectedMessageCount(0);
         // Should only get 1 message the incoming transaction does not rollback.
@@ -266,7 +264,7 @@
         assertIsSatisfied(mockEndpointA, mockEndpointB);
     }
 
-    public void xxxtestSenarioD() throws Exception {
+    public void disabledtestSenarioD() throws Exception {
         String expected = getName() + ": " + System.currentTimeMillis();
         mockEndpointA.expectedMessageCount(1);
         sendBody("activemq:queue:d", expected);

Modified: camel/trunk/components/camel-jms/src/test/java/org/apache/camel/component/jms/tx/QueueToProcessorTransactionTest.java
URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-jms/src/test/java/org/apache/camel/component/jms/tx/QueueToProcessorTransactionTest.java?rev=765920&r1=765919&r2=765920&view=diff
==============================================================================
--- camel/trunk/components/camel-jms/src/test/java/org/apache/camel/component/jms/tx/QueueToProcessorTransactionTest.java (original)
+++ camel/trunk/components/camel-jms/src/test/java/org/apache/camel/component/jms/tx/QueueToProcessorTransactionTest.java Fri Apr 17 09:32:59 2009
@@ -41,7 +41,7 @@
             @Override
             public void configure() throws Exception {
 
-                Policy required = bean(SpringTransactionPolicy.class, "PROPAGATION_REQUIRED_POLICY");
+                Policy required = bean("PROPAGATION_REQUIRED_POLICY", SpringTransactionPolicy.class);
                 from("activemq:queue:foo").policy(required).process(new ConditionalExceptionProcessor());
             }
         });

Modified: camel/trunk/components/camel-jms/src/test/java/org/apache/camel/component/jms/tx/QueueToQueueRequestReplyTransactionTest.java
URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-jms/src/test/java/org/apache/camel/component/jms/tx/QueueToQueueRequestReplyTransactionTest.java?rev=765920&r1=765919&r2=765920&view=diff
==============================================================================
--- camel/trunk/components/camel-jms/src/test/java/org/apache/camel/component/jms/tx/QueueToQueueRequestReplyTransactionTest.java (original)
+++ camel/trunk/components/camel-jms/src/test/java/org/apache/camel/component/jms/tx/QueueToQueueRequestReplyTransactionTest.java Fri Apr 17 09:32:59 2009
@@ -49,7 +49,7 @@
         context.addRoutes(new SpringRouteBuilder() {
             @Override
             public void configure() throws Exception {
-                Policy required = bean(SpringTransactionPolicy.class, "PROPAGATION_REQUIRED_POLICY");
+                Policy required = bean("PROPAGATION_REQUIRED_POLICY", SpringTransactionPolicy.class);
                 from("activemq:queue:foo?replyTo=queue:foo.reply").policy(required).process(cp).to("activemq-1:queue:bar?replyTo=queue:bar.reply");
                 from("activemq-1:queue:bar").process(new Processor() {
                     public void process(Exchange e) {

Modified: camel/trunk/components/camel-jms/src/test/java/org/apache/camel/component/jms/tx/QueueToQueueTransactionTest.java
URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-jms/src/test/java/org/apache/camel/component/jms/tx/QueueToQueueTransactionTest.java?rev=765920&r1=765919&r2=765920&view=diff
==============================================================================
--- camel/trunk/components/camel-jms/src/test/java/org/apache/camel/component/jms/tx/QueueToQueueTransactionTest.java (original)
+++ camel/trunk/components/camel-jms/src/test/java/org/apache/camel/component/jms/tx/QueueToQueueTransactionTest.java Fri Apr 17 09:32:59 2009
@@ -44,7 +44,7 @@
             @Override
             public void configure() throws Exception {
 
-                Policy required = bean(SpringTransactionPolicy.class, "PROPAGATION_REQUIRED_POLICY");
+                Policy required = bean("PROPAGATION_REQUIRED_POLICY", SpringTransactionPolicy.class);
                 from("activemq:queue:foo?transacted=true").policy(required).process(new ConditionalExceptionProcessor())
                     .to("activemq:queue:bar?transacted=true");
             }

Modified: camel/trunk/components/camel-spring/src/main/java/org/apache/camel/spring/SpringRouteBuilder.java
URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-spring/src/main/java/org/apache/camel/spring/SpringRouteBuilder.java?rev=765920&r1=765919&r2=765920&view=diff
==============================================================================
--- camel/trunk/components/camel-spring/src/main/java/org/apache/camel/spring/SpringRouteBuilder.java (original)
+++ camel/trunk/components/camel-spring/src/main/java/org/apache/camel/spring/SpringRouteBuilder.java Fri Apr 17 09:32:59 2009
@@ -44,12 +44,12 @@
      * returns it, or throws an exception if the bean is not present or is not
      * of the given type
      *
-     * @param type the type of the bean
      * @param beanName the name of the bean in the application context
+     * @param type the type of the bean
      * @return the bean
      */
     @SuppressWarnings("unchecked")
-    public <T> T bean(Class<T> type, String beanName) {
+    public <T> T bean(String beanName, Class<T> type) {
         ApplicationContext context = getApplicationContext();
         return (T)context.getBean(beanName, type);
     }

Modified: camel/trunk/components/camel-spring/src/main/java/org/apache/camel/spring/spi/SpringTransactionPolicy.java
URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-spring/src/main/java/org/apache/camel/spring/spi/SpringTransactionPolicy.java?rev=765920&r1=765919&r2=765920&view=diff
==============================================================================
--- camel/trunk/components/camel-spring/src/main/java/org/apache/camel/spring/spi/SpringTransactionPolicy.java (original)
+++ camel/trunk/components/camel-spring/src/main/java/org/apache/camel/spring/spi/SpringTransactionPolicy.java Fri Apr 17 09:32:59 2009
@@ -16,11 +16,10 @@
  */
 package org.apache.camel.spring.spi;
 
-import java.util.Map;
-
 import org.apache.camel.Processor;
 import org.apache.camel.builder.ErrorHandlerBuilder;
 import org.apache.camel.builder.ErrorHandlerBuilderRef;
+import org.apache.camel.builder.ErrorHandlerBuilderSupport;
 import org.apache.camel.spi.RouteContext;
 import org.apache.camel.spi.TransactedPolicy;
 import org.apache.camel.util.ObjectHelper;
@@ -58,12 +57,22 @@
         TransactionErrorHandler answer = new TransactionErrorHandler(getTransactionTemplate());
         answer.setOutput(processor);
 
+        // the goal is to configure the error handler builder on the route as a transacted error handler,
+        // either its already a transacted or if not we replace it with a transacted one that we configure here
+        // and wrap the processor in the transacted error handler as we can have transacted routes that change
+        // propagation behavior, eg: from A required -> B -> requiresNew C (advanced use-case)
+        // if we should not support this we do not need to wrap the processor as we only need one transacted error handler
+
+        // find the existing error handler builder
         ErrorHandlerBuilder builder = routeContext.getRoute().getErrorHandlerBuilder();
 
+        // check if its a ref if so then do a lookup
         if (builder instanceof ErrorHandlerBuilderRef) {
             // its a reference to a error handler so lookup the reference
             ErrorHandlerBuilderRef ref = (ErrorHandlerBuilderRef) builder;
             // only lookup if there was explicit an error handler builder configured
+            // otherwise its just the "default" that has not explicit been configured
+            // and if so then we can safely replace that with our transacted error handler
             if (ref.isErrorHandlerBuilderConfigued()) {
                 if (LOG.isDebugEnabled()) {
                     LOG.debug("Looking up ErrorHandlerBuilder with ref: " + ref.getRef());
@@ -72,11 +81,14 @@
             }
         }
 
-        if (builder instanceof TransactionErrorHandlerBuilder) {
-            // use existing transaction error handler builder
-            TransactionErrorHandlerBuilder txBuilder = (TransactionErrorHandlerBuilder) builder;
-            answer.setExceptionPolicy(txBuilder.getExceptionPolicyStrategy());
-            txBuilder.configure(answer);
+        if (builder != null && builder.supportTransacted()) {
+            // already a TX error handler then we are good to go
+            if (LOG.isDebugEnabled()) {
+                LOG.debug("The ErrorHandlerBuilder configured is already a TransactionErrorHandlerBuilder: " + builder);
+            }
+            answer.setExceptionPolicy(builder.getExceptionPolicyStrategy());
+            // configure our answer based on the existing error handler
+            builder.configure(answer);
         } else {
             // no transaction error handler builder configure so create a temporary one as we got all
             // the needed information form the configured builder anyway this allow us to use transacted
@@ -96,12 +108,14 @@
                 txBuilder.setErrorHandlers(builder.getErrorHandlers());
             }
             answer.setExceptionPolicy(txBuilder.getExceptionPolicyStrategy());
+            // configure our answer based on the existing error handler
             txBuilder.configure(answer);
 
             // set the route to use our transacted error handler builder
             routeContext.getRoute().setErrorHandlerBuilder(txBuilder);
         }
 
+        // return with wrapped transacted error handler
         return answer;
     }
 

Modified: camel/trunk/components/camel-spring/src/main/java/org/apache/camel/spring/spi/TransactedRuntimeCamelException.java
URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-spring/src/main/java/org/apache/camel/spring/spi/TransactedRuntimeCamelException.java?rev=765920&r1=765919&r2=765920&view=diff
==============================================================================
--- camel/trunk/components/camel-spring/src/main/java/org/apache/camel/spring/spi/TransactedRuntimeCamelException.java (original)
+++ camel/trunk/components/camel-spring/src/main/java/org/apache/camel/spring/spi/TransactedRuntimeCamelException.java Fri Apr 17 09:32:59 2009
@@ -23,28 +23,35 @@
  */
 public class TransactedRuntimeCamelException extends RuntimeCamelException {
 
-    private boolean handled;
+    private final boolean handled;
 
     public TransactedRuntimeCamelException() {
+        super();
+        this.handled = false;
     }
 
     public TransactedRuntimeCamelException(String message) {
         super(message);
+        this.handled = false;
     }
 
     public TransactedRuntimeCamelException(String message, Throwable cause) {
         super(message, cause);
+        this.handled = false;
     }
 
     public TransactedRuntimeCamelException(Throwable cause) {
         super(cause);
+        this.handled = false;
+    }
+
+    public TransactedRuntimeCamelException(Throwable cause, boolean handled) {
+        super(cause);
+        this.handled = handled;
     }
 
     public boolean isHandled() {
         return handled;
     }
 
-    public void setHandled(boolean handled) {
-        this.handled = handled;
-    }
 }

Modified: camel/trunk/components/camel-spring/src/main/java/org/apache/camel/spring/spi/TransactionErrorHandler.java
URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-spring/src/main/java/org/apache/camel/spring/spi/TransactionErrorHandler.java?rev=765920&r1=765919&r2=765920&view=diff
==============================================================================
--- camel/trunk/components/camel-spring/src/main/java/org/apache/camel/spring/spi/TransactionErrorHandler.java (original)
+++ camel/trunk/components/camel-spring/src/main/java/org/apache/camel/spring/spi/TransactionErrorHandler.java Fri Apr 17 09:32:59 2009
@@ -56,6 +56,10 @@
         setExceptionPolicy(exceptionPolicy);
     }
 
+    public boolean supportTransacted() {
+        return true;
+    }
+
     @Override
     public String toString() {
         if (output == null) {
@@ -151,15 +155,13 @@
         if (exception instanceof TransactedRuntimeCamelException) {
             return (TransactedRuntimeCamelException) exception;
         } else {
-            TransactedRuntimeCamelException answer = new TransactedRuntimeCamelException(exception);
             // Mark as handled so we dont want to handle the same exception twice or more in other
             // wrapped transaction error handlers in this route.
             // We need to mark this information in the exception as we need to propagage
             // the exception back by rehtrowing it. We cannot mark it on the exchange as Camel
             // uses copies of exchanges in its pipeline and the data isnt copied back in case
             // when an exception occured
-            answer.setHandled(true);
-            return answer;
+            return new TransactedRuntimeCamelException(exception, true);
         }
     }
 
@@ -180,11 +182,11 @@
             Predicate handledPredicate = exceptionPolicy.getHandledPolicy();
 
             Processor processor = exceptionPolicy.getErrorHandler();
+            prepareExchangeBeforeOnException(exchange);
             if (processor != null) {
-                prepareExchangeBeforeOnException(exchange);
                 deliverToFaultProcessor(exchange, processor);
-                prepareExchangeAfterOnException(exchange, handledPredicate);
             }
+            prepareExchangeAfterOnException(exchange, handledPredicate);
         }
     }
 

Modified: camel/trunk/components/camel-spring/src/main/java/org/apache/camel/spring/spi/TransactionErrorHandlerBuilder.java
URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-spring/src/main/java/org/apache/camel/spring/spi/TransactionErrorHandlerBuilder.java?rev=765920&r1=765919&r2=765920&view=diff
==============================================================================
--- camel/trunk/components/camel-spring/src/main/java/org/apache/camel/spring/spi/TransactionErrorHandlerBuilder.java (original)
+++ camel/trunk/components/camel-spring/src/main/java/org/apache/camel/spring/spi/TransactionErrorHandlerBuilder.java Fri Apr 17 09:32:59 2009
@@ -18,7 +18,6 @@
 
 import org.apache.camel.Processor;
 import org.apache.camel.builder.ErrorHandlerBuilderSupport;
-import org.apache.camel.processor.DelayPolicy;
 import org.apache.camel.processor.ErrorHandlerSupport;
 import org.apache.camel.processor.exceptionpolicy.ExceptionPolicyStrategy;
 import org.apache.camel.spi.RouteContext;
@@ -46,6 +45,10 @@
         return transactionTemplate;
     }
 
+    public boolean supportTransacted() {
+        return true;
+    }
+
     public Processor createErrorHandler(RouteContext routeContext, Processor processor) throws Exception {
         TransactionErrorHandler answer = new TransactionErrorHandler(transactionTemplate, processor, exceptionPolicyStrategy);
         configure(answer);

Modified: camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/config/DummyErrorHandlerBuilder.java
URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/config/DummyErrorHandlerBuilder.java?rev=765920&r1=765919&r2=765920&view=diff
==============================================================================
--- camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/config/DummyErrorHandlerBuilder.java (original)
+++ camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/config/DummyErrorHandlerBuilder.java Fri Apr 17 09:32:59 2009
@@ -42,8 +42,8 @@
         this.beanName = beanName;
     }
 
-    public ErrorHandlerBuilder copy() {
-        return new DummyErrorHandlerBuilder(beanName);
+    public boolean supportTransacted() {
+        return false;
     }
 
     public Processor createErrorHandler(RouteContext routeContext, Processor processor) throws Exception {
@@ -55,4 +55,5 @@
             }
         };
     }
+
 }

Copied: camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/interceptor/MixedPropagationTransactedTest.java (from r765844, camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/interceptor/TransactionalClientDataSourceTransactedTest.java)
URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/interceptor/MixedPropagationTransactedTest.java?p2=camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/interceptor/MixedPropagationTransactedTest.java&p1=camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/interceptor/TransactionalClientDataSourceTransactedTest.java&r1=765844&r2=765920&rev=765920&view=diff
==============================================================================
--- camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/interceptor/TransactionalClientDataSourceTransactedTest.java (original)
+++ camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/interceptor/MixedPropagationTransactedTest.java Fri Apr 17 09:32:59 2009
@@ -16,35 +16,152 @@
  */
 package org.apache.camel.spring.interceptor;
 
+import javax.sql.DataSource;
+
+import org.apache.camel.RuntimeCamelException;
 import org.apache.camel.builder.RouteBuilder;
 import org.apache.camel.spring.SpringRouteBuilder;
+import org.apache.camel.spring.SpringTestSupport;
+import org.springframework.context.support.AbstractXmlApplicationContext;
+import org.springframework.context.support.ClassPathXmlApplicationContext;
+import org.springframework.jdbc.core.simple.SimpleJdbcTemplate;
 
 /**
- * Easier transaction configuration as we do not have to setup a transaction error handler
+ * For testing with mixed transacted propagations (required, requires new)
  */
-public class TransactionalClientDataSourceTransactedTest extends TransactionalClientDataSourceTest {
+public class MixedPropagationTransactedTest extends SpringTestSupport {
+
+    protected SimpleJdbcTemplate jdbc;
+    protected boolean useTransactionErrorHandler = true;
+
+    protected AbstractXmlApplicationContext createApplicationContext() {
+        return new ClassPathXmlApplicationContext(
+            "/org/apache/camel/spring/interceptor/mixedPropagationTransactedTest.xml");
+    }
+
+    protected int getExpectedRouteCount() {
+        return 0;
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        // create database and insert dummy data
+        final DataSource ds = getMandatoryBean(DataSource.class, "dataSource");
+        jdbc = new SimpleJdbcTemplate(ds);
+        jdbc.getJdbcOperations().execute("create table books (title varchar(50))");
+        jdbc.update("insert into books (title) values (?)", "Camel in Action");
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        super.tearDown();
+        jdbc.getJdbcOperations().execute("drop table books");
+    }
+
+    public void testRequiredOnly() throws Exception {
+        template.sendBody("direct:required", "Tiger in Action");
+
+        int count = jdbc.queryForInt("select count(*) from books");
+        assertEquals(1, jdbc.queryForInt("select count(*) from books where title = ?", "Tiger in Action"));
+        assertEquals("Number of books", 2, count);
+    }
+
+    public void testRequired2Only() throws Exception {
+        template.sendBody("direct:required2", "Tiger in Action");
+
+        int count = jdbc.queryForInt("select count(*) from books");
+        // we do 2x the book service so we should get 2 tiger books
+        assertEquals(2, jdbc.queryForInt("select count(*) from books where title = ?", "Tiger in Action"));
+        assertEquals("Number of books", 3, count);
+    }
+
+    public void testRequiresNewOnly() throws Exception {
+        template.sendBody("direct:new", "Elephant in Action");
+
+        int count = jdbc.queryForInt("select count(*) from books");
+        assertEquals(1, jdbc.queryForInt("select count(*) from books where title = ?", "Elephant in Action"));
+        assertEquals("Number of books", 2, count);
+    }
+
+    public void testRequiredAndRequiresNew() throws Exception {
+        template.sendBody("direct:requiredAndNew", "Tiger in Action");
+
+        int count = jdbc.queryForInt("select count(*) from books");
+        assertEquals(2, jdbc.queryForInt("select count(*) from books where title = ?", "Tiger in Action"));
+        assertEquals("Number of books", 3, count);
+    }
+
+    public void testRequiredOnlkyRollback() throws Exception {
+        try {
+            template.sendBody("direct:required", "Donkey in Action");
+        } catch (RuntimeCamelException e) {
+            // expeced as we fail
+            assertTrue(e.getCause() instanceof IllegalArgumentException);
+            assertEquals("We don't have Donkeys, only Camels", e.getCause().getMessage());
+        }
+
+        int count = jdbc.queryForInt("select count(*) from books");
+        assertEquals(0, jdbc.queryForInt("select count(*) from books where title = ?", "Donkey in Action"));
+        assertEquals("Number of books", 1, count);
+    }
+
+    public void testRequiresNewOnlkyRollback() throws Exception {
+        try {
+            template.sendBody("direct:new", "Donkey in Action");
+        } catch (RuntimeCamelException e) {
+            // expeced as we fail
+            assertTrue(e.getCause() instanceof IllegalArgumentException);
+            assertEquals("We don't have Donkeys, only Camels", e.getCause().getMessage());
+        }
+
+        int count = jdbc.queryForInt("select count(*) from books");
+        assertEquals(0, jdbc.queryForInt("select count(*) from books where title = ?", "Donkey in Action"));
+        assertEquals("Number of books", 1, count);
+    }
+
+    public void testRequiredAndNewRollback() throws Exception {
+        try {
+            template.sendBody("direct:new", "Tiger in Action");
+        } catch (RuntimeCamelException e) {
+            // expeced as we fail
+            assertTrue(e.getCause() instanceof IllegalArgumentException);
+            assertEquals("We don't have Donkeys, only Camels", e.getCause().getMessage());
+        }
+
+        int count = jdbc.queryForInt("select count(*) from books");
+        assertEquals(1, jdbc.queryForInt("select count(*) from books where title = ?", "Tiger in Action"));
+        assertEquals(0, jdbc.queryForInt("select count(*) from books where title = ?", "Donkey in Action"));
+        // the tiger in action should be committed, but our 2nd route should rollback
+        assertEquals("Number of books", 2, count);
+    }
 
     protected RouteBuilder createRouteBuilder() throws Exception {
         return new SpringRouteBuilder() {
             public void configure() throws Exception {
-                // START SNIPPET: e1
-                from("direct:okay")
-                    // marks this route as transacted, and we dont pass in any parameters so we
-                    // will auto lookup and use the Policy defined in the spring XML file
-                    .transacted()
-                    .setBody(constant("Tiger in Action")).beanRef("bookService")
-                    .setBody(constant("Elephant in Action")).beanRef("bookService");
-
-                // marks this route as transacted that will use the single policy defined in the registry
-                from("direct:fail")
-                    // marks this route as transacted, and we dont pass in any parameters so we
-                    // will auto lookup and use the Policy defined in the spring XML file
-                    .transacted()
-                    .setBody(constant("Tiger in Action")).beanRef("bookService")
-                    .setBody(constant("Donkey in Action")).beanRef("bookService");
-                // END SNIPPET: e1
+                from("direct:required")
+                    .transacted("PROPATATION_REQUIRED")
+                    .beanRef("bookService");
+
+                from("direct:required2")
+                    .transacted("PROPATATION_REQUIRED")
+                    .beanRef("bookService")
+                    .beanRef("bookService");
+
+                from("direct:new")
+                    .transacted("PROPAGATION_REQUIRES_NEW")
+                    .beanRef("bookService");
+
+                from("direct:requiredAndNew").to("direct:required", "direct:new");
+
+                from("direct:requiredAndNewRollback")
+                    .to("direct:required")
+                    // change to donkey so it will rollback
+                    .setBody(constant("Donkey in Action"))
+                    .to("direct:new");
             }
         };
     }
 
-}
+}
\ No newline at end of file

Copied: camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/interceptor/TransactionalClientDataSourceMixedTransactedTest.java (from r765211, camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/interceptor/TransactionalClientDataSourceNotTransactedTest.java)
URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/interceptor/TransactionalClientDataSourceMixedTransactedTest.java?p2=camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/interceptor/TransactionalClientDataSourceMixedTransactedTest.java&p1=camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/interceptor/TransactionalClientDataSourceNotTransactedTest.java&r1=765211&r2=765920&rev=765920&view=diff
==============================================================================
--- camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/interceptor/TransactionalClientDataSourceNotTransactedTest.java (original)
+++ camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/interceptor/TransactionalClientDataSourceMixedTransactedTest.java Fri Apr 17 09:32:59 2009
@@ -16,14 +16,14 @@
  */
 package org.apache.camel.spring.interceptor;
 
+import org.apache.camel.RuntimeCamelException;
 import org.apache.camel.builder.RouteBuilder;
 import org.apache.camel.spring.SpringRouteBuilder;
-import org.apache.camel.RuntimeCamelException;
 
 /**
  * Same route but not transacted
  */
-public class TransactionalClientDataSourceNotTransactedTest extends TransactionalClientDataSourceTest {
+public class TransactionalClientDataSourceMixedTransactedTest extends TransactionalClientDataSourceTest {
 
     public void testTransactionRollback() throws Exception {
         try {
@@ -42,11 +42,18 @@
     protected RouteBuilder createRouteBuilder() throws Exception {
         return new SpringRouteBuilder() {
             public void configure() throws Exception {
+                // ignore failure if its something with Donkey
+                onException(IllegalArgumentException.class).onWhen(exceptionMessage().contains("Donkey")).handled(true);
+
                 from("direct:okay")
+                    // mark this route as transacted
+                    .transacted()
                     .setBody(constant("Tiger in Action")).beanRef("bookService")
-                    .setBody(constant("Elephant in Action")).beanRef("bookService");
+                    .setBody(constant("Elephant in Action")).beanRef("bookService")
+                    .setBody(constant("Donkey in Action")).beanRef("bookService");
 
                 from("direct:fail")
+                    // and this route is not transacted
                     .setBody(constant("Tiger in Action")).beanRef("bookService")
                     .setBody(constant("Donkey in Action")).beanRef("bookService");
             }

Modified: camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/interceptor/TransactionalClientDataSourceNotTransactedTest.java
URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/interceptor/TransactionalClientDataSourceNotTransactedTest.java?rev=765920&r1=765919&r2=765920&view=diff
==============================================================================
--- camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/interceptor/TransactionalClientDataSourceNotTransactedTest.java (original)
+++ camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/interceptor/TransactionalClientDataSourceNotTransactedTest.java Fri Apr 17 09:32:59 2009
@@ -16,9 +16,9 @@
  */
 package org.apache.camel.spring.interceptor;
 
+import org.apache.camel.RuntimeCamelException;
 import org.apache.camel.builder.RouteBuilder;
 import org.apache.camel.spring.SpringRouteBuilder;
-import org.apache.camel.RuntimeCamelException;
 
 /**
  * Same route but not transacted

Modified: camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/interceptor/TransactionalClientDataSourceTest.java
URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/interceptor/TransactionalClientDataSourceTest.java?rev=765920&r1=765919&r2=765920&view=diff
==============================================================================
--- camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/interceptor/TransactionalClientDataSourceTest.java (original)
+++ camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/interceptor/TransactionalClientDataSourceTest.java Fri Apr 17 09:32:59 2009
@@ -97,7 +97,7 @@
             public void configure() throws Exception {
                 // START SNIPPET: e1
                 // lookup the transaction policy
-                SpringTransactionPolicy required = bean(SpringTransactionPolicy.class, "PROPAGATION_REQUIRED");
+                SpringTransactionPolicy required = bean("PROPAGATION_REQUIRED", SpringTransactionPolicy.class);
 
                 // use this error handler instead of DeadLetterChannel that is the default
                 // Notice: transactionErrorHandler is in SpringRouteBuilder

Copied: camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/interceptor/TransactionalClientDataSourceTransactedWithChoiceTest.java (from r765844, camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/interceptor/TransactionalClientDataSourceTransactedTest.java)
URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/interceptor/TransactionalClientDataSourceTransactedWithChoiceTest.java?p2=camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/interceptor/TransactionalClientDataSourceTransactedWithChoiceTest.java&p1=camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/interceptor/TransactionalClientDataSourceTransactedTest.java&r1=765844&r2=765920&rev=765920&view=diff
==============================================================================
--- camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/interceptor/TransactionalClientDataSourceTransactedTest.java (original)
+++ camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/interceptor/TransactionalClientDataSourceTransactedWithChoiceTest.java Fri Apr 17 09:32:59 2009
@@ -22,29 +22,37 @@
 /**
  * Easier transaction configuration as we do not have to setup a transaction error handler
  */
-public class TransactionalClientDataSourceTransactedTest extends TransactionalClientDataSourceTest {
+public class TransactionalClientDataSourceTransactedWithChoiceTest extends TransactionalClientDataSourceTest {
 
     protected RouteBuilder createRouteBuilder() throws Exception {
         return new SpringRouteBuilder() {
             public void configure() throws Exception {
-                // START SNIPPET: e1
                 from("direct:okay")
-                    // marks this route as transacted, and we dont pass in any parameters so we
-                    // will auto lookup and use the Policy defined in the spring XML file
                     .transacted()
-                    .setBody(constant("Tiger in Action")).beanRef("bookService")
+                    .choice()
+                        .when(body().contains("Hello")).to("log:hello")
+                    .otherwise()
+                        .to("log:other")
+                    .end()
+                    .to("direct:tiger")
                     .setBody(constant("Elephant in Action")).beanRef("bookService");
 
+                from("direct:tiger")
+                    .transacted()
+                    .setBody(constant("Tiger in Action")).beanRef("bookService");
+
+                from("direct:donkey")
+                    // notice this one is not marked as transacted but since the exchange is transacted
+                    // the default error handler will not handle it and thus not interfeer
+                    .setBody(constant("Donkey in Action")).beanRef("bookService");
+
                 // marks this route as transacted that will use the single policy defined in the registry
                 from("direct:fail")
-                    // marks this route as transacted, and we dont pass in any parameters so we
-                    // will auto lookup and use the Policy defined in the spring XML file
                     .transacted()
                     .setBody(constant("Tiger in Action")).beanRef("bookService")
-                    .setBody(constant("Donkey in Action")).beanRef("bookService");
-                // END SNIPPET: e1
+                    .to("direct:donkey");
             }
         };
     }
 
-}
+}
\ No newline at end of file

Modified: camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/interceptor/TransactionalClientDataSourceWithOnExceptionTest.java
URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/interceptor/TransactionalClientDataSourceWithOnExceptionTest.java?rev=765920&r1=765919&r2=765920&view=diff
==============================================================================
--- camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/interceptor/TransactionalClientDataSourceWithOnExceptionTest.java (original)
+++ camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/interceptor/TransactionalClientDataSourceWithOnExceptionTest.java Fri Apr 17 09:32:59 2009
@@ -53,7 +53,7 @@
         return new SpringRouteBuilder() {
             public void configure() throws Exception {
                 // use required as transaction policy
-                SpringTransactionPolicy required = bean(SpringTransactionPolicy.class, "PROPAGATION_REQUIRED");
+                SpringTransactionPolicy required = bean("PROPAGATION_REQUIRED", SpringTransactionPolicy.class);
 
                 // configure to use transaction error handler and pass on the required as it will fetch
                 // the transaction manager from it that it needs

Modified: camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/interceptor/TransactionalClientWithRollbackTest.java
URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/interceptor/TransactionalClientWithRollbackTest.java?rev=765920&r1=765919&r2=765920&view=diff
==============================================================================
--- camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/interceptor/TransactionalClientWithRollbackTest.java (original)
+++ camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/interceptor/TransactionalClientWithRollbackTest.java Fri Apr 17 09:32:59 2009
@@ -87,7 +87,7 @@
         return new SpringRouteBuilder() {
             public void configure() throws Exception {
                 // setup the transaction policy
-                SpringTransactionPolicy required = bean(SpringTransactionPolicy.class, "PROPAGATION_REQUIRED");
+                SpringTransactionPolicy required = bean("PROPAGATION_REQUIRED", SpringTransactionPolicy.class);
 
                 // use transaction error handler
                 errorHandler(transactionErrorHandler(required));

Modified: camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/interceptor/route/DataSourceSpringRouteBuilder.java
URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/interceptor/route/DataSourceSpringRouteBuilder.java?rev=765920&r1=765919&r2=765920&view=diff
==============================================================================
--- camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/interceptor/route/DataSourceSpringRouteBuilder.java (original)
+++ camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/interceptor/route/DataSourceSpringRouteBuilder.java Fri Apr 17 09:32:59 2009
@@ -23,7 +23,7 @@
     
     public void configure() throws Exception {
         // get the required policy
-        SpringTransactionPolicy required = bean(SpringTransactionPolicy.class, "PROPAGATION_REQUIRED");
+        SpringTransactionPolicy required = bean("PROPAGATION_REQUIRED", SpringTransactionPolicy.class);
 
         // For spring based transaction, end users are encouraged to use the
         // transaction error handler instead of the default DeadLetterChannel.

Copied: camel/trunk/components/camel-spring/src/test/resources/org/apache/camel/spring/interceptor/mixedPropagationTransactedTest.xml (from r765844, camel/trunk/components/camel-spring/src/test/resources/org/apache/camel/spring/interceptor/transactionalClientDataSource.xml)
URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-spring/src/test/resources/org/apache/camel/spring/interceptor/mixedPropagationTransactedTest.xml?p2=camel/trunk/components/camel-spring/src/test/resources/org/apache/camel/spring/interceptor/mixedPropagationTransactedTest.xml&p1=camel/trunk/components/camel-spring/src/test/resources/org/apache/camel/spring/interceptor/transactionalClientDataSource.xml&r1=765844&r2=765920&rev=765920&view=diff
==============================================================================
--- camel/trunk/components/camel-spring/src/test/resources/org/apache/camel/spring/interceptor/transactionalClientDataSource.xml (original)
+++ camel/trunk/components/camel-spring/src/test/resources/org/apache/camel/spring/interceptor/mixedPropagationTransactedTest.xml Fri Apr 17 09:32:59 2009
@@ -21,8 +21,6 @@
          http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
          http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd">
 
-    <!-- START SNIPPET: e1 -->
-    <!-- datasource to the database -->
     <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
         <property name="driverClassName" value="org.hsqldb.jdbcDriver"/>
         <property name="url" value="jdbc:hsqldb:mem:camel"/>
@@ -30,20 +28,24 @@
         <property name="password" value=""/>
     </bean>
 
-    <!-- spring transaction manager -->
     <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
         <property name="dataSource" ref="dataSource"/>
     </bean>
 
-    <!-- policy for required transaction used in our Camel routes -->
-    <bean id="PROPAGATION_REQUIRED" class="org.apache.camel.spring.spi.SpringTransactionPolicy">
+    <!-- required -->
+    <bean id="PROPATATION_REQUIRED" class="org.apache.camel.spring.spi.SpringTransactionPolicy">
         <property name="transactionManager" ref="txManager"/>
     </bean>
 
+    <!-- requires new -->
+    <bean id="PROPAGATION_REQUIRES_NEW" class="org.apache.camel.spring.spi.SpringTransactionPolicy">
+        <property name="transactionManager" ref="txManager"/>
+        <property name="propagationBehaviorName" value="PROPAGATION_REQUIRES_NEW"/>
+    </bean>
+
     <!-- bean for book business logic -->
     <bean id="bookService" class="org.apache.camel.spring.interceptor.BookService">
         <property name="dataSource" ref="dataSource"/>
     </bean>
-    <!-- END SNIPPET: e1 -->
 
 </beans>