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;
018
019import java.util.ArrayList;
020import java.util.Iterator;
021import java.util.List;
022
023import javax.xml.bind.annotation.XmlAccessType;
024import javax.xml.bind.annotation.XmlAccessorType;
025import javax.xml.bind.annotation.XmlAttribute;
026import javax.xml.bind.annotation.XmlElement;
027import javax.xml.bind.annotation.XmlElementRef;
028import javax.xml.bind.annotation.XmlRootElement;
029import javax.xml.bind.annotation.XmlTransient;
030
031import org.apache.camel.spi.Metadata;
032
033/**
034 * Hystrix Circuit Breaker EIP
035 */
036@Metadata(label = "eip,routing,circuitbreaker")
037@XmlRootElement(name = "hystrix")
038@XmlAccessorType(XmlAccessType.FIELD)
039public class HystrixDefinition extends ProcessorDefinition<HystrixDefinition> implements OutputNode {
040
041    @XmlElement
042    private HystrixConfigurationDefinition hystrixConfiguration;
043    @XmlElementRef
044    private List<ProcessorDefinition<?>> outputs = new ArrayList<>();
045    @XmlTransient
046    private OnFallbackDefinition onFallback;
047    @XmlAttribute
048    private String hystrixConfigurationRef;
049
050    public HystrixDefinition() {
051    }
052
053    @Override
054    public String toString() {
055        return "Hystrix[" + getOutputs() + "]";
056    }
057
058    @Override
059    public String getShortName() {
060        return "hystrix";
061    }
062
063    @Override
064    public String getLabel() {
065        return "hystrix";
066    }
067
068    @Override
069    public List<ProcessorDefinition<?>> getOutputs() {
070        return outputs;
071    }
072
073    public void setOutputs(List<ProcessorDefinition<?>> outputs) {
074        this.outputs = outputs;
075        if (outputs != null) {
076            for (ProcessorDefinition<?> output : outputs) {
077                configureChild(output);
078            }
079        }
080    }
081
082    @Override
083    public void addOutput(ProcessorDefinition<?> output) {
084        if (output instanceof OnFallbackDefinition) {
085            onFallback = (OnFallbackDefinition)output;
086        } else {
087            if (onFallback != null) {
088                onFallback.addOutput(output);
089            } else {
090                super.addOutput(output);
091            }
092        }
093    }
094
095    @Override
096    public ProcessorDefinition<?> end() {
097        if (onFallback != null) {
098            // end fallback as well
099            onFallback.end();
100        }
101        return super.end();
102    }
103
104    @Override
105    public void preCreateProcessor() {
106        // move the fallback from outputs to fallback which we need to ensure
107        // such as when using the XML DSL
108        Iterator<ProcessorDefinition<?>> it = outputs.iterator();
109        while (it.hasNext()) {
110            ProcessorDefinition<?> out = it.next();
111            if (out instanceof OnFallbackDefinition) {
112                onFallback = (OnFallbackDefinition)out;
113                it.remove();
114            }
115        }
116    }
117
118    // Getter/Setter
119    // -------------------------------------------------------------------------
120
121    public HystrixConfigurationDefinition getHystrixConfiguration() {
122        return hystrixConfiguration;
123    }
124
125    public void setHystrixConfiguration(HystrixConfigurationDefinition hystrixConfiguration) {
126        this.hystrixConfiguration = hystrixConfiguration;
127    }
128
129    public String getHystrixConfigurationRef() {
130        return hystrixConfigurationRef;
131    }
132
133    /**
134     * Refers to a Hystrix configuration to use for configuring the Hystrix EIP.
135     */
136    public void setHystrixConfigurationRef(String hystrixConfigurationRef) {
137        this.hystrixConfigurationRef = hystrixConfigurationRef;
138    }
139
140    public OnFallbackDefinition getOnFallback() {
141        return onFallback;
142    }
143
144    public void setOnFallback(OnFallbackDefinition onFallback) {
145        this.onFallback = onFallback;
146    }
147
148    // Fluent API
149    // -------------------------------------------------------------------------
150
151    /**
152     * Sets the group key to use. The default value is CamelHystrix.
153     */
154    public HystrixDefinition groupKey(String groupKey) {
155        hystrixConfiguration().groupKey(groupKey);
156        return this;
157    }
158
159    /**
160     * Sets the thread pool key to use. The default value is CamelHystrix.
161     */
162    public HystrixDefinition threadPoolKey(String threadPoolKey) {
163        hystrixConfiguration().threadPoolKey(threadPoolKey);
164        return this;
165    }
166
167    /**
168     * Configures the Hystrix EIP
169     * <p/>
170     * Use <tt>end</tt> when configuration is complete, to return back to the
171     * Hystrix EIP.
172     */
173    public HystrixConfigurationDefinition hystrixConfiguration() {
174        hystrixConfiguration = hystrixConfiguration == null ? new HystrixConfigurationDefinition(this) : hystrixConfiguration;
175        return hystrixConfiguration;
176    }
177
178    /**
179     * Configures the Hystrix EIP using the given configuration
180     */
181    public HystrixDefinition hystrixConfiguration(HystrixConfigurationDefinition configuration) {
182        hystrixConfiguration = configuration;
183        return this;
184    }
185
186    /**
187     * Refers to a Hystrix configuration to use for configuring the Hystrix EIP.
188     */
189    public HystrixDefinition hystrixConfiguration(String ref) {
190        hystrixConfigurationRef = ref;
191        return this;
192    }
193
194    /**
195     * The Hystrix fallback route path to execute that does <b>not</b> go over
196     * the network.
197     * <p>
198     * This should be a static or cached result that can immediately be returned
199     * upon failure. If the fallback requires network connection then use
200     * {@link #onFallbackViaNetwork()}.
201     */
202    public HystrixDefinition onFallback() {
203        onFallback = new OnFallbackDefinition();
204        onFallback.setParent(this);
205        return this;
206    }
207
208    /**
209     * The Hystrix fallback route path to execute that will go over the network.
210     * <p/>
211     * If the fallback will go over the network it is another possible point of
212     * failure and so it also needs to be wrapped by a HystrixCommand. It is
213     * important to execute the fallback command on a separate thread-pool,
214     * otherwise if the main command were to become latent and fill the
215     * thread-pool this would prevent the fallback from running if the two
216     * commands share the same pool.
217     */
218    public HystrixDefinition onFallbackViaNetwork() {
219        onFallback = new OnFallbackDefinition();
220        onFallback.setFallbackViaNetwork(true);
221        onFallback.setParent(this);
222        return this;
223    }
224
225}