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@Metadata(label = "eip,routing,circuitbreaker")
034@XmlRootElement(name = "circuitBreaker")
035@XmlAccessorType(XmlAccessType.FIELD)
036public class CircuitBreakerDefinition extends OutputDefinition<CircuitBreakerDefinition> {
037
038    @XmlElement
039    private HystrixConfigurationDefinition hystrixConfiguration;
040    @XmlElement
041    private Resilience4jConfigurationDefinition resilience4jConfiguration;
042    @XmlAttribute
043    private String configurationRef;
044    @XmlTransient
045    private OnFallbackDefinition onFallback;
046
047    public CircuitBreakerDefinition() {
048    }
049
050    @Override
051    public String toString() {
052        return "CircuitBreaker[" + getOutputs() + "]";
053    }
054
055    @Override
056    public String getShortName() {
057        return "circuitBreaker";
058    }
059
060    @Override
061    public String getLabel() {
062        return "circuitBreaker";
063    }
064
065    @Override
066    public List<ProcessorDefinition<?>> getOutputs() {
067        return outputs;
068    }
069
070    @XmlElementRef
071    @Override
072    public void setOutputs(List<ProcessorDefinition<?>> outputs) {
073        super.setOutputs(outputs);
074    }
075
076    @Override
077    public void addOutput(ProcessorDefinition<?> output) {
078        if (output instanceof OnFallbackDefinition) {
079            onFallback = (OnFallbackDefinition)output;
080        } else {
081            if (onFallback != null) {
082                onFallback.addOutput(output);
083            } else {
084                super.addOutput(output);
085            }
086        }
087    }
088
089    @Override
090    public ProcessorDefinition<?> end() {
091        if (onFallback != null) {
092            // end fallback as well
093            onFallback.end();
094        }
095        return super.end();
096    }
097
098    @Override
099    public void preCreateProcessor() {
100        // move the fallback from outputs to fallback which we need to ensure
101        // such as when using the XML DSL
102        Iterator<ProcessorDefinition<?>> it = outputs.iterator();
103        while (it.hasNext()) {
104            ProcessorDefinition<?> out = it.next();
105            if (out instanceof OnFallbackDefinition) {
106                onFallback = (OnFallbackDefinition)out;
107                it.remove();
108            }
109        }
110    }
111
112    // Getter/Setter
113    // -------------------------------------------------------------------------
114
115    public HystrixConfigurationDefinition getHystrixConfiguration() {
116        return hystrixConfiguration;
117    }
118
119    public void setHystrixConfiguration(HystrixConfigurationDefinition hystrixConfiguration) {
120        this.hystrixConfiguration = hystrixConfiguration;
121    }
122
123    public Resilience4jConfigurationCommon getResilience4jConfiguration() {
124        return resilience4jConfiguration;
125    }
126
127    public void setResilience4jConfiguration(Resilience4jConfigurationDefinition resilience4jConfiguration) {
128        this.resilience4jConfiguration = resilience4jConfiguration;
129    }
130
131    public String getConfigurationRef() {
132        return configurationRef;
133    }
134
135    /**
136     * Refers to a circuit breaker configuration (such as hystrix, resillience4j, or microprofile-fault-tolerance)
137     * to use for configuring the circuit breaker EIP.
138     */
139    public void setConfigurationRef(String configurationRef) {
140        this.configurationRef = configurationRef;
141    }
142
143    public OnFallbackDefinition getOnFallback() {
144        return onFallback;
145    }
146
147    public void setOnFallback(OnFallbackDefinition onFallback) {
148        this.onFallback = onFallback;
149    }
150
151    // Fluent API
152    // -------------------------------------------------------------------------
153
154    /**
155     * Configures the circuit breaker to use Hystrix.
156     * <p/>
157     * Use <tt>end</tt> when configuration is complete, to return back to the
158     * Circuit Breaker EIP.
159     */
160    public HystrixConfigurationDefinition hystrixConfiguration() {
161        hystrixConfiguration = hystrixConfiguration == null ? new HystrixConfigurationDefinition(this) : hystrixConfiguration;
162        return hystrixConfiguration;
163    }
164
165    /**
166     * Configures the circuit breaker to use Hystrix with the given configuration.
167     */
168    public CircuitBreakerDefinition hystrixConfiguration(HystrixConfigurationDefinition configuration) {
169        hystrixConfiguration = configuration;
170        return this;
171    }
172
173    /**
174     * Configures the circuit breaker to use Resilience4j.
175     * <p/>
176     * Use <tt>end</tt> when configuration is complete, to return back to the
177     * Circuit Breaker EIP.
178     */
179    public Resilience4jConfigurationDefinition resilience4jConfiguration() {
180        resilience4jConfiguration = resilience4jConfiguration == null ? new Resilience4jConfigurationDefinition(this) : resilience4jConfiguration;
181        return resilience4jConfiguration;
182    }
183
184    /**
185     * Configures the circuit breaker to use Resilience4j with the given configuration.
186     */
187    public CircuitBreakerDefinition resilience4jConfiguration(Resilience4jConfigurationDefinition configuration) {
188        resilience4jConfiguration = configuration;
189        return this;
190    }
191
192    /**
193     * Refers to a configuration to use for configuring the circuit breaker.
194     */
195    public CircuitBreakerDefinition configuration(String ref) {
196        configurationRef = ref;
197        return this;
198    }
199
200    /**
201     * The fallback route path to execute that does <b>not</b> go over
202     * the network.
203     * <p>
204     * This should be a static or cached result that can immediately be returned
205     * upon failure. If the fallback requires network connection then use
206     * {@link #onFallbackViaNetwork()}.
207     */
208    public CircuitBreakerDefinition onFallback() {
209        onFallback = new OnFallbackDefinition();
210        onFallback.setParent(this);
211        return this;
212    }
213
214    /**
215     * The fallback route path to execute that will go over the network.
216     * <p/>
217     * If the fallback will go over the network it is another possible point of failure.
218     */
219    public CircuitBreakerDefinition onFallbackViaNetwork() {
220        onFallback = new OnFallbackDefinition();
221        onFallback.setFallbackViaNetwork(Boolean.toString(true));
222        onFallback.setParent(this);
223        return this;
224    }
225
226}