Send Docs Feedback

Note: Most user interface tasks can be performed in Edge Classic or the New Edge experience. For an overview, getting started topics, and release notes specific to the New Edge experience, see the docs.

Use Java to customize an API

This cookbook topic shows how to implement a policy that executes Java code in the context of an API proxy flow.

For the supported versions of Java, see Supported software.

Download and try out the sample code

Sample code: We recommend that you download and try out this topic's sample code from Github. The sample is called java-cookbook, which you can find in the doc-samples folder in the Apigee Edge API Services samples repository in Github. For information on downloading Apigee Edge samples, see Using the sample API proxies

Instructions for deploying and calling the API are provided in the README file that comes with the sample. You can also find brief deployment instructions here: Deploying and testing samples.

About this cookbook example

Apigee Edge provides a range of out-of-the-box policy capabilities that address common API management requirements. However, there are some cases where your API requires custom behavior that is not implemented in the out-of-the-box policy palette. In these cases, Apigee provides several options that enable developers to script or code customized API behavior. One approach is to implement the desired behavior in Java.

This topic illustrates how to create a simple JavaCallout policy that executes your custom Java code within the context of a proxy flow. Java code can examine or manipulate any aspect of the request or response message, and can raise faults, or set or retrieve context variables. The Java code in this example is simple: it reads a query parameter from the inbound API request, performs a simple lookup, and the modifies the in-flight HTTP request by inserting a new query parameter. This modified request is the one that will eventually be sent to the backend target. In this case, the backend API called by the proxy is the Yahoo Weather API.

The proxy is called like this:

The Java code executes in the ProxyEndPoint of the proxy flow. It maps the city name that is passed in as a query parameter to a location id (or WOEID) for that city. At this point, the execution of the Java callout completes. (See! Told you it was simple.) Control then transfers out of the Java code to the proxy flow. Later, the proxy calls the Yahoo Weather API with that WOEID. The API then returns weather information for the city.

While this example shows Java code mediating the inbound Request, Java code can also be used to inspect or modify the Response. This example does not cover that, but the approach is similar.

After working with this cookbook example, you will understand how to implement, compile, and deploy custom Java code for a proxy. 

  • Most system calls are disallowed. For example, you cannot perform local network I/O, or filesystem reads or writes. The callout cannot get information about the current process, the process list, or CPU/memory utilization on the machine. Although some such calls may be functional, they are unsupported and liable to be actively disabled at any time. For forward compatibility, you should avoid making such calls in your code.
  • Reliance on Java libraries that are included with Apigee Edge is not supported, though Apigee Java Callout samples may use them purely to make them work as non-production illustrations. Those libraries are for Edge product functionality only, and there's no guarantee that a library will be available from release to release.

Before you begin

Before you explore this cookbook example, you should also be familiar with these fundamental concepts:

  • What policies are and how to attach them to proxies. For a good introduction to policies, see Policy attachment and enforcement
  • The structure of a proxy flow, as explained in Flow configurations. Flows let you specify the sequence in which policies are executed by an API proxy. In this example, several policies are created and added to the proxy's flow. 
  • How a proxy project is organized on your filesystem, as explained in API proxy configuration reference.  
  • A working knowledge of Java.

If you have downloaded the sample code, you can locate all of the files discussed in this topic in the mashup-policy-cookbook sample folder. The following sections discuss the sample code in detail. 

Going with the flow

Before moving to the JavaCallout policy and Java code, let's take a look a the main flow of our example proxy. The flow XML, shown below, tells us a lot about this proxy and how the JavaCallout policy is called. 

In the sample download, you can find this XML in the file doc-samples/java-cookbook/apiproxy/proxies/default.xml.

<ProxyEndpoint name="default">

   <FaultRule name="MissingCityName">
   <Condition> = "ExecutionReturnedFailure"</Condition>

   <Flow name="forecast">
     <Condition>(proxy.pathsuffix ~/ "/forecastrss") and (request.verb = "GET")</Condition>
     <!-- for every request lookupCityName policy -->
       <!-- Java extension-->

 <RouteRule name="default">


Here's a summary of the flow's elements.

Note: This is a ProxyEndpoint flow. The ProxyEndpoint configuration defines the inbound (app-facing) interface for an API proxy. When you configure a ProxyEndpoint, you define how apps invoke the proxied API.

  • <Request> - The <Request> element consists of several <Step> elements. Each step calls one of the policies that we'll create through the rest of this topic. These policies are concerned with creating a request message, sending it, and parsing the response. By the end of this topic, you'll understand the role of each of these policies.
  • <Response> - The <Response> element also includes <Steps>. These steps also call policies that are responsible for processing the final response from the target endpoint (the Google Elevation API). 
  • <HttpProxyConnection> - Specifies details about how apps will connect to this API proxy, including the <BasePath>, which specifies how this API will be called. 
  • <RouteRule> - This element specifies what happens immediately after the inbound request messages are processed. In this case, the TargetEndpoint is called. We'll discuss more about this important step later in this topic.

Referencing the Java class in a JavaCallout policy

Before we take a look at the Java implementation, let's see how to reference a Java class (or classes) in a policy. In this cookbook sample, there is a policy called cityLookup.xml. You can find it in the standard policies directory inside the apiproxy folder. If you downloaded the code, you can find the policy XML here: doc-samples/java-cookbook/apiproxy/policies/cityLookup.xml.

<JavaCallout name="cityLookUp">

This is a very simple, straightforward policy! Besides a name for the policy (cityLookup), the policy configuration specifies the name of the Java class, and a JAR file. As you might expect, the class file must be available in the the JAR.

If you refer back to the flow, you will note that the cityLookup policy is called in the <Request> stage of the ProxyEndpoint. This means that the Java class is executed at that stage in the flow.

