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.processor; 018 019import java.io.Serializable; 020import java.util.Random; 021 022import org.apache.camel.Exchange; 023import org.apache.camel.LoggingLevel; 024import org.apache.camel.Predicate; 025import org.apache.camel.util.ObjectHelper; 026import org.slf4j.Logger; 027import org.slf4j.LoggerFactory; 028 029/** 030 * The policy used to decide how many times to redeliver and the time between 031 * the redeliveries before being sent to a <a 032 * href="http://camel.apache.org/dead-letter-channel.html">Dead Letter 033 * Channel</a> 034 * <p> 035 * The default values are: 036 * <ul> 037 * <li>maximumRedeliveries = 0</li> 038 * <li>redeliveryDelay = 1000L (the initial delay)</li> 039 * <li>maximumRedeliveryDelay = 60 * 1000L</li> 040 * <li>asyncDelayedRedelivery = false</li> 041 * <li>backOffMultiplier = 2</li> 042 * <li>useExponentialBackOff = false</li> 043 * <li>collisionAvoidanceFactor = 0.15d</li> 044 * <li>useCollisionAvoidance = false</li> 045 * <li>retriesExhaustedLogLevel = LoggingLevel.ERROR</li> 046 * <li>retryAttemptedLogLevel = LoggingLevel.DEBUG</li> 047 * <li>logRetryAttempted = true</li> 048 * <li>logRetryStackTrace = false</li> 049 * <li>logStackTrace = true</li> 050 * <li>logHandled = false</li> 051 * <li>logExhausted = true</li> 052 * <li>logExhaustedMessageHistory = true</li> 053 * <li>logNewException = true</li> 054 * <li>allowRedeliveryWhileStopping = true</li> 055 * </ul> 056 * <p/> 057 * Setting the maximumRedeliveries to a negative value such as -1 will then always redeliver (unlimited). 058 * Setting the maximumRedeliveries to 0 will disable redelivery. 059 * <p/> 060 * This policy can be configured either by one of the following two settings: 061 * <ul> 062 * <li>using conventional options, using all the options defined above</li> 063 * <li>using delay pattern to declare intervals for delays</li> 064 * </ul> 065 * <p/> 066 * <b>Note:</b> If using delay patterns then the following options is not used (delay, backOffMultiplier, useExponentialBackOff, useCollisionAvoidance) 067 * <p/> 068 * <b>Using delay pattern</b>: 069 * <br/>The delay pattern syntax is: <tt>limit:delay;limit 2:delay 2;limit 3:delay 3;...;limit N:delay N</tt>. 070 * <p/> 071 * How it works is best illustrate with an example with this pattern: <tt>delayPattern=5:1000;10:5000:20:20000</tt> 072 * <br/>The delays will be for attempt in range 0..4 = 0 millis, 5..9 = 1000 millis, 10..19 = 5000 millis, >= 20 = 20000 millis. 073 * <p/> 074 * If you want to set a starting delay, then use 0 as the first limit, eg: <tt>0:1000;5:5000</tt> will use 1 sec delay 075 * until attempt number 5 where it will use 5 seconds going forward. 076 * 077 * @version 078 */ 079public class RedeliveryPolicy implements Cloneable, Serializable { 080 protected static Random randomNumberGenerator; 081 private static final long serialVersionUID = -338222777701473252L; 082 private static final Logger LOG = LoggerFactory.getLogger(RedeliveryPolicy.class); 083 084 protected long redeliveryDelay = 1000L; 085 protected int maximumRedeliveries; 086 protected long maximumRedeliveryDelay = 60 * 1000L; 087 protected double backOffMultiplier = 2; 088 protected boolean useExponentialBackOff; 089 // +/-15% for a 30% spread -cgs 090 protected double collisionAvoidanceFactor = 0.15d; 091 protected boolean useCollisionAvoidance; 092 protected LoggingLevel retriesExhaustedLogLevel = LoggingLevel.ERROR; 093 protected LoggingLevel retryAttemptedLogLevel = LoggingLevel.DEBUG; 094 protected boolean logStackTrace = true; 095 protected boolean logRetryStackTrace; 096 protected boolean logHandled; 097 protected boolean logContinued; 098 protected boolean logExhausted = true; 099 protected boolean logNewException = true; 100 protected Boolean logExhaustedMessageHistory; 101 protected boolean logRetryAttempted = true; 102 protected String delayPattern; 103 protected boolean asyncDelayedRedelivery; 104 protected boolean allowRedeliveryWhileStopping = true; 105 protected String exchangeFormatterRef; 106 107 public RedeliveryPolicy() { 108 } 109 110 @Override 111 public String toString() { 112 return "RedeliveryPolicy[maximumRedeliveries=" + maximumRedeliveries 113 + ", redeliveryDelay=" + redeliveryDelay 114 + ", maximumRedeliveryDelay=" + maximumRedeliveryDelay 115 + ", asyncDelayedRedelivery=" + asyncDelayedRedelivery 116 + ", allowRedeliveryWhileStopping=" + allowRedeliveryWhileStopping 117 + ", retriesExhaustedLogLevel=" + retriesExhaustedLogLevel 118 + ", retryAttemptedLogLevel=" + retryAttemptedLogLevel 119 + ", logRetryAttempted=" + logRetryAttempted 120 + ", logStackTrace=" + logStackTrace 121 + ", logRetryStackTrace=" + logRetryStackTrace 122 + ", logHandled=" + logHandled 123 + ", logContinued=" + logContinued 124 + ", logExhausted=" + logExhausted 125 + ", logNewException=" + logNewException 126 + ", logExhaustedMessageHistory=" + logExhaustedMessageHistory 127 + ", useExponentialBackOff=" + useExponentialBackOff 128 + ", backOffMultiplier=" + backOffMultiplier 129 + ", useCollisionAvoidance=" + useCollisionAvoidance 130 + ", collisionAvoidanceFactor=" + collisionAvoidanceFactor 131 + ", delayPattern=" + delayPattern 132 + ", exchangeFormatterRef=" + exchangeFormatterRef + "]"; 133 } 134 135 public RedeliveryPolicy copy() { 136 try { 137 return (RedeliveryPolicy)clone(); 138 } catch (CloneNotSupportedException e) { 139 throw new RuntimeException("Could not clone: " + e, e); 140 } 141 } 142 143 /** 144 * Returns true if the policy decides that the message exchange should be 145 * redelivered. 146 * 147 * @param exchange the current exchange 148 * @param redeliveryCounter the current retry counter 149 * @param retryWhile an optional predicate to determine if we should redeliver or not 150 * @return true to redeliver, false to stop 151 */ 152 public boolean shouldRedeliver(Exchange exchange, int redeliveryCounter, Predicate retryWhile) { 153 // predicate is always used if provided 154 if (retryWhile != null) { 155 return retryWhile.matches(exchange); 156 } 157 158 if (getMaximumRedeliveries() < 0) { 159 // retry forever if negative value 160 return true; 161 } 162 // redeliver until we hit the max 163 return redeliveryCounter <= getMaximumRedeliveries(); 164 } 165 166 167 /** 168 * Calculates the new redelivery delay based on the last one and then <b>sleeps</b> for the necessary amount of time. 169 * <p/> 170 * This implementation will block while sleeping. 171 * 172 * @param redeliveryDelay previous redelivery delay 173 * @param redeliveryCounter number of previous redelivery attempts 174 * @return the calculate delay 175 * @throws InterruptedException is thrown if the sleep is interrupted likely because of shutdown 176 */ 177 public long sleep(long redeliveryDelay, int redeliveryCounter) throws InterruptedException { 178 redeliveryDelay = calculateRedeliveryDelay(redeliveryDelay, redeliveryCounter); 179 180 if (redeliveryDelay > 0) { 181 sleep(redeliveryDelay); 182 } 183 return redeliveryDelay; 184 } 185 186 /** 187 * Sleeps for the given delay 188 * 189 * @param redeliveryDelay the delay 190 * @throws InterruptedException is thrown if the sleep is interrupted likely because of shutdown 191 */ 192 public void sleep(long redeliveryDelay) throws InterruptedException { 193 LOG.debug("Sleeping for: {} millis until attempting redelivery", redeliveryDelay); 194 Thread.sleep(redeliveryDelay); 195 } 196 197 /** 198 * Calculates the new redelivery delay based on the last one 199 * 200 * @param previousDelay previous redelivery delay 201 * @param redeliveryCounter number of previous redelivery attempts 202 * @return the calculate delay 203 */ 204 public long calculateRedeliveryDelay(long previousDelay, int redeliveryCounter) { 205 if (ObjectHelper.isNotEmpty(delayPattern)) { 206 // calculate delay using the pattern 207 return calculateRedeliverDelayUsingPattern(delayPattern, redeliveryCounter); 208 } 209 210 // calculate the delay using the conventional parameters 211 long redeliveryDelayResult; 212 if (previousDelay == 0) { 213 redeliveryDelayResult = redeliveryDelay; 214 } else if (useExponentialBackOff && backOffMultiplier > 1) { 215 redeliveryDelayResult = Math.round(backOffMultiplier * previousDelay); 216 } else { 217 redeliveryDelayResult = previousDelay; 218 } 219 220 if (useCollisionAvoidance) { 221 222 /* 223 * First random determines +/-, second random determines how far to 224 * go in that direction. -cgs 225 */ 226 Random random = getRandomNumberGenerator(); 227 double variance = (random.nextBoolean() ? collisionAvoidanceFactor : -collisionAvoidanceFactor) 228 * random.nextDouble(); 229 redeliveryDelayResult += redeliveryDelayResult * variance; 230 } 231 232 // ensure the calculated result is not bigger than the max delay (if configured) 233 if (maximumRedeliveryDelay > 0 && redeliveryDelayResult > maximumRedeliveryDelay) { 234 redeliveryDelayResult = maximumRedeliveryDelay; 235 } 236 237 return redeliveryDelayResult; 238 } 239 240 /** 241 * Calculates the delay using the delay pattern 242 */ 243 protected static long calculateRedeliverDelayUsingPattern(String delayPattern, int redeliveryCounter) { 244 String[] groups = delayPattern.split(";"); 245 // find the group where the redelivery counter matches 246 long answer = 0; 247 for (String group : groups) { 248 long delay = Long.valueOf(ObjectHelper.after(group, ":")); 249 int count = Integer.valueOf(ObjectHelper.before(group, ":")); 250 if (count > redeliveryCounter) { 251 break; 252 } else { 253 answer = delay; 254 } 255 } 256 257 return answer; 258 } 259 260 // Builder methods 261 // ------------------------------------------------------------------------- 262 263 /** 264 * Sets the initial redelivery delay in milliseconds 265 * 266 * @deprecated will be removed in the near future. Instead use {@link #redeliveryDelay(long)} instead 267 */ 268 @Deprecated 269 public RedeliveryPolicy redeliverDelay(long delay) { 270 return redeliveryDelay(delay); 271 } 272 273 /** 274 * Sets the initial redelivery delay in milliseconds 275 */ 276 public RedeliveryPolicy redeliveryDelay(long delay) { 277 setRedeliveryDelay(delay); 278 return this; 279 } 280 281 /** 282 * Sets the maximum number of times a message exchange will be redelivered 283 */ 284 public RedeliveryPolicy maximumRedeliveries(int maximumRedeliveries) { 285 setMaximumRedeliveries(maximumRedeliveries); 286 return this; 287 } 288 289 /** 290 * Enables collision avoidance which adds some randomization to the backoff 291 * timings to reduce contention probability 292 */ 293 public RedeliveryPolicy useCollisionAvoidance() { 294 setUseCollisionAvoidance(true); 295 return this; 296 } 297 298 /** 299 * Enables exponential backoff using the {@link #getBackOffMultiplier()} to 300 * increase the time between retries 301 */ 302 public RedeliveryPolicy useExponentialBackOff() { 303 setUseExponentialBackOff(true); 304 return this; 305 } 306 307 /** 308 * Enables exponential backoff and sets the multiplier used to increase the 309 * delay between redeliveries 310 */ 311 public RedeliveryPolicy backOffMultiplier(double multiplier) { 312 useExponentialBackOff(); 313 setBackOffMultiplier(multiplier); 314 return this; 315 } 316 317 /** 318 * Enables collision avoidance and sets the percentage used 319 */ 320 public RedeliveryPolicy collisionAvoidancePercent(double collisionAvoidancePercent) { 321 useCollisionAvoidance(); 322 setCollisionAvoidancePercent(collisionAvoidancePercent); 323 return this; 324 } 325 326 /** 327 * Sets the maximum redelivery delay if using exponential back off. 328 * Use -1 if you wish to have no maximum 329 */ 330 public RedeliveryPolicy maximumRedeliveryDelay(long maximumRedeliveryDelay) { 331 setMaximumRedeliveryDelay(maximumRedeliveryDelay); 332 return this; 333 } 334 335 /** 336 * Sets the logging level to use for log messages when retries have been exhausted. 337 */ 338 public RedeliveryPolicy retriesExhaustedLogLevel(LoggingLevel retriesExhaustedLogLevel) { 339 setRetriesExhaustedLogLevel(retriesExhaustedLogLevel); 340 return this; 341 } 342 343 /** 344 * Sets the logging level to use for log messages when retries are attempted. 345 */ 346 public RedeliveryPolicy retryAttemptedLogLevel(LoggingLevel retryAttemptedLogLevel) { 347 setRetryAttemptedLogLevel(retryAttemptedLogLevel); 348 return this; 349 } 350 351 /** 352 * Sets whether to log retry attempts 353 */ 354 public RedeliveryPolicy logRetryAttempted(boolean logRetryAttempted) { 355 setLogRetryAttempted(logRetryAttempted); 356 return this; 357 } 358 359 /** 360 * Sets whether to log stacktrace for failed messages. 361 */ 362 public RedeliveryPolicy logStackTrace(boolean logStackTrace) { 363 setLogStackTrace(logStackTrace); 364 return this; 365 } 366 367 /** 368 * Sets whether to log stacktrace for failed redelivery attempts 369 */ 370 public RedeliveryPolicy logRetryStackTrace(boolean logRetryStackTrace) { 371 setLogRetryStackTrace(logRetryStackTrace); 372 return this; 373 } 374 375 /** 376 * Sets whether to log errors even if its handled 377 */ 378 public RedeliveryPolicy logHandled(boolean logHandled) { 379 setLogHandled(logHandled); 380 return this; 381 } 382 383 /** 384 * Sets whether errors should be logged when a new exception occurred during handling a previous exception 385 */ 386 public RedeliveryPolicy logNewException(boolean logNewException) { 387 setLogNewException(logNewException); 388 return this; 389 } 390 391 /** 392 * Sets whether to log exhausted errors 393 */ 394 public RedeliveryPolicy logExhausted(boolean logExhausted) { 395 setLogExhausted(logExhausted); 396 return this; 397 } 398 399 /** 400 * Sets whether to log exhausted errors including message history 401 */ 402 public RedeliveryPolicy logExhaustedMessageHistory(boolean logExhaustedMessageHistory) { 403 setLogExhaustedMessageHistory(logExhaustedMessageHistory); 404 return this; 405 } 406 407 /** 408 * Sets the delay pattern with delay intervals. 409 */ 410 public RedeliveryPolicy delayPattern(String delayPattern) { 411 setDelayPattern(delayPattern); 412 return this; 413 } 414 415 /** 416 * Disables redelivery by setting maximum redeliveries to 0. 417 */ 418 public RedeliveryPolicy disableRedelivery() { 419 setMaximumRedeliveries(0); 420 return this; 421 } 422 423 /** 424 * Allow asynchronous delayed redelivery. 425 * 426 * @see #setAsyncDelayedRedelivery(boolean) 427 */ 428 public RedeliveryPolicy asyncDelayedRedelivery() { 429 setAsyncDelayedRedelivery(true); 430 return this; 431 } 432 433 /** 434 * Controls whether to allow redelivery while stopping/shutting down a route that uses error handling. 435 * 436 * @param redeliverWhileStopping <tt>true</tt> to allow redelivery, <tt>false</tt> to reject redeliveries 437 */ 438 public RedeliveryPolicy allowRedeliveryWhileStopping(boolean redeliverWhileStopping) { 439 setAllowRedeliveryWhileStopping(redeliverWhileStopping); 440 return this; 441 } 442 443 /** 444 * Sets the reference of the instance of {@link org.apache.camel.spi.ExchangeFormatter} to generate the log message from exchange. 445 * 446 * @param exchangeFormatterRef name of the instance of {@link org.apache.camel.spi.ExchangeFormatter} 447 * @return the builder 448 */ 449 public RedeliveryPolicy exchangeFormatterRef(String exchangeFormatterRef) { 450 setExchangeFormatterRef(exchangeFormatterRef); 451 return this; 452 } 453 454 // Properties 455 // ------------------------------------------------------------------------- 456 457 /** 458 * @deprecated will be removed in the near future. Instead use {@link #getRedeliveryDelay()} 459 */ 460 @Deprecated 461 public long getRedeliverDelay() { 462 return getRedeliveryDelay(); 463 } 464 465 /** 466 * @deprecated will be removed in the near future. Instead use {@link #setRedeliveryDelay(long)} 467 */ 468 @Deprecated 469 public void setRedeliverDelay(long redeliveryDelay) { 470 setRedeliveryDelay(redeliveryDelay); 471 } 472 473 public long getRedeliveryDelay() { 474 return redeliveryDelay; 475 } 476 477 /** 478 * Sets the initial redelivery delay in milliseconds 479 */ 480 public void setRedeliveryDelay(long redeliverDelay) { 481 this.redeliveryDelay = redeliverDelay; 482 // if max enabled then also set max to this value in case max was too low 483 if (maximumRedeliveryDelay > 0 && redeliverDelay > maximumRedeliveryDelay) { 484 this.maximumRedeliveryDelay = redeliverDelay; 485 } 486 } 487 488 public double getBackOffMultiplier() { 489 return backOffMultiplier; 490 } 491 492 /** 493 * Sets the multiplier used to increase the delay between redeliveries if 494 * {@link #setUseExponentialBackOff(boolean)} is enabled 495 */ 496 public void setBackOffMultiplier(double backOffMultiplier) { 497 this.backOffMultiplier = backOffMultiplier; 498 } 499 500 public long getCollisionAvoidancePercent() { 501 return Math.round(collisionAvoidanceFactor * 100); 502 } 503 504 /** 505 * Sets the percentage used for collision avoidance if enabled via 506 * {@link #setUseCollisionAvoidance(boolean)} 507 */ 508 public void setCollisionAvoidancePercent(double collisionAvoidancePercent) { 509 this.collisionAvoidanceFactor = collisionAvoidancePercent * 0.01d; 510 } 511 512 public double getCollisionAvoidanceFactor() { 513 return collisionAvoidanceFactor; 514 } 515 516 /** 517 * Sets the factor used for collision avoidance if enabled via 518 * {@link #setUseCollisionAvoidance(boolean)} 519 */ 520 public void setCollisionAvoidanceFactor(double collisionAvoidanceFactor) { 521 this.collisionAvoidanceFactor = collisionAvoidanceFactor; 522 } 523 524 public int getMaximumRedeliveries() { 525 return maximumRedeliveries; 526 } 527 528 /** 529 * Sets the maximum number of times a message exchange will be redelivered. 530 * Setting a negative value will retry forever. 531 */ 532 public void setMaximumRedeliveries(int maximumRedeliveries) { 533 this.maximumRedeliveries = maximumRedeliveries; 534 } 535 536 public long getMaximumRedeliveryDelay() { 537 return maximumRedeliveryDelay; 538 } 539 540 /** 541 * Sets the maximum redelivery delay. 542 * Use -1 if you wish to have no maximum 543 */ 544 public void setMaximumRedeliveryDelay(long maximumRedeliveryDelay) { 545 this.maximumRedeliveryDelay = maximumRedeliveryDelay; 546 } 547 548 public boolean isUseCollisionAvoidance() { 549 return useCollisionAvoidance; 550 } 551 552 /** 553 * Enables/disables collision avoidance which adds some randomization to the 554 * backoff timings to reduce contention probability 555 */ 556 public void setUseCollisionAvoidance(boolean useCollisionAvoidance) { 557 this.useCollisionAvoidance = useCollisionAvoidance; 558 } 559 560 public boolean isUseExponentialBackOff() { 561 return useExponentialBackOff; 562 } 563 564 /** 565 * Enables/disables exponential backoff using the 566 * {@link #getBackOffMultiplier()} to increase the time between retries 567 */ 568 public void setUseExponentialBackOff(boolean useExponentialBackOff) { 569 this.useExponentialBackOff = useExponentialBackOff; 570 } 571 572 protected static synchronized Random getRandomNumberGenerator() { 573 if (randomNumberGenerator == null) { 574 randomNumberGenerator = new Random(); 575 } 576 return randomNumberGenerator; 577 } 578 579 /** 580 * Sets the logging level to use for log messages when retries have been exhausted. 581 */ 582 public void setRetriesExhaustedLogLevel(LoggingLevel retriesExhaustedLogLevel) { 583 this.retriesExhaustedLogLevel = retriesExhaustedLogLevel; 584 } 585 586 public LoggingLevel getRetriesExhaustedLogLevel() { 587 return retriesExhaustedLogLevel; 588 } 589 590 /** 591 * Sets the logging level to use for log messages when retries are attempted. 592 */ 593 public void setRetryAttemptedLogLevel(LoggingLevel retryAttemptedLogLevel) { 594 this.retryAttemptedLogLevel = retryAttemptedLogLevel; 595 } 596 597 public LoggingLevel getRetryAttemptedLogLevel() { 598 return retryAttemptedLogLevel; 599 } 600 601 public String getDelayPattern() { 602 return delayPattern; 603 } 604 605 /** 606 * Sets an optional delay pattern to use instead of fixed delay. 607 */ 608 public void setDelayPattern(String delayPattern) { 609 this.delayPattern = delayPattern; 610 } 611 612 public boolean isLogStackTrace() { 613 return logStackTrace; 614 } 615 616 /** 617 * Sets whether stack traces should be logged or not 618 */ 619 public void setLogStackTrace(boolean logStackTrace) { 620 this.logStackTrace = logStackTrace; 621 } 622 623 public boolean isLogRetryStackTrace() { 624 return logRetryStackTrace; 625 } 626 627 /** 628 * Sets whether stack traces should be logged or not 629 */ 630 public void setLogRetryStackTrace(boolean logRetryStackTrace) { 631 this.logRetryStackTrace = logRetryStackTrace; 632 } 633 634 public boolean isLogHandled() { 635 return logHandled; 636 } 637 638 /** 639 * Sets whether errors should be logged even if its handled 640 */ 641 public void setLogHandled(boolean logHandled) { 642 this.logHandled = logHandled; 643 } 644 645 public boolean isLogNewException() { 646 return logNewException; 647 } 648 649 /** 650 * Sets whether errors should be logged when a new exception occurred during handling a previous exception 651 */ 652 public void setLogNewException(boolean logNewException) { 653 this.logNewException = logNewException; 654 } 655 656 public boolean isLogContinued() { 657 return logContinued; 658 } 659 660 /** 661 * Sets whether errors should be logged even if its continued 662 */ 663 public void setLogContinued(boolean logContinued) { 664 this.logContinued = logContinued; 665 } 666 667 public boolean isLogRetryAttempted() { 668 return logRetryAttempted; 669 } 670 671 /** 672 * Sets whether retry attempts should be logged or not 673 */ 674 public void setLogRetryAttempted(boolean logRetryAttempted) { 675 this.logRetryAttempted = logRetryAttempted; 676 } 677 678 public boolean isLogExhausted() { 679 return logExhausted; 680 } 681 682 /** 683 * Sets whether exhausted exceptions should be logged or not 684 */ 685 public void setLogExhausted(boolean logExhausted) { 686 this.logExhausted = logExhausted; 687 } 688 689 public boolean isLogExhaustedMessageHistory() { 690 // should default be enabled 691 return logExhaustedMessageHistory == null || logExhaustedMessageHistory; 692 } 693 694 /** 695 * Whether the option logExhaustedMessageHistory has been configured or not 696 * 697 * @return <tt>null</tt> if not configured, or the configured value as true or false 698 * @see #isLogExhaustedMessageHistory() 699 */ 700 public Boolean getLogExhaustedMessageHistory() { 701 return logExhaustedMessageHistory; 702 } 703 704 /** 705 * Sets whether exhausted exceptions should be logged with message history included. 706 */ 707 public void setLogExhaustedMessageHistory(boolean logExhaustedMessageHistory) { 708 this.logExhaustedMessageHistory = logExhaustedMessageHistory; 709 } 710 711 public boolean isAsyncDelayedRedelivery() { 712 return asyncDelayedRedelivery; 713 } 714 715 /** 716 * Sets whether asynchronous delayed redelivery is allowed. 717 * <p/> 718 * This is disabled by default. 719 * <p/> 720 * When enabled it allows Camel to schedule a future task for delayed 721 * redelivery which prevents current thread from blocking while waiting. 722 * <p/> 723 * Exchange which is transacted will however always use synchronous delayed redelivery 724 * because the transaction must execute in the same thread context. 725 * 726 * @param asyncDelayedRedelivery whether asynchronous delayed redelivery is allowed 727 */ 728 public void setAsyncDelayedRedelivery(boolean asyncDelayedRedelivery) { 729 this.asyncDelayedRedelivery = asyncDelayedRedelivery; 730 } 731 732 public boolean isAllowRedeliveryWhileStopping() { 733 return allowRedeliveryWhileStopping; 734 } 735 736 /** 737 * Controls whether to allow redelivery while stopping/shutting down a route that uses error handling. 738 * 739 * @param allowRedeliveryWhileStopping <tt>true</tt> to allow redelivery, <tt>false</tt> to reject redeliveries 740 */ 741 public void setAllowRedeliveryWhileStopping(boolean allowRedeliveryWhileStopping) { 742 this.allowRedeliveryWhileStopping = allowRedeliveryWhileStopping; 743 } 744 745 public String getExchangeFormatterRef() { 746 return exchangeFormatterRef; 747 } 748 749 /** 750 * Sets the reference of the instance of {@link org.apache.camel.spi.ExchangeFormatter} to generate the log message from exchange. 751 */ 752 public void setExchangeFormatterRef(String exchangeFormatterRef) { 753 this.exchangeFormatterRef = exchangeFormatterRef; 754 } 755 756}