Using the handler org.springframework.cloud.function.adapter.aws.FunctionInvoker::handleRequest
I'm receiving the following error when calling my API Gateway endpoint with the payload below. The function is found and it runs the business logic correctly until it returns and throws this NullPointerException:
Cannot invoke "java.util.Map.size()" because "m" is null: java.lang.NullPointerException
java.lang.NullPointerException: Cannot invoke "java.util.Map.size()" because "m" is null
at java.base/java.util.HashMap.putMapEntries(HashMap.java:495)
at java.base/java.util.HashMap.<init>(HashMap.java:484)
at org.springframework.cloud.function.context.catalog.SimpleFunctionRegistry$FunctionInvocationWrapper.enrichInvocationResultIfNecessary(SimpleFunctionRegistry.java:757)
at org.springframework.cloud.function.context.catalog.SimpleFunctionRegistry$FunctionInvocationWrapper.invokeFunctionAndEnrichResultIfNecessary(SimpleFunctionRegistry.java:914)
at org.springframework.cloud.function.context.catalog.SimpleFunctionRegistry$FunctionInvocationWrapper.invokeFunction(SimpleFunctionRegistry.java:863)
at org.springframework.cloud.function.context.catalog.SimpleFunctionRegistry$FunctionInvocationWrapper.doApply(SimpleFunctionRegistry.java:716)
at org.springframework.cloud.function.context.catalog.SimpleFunctionRegistry$FunctionInvocationWrapper.apply(SimpleFunctionRegistry.java:559)
at org.springframework.cloud.function.adapter.aws.FunctionInvoker.handleRequest(FunctionInvoker.java:85)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
END
However, according to the documentation I should be using the handler org.springframework.cloud.function.adapter.aws.SpringBootApiGatewayRequestHandler::handleRequest
but when I do so it does not find the function. I have set both FUNCTION_NAME and MAIN_CLASS environment variables to their respective values.
Class not found: org.springframework.cloud.function.adapter.aws.SpringBootApiGatewayRequestHandler: java.lang.ClassNotFoundException
java.lang.ClassNotFoundException: org.springframework.cloud.function.adapter.aws.SpringBootApiGatewayRequestHandler
at java.base/java.net.URLClassLoader.findClass(URLClassLoader.java:445)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:587)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:520)
at java.base/java.lang.Class.forName0(Native Method)
at java.base/java.lang.Class.forName(Class.java:467)
END RequestId: 83965357-a424-4c0f-b846-7486245380c7
Function
public class Makeuser implements Function<Message<APIGatewayRequest>, Message<User>> {
@Override
public Message<User> apply(Message<APIGatewayRequest> request) {
...
}
}
Application
@SpringBootApplication
public class DemoApplication{
public static void main(String[] args) {
}
}
Request Payload
{
"userRequest": {
"firstName": "userfirst",
"lastName": "userlast",
"email": "user@gmail.com",
"age": 21
}
}
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>demo</artifactId>
<version>4.0.0.RELEASE</version>
<packaging>jar</packaging>
<name>demo</name>
<description>Non-native demo application</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.0.0-SNAPSHOT</version>
<relativePath/>
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<wrapper.version>1.0.28.RELEASE</wrapper.version>
<aws-lambda-events.version>3.11.0</aws-lambda-events.version>
<spring-cloud-function.version>4.0.0-SNAPSHOT</spring-cloud-function.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-function-adapter-aws</artifactId>
</dependency>
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-lambda-java-events</artifactId>
<version>${aws-lambda-events.version}</version>
</dependency>
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-lambda-java-core</artifactId>
<version>1.2.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.modelmapper</groupId>
<artifactId>modelmapper</artifactId>
<version>3.1.0</version>
</dependency>
<dependency>
<groupId>com.github.derjust</groupId>
<artifactId>spring-data-dynamodb</artifactId>
<version>5.1.0</version>
</dependency>
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-java-sdk-dynamodb</artifactId>
<version>1.12.272</version>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-function-dependencies</artifactId>
<version>${spring-cloud-function.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-deploy-plugin</artifactId>
<configuration>
<skip>true</skip>
</configuration>
</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>${wrapper.version}</version>
</dependency>
</dependencies>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.3.0</version>
<configuration>
<createDependencyReducedPom>false</createDependencyReducedPom>
<shadedArtifactAttached>true</shadedArtifactAttached>
<shadedClassifierName>aws</shadedClassifierName>
</configuration>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>spring-snapshots</id>
<name>Spring Snapshots</name>
<url>https://repo.spring.io/snapshot</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>spring-snapshots</id>
<name>Spring Snapshots</name>
<url>https://repo.spring.io/snapshot</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
</pluginRepository>
<pluginRepository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</pluginRepository>
</pluginRepositories>
</project>
This is the documentation I'm working from: https://docs.spring.io/spring-cloud-function/docs/4.0.0-SNAPSHOT/reference/html/aws.html
Update
I switched the spring-cloud-function version from 4.0.0.RELEASE to 3.2.6 and updated the Function class to remove the Message types. The lambda succeeds in test but fails when making the request from Postman to the API Gateway.
Function
public class Makeuser implements Function<APIGatewayRequest, User> {
@Override
public Message<User> apply(APIGatewayRequest request) {
...
return user;
}
}
Stacktrace
Successfully saved user to database 2d1ed481-999e-4e2d-afc0-62f5315c8f4b user1first user1last user1@gmail.com 21
org/springframework/http/HttpStatus: java.lang.NoClassDefFoundError
java.lang.NoClassDefFoundError: org/springframework/http/HttpStatus
at org.springframework.cloud.function.adapter.aws.AWSLambdaUtils.generateOutput(AWSLambdaUtils.java:196)
at org.springframework.cloud.function.adapter.aws.FunctionInvoker.buildResult(FunctionInvoker.java:147)
at org.springframework.cloud.function.adapter.aws.FunctionInvoker.handleRequest(FunctionInvoker.java:114)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
Caused by: java.lang.ClassNotFoundException: org.springframework.http.HttpStatus
... 7 more
END RequestId: 3811dd35-342c-4088-7ef4-f3ed86798b9f