Why invocation of class file in lambda layer throwing error?

659 views Asked by At

I am trying to implement lambda layer using java. I have created a project for lambda layer below are the codes:

Layer code

  1. pom.xml

     <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/xsd/maven- 
     4.0.0.xsd">
         <modelVersion>4.0.0</modelVersion>
         <groupId>com.i3l.layer</groupId>
         <artifactId>customlayer</artifactId>
         <version>1.1.0</version>
     </project>
    
  2. DataHandler.java

    package customlayer;
    
    public class DataHandler {
    
     public String getData(String input) {
        System.out.println("Inside Layer");
        return "Hello from Layer "+input;
     }
    }
    

Function code: I have added the layer dependency in pom.xml like:

<dependency>
    <groupId>com.i3l.layer</groupId>
    <artifactId>customlayer</artifactId>
    <version>1.1.0</version>
    <scope>provided</scope>
</dependency>

In LambdaFunctionHandler.java

package com.amazonaws.lambda.userlayertest;

import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;

import customlayer.DataHandler;

public class LambdaFunctionHandler implements RequestHandler<RequestObject, String> {

@Override
public String handleRequest(RequestObject input, Context context) {
    
    System.out.println("call to layer");
    DataHandler dataHandler = new DataHandler();
    String data = dataHandler.getData(input.getBody());
    return data;
 }
}

I tried uploading the jar directly to layer and putting the jar into a zip and then uploading it to layer. In both cases I am getting error:

"errorMessage": "customlayer/DataHandler",
"errorType": "java.lang.NoClassDefFoundError",

Note: I have already added layer with the version number to the lambda function.

It would be great if someone help me figuring out why the java class is not found in layer. I have downloaded the code from layer and I can see the class file is in correct path as per the import.

2

There are 2 answers

0
Rock On BEST ANSWER

Here the issue was with the directory structure. The layer dependencies should be in a particular directory and it varies with the runtime environment. So in this case the customlayer-1.1.0.jar should be in a java/lib and then it will be archived. Let's say the archive name is customlayer.zip then the structure will be

customlayer.zip
└ java/lib/customlayer-1.1.0.jar

This structure will vary with the runtime environment.

For more details: https://docs.aws.amazon.com/lambda/latest/dg/configuration-layers.html

0
Ruelos Joel On

Moreover, to create it automatically, one can create an assembly.xml like below.

<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
    <id>bin</id>
    <baseDirectory>/</baseDirectory>
    <formats>
        <format>zip</format>
    </formats>
    <fileSets>
        <fileSet>
            <directory>${project.build.directory}</directory>
            <outputDirectory>/java/lib</outputDirectory>
            <includes>
                <include>${project.artifactId}.jar</include>
            </includes>
        </fileSet>
    </fileSets>
</assembly>

Then in your pom.xml, add the plugin and configure this assembly.xml file.

        <plugin>
            <artifactId>maven-assembly-plugin</artifactId>
            <version>2.6</version>
            <configuration>
                <descriptors>
                    <descriptor>assembly.xml</descriptor>
                </descriptors>
                <appendAssemblyId>false</appendAssemblyId>
            </configuration>
            <executions>
                <execution>
                    <id>make-assembly</id> <!-- this is used for inheritance merges -->
                    <phase>package</phase> <!-- append to the packaging phase. -->
                    <goals>
                        <goal>single</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>