Some additional notes about class loading and activation: Edge creates one instance of your callout class per deployed proxy revision, in each Java Virtual Machine. (You should aware that the Edge runtime is multi-node and distributed, which means there will be multiple Java VMs running your code concurrently. Each inbound request is handled by one of those Java VMs.) The callout is loaded via its own Java classloader. When you undeploy the API Proxy, all of your code and its context gets garbage-collected, unless your code does something unusual to prevent that.

Let's look at the Java class next, and then at how it is compiled, packaged, and deployed.  

Coding the Java class

This example Java class is deliberately simple and trivial. However, it illustrates some fundamental concepts common to any Java code that is executed through a JavaCallout policy.

In the sample download, you can find this Java source file in doc-samples/java-cookbook/java/src/com/apigeesample/

The package name prefixes com.apigee.* and io.apigee.* are reserved. To avoid collisions and errors, don't use these in your Java Callout package names.

package com.apigeesample;

import com.apigee.flow.execution.ExecutionContext;
import com.apigee.flow.execution.ExecutionResult;
import com.apigee.flow.execution.spi.Execution;
import com.apigee.flow.message.MessageContext;

public class CityLookup implements Execution{

  public ExecutionResult execute(MessageContext messageContext, 
                                 ExecutionContext executionContext) {
    try {
      int w = 0;
      String cityName = 

      if (cityName.equals("MILAN")) w=718345;
      else if (cityName.equals("ROME")) w=721943;
      else if (cityName.equals("VENICE")) w=725746;

      if(w>0) { 
        messageContext.getRequestMessage().setQueryParam("w", w);
      } else {
        // default to Villafranca di Verona, Italy
        messageContext.getRequestMessage().setQueryParam("w", 20148584);

      return ExecutionResult.SUCCESS;

    } catch (Exception e) {
      return ExecutionResult.ABORT;

The most important things to remember about this Java implementation are:

  • Imports classes from the com.apigee.flow.execution and com.apigee.flow.message packages. These packages must be included in the JAR file that is packaged and deployed. For information on uploading Java JARs, see Resource files and Java Callout policy. In the cookbook sample download, you can find these packages in doc-samples/java-cookbook/lib. 
  • Implements Execution. Any Java code that is executed within an API proxy must implement Execution. 

Brief detour: error handling

The execute() method in our Java class throws an exception if it can't recognize the city query parameter (only three Italian city names are valid: Milan, Venice, and Rome). On error, the method returns an ExectionResult.ABORT status. To handle this error situation, we added a RaiseFault policy to the flow. If you refer back to the proxy flow shown previously, you will see that this policy, called Fault.MissingCityName, is added to the policy's <FaultRules> element. 

Here is the policy XML. If you downloaded the sample code from Github, you can find this policy XML here: doc-samples/java-cookbook/apiproxy/policies/Fault.MissingCityName.xml.

<RaiseFault name="Fault.MissingCityName">
   <Payload contentType="application/xml">
     <errorMessage>Missing City Name in Query Parameter</errorMessage>
     <errorMoreInfo>Valid cities are venice, milan, and rome. </errorMoreInfo>

The policy simply sets an error code and provides information about the error. This information is sent to the client. You can read more about the structure of RaiseFault policies in Raise Fault policy

Specifying the default target endpoint

Our final task is to specify the Yahoo Weather API URL on the proxy's TargetEndPoint. If you downloaded the code, you can find the policy XML here: doc-samples/java-cookbook/apiproxy/targets/default.xml. Here is the source code:

<TargetEndpoint name="default">

Testing the example

Before you can deploy and test this sample, you must first compile the class and generate a JAR file that contains that class plus the required packages that the custom class requires. The required libraries—which are for local compilation only (they are available in the Edge runtime)—are expressions-1.0.0.jar and message-flow-1.0.0.jar, and they are located in the doc-samples/java-cookbook/lib folder. 

If you have not already done so, try to download, deploy, and run the java-cookbook sample, which you can find in the doc-samples folder in the Apigee Edge API Services samples repository on Github. Just follow the instructions in the README file in the java-cookbook folder. 

To summarize, you can call the API as follows. Substitute {myorg} with your organization name. This example assumes you are using the test environment. 

curl http://{myorg}

The response includes weather information for Venice in XML format. Here are the first few lines of the response:

<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<rss version="2.0" xmlns:yweather="" xmlns:geo="">

<title>Yahoo! Weather - Venice, IT</title>
<description>Yahoo! Weather for Venice, IT</description>
<lastBuildDate>Fri, 06 Dec 2013 3:54 pm CET</lastBuildDate>
<yweather:location city="Venice" region="VN" country="Italy"/>
<yweather:units temperature="F" distance="mi" pressure="in" speed="mph"/>
<yweather:wind chill="46" direction="" speed="" />
<yweather:atmosphere humidity="76" visibility="3.73" pressure="29.85" rising="0" />
<yweather:astronomy sunrise="7:35 am" sunset="4:26 pm"/>

Remember that the Java class is hard-wired to recognize only Venice, Milan, and Rome. Try invoking the API with a city that is not in this list, like Sacremento.

curl http://{myorg}

This call results in an error and the JavaCallout policy follows it's Fault path. The resulting message returned is generated by the RaiseFault policy, discussed previously:

 <errorMessage>Missing City Name</errorMessage>
 <errorMoreInfo>Provide a city parameter in the querystring e.g. city=venice</errorMoreInfo>


This cookbook topic explained how to use the JavaCallout policy and implement custom Java code using the JavaCallout Java API. While this example showed Java code mediating the inbound Request, Java code can also be used to inspect or modify the Response. We also looked at error handling using the RaiseFault policy. 

Get Help

For help, see Apigee Customer Support.

Help or comments?