When you write a JavaCallout policy, you may want to do custom error handling in your Java code. For
example, you may wish to return custom error messages and headers and/or set flow variables with
error information in the proxy flow on Apigee.
Let's walk through a simple JavaCallout policy example that illustrates basic custom error handling
patterns. The sample returns a custom error message when an exception occurs. It also places the
error stacktrace into a flow variable, which can be a handy debugging technique.
Download the project
To make things simple, you can download this project from the Apigee api-platform-samples repository on
GitHub.
In a terminal or code editor of your choice, go to the
api-platform-samples/doc-samples/java-error project.
The sample Java code
The error handling patterns are straightforward. You can set flow variables in the current
Apigee flow context with the messageContext.setVariable() method. To return custom
error information, construct an ExecutionResult instance and call methods on it to
set the error response and headers.
packagecom.apigeesample;importcom.apigee.flow.execution.ExecutionContext;importcom.apigee.flow.execution.ExecutionResult;importcom.apigee.flow.execution.spi.Execution;importcom.apigee.flow.message.MessageContext;importcom.apigee.flow.execution.Action;importorg.apache.commons.lang.exception.ExceptionUtils;publicclassJavaErrorimplementsExecution{publicExecutionResultexecute(MessageContextmessageContext,ExecutionContextexecutionContext){try{Stringname=messageContext.getMessage().getHeader("username");if(name!=null && name.length()>0){messageContext.getMessage().setContent("Hello, "+name+"!");messageContext.getMessage().removeHeader("username");}else{thrownewRuntimeException("Please specify a name parameter!");}returnExecutionResult.SUCCESS;}catch(RuntimeExceptionex){ExecutionResultexecutionResult=newExecutionResult(false,Action.ABORT);//--Returns custom error message and headerexecutionResult.setErrorResponse(ex.getMessage());executionResult.addErrorResponseHeader("ExceptionClass",ex.getClass().getName());//--Set flow variables -- may be useful for debugging.messageContext.setVariable("JAVA_ERROR",ex.getMessage());messageContext.setVariable("JAVA_STACKTRACE",ExceptionUtils.getStackTrace(ex));returnexecutionResult;}}}
Compile your code with Maven
The project is set up so that you can compile with Maven. If you want to use
javac, we'll include an example as well.
Be sure that you have Maven installed:
mvn-version
Execute the script java-error/buildsetup.sh. This script installs the required
JAR dependencies in your local Maven repo.
cd to the java-error/callout directory.
Execute Maven:
mvncleanpackage
If you wish, verify that the JAR file edge-custom-policy-java-error.jar was
copied to java-error/apiproxy/resources/java. This is the required location for
JAR files that you wish to deploy with a proxy.
Deploy and call the proxy
A deploy script is provided in the ./java-error directory. But before you run it,
you need to do a quick setup.
[[["Easy to understand","easyToUnderstand","thumb-up"],["Solved my problem","solvedMyProblem","thumb-up"],["Other","otherUp","thumb-up"]],[["Hard to understand","hardToUnderstand","thumb-down"],["Incorrect information or sample code","incorrectInformationOrSampleCode","thumb-down"],["Missing the information/samples I need","missingTheInformationSamplesINeed","thumb-down"],["Other","otherDown","thumb-down"]],["Last updated 2025-08-26 UTC."],[[["\u003cp\u003eThis guide provides an example of creating a Java callout in Apigee and Apigee hybrid that includes custom error handling.\u003c/p\u003e\n"],["\u003cp\u003eJava callouts can handle errors by setting flow variables using \u003ccode\u003emessageContext.setVariable()\u003c/code\u003e and returning custom error information with \u003ccode\u003eExecutionResult\u003c/code\u003e.\u003c/p\u003e\n"],["\u003cp\u003eThe provided sample code demonstrates how to return custom error messages and headers, as well as place error stacktraces into flow variables for debugging.\u003c/p\u003e\n"],["\u003cp\u003eThe project can be downloaded from the Apigee api-platform-samples GitHub repository and compiled using Maven, and detailed compilation instructions are included in the sample.\u003c/p\u003e\n"],["\u003cp\u003eInstructions are provided on deploying the sample proxy to Apigee using a zip file and how to test it using the \u003ccode\u003ecurl\u003c/code\u003e command.\u003c/p\u003e\n"]]],[],null,["# How to handle JavaCallout policy errors\n\n*This page\napplies to **Apigee** and **Apigee hybrid**.*\n\n\n*View [Apigee Edge](https://docs.apigee.com/api-platform/get-started/what-apigee-edge) documentation.*\n\nWhat is a Java Callout?\n-----------------------\n\nIf you're new to JavaCallout, we recommend that you start with [How to create a Java\ncallout](/apigee/docs/api-platform/develop/how-create-java-callout).\n\nHandling errors in JavaCallout policies\n---------------------------------------\n\nWhen you write a JavaCallout policy, you may want to do custom error handling in your Java code. For\nexample, you may wish to return custom error messages and headers and/or set flow variables with\nerror information in the proxy flow on Apigee.\n\nLet's walk through a simple JavaCallout policy example that illustrates basic custom error handling\npatterns. The sample returns a custom error message when an exception occurs. It also places the\nerror stacktrace into a flow variable, which can be a handy debugging technique.\n| **Tip:** See also [this community post](https://community.apigee.com/questions/32883/how-to-continue-on-error-in-a-java-callout.html) about handling errors in Java callout code.\n\n### Download the project\n\nTo make things simple, you can download this project from the Apigee [api-platform-samples](https://github.com/apigee/api-platform-samples) repository on\nGitHub.\n\n1. Download or clone [api-platform-samples](https://github.com/apigee/api-platform-samples) to your system.\n2. In a terminal or code editor of your choice, go to the `api-platform-samples/doc-samples/java-error` project.\n\n### The sample Java code\n\nThe error handling patterns are straightforward. You can set flow variables in the current\nApigee flow context with the `messageContext.setVariable()` method. To return custom\nerror information, construct an `ExecutionResult` instance and call methods on it to\nset the error response and headers. \n\n```java\npackage com.apigeesample;\n\nimport com.apigee.flow.execution.ExecutionContext;\nimport com.apigee.flow.execution.ExecutionResult;\nimport com.apigee.flow.execution.spi.Execution;\nimport com.apigee.flow.message.MessageContext;\nimport com.apigee.flow.execution.Action;\n\nimport org.apache.commons.lang.exception.ExceptionUtils;\n\n\npublic class JavaError implements Execution {\n public ExecutionResult execute(MessageContext messageContext, ExecutionContext executionContext) {\n\n try {\n\n String name = messageContext.getMessage().getHeader(\"username\");\n\n if (name != null && name.length()\u003e0) {\n messageContext.getMessage().setContent(\"Hello, \" + name + \"!\");\n messageContext.getMessage().removeHeader(\"username\");\n\n } else {\n throw new RuntimeException(\"Please specify a name parameter!\");\n }\n\n return ExecutionResult.SUCCESS;\n\n } catch (RuntimeException ex) {\n\n ExecutionResult executionResult = new ExecutionResult(false, Action.ABORT);\n\n //--Returns custom error message and header\n executionResult.setErrorResponse(ex.getMessage());\n executionResult.addErrorResponseHeader(\"ExceptionClass\", ex.getClass().getName());\n\n //--Set flow variables -- may be useful for debugging.\n messageContext.setVariable(\"JAVA_ERROR\", ex.getMessage());\n messageContext.setVariable(\"JAVA_STACKTRACE\", ExceptionUtils.getStackTrace(ex));\n return executionResult;\n }\n }\n}\n```\n\n### Compile your code with Maven\n\nThe project is set up so that you can compile with Maven. If you want to use\n`javac`, we'll include an example as well.\n| **Note:** The POM file and configuration for the Maven compile should work, but are offered in the Git repository as an example only. You may need to make adjustments for your environment. If you make changes to the sample code, you may also need to adjust the Maven configuration.\n\n1. Be sure that you have Maven installed: \n\n ```java\n mvn -version\n ```\n2. Execute the script `java-error/buildsetup.sh`. This script installs the required JAR dependencies in your local Maven repo.\n3. cd to the `java-error/callout` directory.\n4. Execute Maven: \n\n ```java\n mvn clean package\n ```\n | **Note:** If you get a Maven error, be sure that you are in the `java-error/callout` directory.\n5. If you wish, verify that the JAR file `edge-custom-policy-java-error.jar` was copied to `java-error/apiproxy/resources/java`. This is the required location for JAR files that you wish to deploy with a proxy.\n\n### Deploy and call the proxy\n\nA deploy script is provided in the `./java-error` directory. But before you run it,\nyou need to do a quick setup.\n\n1. cd to `api-platform-samples/doc-samples/java-error`\n2. The simplest way to deploy the proxy is to bundle it in a zip file and upload the proxy bundle to an environment in your Apigee organization. See [Creating an API proxy](/apigee/docs/api-platform/develop/ui-create-proxy). Be sure to use the **Upload Proxy Bundle** option. See also [Tips and tricks for uploading API proxy in a proxy bundle](https://community.apigee.com/questions/64498/tips-and-tricks-for-uploading-api-proxy-in-proxy-b.html) in the Apigee community.\n3. When the proxy is deployed, try calling it: \n\n ```java\n curl https://$HOSTNAME/java-error\n ```\n\n Because the call does not include a \"name\" query parameter, the Java code throws a runtime\n error. The proxy returns this message and header:\n\n- Error message: `Please specify a name parameter!`\n- Header: `ExceptionClass: java.lang.RuntimeException`\n\n| **Note:** If you look at the Debug Tool in the Apigee UI, you'll see that a flow variable is set called JAVA_STACKTRACE. This is a useful technique for debugging, rather than returning a stacktrace to the client."]]