There is interface org.openhubframework.openhub.api.exception.ErrorExtEnum for defining own error catalogue that is displayed in admin GUI.
It allows consuments of your services to see possible error codes and be able to handle them.
/** * Catalog of internal error codes. * * @author Petr Juza */ @ErrorCodeCatalog("OHF") public enum InternalErrorEnum implements ErrorExtEnum { /** * unspecified error */ E100("unspecified error"), /** * the request message is not valid against to XSD schema */ E101("the request message is not valid against to XSD schema"), /** * the validation error */ E102("the validation error"), /** * I/O error during communication with target system */ E103("I/O error during communication with target system"), |
All OpenHub framework exceptions are in package org.openhubframework.openhub.api.exception:
Basic error handling concept is well-documented in Apache Camel. |
Basic algorithm of error handling is implemented in parent class of routes - org.openhubframework.openhub.api.route.AbstractBasicRoute.
If yes then next processing steps are determined according to exception/error type:
Example of error handling in communication via Web Services with external system:
private static final Class[] FATAL_EXCEPTIONS = new Class[] {AlreadyExistsException.class, ValidityMismatchException.class, ChargingKeyNotFoundException.class, NonExistingProductOfferingException.class, IllegalOperationException.class}; private static final Class[] NEXT_HANDLING_EXCEPTIONS = new Class[] {CustomerNotFoundException.class, CustomerAccountNotFoundException.class}; .doTry() .to(getBillingUri()) // explicitly converts to UTF-8 .convertBodyTo(String.class, "UTF-8") // XML -> specific payload implementation of child for error check .unmarshal(getUnmarshalDataFormat()) .doCatch(WebServiceIOException.class) .setProperty(ExceptionTranslator.EXCEPTION_ERROR_CODE, constant(ErrorEnum.E600)) .to(AsynchConstants.URI_ERROR_HANDLING) // we handle all exceptions in the same way there are two big catches here .doCatch(NEXT_HANDLING_EXCEPTIONS) .setProperty(ExceptionTranslator.EXCEPTION_ERROR_CODE, constant(ErrorEnum.E602)) .to(AsynchConstants.URI_ERROR_HANDLING) .doCatch(FATAL_EXCEPTIONS) .setProperty(ExceptionTranslator.EXCEPTION_ERROR_CODE, constant(ErrorEnum.E601)) .to(AsynchConstants.URI_ERROR_FATAL) .end(); |
If not (=message is synchronous) then error handling is redirected to URL: AsynchConstants.URI_EX_TRANSLATION and then to ExceptionTranslator. Exception is propagated back to source system.
.onException(WebServiceIOException.class) .handled(true) .setProperty(ExceptionTranslator.EXCEPTION_ERROR_CODE, constant(ErrorEnum.E600)) .process(ExceptionTranslator.getInstance()) .end() .onException(FATAL_EXCEPTIONS) .handled(true) .setProperty(ExceptionTranslator.EXCEPTION_ERROR_CODE, constant(ErrorEnum.E601)) .process(ExceptionTranslator.getInstance()) .end() .onException(NEXT_HANDLING_EXCEPTIONS) .handled(true) .setProperty(ExceptionTranslator.EXCEPTION_ERROR_CODE, constant(ErrorEnum.E602)) .process(ExceptionTranslator.getInstance()) .end() .to(getSapUri()) // explicitly converts to UTF-8 .convertBodyTo(String.class, "UTF-8") // XML -> specific payload implementation of child for error check .unmarshal(getUnmarshalDataFormat()) |
Error handling concept in described in Apache Camel where you can find more details.
In common there are two types of error handling - routes specific and global, there are two ways how to catch exceptions - with Exception Clause or with DoTry Clause.
WSDL contract allows to define exceptions (aka faults) directly in operation definition.
<wsdl:operation name="createSubscriber"> <wsdl:input message="tns:createSubscriber" name="createSubscriber"> </wsdl:input> <wsdl:output message="tns:createSubscriberResponse" name="createSubscriberResponse"> </wsdl:output> <wsdl:fault message="tns:CustomerAccountNotFoundException" name="CustomerAccountNotFoundException"> </wsdl:fault> <wsdl:fault message="tns:CustomerNotFoundException" name="CustomerNotFoundException"> </wsdl:fault> <wsdl:fault message="tns:AlreadyExistsException" name="AlreadyExistsException"> </wsdl:fault> </wsdl:operation> |
Example of fault response with exception detail:
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"> <soap:Body> <soap:Fault> <faultcode>soap:Server</faultcode> <faultstring>Bussiness violation</faultstring> <detail> <ns2:ValidityMismatch xmlns:ns2="http://ws.lbss.com/"> <message> Product offering with externalNo:-1 is not valid on date:Sat May 25 00:00:00 CEST 2013 </message> </ns2:ValidityMismatch> </detail> </soap:Fault> </soap:Body> </soap:Envelope> |
There is helper parent class AbstractSoapExceptionFilter for mapping SOAP fault exceptions (SoapFaultClientException) to internal Java exceptions from WSDL contract.
Example of CrmSoapExceptionFilter:
.onException(WebServiceIOException.class) .handled(true) .setProperty(AsynchConstants.EXCEPTION_ERROR_CODE, constant(ErrorEnum.E403)) .process(ExceptionTranslator.getInstance()) .end() .onException(SoapFaultClientException.class) .handled(true) .process(new CrmSoapExceptionFilter(false)) .end() |