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