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.builder;
018
019import java.util.concurrent.ScheduledExecutorService;
020
021import org.apache.camel.CamelContext;
022import org.apache.camel.Endpoint;
023import org.apache.camel.Expression;
024import org.apache.camel.LoggingLevel;
025import org.apache.camel.Predicate;
026import org.apache.camel.Processor;
027import org.apache.camel.processor.errorhandler.DefaultErrorHandler;
028import org.apache.camel.processor.errorhandler.RedeliveryPolicy;
029import org.apache.camel.spi.CamelLogger;
030import org.apache.camel.spi.ExecutorServiceManager;
031import org.apache.camel.spi.Language;
032import org.apache.camel.spi.RouteContext;
033import org.apache.camel.spi.ThreadPoolProfile;
034import org.apache.camel.support.ExpressionToPredicateAdapter;
035import org.slf4j.LoggerFactory;
036
037/**
038 * The default error handler builder.
039 */
040public class DefaultErrorHandlerBuilder extends ErrorHandlerBuilderSupport {
041
042    protected CamelLogger logger;
043    protected RedeliveryPolicy redeliveryPolicy;
044    protected Processor onRedelivery;
045    protected Predicate retryWhile;
046    protected String retryWhileRef;
047    protected Processor failureProcessor;
048    protected Endpoint deadLetter;
049    protected String deadLetterUri;
050    protected boolean deadLetterHandleNewException = true;
051    protected boolean useOriginalMessage;
052    protected boolean useOriginalBody;
053    protected boolean asyncDelayedRedelivery;
054    protected String executorServiceRef;
055    protected ScheduledExecutorService executorService;
056    protected Processor onPrepareFailure;
057    protected Processor onExceptionOccurred;
058
059    public DefaultErrorHandlerBuilder() {
060    }
061
062    @Override
063    public Processor createErrorHandler(RouteContext routeContext, Processor processor) throws Exception {
064        DefaultErrorHandler answer = new DefaultErrorHandler(routeContext.getCamelContext(), processor, getLogger(), getOnRedelivery(), getRedeliveryPolicy(),
065                                                             getExceptionPolicyStrategy(), getRetryWhilePolicy(routeContext.getCamelContext()),
066                                                             getExecutorService(routeContext.getCamelContext()), getOnPrepareFailure(), getOnExceptionOccurred());
067        // configure error handler before we can use it
068        configure(routeContext, answer);
069        return answer;
070    }
071
072    @Override
073    public boolean supportTransacted() {
074        return false;
075    }
076
077    @Override
078    public ErrorHandlerBuilder cloneBuilder() {
079        DefaultErrorHandlerBuilder answer = new DefaultErrorHandlerBuilder();
080        cloneBuilder(answer);
081        return answer;
082    }
083
084    protected void cloneBuilder(DefaultErrorHandlerBuilder other) {
085        super.cloneBuilder(other);
086
087        if (logger != null) {
088            other.setLogger(logger);
089        }
090        if (redeliveryPolicy != null) {
091            other.setRedeliveryPolicy(redeliveryPolicy.copy());
092        }
093        if (onRedelivery != null) {
094            other.setOnRedelivery(onRedelivery);
095        }
096        if (retryWhile != null) {
097            other.setRetryWhile(retryWhile);
098        }
099        if (retryWhileRef != null) {
100            other.setRetryWhileRef(retryWhileRef);
101        }
102        if (failureProcessor != null) {
103            other.setFailureProcessor(failureProcessor);
104        }
105        if (deadLetter != null) {
106            other.setDeadLetter(deadLetter);
107        }
108        if (deadLetterUri != null) {
109            other.setDeadLetterUri(deadLetterUri);
110        }
111        if (onPrepareFailure != null) {
112            other.setOnPrepareFailure(onPrepareFailure);
113        }
114        if (onExceptionOccurred != null) {
115            other.setOnExceptionOccurred(onExceptionOccurred);
116        }
117        other.setDeadLetterHandleNewException(deadLetterHandleNewException);
118        other.setUseOriginalMessage(useOriginalMessage);
119        other.setUseOriginalBody(useOriginalBody);
120        other.setAsyncDelayedRedelivery(asyncDelayedRedelivery);
121        other.setExecutorServiceRef(executorServiceRef);
122    }
123
124    // Builder methods
125    // -------------------------------------------------------------------------
126    public DefaultErrorHandlerBuilder backOffMultiplier(double backOffMultiplier) {
127        getRedeliveryPolicy().backOffMultiplier(backOffMultiplier);
128        return this;
129    }
130
131    public DefaultErrorHandlerBuilder collisionAvoidancePercent(double collisionAvoidancePercent) {
132        getRedeliveryPolicy().collisionAvoidancePercent(collisionAvoidancePercent);
133        return this;
134    }
135
136    public DefaultErrorHandlerBuilder redeliveryDelay(long delay) {
137        getRedeliveryPolicy().redeliveryDelay(delay);
138        return this;
139    }
140
141    public DefaultErrorHandlerBuilder delayPattern(String delayPattern) {
142        getRedeliveryPolicy().delayPattern(delayPattern);
143        return this;
144    }
145
146    public DefaultErrorHandlerBuilder maximumRedeliveries(int maximumRedeliveries) {
147        getRedeliveryPolicy().maximumRedeliveries(maximumRedeliveries);
148        return this;
149    }
150
151    public DefaultErrorHandlerBuilder disableRedelivery() {
152        getRedeliveryPolicy().maximumRedeliveries(0);
153        return this;
154    }
155
156    public DefaultErrorHandlerBuilder maximumRedeliveryDelay(long maximumRedeliveryDelay) {
157        getRedeliveryPolicy().maximumRedeliveryDelay(maximumRedeliveryDelay);
158        return this;
159    }
160
161    public DefaultErrorHandlerBuilder useCollisionAvoidance() {
162        getRedeliveryPolicy().useCollisionAvoidance();
163        return this;
164    }
165
166    public DefaultErrorHandlerBuilder useExponentialBackOff() {
167        getRedeliveryPolicy().useExponentialBackOff();
168        return this;
169    }
170
171    public DefaultErrorHandlerBuilder retriesExhaustedLogLevel(LoggingLevel retriesExhaustedLogLevel) {
172        getRedeliveryPolicy().setRetriesExhaustedLogLevel(retriesExhaustedLogLevel);
173        return this;
174    }
175
176    public DefaultErrorHandlerBuilder retryAttemptedLogLevel(LoggingLevel retryAttemptedLogLevel) {
177        getRedeliveryPolicy().setRetryAttemptedLogLevel(retryAttemptedLogLevel);
178        return this;
179    }
180
181    public DefaultErrorHandlerBuilder retryAttemptedLogInterval(int retryAttemptedLogInterval) {
182        getRedeliveryPolicy().setRetryAttemptedLogInterval(retryAttemptedLogInterval);
183        return this;
184    }
185
186    public DefaultErrorHandlerBuilder logStackTrace(boolean logStackTrace) {
187        getRedeliveryPolicy().setLogStackTrace(logStackTrace);
188        return this;
189    }
190
191    public DefaultErrorHandlerBuilder logRetryStackTrace(boolean logRetryStackTrace) {
192        getRedeliveryPolicy().setLogRetryStackTrace(logRetryStackTrace);
193        return this;
194    }
195
196    public DefaultErrorHandlerBuilder logHandled(boolean logHandled) {
197        getRedeliveryPolicy().setLogHandled(logHandled);
198        return this;
199    }
200
201    public DefaultErrorHandlerBuilder logNewException(boolean logNewException) {
202        getRedeliveryPolicy().setLogNewException(logNewException);
203        return this;
204    }
205
206    public DefaultErrorHandlerBuilder logExhausted(boolean logExhausted) {
207        getRedeliveryPolicy().setLogExhausted(logExhausted);
208        return this;
209    }
210
211    public DefaultErrorHandlerBuilder logRetryAttempted(boolean logRetryAttempted) {
212        getRedeliveryPolicy().setLogRetryAttempted(logRetryAttempted);
213        return this;
214    }
215
216    public DefaultErrorHandlerBuilder logExhaustedMessageHistory(boolean logExhaustedMessageHistory) {
217        getRedeliveryPolicy().setLogExhaustedMessageHistory(logExhaustedMessageHistory);
218        return this;
219    }
220
221    public DefaultErrorHandlerBuilder logExhaustedMessageBody(boolean logExhaustedMessageBody) {
222        getRedeliveryPolicy().setLogExhaustedMessageBody(logExhaustedMessageBody);
223        return this;
224    }
225
226    public DefaultErrorHandlerBuilder exchangeFormatterRef(String exchangeFormatterRef) {
227        getRedeliveryPolicy().setExchangeFormatterRef(exchangeFormatterRef);
228        return this;
229    }
230
231    /**
232     * Will allow asynchronous delayed redeliveries. The route, in particular
233     * the consumer's component, must support the Asynchronous Routing Engine
234     * (e.g. seda)
235     *
236     * @see RedeliveryPolicy#setAsyncDelayedRedelivery(boolean)
237     * @return the builder
238     */
239    public DefaultErrorHandlerBuilder asyncDelayedRedelivery() {
240        getRedeliveryPolicy().setAsyncDelayedRedelivery(true);
241        return this;
242    }
243
244    /**
245     * Controls whether to allow redelivery while stopping/shutting down a route
246     * that uses error handling.
247     *
248     * @param allowRedeliveryWhileStopping <tt>true</tt> to allow redelivery,
249     *            <tt>false</tt> to reject redeliveries
250     * @return the builder
251     */
252    public DefaultErrorHandlerBuilder allowRedeliveryWhileStopping(boolean allowRedeliveryWhileStopping) {
253        getRedeliveryPolicy().setAllowRedeliveryWhileStopping(allowRedeliveryWhileStopping);
254        return this;
255    }
256
257    /**
258     * Sets a reference to a thread pool to be used for redelivery.
259     *
260     * @param ref reference to a scheduled thread pool
261     * @return the builder.
262     */
263    public DefaultErrorHandlerBuilder executorServiceRef(String ref) {
264        setExecutorServiceRef(ref);
265        return this;
266    }
267
268    /**
269     * Sets the logger used for caught exceptions
270     *
271     * @param logger the logger
272     * @return the builder
273     */
274    public DefaultErrorHandlerBuilder logger(CamelLogger logger) {
275        setLogger(logger);
276        return this;
277    }
278
279    /**
280     * Sets the logging level of exceptions caught
281     *
282     * @param level the logging level
283     * @return the builder
284     */
285    public DefaultErrorHandlerBuilder loggingLevel(LoggingLevel level) {
286        getLogger().setLevel(level);
287        return this;
288    }
289
290    /**
291     * Sets the log used for caught exceptions
292     *
293     * @param log the logger
294     * @return the builder
295     */
296    public DefaultErrorHandlerBuilder log(org.slf4j.Logger log) {
297        getLogger().setLog(log);
298        return this;
299    }
300
301    /**
302     * Sets the log used for caught exceptions
303     *
304     * @param log the log name
305     * @return the builder
306     */
307    public DefaultErrorHandlerBuilder log(String log) {
308        return log(LoggerFactory.getLogger(log));
309    }
310
311    /**
312     * Sets the log used for caught exceptions
313     *
314     * @param log the log class
315     * @return the builder
316     */
317    public DefaultErrorHandlerBuilder log(Class<?> log) {
318        return log(LoggerFactory.getLogger(log));
319    }
320
321    /**
322     * Sets a processor that should be processed <b>before</b> a redelivery
323     * attempt.
324     * <p/>
325     * Can be used to change the {@link org.apache.camel.Exchange} <b>before</b>
326     * its being redelivered.
327     *
328     * @param processor the processor
329     * @return the builder
330     */
331    public DefaultErrorHandlerBuilder onRedelivery(Processor processor) {
332        setOnRedelivery(processor);
333        return this;
334    }
335
336    /**
337     * Sets the retry while expression.
338     * <p/>
339     * Will continue retrying until expression evaluates to <tt>false</tt>.
340     *
341     * @param retryWhile expression that determines when to stop retrying
342     * @return the builder
343     */
344    public DefaultErrorHandlerBuilder retryWhile(Expression retryWhile) {
345        setRetryWhile(ExpressionToPredicateAdapter.toPredicate(retryWhile));
346        return this;
347    }
348
349    /**
350     * Will use the original input {@link org.apache.camel.Message} (original
351     * body and headers) when an {@link org.apache.camel.Exchange} is moved to
352     * the dead letter queue.
353     * <p/>
354     * <b>Notice:</b> this only applies when all redeliveries attempt have
355     * failed and the {@link org.apache.camel.Exchange} is doomed for failure.
356     * <br/>
357     * Instead of using the current inprogress {@link org.apache.camel.Exchange}
358     * IN message we use the original IN message instead. This allows you to
359     * store the original input in the dead letter queue instead of the
360     * inprogress snapshot of the IN message. For instance if you route
361     * transform the IN body during routing and then failed. With the original
362     * exchange store in the dead letter queue it might be easier to manually re
363     * submit the {@link org.apache.camel.Exchange} again as the IN message is
364     * the same as when Camel received it. So you should be able to send the
365     * {@link org.apache.camel.Exchange} to the same input.
366     * <p/>
367     * The difference between useOriginalMessage and useOriginalBody is that the
368     * former includes both the original body and headers, where as the latter
369     * only includes the original body. You can use the latter to enrich the
370     * message with custom headers and include the original message body. The
371     * former wont let you do this, as its using the original message body and
372     * headers as they are. You cannot enable both useOriginalMessage and
373     * useOriginalBody.
374     * <p/>
375     * <b>Important:</b> The original input means the input message that are
376     * bounded by the current {@link org.apache.camel.spi.UnitOfWork}. An unit
377     * of work typically spans one route, or multiple routes if they are
378     * connected using internal endpoints such as direct or seda. When messages
379     * is passed via external endpoints such as JMS or HTTP then the consumer
380     * will create a new unit of work, with the message it received as input as
381     * the original input. Also some EIP patterns such as splitter, multicast,
382     * will create a new unit of work boundary for the messages in their
383     * sub-route (eg the splitted message); however these EIPs have an option
384     * named <tt>shareUnitOfWork</tt> which allows to combine with the parent
385     * unit of work in regard to error handling and therefore use the parent
386     * original message.
387     * <p/>
388     * By default this feature is off.
389     *
390     * @return the builder
391     * @see #useOriginalBody()
392     */
393    public DefaultErrorHandlerBuilder useOriginalMessage() {
394        setUseOriginalMessage(true);
395        return this;
396    }
397
398    /**
399     * Will use the original input {@link org.apache.camel.Message} body
400     * (original body only) when an {@link org.apache.camel.Exchange} is moved
401     * to the dead letter queue.
402     * <p/>
403     * <b>Notice:</b> this only applies when all redeliveries attempt have
404     * failed and the {@link org.apache.camel.Exchange} is doomed for failure.
405     * <br/>
406     * Instead of using the current inprogress {@link org.apache.camel.Exchange}
407     * IN message we use the original IN message instead. This allows you to
408     * store the original input in the dead letter queue instead of the
409     * inprogress snapshot of the IN message. For instance if you route
410     * transform the IN body during routing and then failed. With the original
411     * exchange store in the dead letter queue it might be easier to manually re
412     * submit the {@link org.apache.camel.Exchange} again as the IN message is
413     * the same as when Camel received it. So you should be able to send the
414     * {@link org.apache.camel.Exchange} to the same input.
415     * <p/>
416     * The difference between useOriginalMessage and useOriginalBody is that the
417     * former includes both the original body and headers, where as the latter
418     * only includes the original body. You can use the latter to enrich the
419     * message with custom headers and include the original message body. The
420     * former wont let you do this, as its using the original message body and
421     * headers as they are. You cannot enable both useOriginalMessage and
422     * useOriginalBody.
423     * <p/>
424     * <b>Important:</b> The original input means the input message that are
425     * bounded by the current {@link org.apache.camel.spi.UnitOfWork}. An unit
426     * of work typically spans one route, or multiple routes if they are
427     * connected using internal endpoints such as direct or seda. When messages
428     * is passed via external endpoints such as JMS or HTTP then the consumer
429     * will create a new unit of work, with the message it received as input as
430     * the original input. Also some EIP patterns such as splitter, multicast,
431     * will create a new unit of work boundary for the messages in their
432     * sub-route (eg the splitted message); however these EIPs have an option
433     * named <tt>shareUnitOfWork</tt> which allows to combine with the parent
434     * unit of work in regard to error handling and therefore use the parent
435     * original message.
436     * <p/>
437     * By default this feature is off.
438     *
439     * @return the builder
440     * @see #useOriginalMessage()
441     */
442    public DefaultErrorHandlerBuilder useOriginalBody() {
443        setUseOriginalBody(true);
444        return this;
445    }
446
447    /**
448     * Whether the dead letter channel should handle (and ignore) any new
449     * exception that may been thrown during sending the message to the dead
450     * letter endpoint.
451     * <p/>
452     * The default value is <tt>true</tt> which means any such kind of exception
453     * is handled and ignored. Set this to <tt>false</tt> to let the exception
454     * be propagated back on the {@link org.apache.camel.Exchange}. This can be
455     * used in situations where you use transactions, and want to use Camel's
456     * dead letter channel to deal with exceptions during routing, but if the
457     * dead letter channel itself fails because of a new exception being thrown,
458     * then by setting this to <tt>false</tt> the new exceptions is propagated
459     * back and set on the {@link org.apache.camel.Exchange}, which allows the
460     * transaction to detect the exception, and rollback.
461     *
462     * @param handleNewException <tt>true</tt> to handle (and ignore),
463     *            <tt>false</tt> to catch and propagated the exception on the
464     *            {@link org.apache.camel.Exchange}
465     * @return the builder
466     */
467    public DefaultErrorHandlerBuilder deadLetterHandleNewException(boolean handleNewException) {
468        setDeadLetterHandleNewException(handleNewException);
469        return this;
470    }
471
472    /**
473     * Sets a custom {@link org.apache.camel.Processor} to prepare the
474     * {@link org.apache.camel.Exchange} before handled by the failure processor
475     * / dead letter channel. This allows for example to enrich the message
476     * before sending to a dead letter queue.
477     *
478     * @param processor the processor
479     * @return the builder
480     */
481    public DefaultErrorHandlerBuilder onPrepareFailure(Processor processor) {
482        setOnPrepareFailure(processor);
483        return this;
484    }
485
486    /**
487     * Sets a custom {@link org.apache.camel.Processor} to process the
488     * {@link org.apache.camel.Exchange} just after an exception was thrown.
489     * This allows to execute the processor at the same time the exception was
490     * thrown.
491     * <p/>
492     * Important: Any exception thrown from this processor will be ignored.
493     *
494     * @param processor the processor
495     * @return the builder
496     */
497    public DefaultErrorHandlerBuilder onExceptionOccurred(Processor processor) {
498        setOnExceptionOccurred(processor);
499        return this;
500    }
501
502    // Properties
503    // -------------------------------------------------------------------------
504
505    public Processor getFailureProcessor() {
506        return failureProcessor;
507    }
508
509    public void setFailureProcessor(Processor failureProcessor) {
510        this.failureProcessor = failureProcessor;
511    }
512
513    public RedeliveryPolicy getRedeliveryPolicy() {
514        if (redeliveryPolicy == null) {
515            redeliveryPolicy = createRedeliveryPolicy();
516        }
517        return redeliveryPolicy;
518    }
519
520    /**
521     * Sets the redelivery policy
522     */
523    public void setRedeliveryPolicy(RedeliveryPolicy redeliveryPolicy) {
524        this.redeliveryPolicy = redeliveryPolicy;
525    }
526
527    public CamelLogger getLogger() {
528        if (logger == null) {
529            logger = createLogger();
530        }
531        return logger;
532    }
533
534    public void setLogger(CamelLogger logger) {
535        this.logger = logger;
536    }
537
538    public Processor getOnRedelivery() {
539        return onRedelivery;
540    }
541
542    public void setOnRedelivery(Processor onRedelivery) {
543        this.onRedelivery = onRedelivery;
544    }
545
546    public Predicate getRetryWhilePolicy(CamelContext context) {
547        Predicate answer = getRetryWhile();
548
549        if (getRetryWhileRef() != null) {
550            // its a bean expression
551            Language bean = context.resolveLanguage("bean");
552            answer = bean.createPredicate(getRetryWhileRef());
553        }
554
555        return answer;
556    }
557
558    public Predicate getRetryWhile() {
559        return retryWhile;
560    }
561
562    public void setRetryWhile(Predicate retryWhile) {
563        this.retryWhile = retryWhile;
564    }
565
566    public String getRetryWhileRef() {
567        return retryWhileRef;
568    }
569
570    public void setRetryWhileRef(String retryWhileRef) {
571        this.retryWhileRef = retryWhileRef;
572    }
573
574    public String getDeadLetterUri() {
575        return deadLetterUri;
576    }
577
578    public void setDeadLetterUri(String deadLetterUri) {
579        this.deadLetter = null;
580        this.deadLetterUri = deadLetterUri;
581    }
582
583    public Endpoint getDeadLetter() {
584        return deadLetter;
585    }
586
587    public void setDeadLetter(Endpoint deadLetter) {
588        this.deadLetter = deadLetter;
589        this.deadLetterUri = deadLetter.getEndpointUri();
590    }
591
592    public boolean isDeadLetterHandleNewException() {
593        return deadLetterHandleNewException;
594    }
595
596    public void setDeadLetterHandleNewException(boolean deadLetterHandleNewException) {
597        this.deadLetterHandleNewException = deadLetterHandleNewException;
598    }
599
600    public boolean isUseOriginalMessage() {
601        return useOriginalMessage;
602    }
603
604    public void setUseOriginalMessage(boolean useOriginalMessage) {
605        this.useOriginalMessage = useOriginalMessage;
606    }
607
608    public boolean isUseOriginalBody() {
609        return useOriginalBody;
610    }
611
612    public void setUseOriginalBody(boolean useOriginalBody) {
613        this.useOriginalBody = useOriginalBody;
614    }
615
616    public boolean isAsyncDelayedRedelivery() {
617        return asyncDelayedRedelivery;
618    }
619
620    public void setAsyncDelayedRedelivery(boolean asyncDelayedRedelivery) {
621        this.asyncDelayedRedelivery = asyncDelayedRedelivery;
622    }
623
624    public ScheduledExecutorService getExecutorService() {
625        return executorService;
626    }
627
628    public void setExecutorService(ScheduledExecutorService executorService) {
629        this.executorService = executorService;
630    }
631
632    public String getExecutorServiceRef() {
633        return executorServiceRef;
634    }
635
636    public void setExecutorServiceRef(String executorServiceRef) {
637        this.executorServiceRef = executorServiceRef;
638    }
639
640    public Processor getOnPrepareFailure() {
641        return onPrepareFailure;
642    }
643
644    public void setOnPrepareFailure(Processor onPrepareFailure) {
645        this.onPrepareFailure = onPrepareFailure;
646    }
647
648    public Processor getOnExceptionOccurred() {
649        return onExceptionOccurred;
650    }
651
652    public void setOnExceptionOccurred(Processor onExceptionOccurred) {
653        this.onExceptionOccurred = onExceptionOccurred;
654    }
655
656    protected RedeliveryPolicy createRedeliveryPolicy() {
657        RedeliveryPolicy policy = new RedeliveryPolicy();
658        policy.disableRedelivery();
659        return policy;
660    }
661
662    protected CamelLogger createLogger() {
663        return new CamelLogger(LoggerFactory.getLogger(DefaultErrorHandler.class), LoggingLevel.ERROR);
664    }
665
666    protected synchronized ScheduledExecutorService getExecutorService(CamelContext camelContext) {
667        if (executorService == null || executorService.isShutdown()) {
668            // camel context will shutdown the executor when it shutdown so no
669            // need to shut it down when stopping
670            if (executorServiceRef != null) {
671                executorService = camelContext.getRegistry().lookupByNameAndType(executorServiceRef, ScheduledExecutorService.class);
672                if (executorService == null) {
673                    ExecutorServiceManager manager = camelContext.getExecutorServiceManager();
674                    ThreadPoolProfile profile = manager.getThreadPoolProfile(executorServiceRef);
675                    executorService = manager.newScheduledThreadPool(this, executorServiceRef, profile);
676                }
677                if (executorService == null) {
678                    throw new IllegalArgumentException("ExecutorServiceRef " + executorServiceRef + " not found in registry.");
679                }
680            } else {
681                // no explicit configured thread pool, so leave it up to the
682                // error handler to decide if it need
683                // a default thread pool from
684                // CamelContext#getErrorHandlerExecutorService
685                executorService = null;
686            }
687        }
688        return executorService;
689    }
690
691    @Override
692    public String toString() {
693        return "DefaultErrorHandlerBuilder";
694    }
695
696}