micronaut-gradle-plugin icon indicating copy to clipboard operation
micronaut-gradle-plugin copied to clipboard

Runtime lambda_provided forces function-app main class to default MicronautLambdaRuntime implementation

Open miguelaferreira opened this issue 1 year ago • 6 comments

Expected Behavior

Changing the runtime to lambda_provided should not affect the defined main class for the application, or at least respect that value when explicitly set.

Actual Behaviour

Setting the runtime to lambda_provided, changes the main class defined in the manifest of the built JARs to io.micronaut.function.aws.runtime.MicronautLambdaRuntime.

Steps To Reproduce

  1. Create an application
    mn create-function-app -f aws-lambda-custom-runtime,aws-lambda test-function-app
    cd test-function-app
    
  2. Change build.gradle to set lambda_provided runtime and a different docker container base image
    35c35
    <     runtime("lambda_java")
    ---
    >     runtime("lambda_provided")
    
  3. Build a JAR for the app
    ./gradlew assemble
    cat build/tmp/runnerJar/MANIFEST.MF | grep "Main-Class"
    
    The main class is io.micronaut.function.aws.runtime.MicronautLambdaRuntime

Environment Information

  • Chip: Apple M2 Max
  • Operating System: macOS 13.5.1 (22G90)
  • JDK Version:
    openjdk version "17.0.8" 2023-07-18
    OpenJDK Runtime Environment GraalVM CE 17.0.8+7.1 (build 17.0.8+7-jvmci-23.0-b15)
    OpenJDK 64-Bit Server VM GraalVM CE 17.0.8+7.1 (build 17.0.8+7-jvmci-23.0-b15, mixed mode, sharing)
    

Example Application

No response

Version

4.1.0

miguelaferreira avatar Sep 03 '23 10:09 miguelaferreira

@miguelaferreira lambda-provided is a runtime thought when you deploy to AWS Lambda custom runtime. We need the main class to be the entry point of the Native Image which does the Lambda runtime API polling.

If you want to deploy a JAR file to a AWS Lambda Java runtime, you should use lambda_java runtime instead.

sdelamo avatar Sep 21 '23 09:09 sdelamo

@sdelamo Thanks for getting back to me.

I don't want to deploy a jar, I want to deploy as a container image. Specifying lambda_provided sets the main class to the default micronaut implementation, and then I can't build my container image using the docker gradle tasks.

If there was a way to let me define my own main class, that would solve my problem.

miguelaferreira avatar Sep 21 '23 10:09 miguelaferreira

we don't have any runtime tailored to deploy as a container image. why do you want to do that instead of native executable to custom runtime or java runtime?

sdelamo avatar Sep 22 '23 17:09 sdelamo

Isn't the custom runtime deployed as a container as well? I've always assumed custom runtime is deployed as a container.

Next to that, the MicronautLambdaRuntime class seems wired for API Gateway, and my lambda function isn't integrated with that. Therefore I want to implement my own class and have that wired as the main class of my application.

miguelaferreira avatar Sep 24 '23 10:09 miguelaferreira

It seems that all lambdas I run face this problem now after upgrading to Micronaut 4. For one I was running Micronaut 4.0.0-RC5 with the gradle plugin version 4.0.0-M8. After upgrading to Micronaut 4.3.1 and gradle plugin version 4.0.4, the lambda stops working due to the manipulation of the main class.

As I mentioned before, not all lambdas are integrated with ApiGateway, in my case they are triggered directly form S3 events. I now get errors like this:

Invocation with requestId [6b81b933-0322-460a-b7af-9f6e1af61eca] failed: Cannot invoke "String.length()" because "this.input" is null 
java.lang.NullPointerException: Cannot invoke "String.length()" because "this.input" is null
at java.base/java.net.URI$Parser.parse(Unknown Source)
at java.base/java.net.URI.<init>(Unknown Source)
at java.base/java.net.URI.create(Unknown Source)
at io.micronaut.function.aws.proxy.payload1.ApiGatewayProxyServletRequest.<init>(ApiGatewayProxyServletRequest.java:59)
...

The workaround I've used in other functions is to not use gradle to build the docker containers for the function. That means I have to create and maintain my own Dockerfile and scripts around it, for example like this.

Imposing an implementation for the main class of any lambda function seems overly restrictive from Micronaut.

miguelaferreira avatar Oct 04 '23 10:10 miguelaferreira

I was reading the Micronaut docs again to make sure I didn't miss anything. Please correct me if I'm wrong, but what I understand from it is that we should be able to use custom runtimes and still define our own main class.

Micronaut’s dependency micronaut-function-aws-custom-runtime eases the creation of AWS Lambda Custom runtime to execute a Micronaut function.

The main API you will interact with is AbstractMicronautLambdaRuntime. An abstract class which you can extend to create your custom runtime mainClass. That class includes the necessary code to perform the Processing Tasks described in the Custom Runtime documentation.

Then it goes on saying that Microanut ships 3 already implemented main classes for functions that respond to HTTP triggers.

But maybe the custom runtimes are related to setting lambda-provided for runtime. I could use some clarification here on whether I should configure my build differently.

miguelaferreira avatar Oct 05 '23 10:10 miguelaferreira