Issue
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
Solution
Finally the issue was the jar compilation. Here is the build of a basic pom.xml that put jar dependencies into final jar:
<?xml version="1.0"?>
<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>Productor</groupId>
<artifactId>Productor</artifactId>
<version>0.0.1-SNAPSHOT</version>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<build>
<plugins>
<!-- Build an executable JAR with dependencies -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.3.0</version>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<archive>
<manifest>
<mainClass>productor.Productor</mainClass>
</manifest>
</archive>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<dependencies>
<!-- Otras dependencias aquà -->
<!-- Dependencia para el servicio de Amazon Kinesis -->
<dependency>
<groupId>software.amazon.awssdk</groupId>
<artifactId>kinesis</artifactId>
<version>2.20.135</version>
</dependency>
<!-- Dependencia para el servicio de Amazon S3 -->
<dependency>
<groupId>software.amazon.awssdk</groupId>
<artifactId>s3</artifactId>
<version>2.20.135</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>3.11.2</version>
</dependency>
</dependencies>
</project>
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 ':/
Answered By - Angel Sanchez
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.