Function Compute supports the Java OpenJDK 1.8.0 runtime environment (runtime=java8). This topic describes log printing, error handling, and custom modules of the Java runtime environments.

Print logs

Logs printed by using context.getLogger() are collected to the Logstore that you specify when you create the service.

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 {

        context.getLogger().info("hello world");
        outputStream.write(new String("hello world").getBytes());
    }
}

After the preceding code is executed, the following log is printed:

message:2017-07-05T05:13:35.920Z a72df088-f738-cee3-e0fe-323ad89118e5 [INFO] hello world        

You can use context.getLogger().warn and context.getLogger().error to print a WARN log and an ERROR log respectively.

Handle errors

If an error occurs when Function Compute executes your function, Function Compute captures the error and returns a message.

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 {
        throw new IOException("oops");
    }
} 

When the function is called, the following response is returned:

>>> invk hello-java -f /tmp/a.json
{
  "errorMessage" : "oops",
  "errorType" : "java.io.IOException",
  "errorCause" : "oops",
  "stackTrace" : [ "example.HelloFC.handleRequest(HelloFC.java:15)" ]
}
Error: Request id: 45dd8d90-6b78-cce3-087c-8bf4ebc6c9af. Error type: UnhandledInvocationError   

When an error occurs, the HTTP header in the response contains X-Fc-Error-Type: UnhandledInvocationError.

For more information, see Basic concepts.

Use custom modules

If you need to use the custom modules, package them with the code when you create a JAR file. The following example shows how to package OSS SDK for Java into a project.

  1. Install Java and Maven.
    You can visit the official website to download SDK for Java applicable to your system and then install it. For more information about how to install Maven, see Installing Apache Maven.
  2. Create a Java project with the following directory structure.
    test/src/main/java/example/App.java       
  3. Enter the following content to the App.java file.
    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;
    
    /**
     * Hello world!
     *
     */
    public class App implements StreamRequestHandler, FunctionInitializer {
    
        public void initialize(Context context) throws IOException {
        }
    
        public void handleRequest(
                InputStream inputStream, OutputStream outputStream, Context context) throws IOException {
            outputStream.write(new String("hello world\n").getBytes());
        }
    }             
  4. In the root directory of the project folder, create a pom.xml file. In the pom.xml file, add a maven-assembly-plugin with the following content:
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
      <modelVersion>4.0.0</modelVersion>
      <groupId>example</groupId>
      <artifactId>Java-example</artifactId>
      <packaging>jar</packaging>
      <version>1.0-SNAPSHOT</version>
      <name>Java-example</name>
    
      <properties>
        <maven.compiler.target>1.8</maven.compiler.target>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.test.skip>true</maven.test.skip>
      </properties>
    <build>
      <plugins>
          <plugin>
              <artifactId>maven-assembly-plugin</artifactId>
              <version>3.1.0</version>
              <configuration>
                  <descriptorRefs>
                      <descriptorRef>jar-with-dependencies</descriptorRef>
                  </descriptorRefs>
                  <appendAssemblyId>false</appendAssemblyId> <! -- this is used for not append id to the jar name -->
              </configuration>
              <executions>
                  <execution>
                      <id>make-assembly</id> <! -- this is used for inheritance merges -->
                      <phase>package</phase> <! -- bind to the packaging phase -->
                      <goals>
                          <goal>single</goal>
                      </goals>
                  </execution>
              </executions>
          </plugin>
          <plugin>
              <groupId>org.apache.maven.plugins</groupId>
              <artifactId>maven-compiler-plugin</artifactId>
              <configuration>
                  <source>1.8</source>
                  <target>1.8</target>
              </configuration>
          </plugin>
      </plugins>
      </build>
    </project>            
  5. To reference the external package of Maven Central for the project, add dependencies based on your needs. The following steps use OSS SDK for Java as an example. The pom.xml has the following content:
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
      <modelVersion>4.0.0</modelVersion>
      <groupId>example</groupId>
      <artifactId>Java-example</artifactId>
      <packaging>jar</packaging>
      <version>1.0-SNAPSHOT</version>
      <name>Java-example</name>
    
      <dependencies>
        <dependency>
          <groupId>com.aliyun.fc.runtime</groupId>
          <artifactId>fc-java-core</artifactId>
          <version>1.3.0</version>
        </dependency>
        <dependency>
         <groupId>com.aliyun.oss</groupId>
         <artifactId>aliyun-sdk-oss</artifactId>
         <version>2.6.1</version>
       </dependency>
      </dependencies>
    
      <properties>
        <maven.compiler.target>1.8</maven.compiler.target>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.test.skip>true</maven.test.skip>
      </properties>
    <build>
      <plugins>
          <plugin>
              <artifactId>maven-assembly-plugin</artifactId>
              <version>3.1.0</version>
              <configuration>
                  <descriptorRefs>
                      <descriptorRef>jar-with-dependencies</descriptorRef>
                  </descriptorRefs>
                  <appendAssemblyId>false</appendAssemblyId> <! -- this is used for not append id to the jar name -->
              </configuration>
              <executions>
                  <execution>
                      <id>make-assembly</id> <! -- this is used for inheritance merges -->
                      <phase>package</phase> <! -- bind to the packaging phase -->
                      <goals>
                          <goal>single</goal>
                      </goals>
                  </execution>
              </executions>
          </plugin>
          <plugin>
              <groupId>org.apache.maven.plugins</groupId>
              <artifactId>maven-compiler-plugin</artifactId>
              <configuration>
                  <source>1.8</source>
                  <target>1.8</target>
              </configuration>
          </plugin>
      </plugins>
      </build>
    </project>             
  6. In the project root directory, run the mvn package command to package the files. The following sample code shows the compilation output:
    $mvn package
    [INFO] Scanning for projects...
     ...  ....   ....
    [INFO] --------------------------< example:example >---------------------------
    [INFO] Building Java-example 1.0-SNAPSHOT
    [INFO] --------------------------------[ jar ]---------------------------------
     ...  ....   ....
    [INFO] ------------------------------------------------------------------------
    [INFO] BUILD SUCCESS
    [INFO] ------------------------------------------------------------------------
    [INFO] Total time:  11.681 s
    [INFO] Finished at: 2020-03-26T15:55:05+08:00
    [INFO] ------------------------------------------------------------------------          

    If the message shows that compilation failed, modify the code based on the error message.

    The compiled JAR package is in the target directory of the project folder and is named as Java-example-1.0-SNAPSHOT.jar based on the artifactId and version fields in pom.xml.

  7. Upload the JAR package in the Function Compute console.
    1. Log on to the Function Compute console.
    2. In the top navigation bar, select a region.
    3. Find the target function in the target service and click the name of the function.
    4. On the Code tab, select Import from OSS or Upload Zip File to upload the JAR package.

