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