2

I have a Spring Boot demo project. I am trying to deploy them in AWS Lambda, but I get ClassNotFoundException even thought my jar that I upload contains of the necessary dependencies.

Here goes my code:

pom.xml

<dependencies>
 <dependency>
 <groupId>com.amazonaws</groupId>
 <artifactId>aws-lambda-java-core</artifactId>
 <version>1.2.1</version>
 </dependency>
 <dependency>
 <groupId>com.amazonaws</groupId>
 <artifactId>aws-lambda-java-events</artifactId>
 <version>3.6.0</version>
 </dependency>
 <dependency>
 <groupId>com.amazonaws.serverless</groupId>
 <artifactId>aws-serverless-java-container-spring</artifactId>
 <version>[0.1,)</version>
 </dependency>
</dependencies>
<build>
 <plugins>
 <plugin>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-maven-plugin</artifactId>
 </plugin>
 <plugin>
 <groupId>org.apache.maven.plugins</groupId>
 <artifactId>maven-shade-plugin</artifactId>
 <version>3.2.4</version>
 <configuration>
 <createDependencyReducedPom>false</createDependencyReducedPom>
 </configuration>
 <executions>
 <execution>
 <phase>package</phase>
 <goals>
 <goal>shade</goal>
 </goals>
 </execution>
 </executions>
 </plugin>
 </plugins>
</build>

Application Class

@SpringBootApplication
public class DemoApplication extends SpringBootServletInitializer {
 public static void main(String[] args) {
 SpringApplication.run(DemoApplication.class, args);
 System.out.println("Welcome to demo project");
 }
}

Controller Class

@RestController
public class DemoController {
 @GetMapping(value="/getValue")
 public String getId() {
 return " Call from controller";
 }
}

LambdaHandler Class

public class DemoLambdaHandler implements RequestStreamHandler {
 public static SpringBootLambdaContainerHandler<AwsProxyRequest, AwsProxyResponse> handler;
 static {
 try {
 handler = SpringBootLambdaContainerHandler.getAwsProxyHandler(DemoApplication.class);
 } catch (ContainerInitializationException e) {
 e.printStackTrace();
 throw new RuntimeException("Container not initialized", e);
 }
 }
 @Override
 public void handleRequest(InputStream input, OutputStream output, Context context) throws IOException {
 // TODO Auto-generated method stub
 handler.proxyStream(input, output, context);
 }
}

Not sure what I could be missing in this. Kindly help. Below is my inspected jar enter image description here

asked Dec 1, 2020 at 9:15
4
  • 2
    Did you inspect your resulting JAR and made sure that all dependencies are embedded? And please provide the stacktrace of your ClassNotFoundException. It is important to know which class can not be found. Commented Dec 1, 2020 at 10:46
  • This is the stacktrace. Lambda function is not able to find my handler class. START RequestId: 4570a805-7daa-4938-a950-90c463096d87 Version: $LATEST Class not found: com.example.demo.handler.LambdaHandler: java.lang.ClassNotFoundException java.lang.ClassNotFoundException: com.example.demo.handler.LambdaHandler at java.net.URLClassLoader.findClass(URLClassLoader.java:382) at java.lang.ClassLoader.loadClass(ClassLoader.java:424) at java.lang.ClassLoader.loadClass(ClassLoader.java:357) at java.lang.Class.forName0(Native Method) at java.lang.Class.forName(Class.java:348) Commented Dec 3, 2020 at 7:56
  • "Also I have inspected my jar file. It contains all the necessary dependencies" Commented Dec 3, 2020 at 7:58
  • I had a similar issue the problem was my lambda handler define in the CloudFormation. Now it needs the method name: package.class::handleRequest. Before the explicit method name was not needed. Commented Apr 5, 2023 at 13:35

4 Answers 4

3

I had the same issue, I fixed it marking Spring Boot as a dependency.

By default, Spring Boot plugin will pack your classes into "BOOT-INF/classes" directory, but AWS is looking for the handler class from the root directory so it can't find it.

You can check this by extracting your .jar file and seeing if your file is in:

BOOT-INF/classes/com/example/demo/handler/LambdaHandler.class

instead of:

com/example/demo/handler/LambdaHandler.class

To solve it, just mark your package as exec in your pom.xml file:

<plugin>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-maven-plugin</artifactId>
 <version>2.6.1</version>
 <configuration>
 <classifier>exec</classifier>
 </configuration>
</plugin>

More info here: Spring Boot as a Dependency

answered Mar 18, 2022 at 18:22
Sign up to request clarification or add additional context in comments.

1 Comment

I don't know why this reply hasn't get any upvote) This was exactly my problem. Thank you!
2

Did you find a solution to this? I have been getting the same exact error.

What I can tell so far is that unlike other languages like nodejs, the docker image for java has the command specified like CMD [ "com.example.LambdaHandler::handleRequest" ], instead the nodejs one is CMD [ "app.handler" ]. The difference here is that the nodejs one specifies what the file is e.g. app.js with function called handler.

But the java one only has the class path without the ability to specify the path to the fat JAR file even when the jar file is located in "var/task". How would lambda know the JAR file name?

answered Dec 14, 2020 at 15:58

Comments

0

Try building the project with Maven and ensure you have the required maven-shade-plugin in your POM so that the JAR that is built with the dependencies when you run mvn package. If you are missing this plugin, you will create a JAR that does not contain the dependencies and you will encounter ClassNotFoundException.

To learn how to build and deploy a Lambda function by using the Lambda runtime Java API, see this AWS tutorial. It will walk you step by step through the process of building Lambda functions that work:

https://github.com/awsdocs/aws-doc-sdk-examples/tree/master/javav2/usecases/creating_workflows_stepfunctions

This tutorial then uses the Lambda functions within Step Functions to create a workflow.

Lambda functions are created using the Lambda runtime Java API -- com.amazonaws.services.lambda.runtime.RequestHandler. Please do not use Spring BOOT APIs to create a Lambda function.

However, If you want to invoke a Lambda function from a Spring boot app and then for example display the result in a view, then you can use the Lambda Client Java API - which is software.amazon.awssdk.services.lambda.LambdaClient.

So in summary:

answered Dec 18, 2020 at 2:29

Comments

-2

Please add these two dependencies in pomfile

1)aws-lambda-java-core

2)aws-lambda-java-events

This should fix it

2 Comments

Please add some explanation to your answer such that others can learn from it
These 2 dependencies are already there, but still the error is coming. And please explain how these are related to the ClassNotFound error

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.