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.impl;
018
019import org.apache.camel.Exchange;
020import org.apache.camel.Processor;
021import org.apache.camel.spi.ExceptionHandler;
022import org.apache.camel.spi.UnitOfWork;
023import org.apache.camel.util.UnitOfWorkHelper;
024
025/**
026 * An {@link ExceptionHandler} that uses the {@link DefaultConsumer} to
027 * process the caused exception to send the message into the Camel routing engine
028 * which allows to let the routing engine handle the exception.
029 * <p/>
030 * An endpoint can be configured with <tt>consumer.bridgeErrorHandler=true</tt> in the URI
031 * to enable this {@link BridgeExceptionHandlerToErrorHandler} on the consumer.
032 * The consumer must extend the {@link DefaultConsumer}, to support this, if not an
033 * {@link IllegalArgumentException} is thrown upon startup.
034 * <p/>
035 * <b>Notice:</b> When using this bridging error handler, then interceptors, onCompletions
036 * does <b>not</b> apply. The {@link Exchange} is processed directly by the Camel
037 * error handler, and does not allow prior actions such as interceptors, onCompletion
038 * to take action.
039 */
040public class BridgeExceptionHandlerToErrorHandler implements ExceptionHandler {
041
042    private final LoggingExceptionHandler fallback;
043    private final DefaultConsumer consumer;
044    private final Processor bridge;
045
046    public BridgeExceptionHandlerToErrorHandler(DefaultConsumer consumer) {
047        this.consumer = consumer;
048        this.fallback = new LoggingExceptionHandler(consumer.getEndpoint().getCamelContext(), consumer.getClass());
049        this.bridge = consumer.getProcessor();
050    }
051
052    @Override
053    public void handleException(Throwable exception) {
054        handleException(null, exception);
055    }
056
057    @Override
058    public void handleException(String message, Throwable exception) {
059        handleException(message, null, exception);
060    }
061
062    @Override
063    public void handleException(String message, Exchange exchange, Throwable exception) {
064        if (exchange == null) {
065            exchange = consumer.getEndpoint().createExchange();
066        }
067
068        // set the caused exception
069        exchange.setException(exception);
070        // and the message
071        exchange.getIn().setBody(message);
072        // and mark as redelivery exhausted as we cannot do redeliveries
073        exchange.setProperty(Exchange.REDELIVERY_EXHAUSTED, Boolean.TRUE);
074
075        // wrap in UoW
076        UnitOfWork uow = null;
077        try {
078            uow = consumer.createUoW(exchange);
079            bridge.process(exchange);
080        } catch (Exception e) {
081            fallback.handleException("Error handling exception " + exception.getMessage(), exchange, e);
082        } finally {
083            UnitOfWorkHelper.doneUow(uow, exchange);
084        }
085    }
086}