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     */
017    package org.apache.camel.builder;
018    
019    import org.apache.camel.Endpoint;
020    import org.apache.camel.Expression;
021    import org.apache.camel.LoggingLevel;
022    import org.apache.camel.Predicate;
023    import org.apache.camel.Processor;
024    import org.apache.camel.processor.DefaultErrorHandler;
025    import org.apache.camel.processor.ErrorHandlerSupport;
026    import org.apache.camel.processor.Logger;
027    import org.apache.camel.processor.RedeliveryPolicy;
028    import org.apache.camel.processor.exceptionpolicy.ExceptionPolicyStrategy;
029    import org.apache.camel.spi.RouteContext;
030    import org.apache.commons.logging.Log;
031    import org.apache.commons.logging.LogFactory;
032    import static org.apache.camel.builder.PredicateBuilder.toPredicate;
033    
034    /**
035     * The default error handler builder.
036     *
037     * @version $Revision: 20179 $
038     */
039    public class DefaultErrorHandlerBuilder extends ErrorHandlerBuilderSupport {
040    
041        protected Logger logger;
042        protected ExceptionPolicyStrategy exceptionPolicyStrategy = ErrorHandlerSupport.createDefaultExceptionPolicyStrategy();
043        protected RedeliveryPolicy redeliveryPolicy;
044        protected Processor onRedelivery;
045        protected Predicate handledPolicy;
046        protected Processor failureProcessor;
047        protected Endpoint deadLetter;
048        protected String deadLetterUri;
049        protected boolean useOriginalMessage;
050        protected boolean asyncDelayedRedelivery;
051    
052        public DefaultErrorHandlerBuilder() {
053        }
054    
055        public Processor createErrorHandler(RouteContext routeContext, Processor processor) throws Exception {
056            DefaultErrorHandler answer = new DefaultErrorHandler(routeContext.getCamelContext(), processor, getLogger(),
057                    getOnRedelivery(), getRedeliveryPolicy(), getHandledPolicy(), getExceptionPolicyStrategy());
058            // configure error handler before we can use it
059            configure(answer);
060            return answer;
061        }
062    
063        public boolean supportTransacted() {
064            return false;
065        }
066    
067    
068        // Builder methods
069        // -------------------------------------------------------------------------
070        public DefaultErrorHandlerBuilder backOffMultiplier(double backOffMultiplier) {
071            getRedeliveryPolicy().backOffMultiplier(backOffMultiplier);
072            return this;
073        }
074    
075        public DefaultErrorHandlerBuilder collisionAvoidancePercent(double collisionAvoidancePercent) {
076            getRedeliveryPolicy().collisionAvoidancePercent(collisionAvoidancePercent);
077            return this;
078        }
079    
080        @Deprecated
081        public DefaultErrorHandlerBuilder redeliverDelay(long delay) {
082            getRedeliveryPolicy().redeliveryDelay(delay);
083            return this;
084        }
085    
086        public DefaultErrorHandlerBuilder redeliveryDelay(long delay) {
087            getRedeliveryPolicy().redeliveryDelay(delay);
088            return this;
089        }
090    
091        public DefaultErrorHandlerBuilder delayPattern(String delayPattern) {
092            getRedeliveryPolicy().delayPattern(delayPattern);
093            return this;
094        }
095    
096        public DefaultErrorHandlerBuilder maximumRedeliveries(int maximumRedeliveries) {
097            getRedeliveryPolicy().maximumRedeliveries(maximumRedeliveries);
098            return this;
099        }
100    
101        public DefaultErrorHandlerBuilder disableRedelivery() {
102            getRedeliveryPolicy().maximumRedeliveries(0);
103            return this;
104        }
105    
106        public DefaultErrorHandlerBuilder maximumRedeliveryDelay(long maximumRedeliveryDelay) {
107            getRedeliveryPolicy().maximumRedeliveryDelay(maximumRedeliveryDelay);
108            return this;
109        }
110    
111        public DefaultErrorHandlerBuilder useCollisionAvoidance() {
112            getRedeliveryPolicy().useCollisionAvoidance();
113            return this;
114        }
115    
116        public DefaultErrorHandlerBuilder useExponentialBackOff() {
117            getRedeliveryPolicy().useExponentialBackOff();
118            return this;
119        }
120    
121        public DefaultErrorHandlerBuilder retriesExhaustedLogLevel(LoggingLevel retriesExhaustedLogLevel) {
122            getRedeliveryPolicy().setRetriesExhaustedLogLevel(retriesExhaustedLogLevel);
123            return this;
124        }
125    
126        public DefaultErrorHandlerBuilder retryAttemptedLogLevel(LoggingLevel retryAttemptedLogLevel) {
127            getRedeliveryPolicy().setRetryAttemptedLogLevel(retryAttemptedLogLevel);
128            return this;
129        }
130    
131        public DefaultErrorHandlerBuilder logStackTrace(boolean logStackTrace) {
132            getRedeliveryPolicy().setLogStackTrace(logStackTrace);
133            return this;
134        }
135    
136        public DefaultErrorHandlerBuilder logRetryStackTrace(boolean logRetryStackTrace) {
137            getRedeliveryPolicy().setLogRetryStackTrace(logRetryStackTrace);
138            return this;
139        }
140    
141        public DefaultErrorHandlerBuilder logHandled(boolean logHandled) {
142            getRedeliveryPolicy().setLogHandled(logHandled);
143            return this;
144        }
145    
146        public DefaultErrorHandlerBuilder logExhausted(boolean logExhausted) {
147            getRedeliveryPolicy().setLogExhausted(logExhausted);
148            return this;
149        }
150    
151        /**
152         * Will allow asynchronous delayed redeliveries.
153         *
154         * @see org.apache.camel.processor.RedeliveryPolicy#setAsyncDelayedRedelivery(boolean)
155         * @return the builder
156         */
157        public DefaultErrorHandlerBuilder asyncDelayedRedelivery() {
158            getRedeliveryPolicy().setAsyncDelayedRedelivery(true);
159            return this;
160        }
161    
162        /**
163         * Sets whether the exchange should be marked as handled or not.
164         *
165         * @param handled  handled or not
166         * @return the builder
167         */
168        @Deprecated
169        public DefaultErrorHandlerBuilder handled(boolean handled) {
170            Expression expression = ExpressionBuilder.constantExpression(Boolean.toString(handled));
171            return handled(expression);
172        }
173    
174        /**
175         * Sets whether the exchange should be marked as handled or not.
176         *
177         * @param handled  predicate that determines true or false
178         * @return the builder
179         */
180        @Deprecated
181        public DefaultErrorHandlerBuilder handled(Predicate handled) {
182            this.setHandledPolicy(handled);
183            return this;
184        }
185    
186        /**
187         * Sets whether the exchange should be marked as handled or not.
188         *
189         * @param handled  expression that determines true or false
190         * @return the builder
191         */
192        @Deprecated
193        public DefaultErrorHandlerBuilder handled(Expression handled) {
194            this.setHandledPolicy(toPredicate(handled));
195            return this;
196        }
197    
198        /**
199         * Sets the logger used for caught exceptions
200         *
201         * @param logger the logger
202         * @return the builder
203         */
204        public DefaultErrorHandlerBuilder logger(Logger logger) {
205            setLogger(logger);
206            return this;
207        }
208    
209        /**
210         * Sets the logging level of exceptions caught
211         *
212         * @param level the logging level
213         * @return the builder
214         */
215        public DefaultErrorHandlerBuilder loggingLevel(LoggingLevel level) {
216            getLogger().setLevel(level);
217            return this;
218        }
219    
220        /**
221         * Sets the log used for caught exceptions
222         *
223         * @param log the logger
224         * @return the builder
225         */
226        public DefaultErrorHandlerBuilder log(Log log) {
227            getLogger().setLog(log);
228            return this;
229        }
230    
231        /**
232         * Sets the log used for caught exceptions
233         *
234         * @param log the log name
235         * @return the builder
236         */
237        public DefaultErrorHandlerBuilder log(String log) {
238            return log(LogFactory.getLog(log));
239        }
240    
241        /**
242         * Sets the log used for caught exceptions
243         *
244         * @param log the log class
245         * @return the builder
246         */
247        public DefaultErrorHandlerBuilder log(Class<?> log) {
248            return log(LogFactory.getLog(log));
249        }
250    
251        /**
252         * Sets the exception policy to use
253         *
254         * @return the builder
255         */
256        public DefaultErrorHandlerBuilder exceptionPolicyStrategy(ExceptionPolicyStrategy exceptionPolicyStrategy) {
257            setExceptionPolicyStrategy(exceptionPolicyStrategy);
258            return this;
259        }
260    
261        /**
262         * Sets a processor that should be processed <b>before</b> a redelivey attempt.
263         * <p/>
264         * Can be used to change the {@link org.apache.camel.Exchange} <b>before</b> its being redelivered.
265         *
266         * @return the builder
267         */
268        public DefaultErrorHandlerBuilder onRedelivery(Processor processor) {
269            setOnRedelivery(processor);
270            return this;
271        }
272    
273        /**
274         * Will use the original input {@link org.apache.camel.Message} when an {@link org.apache.camel.Exchange}
275         * is moved to the dead letter queue.
276         * <p/>
277         * <b>Notice:</b> this only applies when all redeliveries attempt have failed and the {@link org.apache.camel.Exchange}
278         * is doomed for failure.
279         * <br/>
280         * Instead of using the current inprogress {@link org.apache.camel.Exchange} IN message we use the original
281         * IN message instead. This allows you to store the original input in the dead letter queue instead of the inprogress
282         * snapshot of the IN message.
283         * For instance if you route transform the IN body during routing and then failed. With the original exchange
284         * store in the dead letter queue it might be easier to manually re submit the {@link org.apache.camel.Exchange}
285         * again as the IN message is the same as when Camel received it.
286         * So you should be able to send the {@link org.apache.camel.Exchange} to the same input.
287         * <p/>
288         * By default this feature is off.
289         *
290         * @return the builder
291         */
292        public DefaultErrorHandlerBuilder useOriginalMessage() {
293            setUseOriginalMessage(true);
294            return this;
295        }
296    
297        // Properties
298        // -------------------------------------------------------------------------
299    
300        public Processor getFailureProcessor() {
301            return failureProcessor;
302        }
303    
304        public void setFailureProcessor(Processor failureProcessor) {
305            this.failureProcessor = failureProcessor;
306        }
307    
308        public RedeliveryPolicy getRedeliveryPolicy() {
309            if (redeliveryPolicy == null) {
310                redeliveryPolicy = createRedeliveryPolicy();
311            }
312            return redeliveryPolicy;
313        }
314    
315        /**
316         * Sets the redelivery policy
317         */
318        public void setRedeliveryPolicy(RedeliveryPolicy redeliveryPolicy) {
319            this.redeliveryPolicy = redeliveryPolicy;
320        }
321    
322        public Logger getLogger() {
323            if (logger == null) {
324                logger = createLogger();
325            }
326            return logger;
327        }
328    
329        public void setLogger(Logger logger) {
330            this.logger = logger;
331        }
332    
333        /**
334         * Sets the exception policy strategy to use for resolving the {@link org.apache.camel.model.OnExceptionDefinition}
335         * to use for a given thrown exception
336         */
337        public ExceptionPolicyStrategy getExceptionPolicyStrategy() {
338            return exceptionPolicyStrategy;
339        }
340    
341        public void setExceptionPolicyStrategy(ExceptionPolicyStrategy exceptionPolicyStrategy) {
342            this.exceptionPolicyStrategy = exceptionPolicyStrategy;
343        }
344    
345        public Processor getOnRedelivery() {
346            return onRedelivery;
347        }
348    
349        public void setOnRedelivery(Processor onRedelivery) {
350            this.onRedelivery = onRedelivery;
351        }
352    
353        @Deprecated
354        public Predicate getHandledPolicy() {
355            if (handledPolicy == null) {
356                handledPolicy = createHandledPolicy();
357            }
358            return handledPolicy;
359        }
360    
361        @Deprecated
362        public void setHandledPolicy(Predicate handled) {
363            this.handledPolicy = handled;
364        }
365    
366        /**
367         * Sets the handled using a boolean and thus easier to use for Spring XML configuration as well
368         */
369        @Deprecated
370        public void setHandled(boolean handled) {
371            handled(handled);
372        }
373    
374        public String getDeadLetterUri() {
375            return deadLetterUri;
376        }
377    
378        public void setDeadLetterUri(String deadLetterUri) {
379            this.deadLetter = null;
380            this.deadLetterUri = deadLetterUri;
381        }
382    
383        public Endpoint getDeadLetter() {
384            return deadLetter;
385        }
386    
387        public void setDeadLetter(Endpoint deadLetter) {
388            this.deadLetter = deadLetter;
389            this.deadLetterUri = deadLetter.getEndpointUri();
390        }
391    
392        public boolean isUseOriginalMessage() {
393            return useOriginalMessage;
394        }
395    
396        public void setUseOriginalMessage(boolean useOriginalMessage) {
397            this.useOriginalMessage = useOriginalMessage;
398        }
399    
400        public boolean isAsyncDelayedRedelivery() {
401            return asyncDelayedRedelivery;
402        }
403    
404        public void setAsyncDelayedRedelivery(boolean asyncDelayedRedelivery) {
405            this.asyncDelayedRedelivery = asyncDelayedRedelivery;
406        }
407    
408        protected Predicate createHandledPolicy() {
409            // should NOT be handled by default for default error handler
410            return PredicateBuilder.toPredicate(ExpressionBuilder.constantExpression(false));
411        }
412    
413        protected RedeliveryPolicy createRedeliveryPolicy() {
414            RedeliveryPolicy policy = new RedeliveryPolicy();
415            policy.disableRedelivery();
416            policy.setRedeliveryDelay(0);
417            return policy;
418        }
419    
420        protected Logger createLogger() {
421            return new Logger(LogFactory.getLog(DefaultErrorHandler.class), LoggingLevel.ERROR);
422        }
423    
424        @Override
425        public String toString() {
426            return "DefaultErrorHandlerBuilder";
427        }
428    
429    }