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:
-
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. -
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
, whereexample
specifies the Java package,Hello
specifies the class, andmainHandler
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 isHelloFC
. Therefore, the value ofhandler
that is specified during function creation isexample.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 theoutputStream
parameter. - Handler repository
The dependency of the
com.aliyun.fc.runtime
package can be referenced in the followingpom.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.
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());
}
}