AWS Lambda: class java.lang.ClassNotFoundException
Asked Answered
H

6

16

I am getting this message and I have no idea how to resolve it. Searched online and tried to implement their suggestion, but no luck yet. enter image description here

I basically followed the instructions specified in this link - http://docs.aws.amazon.com/toolkit-for-eclipse/v1/user-guide/lambda-tutorial.html

But instead of uploading the project using the AWS Management Console embedded in Eclipse, I tried to create a zip of my project and upload it to the AWS web console.

Below is structure of my project - enter image description here

That is it!! There is nothing fancy that I am trying to do here. It is just a HelloWorld example in Lambda.

Now, this is how I am creating the zip file, which is pretty straight forward in Eclipse - enter image description here

Once the zip is created I uploaded it to AWS Web console under the code tab - enter image description here

The Configuration tab looks something like this - enter image description here

Now when I am clicking the Test button it is unable to find the example.Hello class.

How come it is becoming so difficult for the Lambda Function to find this class? Can anyone suggest what possibly is going wrong in this execution??

Also attached the log statement, in case it helps -

enter image description here

Halfmast answered 9/3, 2017 at 10:44 Comment(2)
I resolved this issue, by making the following changes - First, I have changed the method signature to :: public String handleRequest(Map<String,Object> input, Context context) :: and second, instead of exporting it to zip I exported it to normal jar, after making those two changes AWS Lambda was able to find the class. Hope this helps and save your time.Halfmast
Just wanna chime in that i tried the same thing and just uploaded the uber jar file to s3 instead of a zipped package of it and it worked for me.Gynecoid
P
13

The following worked for me.

  1. Go to your lambda function in AWS Console
  2. Click on Code tab.
  3. Edit Run time settings
  4. Replace example.Hello::handleRequest with full class path of your stream handler. For example com.abc.company.app.StreamLambdaHandler::handleRequest
  5. Save it.
Precritical answered 8/3, 2021 at 5:31 Comment(0)
F
3

I had the same problem, what worked for me was if you're running this from eclipse with maven, ensure you have the following plugin in your pom.xml:

  <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-shade-plugin</artifactId>
    <version>3.0.0</version>
    <executions>
      <execution>
        <phase>package</phase>
        <goals>
          <goal>shade</goal>
        </goals>
        <configuration>
          <artifactSet>
            <excludes>
              <exclude>com.amazonaws:aws-lambda-java-events</exclude>
              <exclude>com.amazonaws:aws-lambda-java-core</exclude>
            </excludes>
          </artifactSet>
        </configuration>
      </execution>
    </executions>
  </plugin>

Then run the project with: mvn package shade:shade to generate the jar artifacts in your target directory. After that, eclipse should upload the correct jar to lambda.

Feu answered 27/7, 2017 at 7:49 Comment(2)
I'm having a similar problem and was wondering ... what is "shade" and why do you think this solved the problem? Sorry but I'm a bit out of my depths when it comes to Java.Bergeman
Shade plugin builds JAR with all dependenciesSuperannuate
S
0

Note that the generic type of your RequestHandler interface is different from the default one :

default: public class Hello implements RequestHandler<Object, String>

yours: public class Hello implements RequestHandler<String, String>

The reason why it is giving ClassNotFoundException

Sing answered 4/5, 2018 at 12:39 Comment(0)
A
0

Instead of maven-shade-plugin, you can use spring-boot-maven-plugin plugin with spring-boot-thin-layout dependency and other configurations as shown in below plugin.

<plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot.experimental</groupId>
            <artifactId>spring-boot-thin-layout</artifactId>
            <version>1.0.26.RELEASE</version>
        </dependency>
    </dependencies>
    <configuration>
        <createDependencyReducedPom>false</createDependencyReducedPom>
        <shadedArtifactAttached>true</shadedArtifactAttached>
        <shadedClassifierName>aws</shadedClassifierName>
        <transformers>
            <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
                <resource>META-INF/spring.handlers</resource>
            </transformer>
            <transformer implementation="org.springframework.boot.maven.PropertiesMergingResourceTransformer">
                <resource>META-INF/spring.factories</resource>
            </transformer>
            <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
                <resource>META-INF/spring.schemas</resource>
            </transformer>
        </transformers>
    </configuration>
</plugin>

PS:

  1. remove maven-shade-plugin
  2. I've refereed Official documentation of spring.cloud.io
Alexaalexander answered 7/4, 2021 at 14:38 Comment(1)
Actually, spring-boot-maven-plugin caused ClassNotFoundException for the all the classes in the project, while maven-shade-plugin worked just fine. Also, AWS recommends shade - docs.aws.amazon.com/lambda/latest/dg/java-package.htmlDetroit
S
0

Non-Maven answer

The reason why it's not working is because Lambda is expecting compiled *.class files in the zip. Unfortunately it won't compile the Java files for you.

I was getting the same error message as you when trying to upload a standalone Java file (not using Maven or Gradle or anything else). Although not very well-documented, I noticed this subtle detail on AWS documentation hinting at the class files (the grep part):

Example test-zip.sh

mkdir -p expanded
unzip path/to/my/function.zip -d expanded
find ./expanded/lib -name '*.jar' | xargs -n1 zipinfo -1 | grep '.*.class' | >sort | uniq -c | sort

When I uploaded a zip file with just the class file, Lambda ended up finding the file correctly. Although, I had to remove the AWS Context parameter just for it to compile, so Lambda produced a different error message saying the handler method signature didn't match (it found the file though).

Salinometer answered 28/10, 2021 at 0:31 Comment(0)
N
0

Sample java Code: filename : Main.java

package org.example;   
public class Main implements RequestHandler<Map<String,String>, String> {
    Gson gson = new GsonBuilder().setPrettyPrinting().create();

    @Override
    public String handleRequest(Map<String, String> event, Context context) {
...}
...}

Set configuration as follows:

Handler

org.example.Main::handleRequest

Nazi answered 2/8, 2022 at 10:34 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.