This topic describes how to implement lifecycle hooks for function instances in a Java runtime environment.

Background information

After you configure a lifecycle hook for a function instance, Function Compute invokes the hook when a related lifecycle event for the instance occurs. The following lifecycle hooks can be configured for a function instance: Initializer, PreFreeze, and PreStop hooks. Java runtime supports all the preceding hooks. For more information, see Function instance lifecycle.

Hook method signature

Initializer hook signature

An Initializer hook is executed after the function instance is started and before the handler runs. Function Compute ensures that the Initializer hook is successfully invoked only once in the lifecycle of a function instance. For example, if the initializer callback fails, the system keeps retrying until the initializer callback is successfully invoked, and then runs your handler. Make sure that the Initializer hook is correctly configured when it is repeatedly invoked.

The Initializer hook consists of the context input parameter and can be invoked in the same manner as an event handler.

To use the Initializer hook, FunctionInitializer must be inherited, of which the initialize method must be implemented. The following sample code provides an example on how to define FunctionInitializer:
package com.aliyun.fc.runtime;

import java.io.IOException;

/**
 * This is the interface for the initialization operation
 */
public interface FunctionInitializer {

    /**
     * The interface to handle a function compute initialize request
     *
     * @param context The function compute initialize environment context object.
     * @throws IOException IOException during I/O handling
     */
    void initialize(Context context) throws IOException;
}

PreStop hook signature

The PreStop hook is executed before a function instance is destroyed. To use the PreStop hook, PreStopHandler must be inherited, of which the preStop method must be implemented. The following sample code provides an example on how to define PreStopHandler:
package com.aliyun.fc.runtime;

import java.io.IOException;

/**
 * This is the interface for the preStop operation
 */
public interface PreStopHandler {

    /**
     * The interface to handle a function compute preStop request
     *
     * @param context The function compute preStop environment context object.
     * @throws IOException IOException during I/O handling
     */
    void preStop(Context context) throws IOException;
}

PreFreeze hook signature

The PreFreeze hook is executed before a function instance is frozen. To use the PreFreeze hook, PreFreezeHandler must be inherited, of which the preFreeze method must be implemented. The following sample code provides an example on how to define PreFreezeHandler:
package com.aliyun.fc.runtime;

import java.io.IOException;

/**
 * This is the interface for the preFreeze operation
 */
public interface PreFreezeHandler {

    /**
     * The interface to handle a function compute preFreeze request
     *
     * @param context The function compute preFreeze environment context object.
     * @throws IOException IOException during I/O handling
     */
    void preFreeze(Context context) throws IOException;
}

Example: StreamRequestHandler

package example;

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

import com.aliyun.fc.runtime.Context;
import com.aliyun.fc.runtime.StreamRequestHandler;
import com.aliyun.fc.runtime.FunctionInitializer;
import com.aliyun.fc.runtime.PreFreezeHandler;
import com.aliyun.fc.runtime.PreStopHandler;

public class App implements StreamRequestHandler, FunctionInitializer, PreFreezeHandler, PreStopHandler {
    @Override
    public void initialize(Context context) throws IOException {
        context.getLogger().info("initialize start ...");
    }

    @Override
    public void handleRequest(
            InputStream inputStream, OutputStream outputStream, Context context) throws IOException {
        context.getLogger().info("handlerRequest ...");
        outputStream.write(new String("hello world\n").getBytes());
    }

    @Override
    public void preFreeze(Context context) throws IOException {
        context.getLogger().info("preFreeze start ...");
    }

    @Override
    public void preStop(Context context) throws IOException {
        context.getLogger().info("preStop start ...");
    }
}

Configure lifecycle hooks

Use the Function Compute console

You can configure the lifecycle hooks on the function configuration page in the Function Compute console. The format of a hook is: [Package name].[Class name]::[Method name]. Sample code:db_java_lifecycle
  • If you set Initializer Hook to example.App::initialize, the initialize method in the App.java file of the example is implemented.
  • If you set PreFreeze Hook to example.App::preFreeze, the preFreeze method in the App.java file of the example package is implemented.
  • If you set PreStop Hook to example.App::preStop, the preStop method in the App.java file of the example package is implemented.

Use Serverless Devs

You can use Serverless Devs to configure lifecycle hooks. In this case, you must add the Initializer hook, PreFreeze hook, and PreStop hook to the s.yaml file.
  • Initializer hook

    Add the initializer and initializationTimeout fields to the function parameter.

  • PreFreeze hook

    Add the instanceLifecycleConfig.preFreeze field, including handler and timeout, to the function configurations.

  • PreStop hook

    Add the instanceLifecycleConfig.preStop field, including handler and timeout to the function parameter.

Sample code:

edition: 1.0.0
name: hello-world  #  The name of the project.
access: default    #  The alias of the key.

vars: # The global variables.
  region: cn-shanghai # The ID of the region.
  service:
    name: fc-example
    description: 'fc example by serverless devs'

services:
  helloworld: # The name of the service or module.
    component: fc
    actions: # The custom execution logic.
      pre-deploy: # The operation before the deployment.
        - run: mvn package # The command to run.
          path: ./ # The path in which the command runs.
    props: # The property value of the component.
      region: ${vars.region}
      service: ${vars.service}
      function:
        name: java8-lifecycle-hook-demo
        description: 'fc example by serverless devs'
        runtime: java8
        codeUri: ./target
        handler: example.App::handleRequest
        memorySize: 128
        timeout: 60
        initializationTimeout: 60
        initializer: example.App::initialize
        instanceLifecycleConfig:
          preFreeze:
            handler: example.App::preFreeze
            timeout: 30
          preStop:
            handler: example.App::preStop
            timeout: 30

For more information about the YAML syntax of Serverless Devs, see Basic features.

Sample programs

  • java11-mysql: the sample programs for the Initializer hook and PreStop hook provided by Function Compute.

    This example shows how to use the Initializer hook of the Java runtime to obtain database configurations from the environment variables and create MySQL connections, and how to use the PreStop hook to close MySQL connections.