39

I am having difficulty with a Java based Lambda function setup to receive messages from SNS. My function looks like the below:

package com.mycompany;

import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.LambdaLogger;
import com.amazonaws.services.lambda.runtime.events.SNSEvent;

public class LambdaHandler {  
    public void Handler(SNSEvent event, Context context) {
        //Process the event
    }
}

It compiles just fine and I don't have any problems uploading the jar file to Lambda (via the web console).

However, when I publish to it (via SNS through to the subscribed Lambda function) with JSON representing the SNSEvent model, the Lambda function throws the following exception:

Error loading method handler on class com.mycompany.LambdaHandler: class java.lang.NoClassDefFoundError java.lang.NoClassDefFoundError: com/amazonaws/services/lambda/runtime/events/SNSEvent at

java.lang.Class.getDeclaredMethods0(Native Method) at java.lang.Class.privateGetDeclaredMethods(Class.java:2701) at java.lang.Class.privateGetPublicMethods(Class.java:2902) at java.lang.Class.getMethods(Class.java:1615) Caused by: java.lang.ClassNotFoundException: com.amazonaws.services.lambda.runtime.events.SNSEvent at java.net.URLClassLoader.findClass(URLClassLoader.java:381) at java.lang.ClassLoader.loadClass(ClassLoader.java:424) at java.lang.ClassLoader.loadClass(ClassLoader.java:357)

I use Maven + Netbeans and it's a Maven Java Application project. I downloaded the function from the Lambda console and confirmed, the jar has a lib/ directory with all of the jar's for the imports, including aws-lambda-java-events-1.1.0.jar, which itself includes the /com/amazonaws/services/lambda/runtime/events/SNSEvent.class file.

Why is the runtime unable to find the class when it's definitely in the jar file? Is there anything else I need to do, set any environment variables, etc?

Any help would be appreciated!

EDIT 1 I tried downgrading to aws-lambda-java-events 1.0.0 and it's still reporting the same exception. As requested, below is my POM file (with just project name changed). I don't know how to tell Maven to put the libraries in a tree structure.

<?xml version="1.0" encoding="UTF-8"?>
<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.app</groupId>
    <artifactId>Handler</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>
    <dependencies>
        <dependency>
            <groupId>com.amazonaws</groupId>
            <artifactId>aws-java-sdk-lambda</artifactId>
            <version>1.10.6</version>
        </dependency>
        <dependency>
            <groupId>com.amazonaws</groupId>
            <artifactId>aws-lambda-java-core</artifactId>
            <version>1.0.0</version>
        </dependency>
        <dependency>
            <groupId>com.amazonaws</groupId>
            <artifactId>aws-lambda-java-events</artifactId>
            <version>1.0.0</version>
        </dependency>
    </dependencies>
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
    </properties>
</project>
Brooks
  • 7,099
  • 6
  • 51
  • 82
  • Can you share the relevant section of your Maven file? My comparable working Lambda function did not bundle the aws-lambda-java-events-1.1.0.jar under lib, it had the SNSEvent.class file loose as com/amazonaws/services/lambda/runtime/events/SNSEvents.class. – James Sep 25 '15 at 17:02
  • I can this evening when I get home, but what do you mean it has the SNSEvent.class file "loose"? How does it work if it doesn't provide the runtime environment with the library's jar? – Brooks Sep 25 '15 at 17:05
  • My project does not bundle their jar inside my jar. It bundles the compiled classes in my jar in classpath folder hierarchy alongside the compiled classes for my code. – James Sep 25 '15 at 17:21
  • Just updated the OP with my pom file. How do you put the libraries in a tree structure? Thanks! – Brooks Sep 26 '15 at 02:13
  • Sadly, I'm no maven expert. My pom.xml is similar to yours, but I have only two dependencies: `aws-lambda-java-core` 1.0.0 and `aws-lambda-java-events` 1.1.0. – James Sep 26 '15 at 16:50
  • Then I'm not sure how it's working for you. I had to include the maven shade plugin as described by Mike below in order to get it to work. – Brooks Sep 26 '15 at 17:11

7 Answers7

33

Use the maven-shade plugin so that the JAR contains the dependencies in an uber-jar.

So, add this to your pom.xml

  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-shade-plugin</artifactId>
        <version>2.3</version>
        <configuration>
          <createDependencyReducedPom>false</createDependencyReducedPom>
        </configuration>
        <executions>
          <execution>
            <phase>package</phase>
            <goals>
              <goal>shade</goal>
            </goals>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>

