When you use Java for programming in Function Compute, you must define a Java function as a handler. This topic describes the structure and features of Java event functions.

Background information

Function Compute supports the Java 8 runtime environment. Java must be compiled before it can be run in a Java Virtual Machine (JVM). Unlike scripting languages such as Python and Node.js, Java has the following limits:

  • No support for code upload: You can only upload developed and compiled ZIP packages or JAR packages. Function Compute does not support Java-based compilation.
  • No support for online edition: You cannot edit code online because code cannot be uploaded. You can only submit code on web pages or by using Object Storage Service (OSS).

Event function handlers

When you use Java for programming, you must implement the predefined handlers provided by Function Compute. For event handler functions, the following two predefined handlers are available:

  • StreamRequestHandler

    This handler uses the Stream type to process the input event data and return the execution result. You must read the input data from input streams and then write the execution result to output streams.

  • PojoRequestHandler

    This handler uses the POJO type, which allows you to customize the input and output of the handler. Both the input and output must be of the POJO type.

StreamRequestHandler

The following code defines a simple handler function, which is an event function:

package example;

import com.aliyun.fc.runtime.Context;
import com.aliyun.fc.runtime.StreamRequestHandler;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

public class HelloFC implements StreamRequestHandler {

    @Override
    public void handleRequest(
            InputStream inputStream, OutputStream outputStream, Context context) throws IOException {
        outputStream.write(new String("hello world").getBytes());
    }
}            
  • Package and class names

    Java is different from other languages in execution methods due to its packages. The execution method in the sample code is example.Hello::mainHandler, where example specifies the Java package, Hello specifies the class, and mainHandler specifies the class method.

    This method can be assigned arbitrary package and class names. However, the package and class names must match the Function Handler field that is used to create the function. In the preceding example, the package name is example and the class name is HelloFC. Therefore, the value of handler that is specified during function creation is example.HelloFC::handleRequest, which is in the format of {package}.{class}::{method}.

  • Implemented handler

    Your code must implement the handlers predefined by Function Compute. In the preceding example, the StreamRequestHandler is implemented. The inputStream parameter of the handler is the input parameter when you invoke a function and the outputStream parameter is used for returning the execution result.

  • context parameter

    The context parameter contains the runtime information of a function, such as the request ID and the temporary AccessKey pair. This parameter is of the com.aliyun.fc.runtime.Context type.

  • Return value

    A function that implements the StreamRequestHandler returns the execution result by using the outputStream parameter.

  • Handler repository
    The dependency of the com.aliyun.fc.runtime package can be referenced in the following pom.xml file:
    <dependency>
        <groupId>com.aliyun.fc.runtime</groupId>
        <artifactId>fc-java-core</artifactId>
        <version>1.3.0</version>
    </dependency>           

You can visit the Maven repository to obtain the latest version of the fc-java-core package.

Before you create a function, you must compress the code and its dependency fc-java-core into a JAR package. For more information about how to compress the code and its dependency, see Use custom modules. The hello world code in the example is compressed into a JAR package. You can use the sample code package to conduct the test.

Run the fun deploy command to deploy the function. You can view the related log after the function is executed.
using region: cn-hangzhou
using accountId: ***********3557
using accessKeyId: ***********r3Ra
using timeout: 300

Waiting for service FunDemo to be deployed...
  Waiting for function javademo to be deployed...
    Waiting for packaging function javademo code...
    package function javademo code done
  function javademo deploy success
service FunDemo deploy success            

Log on to the Function Compute console to view the function status and invoke the function.

PojoRequestHandler

The following code defines a simple handler function, which is a processing function:

// HelloFC.java
package example;

import com.aliyun.fc.runtime.Context;
import com.aliyun.fc.runtime.PojoRequestHandler;

public class HelloFC implements PojoRequestHandler<SimpleRequest, SimpleResponse> {

    @Override
    public SimpleResponse handleRequest(SimpleRequest request, Context context) {
        String message = "Hello, " + request.getFirstName() + " " + request.getLastName();
        return new SimpleResponse(message);
    }
}            
// SimpleRequest.java
package example;

public class SimpleRequest {
    String firstName;
    String lastName;

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    public SimpleRequest() {}
    public SimpleRequest(String firstName, String lastName) {
        this.firstName = firstName;
        this.lastName = lastName;
    }
}            
// SimpleResponse.java
package example;

public class SimpleResponse {
    String message;

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

    public SimpleResponse() {}
    public SimpleResponse(String message) {
        this.message = message;
    }
}            

Prepare an input file for invoking the function:

{
  "firstName": "FC",
  "lastName": "aliyun"
}            

Use context

The context parameter is an object that is generated when Function Compute is running. It contains operation information. You can use the information in your code. For more information about how to implement the context parameter, see fc-java-libs. The following example shows its definition:

package com.aliyun.fc.runtime;

public interface Context {

    public String getRequestId();

    public Credentials getExecutionCredentials();

    public FunctionParam getFunctionParam();

    public FunctionComputeLogger getLogger();
}           

The following table lists the fields contained in the context parameter.

Field Description
RequestId The unique ID of the request for invoking the function. You can record the ID for troubleshooting if an error occurs.
Function The basic information of the current function, such as the name, handler, memory, and timeout period of the function.
Credentials The temporary AccessKey pair obtained by Function Compute from assuming your service role. The temporary AccessKey pair is valid for five minutes. You can use credentials in your code to access the related service such as OSS. This allows you not to hardcode your AccessKey pair in the function code. For more information, see Permissions.
Logger The logger encapsulated by Function Compute.

The following sample code shows how to upload a file to OSS by using a temporary AccessKey pair:

package example;

import com.aliyun.fc.runtime.Context;
import com.aliyun.fc.runtime.Credentials;
import com.aliyun.fc.runtime.StreamRequestHandler;
import com.aliyun.oss.OSSClient;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

public class HelloFC implements StreamRequestHandler {

    @Override
    public void handleRequest(
            InputStream inputStream, OutputStream outputStream, Context context) throws IOException {

        String endpoint = "oss-cn-shanghai.aliyuncs.com";
        String bucketName = "my-bucket";

        Credentials creds = context.getExecutionCredentials();
        OSSClient client = new OSSClient(
                endpoint, creds.getAccessKeyId(), creds.getAccessKeySecret(), creds.getSecurityToken());
        client.putObject(bucketName, "my-object", new ByteArrayInputStream(new String("hello").getBytes()));
        outputStream.write(new String("done").getBytes());
    }
}