Наш код:
public class FuseTemplateServiceRoute extends RouteBuilder {
private static final Logger LOG = Logger.getLogger("APPL." +
FuseTemplateServiceRoute.class.getName());
private static final int MAXIMUM_FAILOVER_ATTEMPTS = NUM_OF_SERVERS - 1;
private static final boolean INHERIT_ERROR_HANDLER = Boolean.TRUE;
private static final boolean ROUND_ROBIN = Boolean.TRUE;
private static final boolean STICKY = Boolean.FALSE;
@Override
public void configure() throws Exception {
for (int i = 0; i < 100; i++) {
System.out.println();
}
AtomicInteger counter = new AtomicInteger();
List<Endpoint> cxfEndpoints = URLFactory.getUrls(SERVER_PREFIX, NUM_OF_SERVERS, SERVICE_PATH).stream()//
.map(serviceAddress -> createCxfEndpoint(serviceAddress, counter))//
.collect(Collectors.toList());
onException(Exception.class)//
.handled(true)//
.process(new GenericExceptionHandler(LOG));
onException(SystemException.class)//
.handled(true)//
.process(new SystemExceptionHandler(LOG));
onException(BusinessException.class)//
.handled(true)//
.process(new BusinessExceptionHandler(LOG));
from("direct:start")//
.transacted()//
.process(new OpNameParamExtractor())//
.loadBalance()//
.failover(MAXIMUM_FAILOVER_ATTEMPTS, INHERIT_ERROR_HANDLER, ROUND_ROBIN, STICKY, SystemException.class)//
.to(cxfEndpoints);
}
private CxfEndpoint createCxfEndpoint(String serviceAddress, AtomicInteger counter) {
CxfEndpoint cxfEndpointOut = new CxfEndpoint(serviceAddress, new CxfComponent(getContext()));
cxfEndpointOut.setServiceClass(FuseTemplateFuseServicePortType.class);
cxfEndpointOut.setBeanId("FuseTemplateServiceOutbound_" +
counter.incrementAndGet());
cxfEndpointOut.setLoggingFeatureEnabled(true);
return cxfEndpointOut;
}
GenericExceptionHander:
public class GenericExceptionHandler implements Processor {
@Override
public void process(Exchange exchange) throws Exception {
Exception exception = exchange.getProperty(Exchange.EXCEPTION_CAUGHT, Exception.class);
throw new SystemException("Technischer Fehler: " + exception.getMessage(), FaultTypeHelper.createSystemFault(500));
}
}
SystemExceptionHandler:
public class SystemExceptionHandler implements Processor {
private final Logger logger;
public SystemExceptionHandler(Logger logger) {
this.logger = logger;
}
public void process(Exchange exchange) throws Exception {
SystemException exception =
exchange.getProperty(Exchange.EXCEPTION_CAUGHT, SystemException.class);
String errorMessage = "SystemException aus dem Backend erkannt, Message: [" + exception.getMessage() + "] mit ErrorCode: [" + exception.getErrorCode() + "].";
logger.error(errorMessage);
throw exception;
}
}
что мы хотим достичь:
наш потребитель услуги должен получить только:
BusinessException для невосстановимых ситуаций - только выбрасывается серверной реализацией Webservice
Системные исключения для восстанавливаемых ситуаций
- выдается серверной реализацией WebService и
- сам маршрут в случае любого другого внутреннего исключения (например, NullPointerException) - сопоставляется с SystemException в маршруте
У нас есть обработка SystemException по причине отработки отказа - все доступные серверные службы должны быть опробованы до отказа.
ПРОБЛЕМА:
созданный маршрут SystemException, отображенный от имени упомянутого исключения NullPointerException, перехватывается маршрутом - и все узлы пробуются снова, хотя они определенно потерпят неудачу снова.
Есть ли способ заставить верблюда различать маршрутные Исключения и Исключения, происходящие из бэкэнда?
Другими словами - запретить Camel обрабатывать исключения на основе маршрутов?