Source: http://docs.aws.amazon.com/lambda/latest/dg/java-create-jar-pkg-maven-no-ide.html

Potentially you may have this issue https://github.com/aws/aws-lambda-java-libs/issues/2 which requires a downgrade to aws-lambda-java-events-1.0.0.jar

pattyd
  • 5,927
  • 11
  • 38
  • 57
Mike76
  • 914
  • 7
  • 8
  • 3
    Unfortunately, this did not work for me...still getting the same exception. – Brooks Sep 26 '15 at 02:13
  • 1
    Ah, just seen your pom.xml. Try using the maven-shade plugin as detailed here: http://docs.aws.amazon.com/lambda/latest/dg/java-create-jar-pkg-maven-no-ide.html – Mike76 Sep 26 '15 at 09:44
  • Worked! I'll accept, but you should put the URL in your answer so it can be upvoted some more. – Brooks Sep 26 '15 at 11:16
  • Excellent. I've edited the answer. Does it still work with aws-lambda-java-events-1.1.0.jar? If so, I'll remove that part from the answer so it doesn't mislead anyone else. – Mike76 Sep 26 '15 at 18:49
  • I just tried it with 1.1.0 and it worked still. It was just that it couldn't find it. What's strange is that it couldn't find it, even when I had the jar's installed. In fact, someone on the AWS forums had the same problem and he had the jar's installed as well. I suggested he use the shade plugin and it worked for him as well. Thanks! – Brooks Sep 27 '15 at 17:10
  • Hi there, I tried your solution bt its still shows me some comflict with the spring dependencies and the amazon libraries... – Baradwaj Aryasomayajula Mar 19 '16 at 02:54
  • Worked like a charm!! Spent hours searching for the solution!! Thank you. – Lakshman Diwaakar Jan 16 '17 at 06:15
  • Is it normal that the jar is very large after shading? – Jakub Wisniewski Apr 19 '19 at 11:48
  • How to use this plugin in case of gradle ? – Bishnu Das May 14 '20 at 11:50
  • For reducing the shaded-jar size - https://stackoverflow.com/questions/8817257/minimize-an-uber-jar-correctly-using-shade-plugin – Sanket Mehta Jun 11 '20 at 12:01
3

=== If this issue exists even after including shaded jar ===

If you have this issue even after having shaded jar then the issue should be related to aws-lambda-java-events package version (should be some incompatibility between AWS lamda version and newer aws-lambda-java-events version) . i.e. I had this issue with latest version (2.0.2) of aws-lambda-java-events package and I have to downgrade the version to 1.3.0.

Seems like newer aws-lambda-java-events version doesn't have many dependencies.

barath
  • 762
  • 1
  • 8
  • 26
2

Sometimes you have to upload your lambda again. Also I got the same issue I fixed with this pom.xml:

<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>

   <dependencyManagement>
  <dependencies>
    <dependency>
      <groupId>com.amazonaws</groupId>
      <artifactId>aws-java-sdk-bom</artifactId>
      <version>1.11.83</version>
      <type>pom</type>
      <scope>import</scope>
    </dependency>
  </dependencies>

 </dependencyManagement>

  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8.1</version>
      <scope>test</scope>
    </dependency>
  </dependencies>

   <build>
<plugins>
  <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-shade-plugin</artifactId>
    <version>2.3</version>
    <configuration>
      <createDependencyReducedPom>false</createDependencyReducedPom>
    </configuration>
    <executions>
      <execution>
        <phase>package</phase>
        <goals>
          <goal>shade</goal>
        </goals>
      </execution>
    </executions>
  </plugin>
</plugins>
 </build>
</project>
Paul Roub
  • 36,322
  • 27
  • 84
  • 93
0

In the plugins section of your pom.xml, add the Apache Maven Shade Plugin.It is used during the build process. This plugin is used for packaging jars to create a standalone .jar.The maven-shade-plugin will take artifacts (jars) produced by the package goal , and created a standalone .jar that contains the compiled code, and the resolved dependencies from the pom.xml.

<dependency>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.0.0</version>

user3165739
  • 166
  • 2
  • 3
0

If you have <scope>provided</scope> in aws-lambda-java-events artifact, remove it.

0

Whenever We tried to upload java based Jar or Zip into AWS lambda Console we have to take care of some basic things like,

The Code URI, Which is present in SAM Template or the template.yml file. eg: enter image description here

Eg: runwayDetails - package Name App - class name handleRequest - lambda handler method.

Syntax should be like this - packageName.className::methodName

It will solve the the error

0

upload the function.zip instead of jar to lambda

Ameen
  • 37
  • 3