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.List; 020import java.util.concurrent.ExecutorService; 021import java.util.function.Supplier; 022 023import javax.xml.bind.annotation.XmlAccessType; 024import javax.xml.bind.annotation.XmlAccessorType; 025import javax.xml.bind.annotation.XmlAttribute; 026import javax.xml.bind.annotation.XmlElementRef; 027import javax.xml.bind.annotation.XmlRootElement; 028import javax.xml.bind.annotation.XmlTransient; 029 030import org.apache.camel.AggregationStrategy; 031import org.apache.camel.Processor; 032import org.apache.camel.builder.AggregationStrategyClause; 033import org.apache.camel.builder.ProcessClause; 034import org.apache.camel.spi.Metadata; 035 036/** 037 * Routes the same message to multiple paths either sequentially or in parallel. 038 */ 039@Metadata(label = "eip,routing") 040@XmlRootElement(name = "multicast") 041@XmlAccessorType(XmlAccessType.FIELD) 042public class MulticastDefinition extends OutputDefinition<MulticastDefinition> implements ExecutorServiceAwareDefinition<MulticastDefinition> { 043 @XmlAttribute 044 private String parallelProcessing; 045 @XmlAttribute 046 private String strategyRef; 047 @XmlAttribute 048 private String strategyMethodName; 049 @XmlAttribute 050 private String strategyMethodAllowNull; 051 @XmlTransient 052 private ExecutorService executorService; 053 @XmlAttribute 054 private String executorServiceRef; 055 @XmlAttribute 056 private String streaming; 057 @XmlAttribute 058 private String stopOnException; 059 @XmlAttribute 060 @Metadata(defaultValue = "0") 061 private String timeout; 062 @XmlTransient 063 private AggregationStrategy aggregationStrategy; 064 @XmlAttribute 065 private String onPrepareRef; 066 @XmlTransient 067 private Processor onPrepare; 068 @XmlAttribute 069 private String shareUnitOfWork; 070 @XmlAttribute 071 private String parallelAggregate; 072 @XmlAttribute 073 private String stopOnAggregateException; 074 075 public MulticastDefinition() { 076 } 077 078 @Override 079 public List<ProcessorDefinition<?>> getOutputs() { 080 return outputs; 081 } 082 083 @XmlElementRef 084 @Override 085 public void setOutputs(List<ProcessorDefinition<?>> outputs) { 086 super.setOutputs(outputs); 087 } 088 089 @Override 090 public String toString() { 091 return "Multicast[" + getOutputs() + "]"; 092 } 093 094 @Override 095 public String getShortName() { 096 return "multicast"; 097 } 098 099 @Override 100 public String getLabel() { 101 return "multicast"; 102 } 103 104 // Fluent API 105 // ------------------------------------------------------------------------- 106 107 /** 108 * Sets the AggregationStrategy to be used to assemble the replies from the 109 * multicasts, into a single outgoing message from the Multicast using a 110 * fluent builder. 111 */ 112 public AggregationStrategyClause<MulticastDefinition> aggregationStrategy() { 113 AggregationStrategyClause<MulticastDefinition> clause = new AggregationStrategyClause<>(this); 114 setAggregationStrategy(clause); 115 return clause; 116 } 117 118 /** 119 * Sets the AggregationStrategy to be used to assemble the replies from the 120 * multicasts, into a single outgoing message from the Multicast. By default 121 * Camel will use the last reply as the outgoing message. You can also use a 122 * POJO as the AggregationStrategy. If an exception is thrown from the 123 * aggregate method in the AggregationStrategy, then by default, that 124 * exception is not handled by the error handler. The error handler can be 125 * enabled to react if enabling the shareUnitOfWork option. 126 */ 127 public MulticastDefinition aggregationStrategy(AggregationStrategy aggregationStrategy) { 128 setAggregationStrategy(aggregationStrategy); 129 return this; 130 } 131 132 /** 133 * Sets the AggregationStrategy to be used to assemble the replies from the 134 * multicasts, into a single outgoing message from the Multicast. By default 135 * Camel will use the last reply as the outgoing message. You can also use a 136 * POJO as the AggregationStrategy. If an exception is thrown from the 137 * aggregate method in the AggregationStrategy, then by default, that 138 * exception is not handled by the error handler. The error handler can be 139 * enabled to react if enabling the shareUnitOfWork option. 140 */ 141 public MulticastDefinition aggregationStrategy(Supplier<AggregationStrategy> aggregationStrategy) { 142 setAggregationStrategy(aggregationStrategy.get()); 143 return this; 144 } 145 146 /** 147 * Sets a reference to the AggregationStrategy to be used to assemble the 148 * replies from the multicasts, into a single outgoing message from the 149 * Multicast. By default Camel will use the last reply as the outgoing 150 * message. You can also use a POJO as the AggregationStrategy If an 151 * exception is thrown from the aggregate method in the AggregationStrategy, 152 * then by default, that exception is not handled by the error handler. The 153 * error handler can be enabled to react if enabling the shareUnitOfWork 154 * option. 155 */ 156 public MulticastDefinition aggregationStrategyRef(String aggregationStrategyRef) { 157 setStrategyRef(aggregationStrategyRef); 158 return this; 159 } 160 161 /** 162 * This option can be used to explicit declare the method name to use, when 163 * using POJOs as the AggregationStrategy. 164 * 165 * @param methodName the method name to call 166 * @return the builder 167 */ 168 public MulticastDefinition aggregationStrategyMethodName(String methodName) { 169 setStrategyMethodName(methodName); 170 return this; 171 } 172 173 /** 174 * If this option is false then the aggregate method is not used if there 175 * was no data to enrich. If this option is true then null values is used as 176 * the oldExchange (when no data to enrich), when using POJOs as the 177 * AggregationStrategy 178 * 179 * @return the builder 180 */ 181 public MulticastDefinition aggregationStrategyMethodAllowNull() { 182 setStrategyMethodAllowNull(Boolean.toString(true)); 183 return this; 184 } 185 186 /** 187 * If enabled then sending messages to the multicasts occurs concurrently. 188 * Note the caller thread will still wait until all messages has been fully 189 * processed, before it continues. Its only the sending and processing the 190 * replies from the multicasts which happens concurrently. 191 * 192 * @return the builder 193 */ 194 public MulticastDefinition parallelProcessing() { 195 setParallelProcessing(Boolean.toString(true)); 196 return this; 197 } 198 199 /** 200 * If enabled then sending messages to the multicasts occurs concurrently. 201 * Note the caller thread will still wait until all messages has been fully 202 * processed, before it continues. Its only the sending and processing the 203 * replies from the multicasts which happens concurrently. 204 * 205 * @return the builder 206 */ 207 public MulticastDefinition parallelProcessing(boolean parallelProcessing) { 208 setParallelProcessing(Boolean.toString(parallelProcessing)); 209 return this; 210 } 211 212 /** 213 * If enabled then the aggregate method on AggregationStrategy can be called 214 * concurrently. Notice that this would require the implementation of 215 * AggregationStrategy to be implemented as thread-safe. By default this is 216 * false meaning that Camel synchronizes the call to the aggregate method. 217 * Though in some use-cases this can be used to archive higher performance 218 * when the AggregationStrategy is implemented as thread-safe. 219 * 220 * @return the builder 221 */ 222 public MulticastDefinition parallelAggregate() { 223 setParallelAggregate(Boolean.toString(true)); 224 return this; 225 } 226 227 /** 228 * If enabled, unwind exceptions occurring at aggregation time to the error 229 * handler when parallelProcessing is used. Currently, aggregation time 230 * exceptions do not stop the route processing when parallelProcessing is 231 * used. Enabling this option allows to work around this behavior. The 232 * default value is <code>false</code> for the sake of backward 233 * compatibility. 234 * 235 * @return the builder 236 */ 237 public MulticastDefinition stopOnAggregateException() { 238 setStopOnAggregateException(Boolean.toString(true)); 239 return this; 240 } 241 242 /** 243 * If enabled then Camel will process replies out-of-order, eg in the order 244 * they come back. If disabled, Camel will process replies in the same order 245 * as defined by the multicast. 246 * 247 * @return the builder 248 */ 249 public MulticastDefinition streaming() { 250 setStreaming(Boolean.toString(true)); 251 return this; 252 } 253 254 /** 255 * Will now stop further processing if an exception or failure occurred 256 * during processing of an {@link org.apache.camel.Exchange} and the caused 257 * exception will be thrown. 258 * <p/> 259 * Will also stop if processing the exchange failed (has a fault message) or 260 * an exception was thrown and handled by the error handler (such as using 261 * onException). In all situations the multicast will stop further 262 * processing. This is the same behavior as in pipeline, which is used by 263 * the routing engine. 264 * <p/> 265 * The default behavior is to <b>not</b> stop but continue processing till 266 * the end 267 * 268 * @return the builder 269 */ 270 public MulticastDefinition stopOnException() { 271 return stopOnException(Boolean.toString(true)); 272 } 273 274 /** 275 * Will now stop further processing if an exception or failure occurred 276 * during processing of an {@link org.apache.camel.Exchange} and the caused 277 * exception will be thrown. 278 * <p/> 279 * Will also stop if processing the exchange failed (has a fault message) or 280 * an exception was thrown and handled by the error handler (such as using 281 * onException). In all situations the multicast will stop further 282 * processing. This is the same behavior as in pipeline, which is used by 283 * the routing engine. 284 * <p/> 285 * The default behavior is to <b>not</b> stop but continue processing till 286 * the end 287 * 288 * @return the builder 289 */ 290 public MulticastDefinition stopOnException(String stopOnException) { 291 setStopOnException(stopOnException); 292 return this; 293 } 294 295 /** 296 * To use a custom Thread Pool to be used for parallel processing. Notice if 297 * you set this option, then parallel processing is automatic implied, and 298 * you do not have to enable that option as well. 299 */ 300 @Override 301 public MulticastDefinition executorService(ExecutorService executorService) { 302 setExecutorService(executorService); 303 return this; 304 } 305 306 /** 307 * Refers to a custom Thread Pool to be used for parallel processing. Notice 308 * if you set this option, then parallel processing is automatic implied, 309 * and you do not have to enable that option as well. 310 */ 311 @Override 312 public MulticastDefinition executorServiceRef(String executorServiceRef) { 313 setExecutorServiceRef(executorServiceRef); 314 return this; 315 } 316 317 /** 318 * Set the {@link Processor} to use when preparing the 319 * {@link org.apache.camel.Exchange} to be send using a fluent builder. 320 */ 321 public ProcessClause<MulticastDefinition> onPrepare() { 322 ProcessClause<MulticastDefinition> clause = new ProcessClause<>(this); 323 setOnPrepare(clause); 324 return clause; 325 } 326 327 /** 328 * Uses the {@link Processor} when preparing the 329 * {@link org.apache.camel.Exchange} to be send. This can be used to 330 * deep-clone messages that should be send, or any custom logic needed 331 * before the exchange is send. 332 * 333 * @param onPrepare the processor 334 * @return the builder 335 */ 336 public MulticastDefinition onPrepare(Processor onPrepare) { 337 setOnPrepare(onPrepare); 338 return this; 339 } 340 341 /** 342 * Uses the {@link Processor} when preparing the 343 * {@link org.apache.camel.Exchange} to be send. This can be used to 344 * deep-clone messages that should be send, or any custom logic needed 345 * before the exchange is send. 346 * 347 * @param onPrepareRef reference to the processor to lookup in the 348 * {@link org.apache.camel.spi.Registry} 349 * @return the builder 350 */ 351 public MulticastDefinition onPrepareRef(String onPrepareRef) { 352 setOnPrepareRef(onPrepareRef); 353 return this; 354 } 355 356 /** 357 * Sets a total timeout specified in millis, when using parallel processing. 358 * If the Multicast hasn't been able to send and process all replies within 359 * the given timeframe, then the timeout triggers and the Multicast breaks 360 * out and continues. Notice if you provide a 361 * TimeoutAwareAggregationStrategy then the timeout method is invoked before 362 * breaking out. If the timeout is reached with running tasks still 363 * remaining, certain tasks for which it is difficult for Camel to shut down 364 * in a graceful manner may continue to run. So use this option with a bit 365 * of care. 366 * 367 * @param timeout timeout in millis 368 * @return the builder 369 */ 370 public MulticastDefinition timeout(long timeout) { 371 return timeout(Long.toString(timeout)); 372 } 373 374 /** 375 * Sets a total timeout specified in millis, when using parallel processing. 376 * If the Multicast hasn't been able to send and process all replies within 377 * the given timeframe, then the timeout triggers and the Multicast breaks 378 * out and continues. Notice if you provide a 379 * TimeoutAwareAggregationStrategy then the timeout method is invoked before 380 * breaking out. If the timeout is reached with running tasks still 381 * remaining, certain tasks for which it is difficult for Camel to shut down 382 * in a graceful manner may continue to run. So use this option with a bit 383 * of care. 384 * 385 * @param timeout timeout in millis 386 * @return the builder 387 */ 388 public MulticastDefinition timeout(String timeout) { 389 setTimeout(timeout); 390 return this; 391 } 392 393 /** 394 * Shares the {@link org.apache.camel.spi.UnitOfWork} with the parent and 395 * each of the sub messages. Multicast will by default not share unit of 396 * work between the parent exchange and each multicasted exchange. This 397 * means each sub exchange has its own individual unit of work. 398 * 399 * @return the builder. 400 */ 401 public MulticastDefinition shareUnitOfWork() { 402 setShareUnitOfWork(Boolean.toString(true)); 403 return this; 404 } 405 406 public AggregationStrategy getAggregationStrategy() { 407 return aggregationStrategy; 408 } 409 410 public MulticastDefinition setAggregationStrategy(AggregationStrategy aggregationStrategy) { 411 this.aggregationStrategy = aggregationStrategy; 412 return this; 413 } 414 415 public String getParallelProcessing() { 416 return parallelProcessing; 417 } 418 419 public void setParallelProcessing(String parallelProcessing) { 420 this.parallelProcessing = parallelProcessing; 421 } 422 423 public String getStreaming() { 424 return streaming; 425 } 426 427 public void setStreaming(String streaming) { 428 this.streaming = streaming; 429 } 430 431 public String getStopOnException() { 432 return stopOnException; 433 } 434 435 public void setStopOnException(String stopOnException) { 436 this.stopOnException = stopOnException; 437 } 438 439 @Override 440 public ExecutorService getExecutorService() { 441 return executorService; 442 } 443 444 @Override 445 public void setExecutorService(ExecutorService executorService) { 446 this.executorService = executorService; 447 } 448 449 public String getStrategyRef() { 450 return strategyRef; 451 } 452 453 /** 454 * Refers to an AggregationStrategy to be used to assemble the replies from 455 * the multicasts, into a single outgoing message from the Multicast. By 456 * default Camel will use the last reply as the outgoing message. You can 457 * also use a POJO as the AggregationStrategy 458 */ 459 public void setStrategyRef(String strategyRef) { 460 this.strategyRef = strategyRef; 461 } 462 463 public String getStrategyMethodName() { 464 return strategyMethodName; 465 } 466 467 /** 468 * This option can be used to explicit declare the method name to use, when 469 * using POJOs as the AggregationStrategy. 470 */ 471 public void setStrategyMethodName(String strategyMethodName) { 472 this.strategyMethodName = strategyMethodName; 473 } 474 475 public String getStrategyMethodAllowNull() { 476 return strategyMethodAllowNull; 477 } 478 479 /** 480 * If this option is false then the aggregate method is not used if there 481 * was no data to enrich. If this option is true then null values is used as 482 * the oldExchange (when no data to enrich), when using POJOs as the 483 * AggregationStrategy 484 */ 485 public void setStrategyMethodAllowNull(String strategyMethodAllowNull) { 486 this.strategyMethodAllowNull = strategyMethodAllowNull; 487 } 488 489 @Override 490 public String getExecutorServiceRef() { 491 return executorServiceRef; 492 } 493 494 /** 495 * Refers to a custom Thread Pool to be used for parallel processing. Notice 496 * if you set this option, then parallel processing is automatic implied, 497 * and you do not have to enable that option as well. 498 */ 499 @Override 500 public void setExecutorServiceRef(String executorServiceRef) { 501 this.executorServiceRef = executorServiceRef; 502 } 503 504 public String getTimeout() { 505 return timeout; 506 } 507 508 public void setTimeout(String timeout) { 509 this.timeout = timeout; 510 } 511 512 public String getOnPrepareRef() { 513 return onPrepareRef; 514 } 515 516 public void setOnPrepareRef(String onPrepareRef) { 517 this.onPrepareRef = onPrepareRef; 518 } 519 520 public Processor getOnPrepare() { 521 return onPrepare; 522 } 523 524 public void setOnPrepare(Processor onPrepare) { 525 this.onPrepare = onPrepare; 526 } 527 528 public String getShareUnitOfWork() { 529 return shareUnitOfWork; 530 } 531 532 public void setShareUnitOfWork(String shareUnitOfWork) { 533 this.shareUnitOfWork = shareUnitOfWork; 534 } 535 536 public String getParallelAggregate() { 537 return parallelAggregate; 538 } 539 540 public void setParallelAggregate(String parallelAggregate) { 541 this.parallelAggregate = parallelAggregate; 542 } 543 544 public String getStopOnAggregateException() { 545 return stopOnAggregateException; 546 } 547 548 public void setStopOnAggregateException(String stopOnAggregateException) { 549 this.stopOnAggregateException = stopOnAggregateException; 550 } 551 552}