How to create a Java callout

You're viewing Apigee Edge documentation.
Go to the Apigee X documentation.
info

What is a Java callout?

Apigee Edge provides a range of policies that address common API management requirements such as security, data transformation, traffic management, and others.

However, there are some cases where your API requires custom behavior that is not implemented in a standard policy. In these cases, Apigee provides several options that enable you to script or code customized API behavior. One approach is to implement the desired behavior in Java.

For the supported versions of Java, see Supported software and supported versions.

How do I use Java code in a proxy?

A Java callout policy lets you call Java code from within an executing proxy flow. Your Java code needs to implement certain Edge-specific Java interfaces that allow the code to interact with the executing proxy. For example, Java methods exist for getting and setting headers, query parameters, flow variables, and other entities within the current flow context of the proxy.

When should I use a Java callout?

Let's look at situations where Java callouts are useful, and situations where you should consider other approaches.

First, consider alternative approaches

Before using a Java callout, note that there may be alternative approaches that you can use instead. For example:

  • For lightweight operations, such as HTTP API calls to remote services, consider using the ServiceCallout policy. See Service Callout policy.
  • For relatively simple interactions with message content, such as modifying or extracting HTTP headers, parameters, or message content, you can use JavaScript or Python languages.

What you can do in Java code

A Java callout supports these basic operations:

  • Examining or manipulating request or response messages
  • Getting and setting flow variables. You can use Java methods to access Edge flow variables. If you want to access Key Value Map (KVM) information, use a KVM policy, assign KVM values to flow variables, and then you can access the flow variables from within the Java callout.
  • Calling external services
  • Raising faults
  • Manipulating error messages and status codes

What you cannot do in Java code

Most system calls are disallowed. You cannot:

  • Make internal file system reads or writes. This means that you cannot use any of the Java packages to read/write into internal file systems; however, you can make external remote calls.
  • Get information about the current process, the process list, or CPU/memory utilization on the machine.
  • Access the source code in `expressions-1.0.0.jar` and `message-flow-1.0.0.jar`.

Although some such calls may work, they are unsupported and liable to be actively disabled at any time. Avoid making such calls in your code.

Do not use or rely on Java libraries that are included with Apigee Edge. Those libraries are for Edge product functionality only, and there's no guarantee that a library will be available from release to release. If you use such libraries, use them in non-production demonstrations only.

Hello Java callout

Let's walk through a basic hello world Java callout example. In this example, we create a simple proxy with a Java callout that returns a "hello world" response. The proxy can return one of two possible responses:

  • If you pass in a "username" header with a "name" value, the proxy returns:

    Hello, <name>!
  • If you omit the header, the proxy just returns:

    "Hello, Guest!"

Download the starter project

To make things simple, we have a basic project prepared for you on GitHub in the Apigee api-platform-samples repository.

  1. Download or clone api-platform-samples to your system.
  2. In a terminal or code editor of your choice, go to the api-platform-samples/doc-samples/java-hello project.

Write the Java code

  1. Open the Java source file: java-hello/callout/src/main/java/HelloJava.java. This file is a skeleton version of the main Java class that we will implement. The imported packages are required for Edge Java Callout code. These classes provide methods that allow you to access the proxy execution context. We'll walk through the steps for compiling and deploying this code shortly.
    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 HelloJava implements Execution {
    
            public ExecutionResult execute(MessageContext messageContext, ExecutionContext executionContext) {
                    
                    try {
    
                            // Your code here.
                
                return ExecutionResult.SUCCESS;
    
                    } catch (Exception e) {
                            return ExecutionResult.ABORT;
                    }
            }
    
    }
  2. Replace the commented line // Your code here with the following code:

    String name = messageContext.getMessage().getHeader("username");
    
    if (name != null && name.length()>0) {
            messageContext.getMessage().setContent("Hello, " + name + "!");
            messageContext.getMessage().removeHeader("username");
    } else {
            messageContext.getMessage().setContent("Hello, Guest!");
    }
  3. Save the file.


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 following the Maven example.

  1. Be sure that you have Maven installed:

    mvn -version
  2. Execute the script java-hello/buildsetup.sh. This script installs the required JAR dependencies in your local Maven repo.
  3. cd to the java-hello/callout directory.
  4. Execute Maven:

    mvn clean package
  5. If you wish, verify that the JAR file edge-custom-policy-java-hello.jar was copied to java-hello/apiproxy/resources/java. This is the required location for JAR files that you wish to deploy with a proxy.

