Debugging Java Callouts

7 1 2,242

If you have a Java Callout policy (or you are writing one), and you are getting an error something like this:

{ "fault": { "faultstring": "flow.execution.ExecutionReturnedFailure", "detail": { "errorcode": "flow.execution.ExecutionReturnedFailure" } } }

...it often means there is an uncaught exception in your Java code.

Here are some tips that will allow you to get more visibility into your code, and where the exception is occurring.

If you have an on-prem/private cloud deployment, all your system.out.println s will go to MP logs, that is the place you will want to check, to see if your code segments are executed properly.

If you are using a public cloud deployment, or if you do not have access to the MP logs, the alternative to that is to set flow variables and check them from trace. This is the code snippet if you want to set a flow variable from your java callout:

messageContext.setVariable("some_variable", "variable_value");

Beyond that, you can handle the Exception, and set whatever you want, to flow variables, like this:

import org.apache.commons.lang.exception.ExceptionUtils;


....


try {
    // ... do things here...
}
catch (Exception e) {
    e.printStackTrace(); // goes to MP stdout, not visible in trace
    String varName = "mycallout_error";
    msgCtxt.setVariable(varName, "Exception: " + e.toString());
    varName = "mycallout_stacktrace";
    msgCtxt.setVariable(varName, "Stack: " + ExceptionUtils.getStackTrace(e));
    return ExecutionResult.ABORT;
}

This relies on the ExceptionUtils class from the Apache commons-lang library. If you use this class, you should compile the Java callout against v2.6 of the library. The Apigee Edge includes commons-lang, there is no need to upload that particular jar when you import your API Proxy.

While debugging, if you want to set you error message to the response content, you can do that too:

import org.apache.commons.lang.exception.ExceptionUtils;


....


try {
    // ... do things here...
}
catch (Exception e) {
    messageContext.getErrorMessage().setContent( "Stack: " + ExceptionUtils.getStackTrace(e)); //sets the stacktrace as the error message
    return ExecutionResult.ABORT; 
}

This will cause the stacktrace information to be returned as an error to the API caller. This is handy during development, but you will have to make sure that you are removing this logic once you move to production. You don't want your API to emit Java stacktraces in production! Something more appropriate for production might be:

import org.apache.commons.lang.exception.ExceptionUtils;


....


try {
    // ... do things here...
}
catch (Exception e) {
    messageContext.getErrorMessage().setContent( "Error during the callout");
    return ExecutionResult.ABORT; 
}
Comments
Not applicable

Hi @Sandeep Murusupalli,

I am getting the same error , I have modified the code and returning exception trace from the catch block as you suggested so ideally if there is an exception happening in the code i should get

"Stack" +"error message"

But i am not getting this i am getting only

{"fault":{"faultstring":"Failed to execute JavaCallout. null","detail":{"errorcode":"steps.javacallout.ExecutionError"}}}

in the response.

Can you suggest some pointers

Version history
Last update:
‎06-12-2015 11:36 AM
Updated by: