001 /** 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017 package org.apache.camel.spring.spi; 018 019 import java.util.Map; 020 021 import org.apache.camel.LoggingLevel; 022 import org.apache.camel.Processor; 023 import org.apache.camel.builder.DefaultErrorHandlerBuilder; 024 import org.apache.camel.processor.Logger; 025 import org.apache.camel.spi.RouteContext; 026 import org.apache.camel.spi.TransactedPolicy; 027 import org.apache.camel.util.ObjectHelper; 028 import org.apache.commons.logging.Log; 029 import org.apache.commons.logging.LogFactory; 030 import org.springframework.transaction.PlatformTransactionManager; 031 import org.springframework.transaction.support.TransactionTemplate; 032 033 /** 034 * A transactional error handler that supports leveraging Spring TransactionManager. 035 * 036 * @version $Revision: 785080 $ 037 */ 038 public class TransactionErrorHandlerBuilder extends DefaultErrorHandlerBuilder { 039 040 private static final transient Log LOG = LogFactory.getLog(TransactionErrorHandlerBuilder.class); 041 private static final String PROPAGATION_REQUIRED = "PROPAGATION_REQUIRED"; 042 private TransactionTemplate transactionTemplate; 043 044 public TransactionErrorHandlerBuilder() { 045 // no-arg constructor used by Spring DSL 046 } 047 048 public TransactionTemplate getTransactionTemplate() { 049 return transactionTemplate; 050 } 051 052 public boolean supportTransacted() { 053 return true; 054 } 055 056 public Processor createErrorHandler(RouteContext routeContext, Processor processor) throws Exception { 057 if (transactionTemplate == null) { 058 // lookup in context if no transaction template has been configured 059 LOG.debug("No TransactionTemplate configured on TransactionErrorHandlerBuilder. Will try find it in the registry."); 060 061 if (transactionTemplate == null) { 062 Map<String, TransactedPolicy> map = routeContext.lookupByType(TransactedPolicy.class); 063 if (map != null && map.size() == 1) { 064 TransactedPolicy policy = map.values().iterator().next(); 065 if (policy != null && policy instanceof SpringTransactionPolicy) { 066 transactionTemplate = ((SpringTransactionPolicy) policy).getTransactionTemplate(); 067 } 068 } 069 } 070 071 if (transactionTemplate == null) { 072 TransactedPolicy policy = routeContext.lookup(PROPAGATION_REQUIRED, TransactedPolicy.class); 073 if (policy != null && policy instanceof SpringTransactionPolicy) { 074 transactionTemplate = ((SpringTransactionPolicy) policy).getTransactionTemplate(); 075 } 076 } 077 078 if (transactionTemplate == null) { 079 Map<String, TransactionTemplate> map = routeContext.lookupByType(TransactionTemplate.class); 080 if (map != null && map.size() == 1) { 081 transactionTemplate = map.values().iterator().next(); 082 } else if (LOG.isDebugEnabled()) { 083 if (map == null || map.isEmpty()) { 084 LOG.trace("No TransactionTemplate found in registry."); 085 } else { 086 LOG.debug("Found " + map.size() + " TransactionTemplate in registry. " 087 + "Cannot determine which one to use. Please configure a TransactionTemplate on the TransactionErrorHandlerBuilder"); 088 } 089 } 090 } 091 092 if (transactionTemplate == null) { 093 Map<String, PlatformTransactionManager> map = routeContext.lookupByType(PlatformTransactionManager.class); 094 if (map != null && map.size() == 1) { 095 transactionTemplate = new TransactionTemplate(map.values().iterator().next()); 096 } else if (LOG.isDebugEnabled()) { 097 if (map == null || map.isEmpty()) { 098 LOG.trace("No PlatformTransactionManager found in registry."); 099 } else { 100 LOG.debug("Found " + map.size() + " PlatformTransactionManager in registry. " 101 + "Cannot determine which one to use for TransactionTemplate. Please configure a TransactionTemplate on the TransactionErrorHandlerBuilder"); 102 } 103 } 104 } 105 106 if (transactionTemplate != null) { 107 LOG.debug("Found TransactionTemplate in registry to use: " + transactionTemplate); 108 } 109 } 110 111 ObjectHelper.notNull(transactionTemplate, "transactionTemplate", this); 112 113 TransactionErrorHandler answer = new TransactionErrorHandler(processor, getLogger(), getOnRedelivery(), 114 getRedeliveryPolicy(), getHandledPolicy(), getExceptionPolicyStrategy(), transactionTemplate); 115 // configure error handler before we can use it 116 configure(answer); 117 return answer; 118 } 119 120 public void setTransactionTemplate(TransactionTemplate transactionTemplate) { 121 this.transactionTemplate = transactionTemplate; 122 } 123 124 public void setSpringTransactionPolicy(SpringTransactionPolicy policy) { 125 this.transactionTemplate = policy.getTransactionTemplate(); 126 } 127 128 // Builder methods 129 // ------------------------------------------------------------------------- 130 131 protected Logger createLogger() { 132 return new Logger(LogFactory.getLog(TransactionErrorHandler.class), LoggingLevel.ERROR); 133 } 134 135 @Override 136 public String toString() { 137 return "TransactionErrorHandlerBuilder"; 138 } 139 140 }