Compile with javac (optional)

In the previous section, you generate the required Java JAR file automatically with a Maven command. Alternatively, if you want to use javac to compile the code, you can do something similar to the following (from the java-hello directory). The required JAR files are provided for you in the java-hello/lib directory.

  1. cd to api-platform-samples/doc-samples/java-hello.
  2. Be sure you have javac in your path.

    javac -version
  3. Execute the following javac command:

    javac -d . -classpath ./lib/expressions-1.0.0.jar:./lib/message-flow-1.0.0.jar:. callout/src/main/java/HelloJava.java
    This creates com/apigeesample/HelloJava.class.
  4. Create a JAR file containing the compiled class in the apiproxy/resources/java directory. This is the required location for JAR files that you wish to deploy with a proxy. You can do this by running the following command in the java-hello directory (don't forget the period at the end).

    jar cvf apiproxy/resources/java/edge-custom-policy-java-hello.jar -C com .
    

Deploy and call the proxy

A deploy script is provided in the ./java-hello directory. But before you run it, you need to do a quick setup.

  1. cd to api-platform-samples/doc-samples/java-hello
  2. If you haven't already done so, open the file ../../setup/setenv.sh and edit it as indicated with your Apigee account information: your username (the email address associated with your account), your organization name, and the domain you use to make API management calls. For example, for Edge cloud, the domain is https://api.enterprise.apigee.com; however, your domain may be different if you're using Edge Private Cloud.
  3. Save the setenv.sh file.
  4. Execute the deploy script:

    ./deploy.sh
  5. If the deploy succeeds, execute the invoke script:

    ./invoke.sh

    The invoke script calls a cURL command that looks like this:

    curl  http://$org-$env.$api_domain/java-hello -H "username:Will"

    Which returns "Hello, Will!

    You can edit the invoke.sh script to change the name, or if you change the cURL call to remove the header, then the command returns "Hello, Guest!"

About the proxy

Let's quickly examine the policies used in this proxy. Pay attention to where the policies are positioned in the proxy flow and why.

The Assign message policy

An Assign message policy is attached to the ProxyEndpoint request flow. It copies the username header from the request and assigns it to the response. This operation allows the Java Callout policy, which is attached to the response flow, to access the username header and build a custom response body using the value of that header.

<AssignMessage async="false" continueOnError="false" enabled="true" name="CopyHeader">     
    <DisplayName>CopyHeader</DisplayName>     
    <Copy source="request">         
        <Headers>             
          <Header name="username"/>         
        </Headers>     
    </Copy>     
    <IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables>     
    <AssignTo createNew="false" transport="http" type="response"/> 
</AssignMessage>

The Java callout policy

The Java callout policy is attached to the response flow. This is because the custom Java code makes changes to the response headers and message. The policy's ClassName element specifies the main class that is executed by the policy. The ResourceURL element is the name of the JAR file that you built and added to the resources/java directory of the proxy.

<JavaCallout name="hello-java">         
    <ClassName>com.apigeesample.HelloJava</ClassName>         
    <ResourceURL>java://edge-custom-policy-java-hello.jar</ResourceURL> 
</JavaCallout>

What you need to know about Java callout

Important things to note about implementing a Java callout 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. You can upload your Java JAR through the Management UI proxy editor, or you can include it in the /resources/java directory in API proxies that you develop locally.
  • Implements the Execution interface. Any Java code that is executed within an API proxy must implement Execution.
  • A Java Callout policy contains no actual code. Instead, a Java Callout policy references a Java 'resource', which you must package in a JAR.
  • Package names to avoid: Do not use io.apigee or com.apigee as package names in Java Callouts. Those are reserved and used by other Apigee modules.
  • If your Java Callout relies on additional third-party libraries packaged as independent JAR files, then place those JAR files in the /resources/java directory as well to ensure that they are loaded correctly at runtime.
  • If there are multiple JARs, simply add them as additional resources. You do not need to modify the policy configuration to refer to additional JAR files. Putting them in /resources/java is sufficient.
  • For additional information on uploading Java JARs, see Resource files.