Search code examples
javaapache-camelspring-camelorchestration

How do I return my API exception when orchestrating with Apache Camel?


I've been using Apache Camel on a project and I need the API response I call to be returned when it throws an exception.

<route customId="true" id="restrictionsBlackList" streamCache="false">
    <from uri="direct:restrictionsBlackList" />
    <setHeader customId="true" id="StepNameDefinitionRBL" name="stepName">
        <constant>restrictionsBlackList</constant>
    </setHeader>
    <setHeader customId="true" id="MethodNameRBL" name="CamelHttpMethod">
        <constant>POST</constant>
    </setHeader>
    <doTry>
        <setProperty customId="true" id="ProspectDefinitionRBL" name="prospect">
            <jsonpath>$.request.body.prospect</jsonpath>
        </setProperty>
        <log customId="true" id="LogProspectDefinitionRBL" message="prospect ${exchangeProperty[prospect]}" />
        <setProperty customId="true" id="SearchDefinition" name="search">
            <jsonpath>$.request.body.search</jsonpath>
        </setProperty>
        <log customId="true" id="LogSearchDefinitionRBL" message="search ${exchangeProperty[search]}" />
        <setProperty customId="true" id="CompositionDefinition" name="compositions">
            <jsonpath>$.request.body.compositions</jsonpath>
        </setProperty>      
        <!-- headers -->
        <setHeader name="X-Company-Id">
            <simple>${exchangeProperty[companyId]}</simple>
        </setHeader>
        <setHeader name="X-Application-Id">
            <simple>${exchangeProperty[applicationId]}</simple>
        </setHeader>
        <to customId="true" id="URLRestrictionBlackList" uri="{{RESTRICTIONS_BLACKLIST_URL}}" />
        <doCatch>
            <exception>org.apache.camel.CamelException</exception>
            <log message="body is : ${exception.responseBody}" />
        </doCatch>      
    </doTry>
</route>

The API is returning the following message:

{
 "code": 16,
 "message": "JWT validation failed: TIME_CONSTRAINT_FAILURE",
 "details": [
  {
   "@type": "type.googleapis.com/google.rpc.DebugInfo",
   "stackEntries": [],
   "detail": "auth"
  }
 ]
}

But when I re-throw the exception, I end up with this return:

{
    "message": "{\n \"code\": 16,\n \"message\": \"JWT validation failed: TIME_CONSTRAINT_FAILURE\",\n \"details\": [\n  {\n   \"@type\": \"type.googleapis.com/google.rpc.DebugInfo\",\n   \"stackEntries\": [],\n   \"detail\": \"auth\"\n  }\n ]\n}\n",
    "errors": []
}

Solution

  • I found an alternative, since I'm using Spring Boot, I ended up choosing to add a specific error handling for CamelException and CamelExecutionException and check if their source is an HttpOperationFailedException

            @ExceptionHandler({CamelException.class, CamelExecutionException.class})
            public ResponseEntity<?> camelExchangeExceptions(CamelException ex) {
            if (ex instanceof org.apache.camel.http.common.HttpOperationFailedException) {
                org.apache.camel.http.common.HttpOperationFailedException exception = (org.apache.camel.http.common.HttpOperationFailedException) ex;
                return ResponseEntity
                        .status(exception.getStatusCode())
                        .body(stringToJsonNode(exception.getResponseBody()));
            }
    
            if (ex.getCause() instanceof org.apache.camel.http.common.HttpOperationFailedException) {
                org.apache.camel.http.common.HttpOperationFailedException exception = (org.apache.camel.http.common.HttpOperationFailedException) ex.getCause();
                return ResponseEntity
                        .status(exception.getStatusCode())
                        .body(stringToJsonNode(exception.getResponseBody()));
                    }
    
                    return ResponseEntity
                        .status(499)
                        .body(new ApiErrorResponse(ex.getMessage()));
                }