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.concurrent.ExecutorService; 020 021import javax.xml.bind.annotation.XmlAccessType; 022import javax.xml.bind.annotation.XmlAccessorType; 023import javax.xml.bind.annotation.XmlAttribute; 024import javax.xml.bind.annotation.XmlElement; 025import javax.xml.bind.annotation.XmlRootElement; 026import javax.xml.bind.annotation.XmlTransient; 027import javax.xml.bind.annotation.XmlType; 028 029import org.apache.camel.Expression; 030import org.apache.camel.builder.ExpressionBuilder; 031import org.apache.camel.model.language.ExpressionDefinition; 032import org.apache.camel.spi.Metadata; 033 034/** 035 * Controls the rate at which messages are passed to the next node in the route 036 */ 037@Metadata(label = "eip,routing") 038@XmlRootElement(name = "throttle") 039@XmlAccessorType(XmlAccessType.FIELD) 040@XmlType(propOrder = {"expression", "correlationExpression"}) 041public class ThrottleDefinition extends ExpressionNode implements ExecutorServiceAwareDefinition<ThrottleDefinition> { 042 043 @XmlElement(name = "correlationExpression") 044 private ExpressionSubElementDefinition correlationExpression; 045 @XmlTransient 046 private ExecutorService executorService; 047 @XmlAttribute 048 private String executorServiceRef; 049 @XmlAttribute 050 @Metadata(defaultValue = "1000", javaType = "java.time.Duration") 051 private String timePeriodMillis; 052 @XmlAttribute 053 @Metadata(javaType = "java.lang.Boolean") 054 private String asyncDelayed; 055 @XmlAttribute 056 @Metadata(defaultValue = "true", javaType = "java.lang.Boolean") 057 private String callerRunsWhenRejected; 058 @XmlAttribute 059 @Metadata(javaType = "java.lang.Boolean") 060 private String rejectExecution; 061 062 public ThrottleDefinition() { 063 } 064 065 public ThrottleDefinition(Expression maximumRequestsPerPeriod) { 066 super(maximumRequestsPerPeriod); 067 } 068 069 public ThrottleDefinition(Expression maximumRequestsPerPeriod, Expression correlationExpression) { 070 this(ExpressionNodeHelper.toExpressionDefinition(maximumRequestsPerPeriod), correlationExpression); 071 } 072 073 private ThrottleDefinition(ExpressionDefinition maximumRequestsPerPeriod, Expression correlationExpression) { 074 super(maximumRequestsPerPeriod); 075 076 ExpressionSubElementDefinition cor = new ExpressionSubElementDefinition(); 077 cor.setExpressionType(ExpressionNodeHelper.toExpressionDefinition(correlationExpression)); 078 setCorrelationExpression(cor); 079 } 080 081 @Override 082 public String toString() { 083 return "Throttle[" + description() + "]"; 084 } 085 086 protected String description() { 087 return getExpression() + " request per " + getTimePeriodMillis() + " millis"; 088 } 089 090 @Override 091 public String getShortName() { 092 return "throttle"; 093 } 094 095 @Override 096 public String getLabel() { 097 return "throttle[" + description() + "]"; 098 } 099 100 // Fluent API 101 // ------------------------------------------------------------------------- 102 /** 103 * Sets the time period during which the maximum request count is valid for 104 * 105 * @param timePeriodMillis period in millis 106 * @return the builder 107 */ 108 public ThrottleDefinition timePeriodMillis(long timePeriodMillis) { 109 return timePeriodMillis(Long.toString(timePeriodMillis)); 110 } 111 112 /** 113 * Sets the time period during which the maximum request count is valid for 114 * 115 * @param timePeriodMillis period in millis 116 * @return the builder 117 */ 118 public ThrottleDefinition timePeriodMillis(String timePeriodMillis) { 119 setTimePeriodMillis(timePeriodMillis); 120 return this; 121 } 122 123 /** 124 * Sets the time period during which the maximum request count per period 125 * 126 * @param maximumRequestsPerPeriod the maximum request count number per time 127 * period 128 * @return the builder 129 */ 130 public ThrottleDefinition maximumRequestsPerPeriod(long maximumRequestsPerPeriod) { 131 setExpression(ExpressionNodeHelper.toExpressionDefinition(ExpressionBuilder.constantExpression(maximumRequestsPerPeriod))); 132 return this; 133 } 134 135 /** 136 * Sets the time period during which the maximum request count per period 137 * 138 * @param maximumRequestsPerPeriod the maximum request count number per time 139 * period 140 * @return the builder 141 */ 142 public ThrottleDefinition maximumRequestsPerPeriod(String maximumRequestsPerPeriod) { 143 setExpression(ExpressionNodeHelper.toExpressionDefinition(ExpressionBuilder.simpleExpression(maximumRequestsPerPeriod))); 144 return this; 145 } 146 147 /** 148 * Whether or not the caller should run the task when it was rejected by the 149 * thread pool. 150 * <p/> 151 * Is by default <tt>true</tt> 152 * 153 * @param callerRunsWhenRejected whether or not the caller should run 154 * @return the builder 155 */ 156 public ThrottleDefinition callerRunsWhenRejected(boolean callerRunsWhenRejected) { 157 return callerRunsWhenRejected(Boolean.toString(callerRunsWhenRejected)); 158 } 159 160 /** 161 * Whether or not the caller should run the task when it was rejected by the 162 * thread pool. 163 * <p/> 164 * Is by default <tt>true</tt> 165 * 166 * @param callerRunsWhenRejected whether or not the caller should run 167 * @return the builder 168 */ 169 public ThrottleDefinition callerRunsWhenRejected(String callerRunsWhenRejected) { 170 setCallerRunsWhenRejected(callerRunsWhenRejected); 171 return this; 172 } 173 174 /** 175 * Enables asynchronous delay which means the thread will <b>not</b> block 176 * while delaying. 177 * 178 * @return the builder 179 */ 180 public ThrottleDefinition asyncDelayed() { 181 return asyncDelayed(true); 182 } 183 184 /** 185 * Enables asynchronous delay which means the thread will <b>not</b> block 186 * while delaying. 187 * 188 * @return the builder 189 */ 190 public ThrottleDefinition asyncDelayed(boolean asyncDelayed) { 191 return asyncDelayed(Boolean.toString(asyncDelayed)); 192 } 193 194 /** 195 * Enables asynchronous delay which means the thread will <b>not</b> block 196 * while delaying. 197 * 198 * @return the builder 199 */ 200 public ThrottleDefinition asyncDelayed(String asyncDelayed) { 201 setAsyncDelayed(asyncDelayed); 202 return this; 203 } 204 205 /** 206 * Whether or not throttler throws the ThrottlerRejectedExecutionException 207 * when the exchange exceeds the request limit 208 * <p/> 209 * Is by default <tt>false</tt> 210 * 211 * @param rejectExecution throw the RejectExecutionException if the exchange 212 * exceeds the request limit 213 * @return the builder 214 */ 215 public ThrottleDefinition rejectExecution(boolean rejectExecution) { 216 return rejectExecution(Boolean.toString(rejectExecution)); 217 } 218 219 /** 220 * Whether or not throttler throws the ThrottlerRejectedExecutionException 221 * when the exchange exceeds the request limit 222 * <p/> 223 * Is by default <tt>false</tt> 224 * 225 * @param rejectExecution throw the RejectExecutionException if the exchange 226 * exceeds the request limit 227 * @return the builder 228 */ 229 public ThrottleDefinition rejectExecution(String rejectExecution) { 230 setRejectExecution(rejectExecution); 231 return this; 232 } 233 234 /** 235 * To use a custom thread pool (ScheduledExecutorService) by the throttler. 236 * 237 * @param executorService the custom thread pool (must be scheduled) 238 * @return the builder 239 */ 240 @Override 241 public ThrottleDefinition executorService(ExecutorService executorService) { 242 setExecutorService(executorService); 243 return this; 244 } 245 246 /** 247 * To use a custom thread pool (ScheduledExecutorService) by the throttler. 248 * 249 * @param executorServiceRef the reference id of the thread pool (must be 250 * scheduled) 251 * @return the builder 252 */ 253 @Override 254 public ThrottleDefinition executorServiceRef(String executorServiceRef) { 255 setExecutorServiceRef(executorServiceRef); 256 return this; 257 } 258 259 // Properties 260 // ------------------------------------------------------------------------- 261 262 /** 263 * Expression to configure the maximum number of messages to throttle per 264 * request 265 */ 266 @Override 267 public void setExpression(ExpressionDefinition expression) { 268 // override to include javadoc what the expression is used for 269 super.setExpression(expression); 270 } 271 272 public String getTimePeriodMillis() { 273 return timePeriodMillis; 274 } 275 276 public void setTimePeriodMillis(String timePeriodMillis) { 277 this.timePeriodMillis = timePeriodMillis; 278 } 279 280 public String getAsyncDelayed() { 281 return asyncDelayed; 282 } 283 284 public void setAsyncDelayed(String asyncDelayed) { 285 this.asyncDelayed = asyncDelayed; 286 } 287 288 public String getCallerRunsWhenRejected() { 289 return callerRunsWhenRejected; 290 } 291 292 public void setCallerRunsWhenRejected(String callerRunsWhenRejected) { 293 this.callerRunsWhenRejected = callerRunsWhenRejected; 294 } 295 296 @Override 297 public ExecutorService getExecutorService() { 298 return executorService; 299 } 300 301 @Override 302 public void setExecutorService(ExecutorService executorService) { 303 this.executorService = executorService; 304 } 305 306 @Override 307 public String getExecutorServiceRef() { 308 return executorServiceRef; 309 } 310 311 @Override 312 public void setExecutorServiceRef(String executorServiceRef) { 313 this.executorServiceRef = executorServiceRef; 314 } 315 316 public String getRejectExecution() { 317 return rejectExecution; 318 } 319 320 public void setRejectExecution(String rejectExecution) { 321 this.rejectExecution = rejectExecution; 322 } 323 324 /** 325 * The expression used to calculate the correlation key to use for throttle 326 * grouping. The Exchange which has the same correlation key is throttled 327 * together. 328 */ 329 public void setCorrelationExpression(ExpressionSubElementDefinition correlationExpression) { 330 this.correlationExpression = correlationExpression; 331 } 332 333 public ExpressionSubElementDefinition getCorrelationExpression() { 334 return correlationExpression; 335 } 336}