Apache Camel: избегайте обработки исключений созданных маршрутов с помощью CXF WebServices - PullRequest
0 голосов
/ 05 сентября 2018

Наш код:

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;
}
}

что мы хотим достичь:

наш потребитель услуги должен получить только:

  1. BusinessException для невосстановимых ситуаций - только выбрасывается серверной реализацией Webservice

  2. Системные исключения для восстанавливаемых ситуаций

    • выдается серверной реализацией WebService и
    • сам маршрут в случае любого другого внутреннего исключения (например, NullPointerException) - сопоставляется с SystemException в маршруте

У нас есть обработка SystemException по причине отработки отказа - все доступные серверные службы должны быть опробованы до отказа.

ПРОБЛЕМА:

созданный маршрут SystemException, отображенный от имени упомянутого исключения NullPointerException, перехватывается маршрутом - и все узлы пробуются снова, хотя они определенно потерпят неудачу снова.

Есть ли способ заставить верблюда различать маршрутные Исключения и Исключения, происходящие из бэкэнда? Другими словами - запретить Camel обрабатывать исключения на основе маршрутов?

...