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 }