Apache Camel:避免使用CXF WebServices处理路由创建的异常

时间:2018-09-05 11:58:15

标签: java exception exception-handling apache-camel

我们的代码:

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. 用于不可恢复情况的业务异常-仅由后端Web服务实现抛出

  2. 可恢复情况下的SystemException

    • 由后端WebService实现和
    • 抛出
    • 如果发生任何其他后端引发的异常(例如NullPointerException),则路由本身-映射到路由中的SystemException

出于故障转移的原因,我们准备了SystemException处理-应该在放弃之前尝试所有可用的后端服务。

问题:

代表所提到的NullPointerException映射的SystemException创建的路由被路由捕获-并且所有节点都将再次尝试,尽管它们肯定会再次失败。

是否有一种方法可以告诉骆驼区分本地路由异常和后端异常? 换句话说-防止Camel处理基于路由的异常?

0 个答案:

没有答案