Running micronaut serverless locally

1.3k views Asked by At

I'm trying to create an AWS Lambda function with micronaut using functions i.e. I created my poc project with:

mn create-function-app --build=maven --jdk=11 micronaut-test

I can build and deploy it to AWS very easily but I wonder if there is a way to run it locally so I can quickly test changes in the same way you can run a regular micronaut app with

mvn mn:run

Right now is just the sample app, reformulating my question; Can I trigger the execute method in BookRequestHandler without uploading it to AWS?

Thanks in advance.

2

There are 2 answers

1
Fernando Soto Dev On BEST ANSWER

Maven profiles can be used to select the runtime (in this expample uses netty) and the main class:

    <profiles>
        <profile>
            <id>local</id>
            <properties>
                <exec.mainClass>micronaut.Application</exec.mainClass>
                <micronaut.runtime>netty</micronaut.runtime>
            </properties>
            <dependencies>
                <dependency>
                    <groupId>io.micronaut</groupId>
                    <artifactId>micronaut-http-server-netty</artifactId>
                    <scope>compile</scope>
                </dependency>
            </dependencies>
        </profile>
    </profiles>

Create the main class with a controller with a Post method that calls the function

package micronaut;

import io.micronaut.http.annotation.Body;
import io.micronaut.http.annotation.Controller;
import io.micronaut.http.annotation.Post;
import io.micronaut.runtime.Micronaut;
import micronaut.test.Book;
import micronaut.test.BookRequestHandler;
import micronaut.test.BookSaved;

public class Application {

    public static void main(String[] args) {
        Micronaut.run(Application.class, args);
    }

    @Controller()
    public static class LambdaController {

        private static final BookRequestHandler handler = new BookRequestHandler();

        @Post
        public BookSaved execute(@Body Book book) {
            return handler.execute(book);
        }
    }
}

and run with

mvnw mn:run -Plocal

Now you can use

curl --location --request POST 'http://localhost:8080/' \
--header 'Content-Type: application/json' \
--data-raw '{"name": "Test"}'

returning

{
    "name": "Test",
    "isbn": "2a163c3d-4bd6-444d-914d-58daf3e649b8"
}

This a bit hacky, to test your function you can see micronaut-test/src/test/java/micronaut/test/BookRequestHandlerTest.java class or see Testing Lambda Handlers official docs.

Note: For applications created with mn create-app -f aws-lambda ... is not needed the <exec.mainClass> in pom.xml, and the Application.java is generated.

0
Dangari On

I wanted to achieve the same result using a Micronaut project with Gradle and Kotlin, and after extensive searching, this was the only solution I found. Now, I'd like to share my solution with others who may encounter the same problem while working with Gradle.

Define a new configuration in your build.gradle file:

configurations {
    create("localRuntime")
}

Add the Micronaut Netty runtime dependency to your dependencies block:

dependencies {
    ...
    localRuntime("io.micronaut:micronaut-http-server-netty:$micronautVersion")
}

Make sure to replace $micronautVersion with the appropriate version of Micronaut. Create a new Gradle task to run the project locally:

tasks.register('runLocal', JavaExec) {
    print(configurations.getByName("localRuntime"))
    classpath = configurations.getByName("localRuntime") + sourceSets.main.runtimeClasspath
    mainClass = "com.example.ApplicationKt"
    args("--micronaut.runtime=netty")
}

Run the project locally using the runLocal task:

gradle runLocal

My Application.kt:

package com.example

import io.micronaut.runtime.Micronaut.run


fun main(args: Array<String>) {
    run(*args)
}

Controller:

package com.example

import io.micronaut.http.annotation.Controller
import io.micronaut.http.annotation.Get

@Controller
class ExampleController {

    @Get("/hello")
    fun helloWorld() = mapOf("message" to "Hello World")
}