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.Arrays; 021 import java.util.Collection; 022 import java.util.List; 023 024 import javax.xml.bind.annotation.XmlAccessType; 025 import javax.xml.bind.annotation.XmlAccessorType; 026 import javax.xml.bind.annotation.XmlAttribute; 027 import javax.xml.bind.annotation.XmlElement; 028 import javax.xml.bind.annotation.XmlElementRef; 029 import javax.xml.bind.annotation.XmlElements; 030 import javax.xml.bind.annotation.XmlRootElement; 031 032 import org.apache.camel.Expression; 033 import org.apache.camel.Processor; 034 import org.apache.camel.model.loadbalancer.FailoverLoadBalancerDefinition; 035 import org.apache.camel.model.loadbalancer.RandomLoadBalancerDefinition; 036 import org.apache.camel.model.loadbalancer.RoundRobinLoadBalancerDefinition; 037 import org.apache.camel.model.loadbalancer.StickyLoadBalancerDefinition; 038 import org.apache.camel.model.loadbalancer.TopicLoadBalancerDefinition; 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 = FailoverLoadBalancerDefinition.class), 060 @XmlElement(required = false, name = "random", type = RandomLoadBalancerDefinition.class), 061 @XmlElement(required = false, name = "roundRobin", type = RoundRobinLoadBalancerDefinition.class), 062 @XmlElement(required = false, name = "sticky", type = StickyLoadBalancerDefinition.class), 063 @XmlElement(required = false, name = "topic", type = TopicLoadBalancerDefinition.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 public String getRef() { 092 return ref; 093 } 094 095 public void setRef(String ref) { 096 this.ref = ref; 097 } 098 099 public LoadBalancerDefinition getLoadBalancerType() { 100 return loadBalancerType; 101 } 102 103 public void setLoadBalancerType(LoadBalancerDefinition loadbalancer) { 104 loadBalancerType = loadbalancer; 105 } 106 107 protected Processor createOutputsProcessor(RouteContext routeContext, Collection<ProcessorDefinition> outputs) 108 throws Exception { 109 LoadBalancer loadBalancer = LoadBalancerDefinition.getLoadBalancer(routeContext, loadBalancerType, ref); 110 for (ProcessorDefinition processorType : outputs) { 111 // The outputs should be the SendProcessor 112 SendProcessor processor = (SendProcessor) processorType.createProcessor(routeContext); 113 loadBalancer.addProcessor(processor); 114 } 115 return loadBalancer; 116 } 117 118 @Override 119 public Processor createProcessor(RouteContext routeContext) throws Exception { 120 LoadBalancer loadBalancer = LoadBalancerDefinition.getLoadBalancer(routeContext, loadBalancerType, ref); 121 for (ProcessorDefinition processorType : getOutputs()) { 122 Processor processor = processorType.createProcessor(routeContext); 123 processor = wrapProcessor(routeContext, processor); 124 loadBalancer.addProcessor(processor); 125 } 126 127 return loadBalancer; 128 } 129 130 // Fluent API 131 // ------------------------------------------------------------------------- 132 133 /** 134 * Uses a custom load balancer 135 * 136 * @param loadBalancer the load balancer 137 * @return the builder 138 */ 139 public LoadBalanceDefinition loadBalance(LoadBalancer loadBalancer) { 140 loadBalancerType = new LoadBalancerDefinition(loadBalancer); 141 return this; 142 } 143 144 /** 145 * Uses fail over load balancer 146 * 147 * @return the builder 148 */ 149 public LoadBalanceDefinition failover() { 150 loadBalancerType = new LoadBalancerDefinition(new FailOverLoadBalancer()); 151 return this; 152 } 153 154 /** 155 * Uses fail over load balancer 156 * 157 * @param exceptions exception classes which we want to failover if one of them was thrown 158 * @return the builder 159 */ 160 public LoadBalanceDefinition failover(Class... exceptions) { 161 loadBalancerType = new LoadBalancerDefinition(new FailOverLoadBalancer(Arrays.asList(exceptions))); 162 return this; 163 } 164 165 /** 166 * Uses round robin load balancer 167 * 168 * @return the builder 169 */ 170 public LoadBalanceDefinition roundRobin() { 171 loadBalancerType = new LoadBalancerDefinition(new RoundRobinLoadBalancer()); 172 return this; 173 } 174 175 /** 176 * Uses random load balancer 177 * @return the builder 178 */ 179 public LoadBalanceDefinition random() { 180 loadBalancerType = new LoadBalancerDefinition(new RandomLoadBalancer()); 181 return this; 182 } 183 184 /** 185 * Uses sticky load balancer 186 * 187 * @param correlationExpression the expression for correlation 188 * @return the builder 189 */ 190 public LoadBalanceDefinition sticky(Expression correlationExpression) { 191 loadBalancerType = new LoadBalancerDefinition(new StickyLoadBalancer(correlationExpression)); 192 return this; 193 } 194 195 /** 196 * Uses topic load balancer 197 * 198 * @return the builder 199 */ 200 public LoadBalanceDefinition topic() { 201 loadBalancerType = new LoadBalancerDefinition(new TopicLoadBalancer()); 202 return this; 203 } 204 205 @Override 206 public String getLabel() { 207 CollectionStringBuffer buffer = new CollectionStringBuffer(); 208 List<ProcessorDefinition> list = getOutputs(); 209 for (ProcessorDefinition processorType : list) { 210 buffer.append(processorType.getLabel()); 211 } 212 return buffer.toString(); 213 } 214 215 @Override 216 public String toString() { 217 if (loadBalancerType != null) { 218 return "LoadBalanceType[" + loadBalancerType + ", " + getOutputs() + "]"; 219 } else { 220 return "LoadBalanceType[ref:" + ref + ", " + getOutputs() + "]"; 221 } 222 } 223 224 }