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.model; 018 019 import java.util.ArrayList; 020 import java.util.Collection; 021 import java.util.List; 022 023 import javax.xml.bind.annotation.XmlAccessType; 024 import javax.xml.bind.annotation.XmlAccessorType; 025 import javax.xml.bind.annotation.XmlAttribute; 026 import javax.xml.bind.annotation.XmlElement; 027 import javax.xml.bind.annotation.XmlElementRef; 028 import javax.xml.bind.annotation.XmlElements; 029 import javax.xml.bind.annotation.XmlRootElement; 030 031 import org.apache.camel.Expression; 032 import org.apache.camel.Processor; 033 import org.apache.camel.model.loadbalancer.FailOverLoadBalanceStrategy; 034 import org.apache.camel.model.loadbalancer.LoadBalancerDefinition; 035 import org.apache.camel.model.loadbalancer.RandomLoadBalanceStrategy; 036 import org.apache.camel.model.loadbalancer.RoundRobinLoadBalanceStrategy; 037 import org.apache.camel.model.loadbalancer.StickyLoadBalanceStrategy; 038 import org.apache.camel.model.loadbalancer.TopicLoadBalanceStrategy; 039 import org.apache.camel.processor.SendProcessor; 040 import org.apache.camel.processor.loadbalancer.FailOverLoadBalancer; 041 import org.apache.camel.processor.loadbalancer.LoadBalancer; 042 import org.apache.camel.processor.loadbalancer.RandomLoadBalancer; 043 import org.apache.camel.processor.loadbalancer.RoundRobinLoadBalancer; 044 import org.apache.camel.processor.loadbalancer.StickyLoadBalancer; 045 import org.apache.camel.processor.loadbalancer.TopicLoadBalancer; 046 import org.apache.camel.spi.RouteContext; 047 import org.apache.camel.util.CollectionStringBuffer; 048 049 /** 050 * Represents an XML <loadBalance/> element 051 */ 052 @XmlRootElement(name = "loadBalance") 053 @XmlAccessorType(XmlAccessType.FIELD) 054 public class LoadBalanceDefinition extends ProcessorDefinition<LoadBalanceDefinition> { 055 @XmlAttribute(required = false) 056 private String ref; 057 058 @XmlElements({ 059 @XmlElement(required = false, name = "failOver", type = FailOverLoadBalanceStrategy.class), 060 @XmlElement(required = false, name = "roundRobin", type = RoundRobinLoadBalanceStrategy.class), 061 @XmlElement(required = false, name = "random", type = RandomLoadBalanceStrategy.class), 062 @XmlElement(required = false, name = "sticky", type = StickyLoadBalanceStrategy.class), 063 @XmlElement(required = false, name = "topic", type = TopicLoadBalanceStrategy.class)} 064 ) 065 private LoadBalancerDefinition loadBalancerType; 066 067 @XmlElementRef 068 private List<ProcessorDefinition> outputs = new ArrayList<ProcessorDefinition>(); 069 070 public LoadBalanceDefinition() { 071 } 072 073 @Override 074 public String getShortName() { 075 return "loadbalance"; 076 } 077 078 public List<ProcessorDefinition> getOutputs() { 079 return outputs; 080 } 081 082 public void setOutputs(List<ProcessorDefinition> outputs) { 083 this.outputs = outputs; 084 if (outputs != null) { 085 for (ProcessorDefinition output : outputs) { 086 configureChild(output); 087 } 088 } 089 } 090 091 092 @Override 093 protected void configureChild(ProcessorDefinition output) { 094 super.configureChild(output); 095 if (isInheritErrorHandler()) { 096 output.setErrorHandlerBuilder(getErrorHandlerBuilder()); 097 } 098 } 099 100 public String getRef() { 101 return ref; 102 } 103 104 public void setRef(String ref) { 105 this.ref = ref; 106 } 107 108 public LoadBalancerDefinition getLoadBalancerType() { 109 return loadBalancerType; 110 } 111 112 public void setLoadBalancerType(LoadBalancerDefinition loadbalancer) { 113 loadBalancerType = loadbalancer; 114 } 115 116 protected Processor createOutputsProcessor(RouteContext routeContext, Collection<ProcessorDefinition> outputs) 117 throws Exception { 118 LoadBalancer loadBalancer = LoadBalancerDefinition.getLoadBalancer(routeContext, loadBalancerType, ref); 119 for (ProcessorDefinition processorType : outputs) { 120 // The outputs should be the SendProcessor 121 SendProcessor processor = (SendProcessor) processorType.createProcessor(routeContext); 122 loadBalancer.addProcessor(processor); 123 } 124 return loadBalancer; 125 } 126 127 @Override 128 public Processor createProcessor(RouteContext routeContext) throws Exception { 129 LoadBalancer loadBalancer = LoadBalancerDefinition.getLoadBalancer(routeContext, loadBalancerType, ref); 130 for (ProcessorDefinition processorType : getOutputs()) { 131 Processor processor = processorType.createProcessor(routeContext); 132 processor = processorType.wrapProcessorInInterceptors(routeContext, processor); 133 loadBalancer.addProcessor(processor); 134 } 135 136 return loadBalancer; 137 } 138 139 // Fluent API 140 // ------------------------------------------------------------------------- 141 /** 142 * Sets the load balancer to use 143 * 144 * @param loadBalancer the load balancer 145 * @return the builder 146 */ 147 public LoadBalanceDefinition setLoadBalancer(LoadBalancer loadBalancer) { 148 loadBalancerType = new LoadBalancerDefinition(loadBalancer); 149 return this; 150 } 151 152 /** 153 * Uses fail over load balancer 154 * 155 * @return the builder 156 */ 157 public LoadBalanceDefinition failOver() { 158 loadBalancerType = new LoadBalancerDefinition(new FailOverLoadBalancer()); 159 return this; 160 } 161 162 /** 163 * Uses fail over load balancer 164 * 165 * @param throwable exception Class which we want to catch 166 * @return the builder 167 */ 168 public LoadBalanceDefinition failOver(Class throwable) { 169 loadBalancerType = new LoadBalancerDefinition(new FailOverLoadBalancer(throwable)); 170 return this; 171 } 172 173 /** 174 * Uses round robin load balancer 175 * 176 * @return the builder 177 */ 178 public LoadBalanceDefinition roundRobin() { 179 loadBalancerType = new LoadBalancerDefinition(new RoundRobinLoadBalancer()); 180 return this; 181 } 182 183 /** 184 * Uses random load balancer 185 * @return the builder 186 */ 187 public LoadBalanceDefinition random() { 188 loadBalancerType = new LoadBalancerDefinition(new RandomLoadBalancer()); 189 return this; 190 } 191 192 /** 193 * Uses sticky load balancer 194 * 195 * @param correlationExpression the expression for correlation 196 * @return the builder 197 */ 198 public LoadBalanceDefinition sticky(Expression correlationExpression) { 199 loadBalancerType = new LoadBalancerDefinition(new StickyLoadBalancer(correlationExpression)); 200 return this; 201 } 202 203 /** 204 * Uses topic load balancer 205 * 206 * @return the builder 207 */ 208 public LoadBalanceDefinition topic() { 209 loadBalancerType = new LoadBalancerDefinition(new TopicLoadBalancer()); 210 return this; 211 } 212 213 @Override 214 public String getLabel() { 215 CollectionStringBuffer buffer = new CollectionStringBuffer(); 216 List<ProcessorDefinition> list = getOutputs(); 217 for (ProcessorDefinition processorType : list) { 218 buffer.append(processorType.getLabel()); 219 } 220 return buffer.toString(); 221 } 222 223 @Override 224 public String toString() { 225 if (loadBalancerType != null) { 226 return "LoadBalanceType[" + loadBalancerType + ", " + getOutputs() + "]"; 227 } else { 228 return "LoadBalanceType[ref: " + ref + ", " + getOutputs() + "]"; 229 } 230 } 231 232 }