You can also use maven-shade-plugin to package the files. Generally, the preceding package methods can meet the needs in most scenarios. If you want to package JAR packages that are not managed by Maven, such as JAR packages in other non-Maven repositories that you reference in resources/lib, you can use maven-jar-plugin and maven-dependency-plugin to package the JAR packages into the final JAR package.

Use IntelliJ IDEA to install dependencies, and then compress and upload the dependencies

  1. Create a local Java project. The pom.xml file contains the following content:
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
      <modelVersion>4.0.0</modelVersion>
      <groupId>example</groupId>
      <artifactId>Java-example</artifactId>
      <packaging>jar</packaging>
      <version>1.0-SNAPSHOT</version>
      <name>Java-example</name>
      <dependencies>
        <dependency>
          <groupId>com.aliyun.fc.runtime</groupId>
          <artifactId>fc-java-core</artifactId>
          <version>1.3.0</version>
        </dependency>
        <dependency>
         <groupId>com.aliyun.oss</groupId>
         <artifactId>aliyun-sdk-oss</artifactId>
         <version>2.6.1</version>
       </dependency>
      </dependencies>
    </project>       
  2. Use IntelliJ IDEA to export JAR package configurations.
    1. Choose File > Project Structure.
      export jar
    2. In the dialog box that appears, choose Artifacts > + > JAR > From modules with dependencies.
      choose from modules with dependencies
    3. In the dialog box that appears, use the default configuration and click OK.
      ok
    4. In the top navigation bar of IntelliJ IDEA, choose Build > Build Artifacts, and then click Build or Rebuild to generate a JAR package.
      build
  3. You can upload the JAR package from out/artifacts/example_jar of the project root directory to Function Compute. In the Function Compute console, click the Code tab, and then select Import from OSS or Upload Zip File to upload the exported JAR package.

Use FunCraft to package project files

If you use FunCraft to deploy an application, you can run the fun install command to create the application.

  1. In the root directory of the project, create a template.yml with the following content:
    ROSTemplateFormatVersion: '2015-09-01'
    Transform: 'Aliyun::Serverless-2018-04-03'
    Resources:
      JavaDemo:
        Type: 'Aliyun::Serverless::Service'
        Properties:
          Description: 'helloworld'
        test:
          Type: 'Aliyun::Serverless::Function'
          Properties:
            Handler: example.App::handleRequest
            Initializer: example.App::initialize
            Runtime: java8
            CodeUri: '. /'               
  2. Run the following command to package the project files:
    fun build             
    The following result is returned:
    using template: template.yml
    start building function dependencies without docker
    
    building JavaDemo/test
    running task flow MavenTaskFlow
    running task: MavenCompileTask
    running task: MavenCopyDependencies
    running task: CopyMavenArtifacts
    
    Build Success
    
    Built artifacts: .fun/build/artifacts
    Built template: .fun/build/artifacts/template.yml
    
    Tips for next step
    ======================
    * Invoke Event Function: fun local invoke
    * Invoke Http Function: fun local start
    * Deploy Resources: fun deploy  
  3. Run the following command to deploy the function:
    fun deploy -y              
    The following result is returned:
    using template: .fun/build/artifacts/template.yml
    using region: cn-qingdao
    using accountId: ***********3743
    using accessKeyId: ***********Ptgk
    using timeout: 60
    
    Collecting your services information, in order to caculate devlopment changes...
    
    Resources Changes(Beta version! Only FC resources changes will be displayed):
    
    ***********
    
    Waiting for service JavaDemo to be deployed...
            Waiting for function test to be deployed...
                    Waiting for packaging function test code...
                    The function test has been packaged. A total of 3 files were compressed and the final size was 330.35 KB
            function test deploy success
    service JavaDemo deploy success  

Result

Log on to the Function Compute console. The related service and function are displayed. If you click Invoke on the Code tab, the correct results are returned.