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 */ 017package org.apache.camel.model.loadbalancer; 018 019import java.util.ArrayList; 020import java.util.List; 021import javax.xml.bind.annotation.XmlAccessType; 022import javax.xml.bind.annotation.XmlAccessorType; 023import javax.xml.bind.annotation.XmlAttribute; 024import javax.xml.bind.annotation.XmlElement; 025import javax.xml.bind.annotation.XmlRootElement; 026import javax.xml.bind.annotation.XmlTransient; 027 028import org.apache.camel.model.LoadBalancerDefinition; 029import org.apache.camel.processor.loadbalancer.FailOverLoadBalancer; 030import org.apache.camel.processor.loadbalancer.LoadBalancer; 031import org.apache.camel.spi.Metadata; 032import org.apache.camel.spi.RouteContext; 033import org.apache.camel.util.ObjectHelper; 034 035/** 036 * Failover load balancer 037 * 038 * The failover load balancer is capable of trying the next processor in case an Exchange failed with an exception during processing. 039 * You can constrain the failover to activate only when one exception of a list you specify occurs. 040 * If you do not specify a list any exception will cause fail over to occur. 041 * This balancer uses the same strategy for matching exceptions as the Exception Clause does for the onException. 042 */ 043@Metadata(label = "configuration,loadbalance") 044@XmlRootElement(name = "failover") 045@XmlAccessorType(XmlAccessType.FIELD) 046public class FailoverLoadBalancerDefinition extends LoadBalancerDefinition { 047 @XmlTransient 048 private List<Class<?>> exceptionTypes = new ArrayList<Class<?>>(); 049 @XmlElement(name = "exception") 050 private List<String> exceptions = new ArrayList<String>(); 051 @XmlAttribute 052 private Boolean roundRobin; 053 @XmlAttribute @Metadata(defaultValue = "-1") 054 private Integer maximumFailoverAttempts; 055 056 public FailoverLoadBalancerDefinition() { 057 } 058 059 @Override 060 protected LoadBalancer createLoadBalancer(RouteContext routeContext) { 061 FailOverLoadBalancer answer; 062 063 List<Class<?>> classes = new ArrayList<Class<?>>(); 064 if (!exceptionTypes.isEmpty()) { 065 classes.addAll(exceptionTypes); 066 } else if (!exceptions.isEmpty()) { 067 for (String name : exceptions) { 068 Class<?> type = routeContext.getCamelContext().getClassResolver().resolveClass(name); 069 if (type == null) { 070 throw new IllegalArgumentException("Cannot find class: " + name + " in the classpath"); 071 } 072 if (!ObjectHelper.isAssignableFrom(Throwable.class, type)) { 073 throw new IllegalArgumentException("Class is not an instance of Throwable: " + type); 074 } 075 classes.add(type); 076 } 077 } 078 if (classes.isEmpty()) { 079 answer = new FailOverLoadBalancer(); 080 } else { 081 answer = new FailOverLoadBalancer(classes); 082 } 083 084 if (getMaximumFailoverAttempts() != null) { 085 answer.setMaximumFailoverAttempts(getMaximumFailoverAttempts()); 086 } 087 if (roundRobin != null) { 088 answer.setRoundRobin(roundRobin); 089 } 090 091 return answer; 092 } 093 094 public List<String> getExceptions() { 095 return exceptions; 096 } 097 098 /** 099 * A list of class names for specific exceptions to monitor. 100 * If no exceptions is configured then all exceptions is monitored 101 */ 102 public void setExceptions(List<String> exceptions) { 103 this.exceptions = exceptions; 104 } 105 106 public List<Class<?>> getExceptionTypes() { 107 return exceptionTypes; 108 } 109 110 /** 111 * A list of specific exceptions to monitor. 112 * If no exceptions is configured then all exceptions is monitored 113 */ 114 public void setExceptionTypes(List<Class<?>> exceptionTypes) { 115 this.exceptionTypes = exceptionTypes; 116 } 117 118 public Boolean getRoundRobin() { 119 return roundRobin; 120 } 121 122 /** 123 * Whether or not the failover load balancer should operate in round robin mode or not. 124 * If not, then it will always start from the first endpoint when a new message is to be processed. 125 * In other words it restart from the top for every message. 126 * If round robin is enabled, then it keeps state and will continue with the next endpoint in a round robin fashion. 127 * When using round robin it will not stick to last known good endpoint, it will always pick the next endpoint to use. 128 */ 129 public void setRoundRobin(Boolean roundRobin) { 130 this.roundRobin = roundRobin; 131 } 132 133 public Integer getMaximumFailoverAttempts() { 134 return maximumFailoverAttempts; 135 } 136 137 /** 138 * A value to indicate after X failover attempts we should exhaust (give up). 139 * Use -1 to indicate never give up and continuously try to failover. Use 0 to never failover. 140 * And use e.g. 3 to failover at most 3 times before giving up. 141 * his option can be used whether or not roundRobin is enabled or not. 142 */ 143 public void setMaximumFailoverAttempts(Integer maximumFailoverAttempts) { 144 this.maximumFailoverAttempts = maximumFailoverAttempts; 145 } 146 147 @Override 148 public String toString() { 149 return "FailoverLoadBalancer"; 150 } 151}