I'm trying to implement an AWS Lambda service using Java Spring. I've gone through a whole bunch of tutorials which have told me a whole bunch of ways to do it, but I can't get it to work.
The main problem I'm having is that the AWS Lambda library requires classes to have zero-arg constructors, which makes it difficult to use the Spring IOC container. I found a tutorial which has a workaround for that and is able to inject my Spring beans into the class after creation, but that approach doesn't seem to work for bean instantiations of anonymous classes created from defined interfaces (e.g. Spring Data Repositories), which is something my application uses.
I found a tutorial on the Spring wrapper for the AWS lambda library, but that also doesn't seem to work; I think I've copied their code more or less properly from their sample code, but when I run it on Lambda I get the following error:
START RequestId: d9e62756-e72b-45f0-8df4-2164f3979dd7 Version: $LATEST
Failed to discover main class. An attempt was made to discover main class as 'MAIN_CLASS' environment variable, system property as well as entry in META-INF/MANIFEST.MF (in that order).: java.lang.IllegalStateException
java.lang.IllegalStateException: Failed to discover main class. An attempt was made to discover main class as 'MAIN_CLASS' environment variable, system property as well as entry in META-INF/MANIFEST.MF (in that order).
at org.springframework.cloud.function.utils.FunctionClassUtils.getStartClass(FunctionClassUtils.java:83)
at org.springframework.cloud.function.utils.FunctionClassUtils.getStartClass(FunctionClassUtils.java:60)
at org.springframework.cloud.function.adapter.aws.FunctionInvoker.start(FunctionInvoker.java:104)
at org.springframework.cloud.function.adapter.aws.FunctionInvoker.<init>(FunctionInvoker.java:70)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
Here's my code:
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<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">
<parent>
<artifactId>spring-boot-starter-parent</artifactId>
<groupId>org.springframework.boot</groupId>
<version>2.2.4.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>JobsTest</artifactId>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-function-adapter-aws</artifactId>
<version>3.0.2.RELEASE</version>
</dependency>
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-lambda-java-events</artifactId>
<version>2.0.2</version>
</dependency>
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-lambda-java-core</artifactId>
<version>1.1.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
<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>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<configuration>
<createDependencyReducedPom>false</createDependencyReducedPom>
<shadedArtifactAttached>true</shadedArtifactAttached>
<shadedClassifierName>aws</shadedClassifierName>
</configuration>
</plugin>
</plugins>
</build>
</project>
JobTestApplication.java (a sample PoC application I'm using to try to get this dang thing working, then I'm going to add more advanced features to it one by one):
package jobtest;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import java.util.function.Function;
@SpringBootApplication
public class JobTestApplication {
public static void main(String[] args) {
SpringApplication.run(JobTestApplication.class, args);
}
@Bean
public Function<Object, String> uppercase() {
return input -> "Hello World!";
}
}
Can someone explain to me what I'm doing wrong? I've spent 2 and a half days on this and I can't figure it out. Thanks.
