Its very simple. This code works as jar and lambda (maven project):
package test2;
import java.util.Map;
import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;
public class test implements RequestHandler<Map<String,String>, String>{
@Override
public String handleRequest(Map<String,String> event, Context context)
{
String prueba = "Prueba";
return prueba;
}
public static void main(String[] args) {
// TODO Auto-generated method stub
System.out.println("Testing def");
}
}
Pom.xml with dependencies:
<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>test2</groupId>
<artifactId>test2</artifactId>
<version>0.0.1-SNAPSHOT</version>
<build>
<sourceDirectory>src</sourceDirectory>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<release>17</release>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<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>3.11.2</version>
</dependency>
</dependencies>
</project>
I export it as a runable jar, with its run configuration:
export; runnable jar file; runable configuration and package required libraries
Later I go to localstack:
aws –endpoint-url=http://localhost:4566 lambda create-function –function-name Test3 –runtime java17 –handler test2.test::handleRequest –role arn:aws:iam::000000000000:role/RolLambda –zip-file fileb://./test.jar
aws –endpoint-url=http://localhost:4566 lambda invoke –function-name Test3 output.json
Output: It works!
Now the code THAT DOESNT WORK as lambda (maven project too). I only added a kinesisclient object:
package main;
import java.net.URI;
import java.util.Map;
import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.kinesis.KinesisClient;
public class Test implements RequestHandler<Map<String,String>, String>{
public static void main(String[] args) {
// TODO Auto-generated method stub
System.out.println("Testing def");
}
@Override
public String handleRequest(Map<String,String> event, Context context)
{
String Error = "kinesis_Error";
String prueba = "Prueba";
try {
KinesisClient kinesis_client = KinesisClient.builder().region(Region.US_EAST_1).endpointOverride(URI.create("http://127.0.0.1:4566")).build();
} catch (Exception e) {
return Error;
}
return prueba;
}
}
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>definitive_test</groupId>
<artifactId>definitive_test</artifactId>
<version>0.0.1-SNAPSHOT</version>
<build>
<sourceDirectory>src</sourceDirectory>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<release>17</release>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<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>3.11.2</version>
</dependency>
<dependency>
<groupId>software.amazon.awssdk</groupId>
<artifactId>kinesis</artifactId>
<version>2.20.135</version>
</dependency>
</dependencies>
</project>
I do the same steps:
-runnable jar with the properly configuration set
-create lambda and make the execution:
aws –endpoint-url=http://localhost:4566 lambda create-function –function-name Test3 –runtime java17 –handler main.Test::handleRequest –role arn:aws:iam::000000000000:role/RolLambda –zip-file fileb://./test.jar
But now I get the unhandled:
aws –endpoint-url=http://localhost:4566 lambda invoke –function-name Test3 output.json
{
"StatusCode": 200,
"FunctionError": "Unhandled",
"ExecutedVersion": "$LATEST"
}
The output:
{"errorMessage":"software/amazon/awssdk/services/kinesis/KinesisClient","errorType":"java.lang.NoClassDefFoundError","stackTrace":["main.Test.handleRequest(Test.java:25)","java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)","java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)","java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)","java.base/java.lang.reflect.Method.invoke(Unknown Source)"],"cause":{"errorMessage":"software.amazon.awssdk.services.kinesis.KinesisClient","errorType":"java.lang.ClassNotFoundException","stackTrace":["java.base/java.net.URLClassLoader.findClass(Unknown Source)","java.base/java.lang.ClassLoader.loadClass(Unknown Source)","java.base/java.lang.ClassLoader.loadClass(Unknown Source)","main.Test.handleRequest(Test.java:25)","java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)","java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)","java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)","java.base/java.lang.reflect.Method.invoke(Unknown Source)"]}}
I don’t know why this happens. I have already checked rol permissions. I think its ok (its the arn arn:aws:iam::000000000000:role/RolLambda)
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "lambda:*",
"Resource": "*"
},
{
"Effect": "Allow",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::bucket1/*"
},
{
"Effect": "Allow",
"Action": "s3:PutObject",
"Resource": "arn:aws:s3:::bucket1/*"
},
{
"Effect": "Allow",
"Action": [
"kinesis:PutRecord",
"kinesis:PutRecords",
"kinesis:GetRecords",
"kinesis:GetShardIterator",
"kinesis:DescribeStream",
"kinesis:ListStreams"
],
"Resource": "*"
}
]
}
Any suggestions? Thanks for your time
2
Answers
Finally the issue was the jar compilation. Here is the build of a basic pom.xml that put jar dependencies into final jar:
You can put any dependency you need in dependencies flag. And you need to input your package and main class in mainclass flag (in my case productor.Productor). Properties set java version and encoding. Now with @smac2020 command mvn package you can make JAR file correctly. Now I face a aws credential problem in a more complex code, but that's other history ':/
I will test that code. However – i will make a few changes. 1st to ensure all of the dependencies are included in your JAR, I will create a FAT JAR using:
mvn package
Then to test it, I will upload the JAR to the Lambda AWS console and directly invoke the Lambda function using the AWS Console.
By the way – your issues is this:
errorMessage":"software/amazon/awssdk/services/kinesis/KinesisClient","errorType":"java.lang.NoClassDefFoundError","stackTrace":
The Kinesisclient cannot be found. This means you did not create the JAR properly.
UPDATE
As promised – here is the result. The code works when built with mvn package and deploying via AWS Lambda Console at
https://us-east-1.console.aws.amazon.com/lambda/home?region=us-east-1#/functions
The Java Code.
I deployed it using the AWS Lambda console:
I tested it and it worked pefectly:
Here is output in logs:
Finally my POM (there may be a few extra dependencies):