GithubHelp home page GithubHelp logo

micronaut-projects / micronaut-aws Goto Github PK

View Code? Open in Web Editor NEW
83.0 83.0 81.0 61.38 MB

Projects specific to integrating Micronaut and Amazon Web Services (AWS)

License: Apache License 2.0

Java 71.04% Groovy 28.76% Kotlin 0.20% Handlebars 0.01%

micronaut-aws's People

Contributors

alvarosanchez avatar benrhine avatar cero-t avatar ctoestreich avatar davidgammon-mettle avatar dependabot-preview[bot] avatar dependabot[bot] avatar driverpt avatar dstepanov avatar forresthopkinsa avatar graemerocher avatar ilopmar avatar jameskleeh avatar micronaut-build avatar msupic avatar musketyr avatar n0tl3ss avatar niravassar avatar pgressa avatar puneetbehl avatar renovate[bot] avatar rnielsen avatar sbodvanski avatar sdelamo avatar shashankmishra avatar sullis avatar timyates avatar ttzn avatar wetted avatar zacharyklein avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

micronaut-aws's Issues

Filters not run on Exception in AWS API Gateway

Filters are not run when Exception Handlers are invoked and Micronaut is run through API Gateway integration.

The specific issue affecting me is that the CorsFilter is not running so CORS headers are not being added when exceptions are thrown.

Example project at https://github.com/rnielsen/micronaut-aws-apiproxy-test

curl -i http://localhost:8080/test/exception
HTTP/1.1 200 OK
X-Test-Filter: true

Exception Handled
curl -i https://3kf8ik2za4.execute-api.ap-southeast-2.amazonaws.com/dev/test/exception
HTTP/2 200 

Exception Handled

Tested against io.micronaut.aws:micronaut-function-aws-api-proxy:1.1.0.BUILD-SNAPSHOT"

application/json should be a default content type

API Gateway assumes that the endpoints accept/produce JSON objects. This should be the default for MIcronaut as well. Currently, for example, if you are missing the Content-Type header then @Body objects are not populated correctly.

SAM Testing of lambda - fails while deploying to AWS works!

Hello I was going through the article here .

I decided to experiment with a far simpler version - following though the steps of the article.
Full example project:https://www.dropbox.com/s/af87ua716lh85cw/papolambda.zip

Practically is a simple λ function that returns a String nothing special.

I have tried to test it with AWS ASM

sam --version
SAM CLI, version 0.11.0

echo '{}' | sam local invoke papolambda
  <properties>
    <micronaut.version>1.1.0.M1</micronaut.version>
    <jdk.version>8</jdk.version>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <exec.mainClass>io.micronaut.function.executor.FunctionApplication</exec.mainClass>
  </properties>

using the template.yaml below :

AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Globals:
  Function:
    Timeout: 25
Resources:
  papolambda:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: target/papolamda-0.1.jar
      Handler: io.micronaut.function.aws.MicronautRequestStreamHandler
      Runtime: java8

Where I get the following error :

START RequestId: f778d699-f29b-4410-a211-8ee626e6fb90 Version: $LATEST
java.lang.ClassNotFoundException: io.micronaut.function.aws.MicronautRequestStreamHandler
	at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
	at java.lang.Class.forName0(Native Method)
	at java.lang.Class.forName(Class.java:348)

END RequestId: f778d699-f29b-4410-a211-8ee626e6fb90
REPORT RequestId: f778d699-f29b-4410-a211-8ee626e6fb90	Duration: 6.81 ms	Billed Duration: 100 ms	Memory Size: 128 MB	Max Memory Used: 3 MB

While deploying to AWS it works!

Support for API Gateway with a custom domain

When using the API Gateway support added in micronaut-projects/micronaut-core#540 it works until you add a custom domain name to the API Gateway, then the Lambda is invoked but return a 404.

Steps to Reproduce

Not sure how I can add a easy to reproduce test case since some setup for the domain is needed.

  1. Create Micronaut app with AWS API Gateway support
  2. Create/use custom domain and add it to AWS API Gateway
  3. Call the custom domain name API URL

Expected Behaviour

Same output as the generated API Gateway URL should be given

Actual Behaviour

Tell us what happens instead

The Lambda is invoked but a HTTP 404 is generated.

  • There is some reference to this issue in the aws-serverless-java-container library: aws/serverless-java-container#112
  • @musketyr has already pointed out the same issue in his library: ttps://github.com/agorapulse/micronaut-libraries/blob/master/micronaut-function-aws-agp/src/main/groovy/com/agorapulse/micronaut/agp/ApiGatewayProxyHttpRequest.java#L203-L212

Environment Information

  • Operating System: AWS Lambda
  • Micronaut Version: 1.1.0.M2
  • JDK Version: 1.8

Self-injecting MicronautRequestHandler prevents Spock mocks

The MicronautRequestHandler currently creates its ApplicationContext during the handleRequest method, and uses it to inject its dependencies immediately before calling the abstract execute method implemented by the subclass.

For anyone using Spock as their test framework, this breaks the ability to implement tests using mocked beans that are injected into the handler class. I.e., in the current flow, a test is unable to:

  1. Create and start an ApplicationContext that will contain the mock versions of beans
  2. Extract the mocks from the started context, and call MockUtil.attachMock to attach them to the current specification
  3. Declare mock/stub interactions on the mocks
  4. Call the handler (which will then self-inject the mocks) prior to calling execute

I will submit a PR shortly with a proposed fix.

Improve the documentation about AWS API Gateway proxy and Lambda integration

This request is related to this stackoverflow question: https://stackoverflow.com/questions/54747222/how-to-create-a-crud-api-on-amazon-lambda-using-micronaut

I wanted to develop a CRUD API in a single Micronaut project, including all the processing functions in it and deploying a single Lambda function.

After a lot of trial and error I managed to make it work as described in the stackoverflow answer. I'd suggest clearing up the documentation in this regard.

Also, one thing that got me stuck for a while was the need to pass a host header in the API Gateway request, otherwise io.micronaut.function.aws.proxy.MicronautAwsProxyRequest with throw a NullPointerException at line 164: String hostHeader = awsProxyRequest.getMultiValueHeaders().getFirst(HttpHeaders.HOST); I'd be great if it were explicitly said that we have to pass it.

What's the point of setting this header? I set it to a made up value and everything works ok ->

hostHeader = new StringBuilder().append(requestContext.getApiId())
                    .append(".execute-api.")
                    .append(region)
                    .append(".amazonaws.com").toString();

Authorization header not bound in AWS API Gateway Lambda Authorizer

I am using Micronaut 1.1.0.M2 and have created a lambda function to act as an API Gateway Lambda Authorizer (https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-use-lambda-authorizer.html).

The user sends a header (JWT-Authorization) containing a Jwt token to validate in the authorizer. I've tried different ways to access it, but I haven't found a way to get its value in the Micronaut Controller.

The authorizer testing functionality from AWS shows this info when I execute a request:

Execution log for request 9c9ecac2-3f95-11e9-9c88-c13e47b5ed68
Tue Mar 05 22:25:42 UTC 2019 : Starting authorizer: tqjif0 for request: 9c9ecac2-3f95-11e9-9c88-c13e47b5ed68
Tue Mar 05 22:25:42 UTC 2019 : Incoming identity: ****ken
Tue Mar 05 22:25:42 UTC 2019 : Endpoint request URI: https://lambda.eu-central-1.amazonaws.com/2015-03-31/functions/arn:aws:lambda:eu-central-1:313316477550:function:micronaut-aws-lambda-authorizer/invocations
Tue Mar 05 22:25:42 UTC 2019 : Endpoint request headers: {x-amzn-lambda-integration-tag=9c9ecac2-3f95-11e9-9c88-c13e47b5ed68, Authorization=***************************************************************************************************************************************************************************************************************************************************************************************************************************2ea0f2, X-Amz-Date=20190305T222542Z, x-amzn-apigateway-api-id=9ed0gu04wl, X-Amz-Source-Arn=arn:aws:execute-api:eu-central-1:313316477550:9ed0gu04wl/authorizers/tqjif0, Accept=application/json, User-Agent=AmazonAPIGateway_9ed0gu04wl, X-Amz-Security-Token=FQoGZXIvYXdzEGcaDJysESX/XhVxv+8uUCK9A5euGyCl+MetHimyYVeuLi/qKKzX3zJRsaN9jV+jD+FAl6pRohhX3Q37JqZBClIHHA8vofZw+sktldCDWd2ncv2XhzUjm6YnB+YI8FsZSPfpC8hnE3b1IFF+C6Carfy61DwD+PDPVUebbTIUo0rNwzt6dIm86faV1lHYmn22biT2da7RY6QCvchEqzCcLxyB/oicQUvu09UvrL8+LOrrxoSzcZ+WAD4hv6t3nLi///pDwpMuL7f4uceCNgK6qPDSopQu+bnsK5caBiTbZLvkFzD2iSEiQrZTd28kXUhkCplaimDGEA1ebr [TRUNCATED]
Tue Mar 05 22:25:42 UTC 2019 : Endpoint request body after transformations: {"type":"TOKEN","methodArn":"arn:aws:execute-api:eu-central-1:313316477550:9ed0gu04wl/ESTestInvoke-stage/GET/","authorizationToken":"mytoken"}
Tue Mar 05 22:25:42 UTC 2019 : Sending request to https://lambda.eu-central-1.amazonaws.com/2015-03-31/functions/arn:aws:lambda:eu-central-1:313316477550:function:micronaut-aws-lambda-authorizer/invocations
Tue Mar 05 22:25:47 UTC 2019 : Authorizer result body before parsing: {"statusCode":502,"multiValueHeaders":{"Content-Type":["application/json"]},"body":"{\"message\":\"Gateway timeout\"}","isBase64Encoded":false}
Tue Mar 05 22:25:47 UTC 2019 : Execution failed due to configuration error: Invalid JSON in response: {"statusCode":502,"multiValueHeaders":{"Content-Type":["application/json"]},"body":"{\"message\":\"Gateway timeout\"}","isBase64Encoded":false}
Tue Mar 05 22:25:47 UTC 2019 : AuthorizerConfigurationException

So the user header is turned into a body containing the token as "authorizationToken":"mytoken".

I've tried to bind this info like this:

@Controller("/")
class AuthorizerController {

    private val logger = LoggerFactory.getLogger(LambdaAuthorizer::class.java)

    @Get
    fun authorize(@Body map: Map<Any, Any>): AuthPolicy {
        logger.info(map.toString())
        return AuthPolicy("", AuthPolicy.PolicyDocument.getDenyAllPolicy("", "", "", ""))
    }

}

This call fails with:

[36m22:25:46.987�[0;39m �[1;30m[main]�[0;39m �[1;31mERROR�[0;39m �[35mi.m.f.a.p.AbstractLambdaContainerHandler�[0;39m - Error while handling request
io.micronaut.web.router.exceptions.UnsatisfiedRouteException: Required argument [Map map] not specified
at io.micronaut.web.router.AbstractRouteMatch.execute(AbstractRouteMatch.java:279)
at io.micronaut.web.router.RouteMatch.execute(RouteMatch.java:122)
at io.micronaut.function.aws.proxy.MicronautLambdaContainerHandler.lambda$null$1(MicronautLambdaContainerHandler.java:240)
at io.reactivex.internal.operators.flowable.FlowableDefer.subscribeActual(FlowableDefer.java:35)

As an alternative I tried with HttpRequest:

@Controller("/")
class AuthorizerController {

    private val logger = LoggerFactory.getLogger(LambdaAuthorizer::class.java)

    @Get
    fun authorize(request: HttpRequest<String>): AuthPolicy {

        logger.info(request.body.toString())
        logger.info(request.headers.toString())
        logger.info(request.headers.values().toString())

        request.headers.forEach {
            logger.info("{} - {}", it.key, it.value)
        }

        return AuthPolicy("", AuthPolicy.PolicyDocument.getDenyAllPolicy("", "", "", ""))


    }

}

In this case the body is empty and there aren't any headers either.

START RequestId: d3a7975d-791a-4f96-b193-bdc2d1ea0b91 Version: $LATEST
�[36m22:34:27.848�[0;39m �[1;30m[pool-1-thread-5]�[0;39m �[34mINFO �[0;39m �[35mm.a.l.authorizer.LambdaAuthorizer�[0;39m - Optional.empty
�[36m22:34:27.848�[0;39m �[1;30m[pool-1-thread-5]�[0;39m �[34mINFO �[0;39m �[35mm.a.l.authorizer.LambdaAuthorizer�[0;39m - io.micronaut.function.aws.proxy.MicronautAwsProxyRequest$AwsHeaders@15d5c4bd
�[36m22:34:27.848�[0;39m �[1;30m[pool-1-thread-5]�[0;39m �[34mINFO �[0;39m �[35mm.a.l.authorizer.LambdaAuthorizer�[0;39m - []
END RequestId: d3a7975d-791a-4f96-b193-bdc2d1ea0b91

Could this be a bug or am I missing something?

MicronautAwsProxyExceptionHandler giving 500 in case of JSON Mapping exception

We are deserialising request json dates with our custom deserialiser.
In case of invalid date format we are throwing our custom exception which ultimately gets wrapped in JSONMappingException and later on to InvalidRequestEventException.

Now since I want to send 400 BAD REQUEST in such cases but MicronautAwsProxyExceptionHandler is handling these exception by default and send

500 Internal Server Error

in place of

400 BAD REQUEST.

We tried creating our own error handler and tried replacing MicronautAwsProxyExceptionHandler but that too is not working because this exception handler is directly injected in MicronautLambdaContainerHandler.

Flow :

  1. Request forwarded to lambda handler from our function -
    @Override
    public void handleRequest(InputStream input, OutputStream output, Context context) throws IOException {
        logger.info("Input: {}", input);
        handler.proxyStream(input, output, context);
    } 
  1. Gets exception generated due to json deserialisation of wrong format of request at - MicronautLambdaContainerHandler.java
    public void proxyStream(InputStream input, OutputStream output, Context context)
            throws IOException {

        try {
            RequestType request = readerFor(requestTypeClass).readValue(input);
            ResponseType resp = proxy(request, context);

            writerFor(responseTypeClass).writeValue(output, resp);
        } catch (JsonParseException e) {
            log.error("Error while parsing request object stream", e);
            objectMapper().writeValue(output, exceptionHandler.handle(e));
        } catch (JsonMappingException e) {
            log.error("Error while mapping object to RequestType class", e);
            objectMapper().writeValue(output, exceptionHandler.handle(e));
        } finally {
            output.flush();
            output.close();
        }
    }
  1. MicronautAwsProxyExceptionHandler handling exception and sending 500 in place of 400 Bad request.
    @Override
    public AwsProxyResponse handle(Throwable ex) {
        LOG.error("Called exception handler for:", ex);

        // adding a print stack trace in case we have no appender or we are running inside SAM local, where need the
        // output to go to the stderr.
        ex.printStackTrace();
        **if (ex instanceof InvalidRequestEventException) {
            return new AwsProxyResponse(500, headers,** getErrorJson(INTERNAL_SERVER_ERROR));
        } else {
            return new AwsProxyResponse(502, headers, getErrorJson(GATEWAY_TIMEOUT_ERROR));
        }
    }

Why is it doing this part, sending 500 for InvalidRequestEventException :

if (ex instanceof InvalidRequestEventException) {
return new AwsProxyResponse(500, headers,

Micronaut app as AWS Lambda doesn't enforce the status code set in the controller method

Task List

I have a Micronaut AWS Lambda application using the api gateway feature. Thus I have the following StreamLambdaHandler:

public class StreamLambdaHandler implements RequestStreamHandler {
    private static MicronautLambdaContainerHandler handler; // <1>
    static {
        try {
            handler = MicronautLambdaContainerHandler.getAwsProxyHandler();
        } catch (ContainerInitializationException e) {
            // if we fail here. We re-throw the exception to force another cold start
            e.printStackTrace();
            throw new RuntimeException("Could not initialize Micronaut", e);
        }
    }

    @Override
    public void handleRequest(InputStream inputStream, OutputStream outputStream, Context context)
            throws IOException {
        handler.proxyStream(inputStream, outputStream, context); // <2>
    }
}

And this Controller:

@Controller("/")
class PongController {

    @Post("/")
    @Status(HttpStatus.CREATED)
    fun post(): String {
        println("PONG!!!!!!!")
        return "{\"ping\":true}"
    }
}

When invoked from AWS API Gateway, configured as proxy resource, the returned status is 200 when it shoud be 201 as defined in the controller method.

Expected Behaviour

The returned status code in AWS API Gateway should be 201

Actual Behaviour

The returned status code is 200

Environment Information

  • Operating System: AWS API Gateway + AWS Lambda
  • Micronaut Version: 1.1.0-M1
  • JDK Version: 1.8

MicronautLambdaContainerHandler does not proxy static routes

If you set up your fatJar with some static resources and configure the app like so....

micronaut:
  security:
    enabled: true
    intercept-url-map:
      -
        pattern: /**
        http-method: GET
        access:
          - isAnonymous()
  router:
    static-resources:
      default:
        enabled: true
        mapping: "/**"
        paths: "classpath:public"

Requests like GET /statics/icon/favicon.ico are not proxied. Therefore gateway just returns a 404.

This makes it hard to deliver something like an SPA out of your jar.

need a reliable environment when running on AWS

Currently, there is only one active environment present when the function is deployed to AWS Lambda which is function. The problem is that the same environment is for example present in tests. I know that start up time is crucial for lambda functions but there should be a way how to for example enable environment aws based on environment variables.

java.lang.IndexOutOfBoundsException: Too many elements in the Publisher when returning Flux<X>

Micronaut version 1.1.3

Given this simple code of a Lambda with proxy integration:

@Controller("/users")
class UserController(private val userService: UserService) {

    @Get
    fun getAll(): Flux<User> {
        return userService.getAll()
    }

}

@Singleton
class UserServiceImpl : UserService {

    private val users = mutableListOf(
            User("1234D", "Joe"),
            User("2345C", "Lewis"))

    override fun getAll(): Flux<User> {
        return users.toFlux()
    }
}

When calling GET /users from the API Gateway I get and exception with the message Too many elements in the Publisher, even though the Lambda only returns a Flux with two elements.

This is the full stacktrace:

%d [%thread] %-5level %logger - %msg%n java.lang.IndexOutOfBoundsException: Too many elements in the Publisher
at io.reactivex.internal.operators.single.SingleFromPublisher$ToSingleObserver.onNext(SingleFromPublisher.java:73) ~[task/:?]
at reactor.core.publisher.StrictSubscriber.onNext(StrictSubscriber.java:89) ~[task/:?]
at reactor.core.publisher.FluxIterable$IterableSubscription.fastPath(FluxIterable.java:311) ~[task/:?]
at reactor.core.publisher.FluxIterable$IterableSubscription.request(FluxIterable.java:198) ~[task/:?]
at reactor.core.publisher.StrictSubscriber.onSubscribe(StrictSubscriber.java:77) ~[task/:?]
at reactor.core.publisher.FluxIterable.subscribe(FluxIterable.java:139) ~[task/:?]
at reactor.core.publisher.FluxIterable.subscribe(FluxIterable.java:63) ~[task/:?]
at reactor.core.publisher.Flux.subscribe(Flux.java:7743) ~[task/:?]
at io.reactivex.internal.operators.single.SingleFromPublisher.subscribeActual(SingleFromPublisher.java:35) ~[task/:?]
at io.reactivex.Single.subscribe(Single.java:3575) ~[task/:?]
at io.micronaut.reactive.rxjava2.RxInstrumentedSingle.subscribeActual(RxInstrumentedSingle.java:64) ~[task/:?]
at io.reactivex.Single.subscribe(Single.java:3575) ~[task/:?]
at io.reactivex.internal.operators.single.SingleMap.subscribeActual(SingleMap.java:34) ~[task/:?]
at io.reactivex.Single.subscribe(Single.java:3575) ~[task/:?]
at io.micronaut.reactive.rxjava2.RxInstrumentedSingle.subscribeActual(RxInstrumentedSingle.java:64) ~[task/:?]
at io.reactivex.Single.subscribe(Single.java:3575) ~[task/:?]
at io.reactivex.internal.operators.single.SingleToFlowable.subscribeActual(SingleToFlowable.java:37) ~[task/:?]
at io.reactivex.Flowable.subscribe(Flowable.java:14805) ~[task/:?]
at io.reactivex.Flowable.subscribe(Flowable.java:14752) ~[task/:?]
at io.micronaut.reactive.rxjava2.RxInstrumentedFlowable.subscribeActual(RxInstrumentedFlowable.java:68) ~[task/:?]
at io.reactivex.Flowable.subscribe(Flowable.java:14805) ~[task/:?]
at io.reactivex.Flowable.subscribe(Flowable.java:14752) ~[task/:?]
at io.reactivex.internal.operators.flowable.FlowableDefer.subscribeActual(FlowableDefer.java:42) ~[task/:?]
at io.reactivex.Flowable.subscribe(Flowable.java:14805) ~[task/:?]
at io.reactivex.Flowable.subscribe(Flowable.java:14752) ~[task/:?]
at io.micronaut.reactive.rxjava2.RxInstrumentedFlowable.subscribeActual(RxInstrumentedFlowable.java:68) ~[task/:?]
at io.reactivex.Flowable.subscribe(Flowable.java:14805) ~[task/:?]
at io.reactivex.Flowable.subscribe(Flowable.java:14755) ~[task/:?]
at io.micronaut.http.context.ServerRequestTracingPublisher.lambda$subscribe$0(ServerRequestTracingPublisher.java:52) ~[task/:?]
at io.micronaut.http.context.ServerRequestContext.with(ServerRequestContext.java:52) ~[task/:?]
at io.micronaut.http.context.ServerRequestTracingPublisher.subscribe(ServerRequestTracingPublisher.java:52) ~[task/:?]
at io.reactivex.internal.operators.flowable.FlowableFromPublisher.subscribeActual(FlowableFromPublisher.java:29) ~[task/:?]
at io.reactivex.Flowable.subscribe(Flowable.java:14805) ~[task/:?]
at io.reactivex.Flowable.subscribe(Flowable.java:14752) ~[task/:?]
at io.micronaut.reactive.rxjava2.RxInstrumentedFlowable.subscribeActual(RxInstrumentedFlowable.java:68) ~[task/:?]
at io.reactivex.Flowable.subscribe(Flowable.java:14805) ~[task/:?]
at io.reactivex.internal.operators.flowable.FlowableOnErrorNext.subscribeActual(FlowableOnErrorNext.java:40) ~[task/:?]
at io.reactivex.Flowable.subscribe(Flowable.java:14805) ~[task/:?]
at io.reactivex.Flowable.subscribe(Flowable.java:14752) ~[task/:?]
at io.micronaut.reactive.rxjava2.RxInstrumentedFlowable.subscribeActual(RxInstrumentedFlowable.java:68) ~[task/:?]
at io.reactivex.Flowable.subscribe(Flowable.java:14805) ~[task/:?]
at io.reactivex.Flowable.blockingFirst(Flowable.java:5607) ~[task/:?]
at io.micronaut.function.aws.proxy.MicronautLambdaContainerHandler.lambda$handleRequest$5(MicronautLambdaContainerHandler.java:274) ~[task/:?]
at io.micronaut.http.context.ServerRequestContext.with(ServerRequestContext.java:52) ~[task/:?]
at io.micronaut.function.aws.proxy.MicronautLambdaContainerHandler.handleRequest(MicronautLambdaContainerHandler.java:206) ~[task/:?]
at io.micronaut.function.aws.proxy.MicronautLambdaContainerHandler.handleRequest(MicronautLambdaContainerHandler.java:73) ~[task/:?]
at io.micronaut.function.aws.proxy.AbstractLambdaContainerHandler.proxy(AbstractLambdaContainerHandler.java:207) [task/:?]
at io.micronaut.function.aws.proxy.AbstractLambdaContainerHandler.proxyStream(AbstractLambdaContainerHandler.java:239) [task/:?]
at com.codependent.awsintercomm.user.StreamLambdaHandler.handleRequest(StreamLambdaHandler.java:24) [task/:?]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.8.0_201]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[?:1.8.0_201]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:1.8.0_201]
at java.lang.reflect.Method.invoke(Method.java:498) ~[?:1.8.0_201]
at lambdainternal.EventHandlerLoader$StreamMethodRequestHandler.handleRequest(EventHandlerLoader.java:350) [LambdaSandboxJava-1.0.jar:?]
at lambdainternal.EventHandlerLoader$2.call(EventHandlerLoader.java:888) [LambdaSandboxJava-1.0.jar:?]
at lambdainternal.AWSLambda.startRuntime(AWSLambda.java:293) [LambdaSandboxJava-1.0.jar:?]
at lambdainternal.AWSLambda.<clinit>(AWSLambda.java:64) [LambdaSandboxJava-1.0.jar:?]
at java.lang.Class.forName0(Native Method) ~[?:1.8.0_201]
at java.lang.Class.forName(Class.java:348) [?:1.8.0_201]
at lambdainternal.LambdaRTEntry.main(LambdaRTEntry.java:114) [LambdaJavaRTEntry-1.0.jar:?]
%d [%thread] %-5level %logger - %msg%n java.lang.IndexOutOfBoundsException: Too many elements in the Publisher
at io.reactivex.internal.operators.single.SingleFromPublisher$ToSingleObserver.onNext(SingleFromPublisher.java:73) ~[task/:?]
at reactor.core.publisher.StrictSubscriber.onNext(StrictSubscriber.java:89) ~[task/:?]
at reactor.core.publisher.FluxIterable$IterableSubscription.fastPath(FluxIterable.java:311) ~[task/:?]
at reactor.core.publisher.FluxIterable$IterableSubscription.request(FluxIterable.java:198) ~[task/:?]
at reactor.core.publisher.StrictSubscriber.onSubscribe(StrictSubscriber.java:77) ~[task/:?]
at reactor.core.publisher.FluxIterable.subscribe(FluxIterable.java:139) ~[task/:?]
at reactor.core.publisher.FluxIterable.subscribe(FluxIterable.java:63) ~[task/:?]
at reactor.core.publisher.Flux.subscribe(Flux.java:7743) ~[task/:?]
at io.reactivex.internal.operators.single.SingleFromPublisher.subscribeActual(SingleFromPublisher.java:35) ~[task/:?]
at io.reactivex.Single.subscribe(Single.java:3575) ~[task/:?]
at io.micronaut.reactive.rxjava2.RxInstrumentedSingle.subscribeActual(RxInstrumentedSingle.java:64) ~[task/:?]
at io.reactivex.Single.subscribe(Single.java:3575) ~[task/:?]
at io.reactivex.internal.operators.single.SingleMap.subscribeActual(SingleMap.java:34) ~[task/:?]
at io.reactivex.Single.subscribe(Single.java:3575) ~[task/:?]
at io.micronaut.reactive.rxjava2.RxInstrumentedSingle.subscribeActual(RxInstrumentedSingle.java:64) ~[task/:?]
at io.reactivex.Single.subscribe(Single.java:3575) ~[task/:?]
at io.reactivex.internal.operators.single.SingleToFlowable.subscribeActual(SingleToFlowable.java:37) ~[task/:?]
at io.reactivex.Flowable.subscribe(Flowable.java:14805) ~[task/:?]
at io.reactivex.Flowable.subscribe(Flowable.java:14752) ~[task/:?]
at io.micronaut.reactive.rxjava2.RxInstrumentedFlowable.subscribeActual(RxInstrumentedFlowable.java:68) ~[task/:?]
at io.reactivex.Flowable.subscribe(Flowable.java:14805) ~[task/:?]
at io.reactivex.Flowable.subscribe(Flowable.java:14752) ~[task/:?]
at io.reactivex.internal.operators.flowable.FlowableDefer.subscribeActual(FlowableDefer.java:42) ~[task/:?]
at io.reactivex.Flowable.subscribe(Flowable.java:14805) ~[task/:?]
at io.reactivex.Flowable.subscribe(Flowable.java:14752) ~[task/:?]
at io.micronaut.reactive.rxjava2.RxInstrumentedFlowable.subscribeActual(RxInstrumentedFlowable.java:68) ~[task/:?]
at io.reactivex.Flowable.subscribe(Flowable.java:14805) ~[task/:?]
at io.reactivex.Flowable.subscribe(Flowable.java:14755) ~[task/:?]
at io.micronaut.http.context.ServerRequestTracingPublisher.lambda$subscribe$0(ServerRequestTracingPublisher.java:52) ~[task/:?]
at io.micronaut.http.context.ServerRequestContext.with(ServerRequestContext.java:52) ~[task/:?]
at io.micronaut.http.context.ServerRequestTracingPublisher.subscribe(ServerRequestTracingPublisher.java:52) ~[task/:?]
at io.reactivex.internal.operators.flowable.FlowableFromPublisher.subscribeActual(FlowableFromPublisher.java:29) ~[task/:?]
at io.reactivex.Flowable.subscribe(Flowable.java:14805) ~[task/:?]
at io.reactivex.Flowable.subscribe(Flowable.java:14752) ~[task/:?]
at io.micronaut.reactive.rxjava2.RxInstrumentedFlowable.subscribeActual(RxInstrumentedFlowable.java:68) ~[task/:?]
at io.reactivex.Flowable.subscribe(Flowable.java:14805) ~[task/:?]
at io.reactivex.internal.operators.flowable.FlowableOnErrorNext.subscribeActual(FlowableOnErrorNext.java:40) ~[task/:?]
at io.reactivex.Flowable.subscribe(Flowable.java:14805) ~[task/:?]
at io.reactivex.Flowable.subscribe(Flowable.java:14752) ~[task/:?]
at io.micronaut.reactive.rxjava2.RxInstrumentedFlowable.subscribeActual(RxInstrumentedFlowable.java:68) ~[task/:?]
at io.reactivex.Flowable.subscribe(Flowable.java:14805) ~[task/:?]
at io.reactivex.Flowable.blockingFirst(Flowable.java:5607) ~[task/:?]
at io.micronaut.function.aws.proxy.MicronautLambdaContainerHandler.lambda$handleRequest$5(MicronautLambdaContainerHandler.java:274) ~[task/:?]
at io.micronaut.http.context.ServerRequestContext.with(ServerRequestContext.java:52) ~[task/:?]
at io.micronaut.function.aws.proxy.MicronautLambdaContainerHandler.handleRequest(MicronautLambdaContainerHandler.java:206) ~[task/:?]
at io.micronaut.function.aws.proxy.MicronautLambdaContainerHandler.handleRequest(MicronautLambdaContainerHandler.java:73) ~[task/:?]
at io.micronaut.function.aws.proxy.AbstractLambdaContainerHandler.proxy(AbstractLambdaContainerHandler.java:207) [task/:?]
at io.micronaut.function.aws.proxy.AbstractLambdaContainerHandler.proxyStream(AbstractLambdaContainerHandler.java:239) [task/:?]
at com.codependent.awsintercomm.user.StreamLambdaHandler.handleRequest(StreamLambdaHandler.java:24) [task/:?]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.8.0_201]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[?:1.8.0_201]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:1.8.0_201]
at java.lang.reflect.Method.invoke(Method.java:498) ~[?:1.8.0_201]
at lambdainternal.EventHandlerLoader$StreamMethodRequestHandler.handleRequest(EventHandlerLoader.java:350) [LambdaSandboxJava-1.0.jar:?]
at lambdainternal.EventHandlerLoader$2.call(EventHandlerLoader.java:888) [LambdaSandboxJava-1.0.jar:?]
at lambdainternal.AWSLambda.startRuntime(AWSLambda.java:293) [LambdaSandboxJava-1.0.jar:?]
at lambdainternal.AWSLambda.<clinit>(AWSLambda.java:64) [LambdaSandboxJava-1.0.jar:?]
at java.lang.Class.forName0(Native Method) ~[?:1.8.0_201]
at java.lang.Class.forName(Class.java:348) [?:1.8.0_201]
at lambdainternal.LambdaRTEntry.main(LambdaRTEntry.java:114) [LambdaJavaRTEntry-1.0.jar:?]
java.lang.IndexOutOfBoundsException: Too many elements in the Publisher
at io.reactivex.internal.operators.single.SingleFromPublisher$ToSingleObserver.onNext(SingleFromPublisher.java:73)
at reactor.core.publisher.StrictSubscriber.onNext(StrictSubscriber.java:89)
at reactor.core.publisher.FluxIterable$IterableSubscription.fastPath(FluxIterable.java:311)
at reactor.core.publisher.FluxIterable$IterableSubscription.request(FluxIterable.java:198)
at reactor.core.publisher.StrictSubscriber.onSubscribe(StrictSubscriber.java:77)
at reactor.core.publisher.FluxIterable.subscribe(FluxIterable.java:139)
at reactor.core.publisher.FluxIterable.subscribe(FluxIterable.java:63)
at reactor.core.publisher.Flux.subscribe(Flux.java:7743)
at io.reactivex.internal.operators.single.SingleFromPublisher.subscribeActual(SingleFromPublisher.java:35)
at io.reactivex.Single.subscribe(Single.java:3575)
at io.micronaut.reactive.rxjava2.RxInstrumentedSingle.subscribeActual(RxInstrumentedSingle.java:64)
at io.reactivex.Single.subscribe(Single.java:3575)
at io.reactivex.internal.operators.single.SingleMap.subscribeActual(SingleMap.java:34)
at io.reactivex.Single.subscribe(Single.java:3575)
at io.micronaut.reactive.rxjava2.RxInstrumentedSingle.subscribeActual(RxInstrumentedSingle.java:64)
at io.reactivex.Single.subscribe(Single.java:3575)
at io.reactivex.internal.operators.single.SingleToFlowable.subscribeActual(SingleToFlowable.java:37)
at io.reactivex.Flowable.subscribe(Flowable.java:14805)
at io.reactivex.Flowable.subscribe(Flowable.java:14752)
at io.micronaut.reactive.rxjava2.RxInstrumentedFlowable.subscribeActual(RxInstrumentedFlowable.java:68)
at io.reactivex.Flowable.subscribe(Flowable.java:14805)
at io.reactivex.Flowable.subscribe(Flowable.java:14752)
at io.reactivex.internal.operators.flowable.FlowableDefer.subscribeActual(FlowableDefer.java:42)
at io.reactivex.Flowable.subscribe(Flowable.java:14805)
at io.reactivex.Flowable.subscribe(Flowable.java:14752)
at io.micronaut.reactive.rxjava2.RxInstrumentedFlowable.subscribeActual(RxInstrumentedFlowable.java:68)
at io.reactivex.Flowable.subscribe(Flowable.java:14805)
at io.reactivex.Flowable.subscribe(Flowable.java:14755)
at io.micronaut.http.context.ServerRequestTracingPublisher.lambda$subscribe$0(ServerRequestTracingPublisher.java:52)
at io.micronaut.http.context.ServerRequestContext.with(ServerRequestContext.java:52)
at io.micronaut.http.context.ServerRequestTracingPublisher.subscribe(ServerRequestTracingPublisher.java:52)
at io.reactivex.internal.operators.flowable.FlowableFromPublisher.subscribeActual(FlowableFromPublisher.java:29)
at io.reactivex.Flowable.subscribe(Flowable.java:14805)
at io.reactivex.Flowable.subscribe(Flowable.java:14752)
at io.micronaut.reactive.rxjava2.RxInstrumentedFlowable.subscribeActual(RxInstrumentedFlowable.java:68)
at io.reactivex.Flowable.subscribe(Flowable.java:14805)
at io.reactivex.internal.operators.flowable.FlowableOnErrorNext.subscribeActual(FlowableOnErrorNext.java:40)
at io.reactivex.Flowable.subscribe(Flowable.java:14805)
at io.reactivex.Flowable.subscribe(Flowable.java:14752)
at io.micronaut.reactive.rxjava2.RxInstrumentedFlowable.subscribeActual(RxInstrumentedFlowable.java:68)
at io.reactivex.Flowable.subscribe(Flowable.java:14805)
at io.reactivex.Flowable.blockingFirst(Flowable.java:5607)
at io.micronaut.function.aws.proxy.MicronautLambdaContainerHandler.lambda$handleRequest$5(MicronautLambdaContainerHandler.java:274)
at io.micronaut.http.context.ServerRequestContext.with(ServerRequestContext.java:52)
at io.micronaut.function.aws.proxy.MicronautLambdaContainerHandler.handleRequest(MicronautLambdaContainerHandler.java:206)
at io.micronaut.function.aws.proxy.MicronautLambdaContainerHandler.handleRequest(MicronautLambdaContainerHandler.java:73)
at io.micronaut.function.aws.proxy.AbstractLambdaContainerHandler.proxy(AbstractLambdaContainerHandler.java:207)
at io.micronaut.function.aws.proxy.AbstractLambdaContainerHandler.proxyStream(AbstractLambdaContainerHandler.java:239)
at com.codependent.awsintercomm.user.StreamLambdaHandler.handleRequest(StreamLambdaHandler.java:24)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at lambdainternal.EventHandlerLoader$StreamMethodRequestHandler.handleRequest(EventHandlerLoader.java:350)
at lambdainternal.EventHandlerLoader$2.call(EventHandlerLoader.java:888)
at lambdainternal.AWSLambda.startRuntime(AWSLambda.java:293)
at lambdainternal.AWSLambda.<clinit>(AWSLambda.java:64)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:348)
at lambdainternal.LambdaRTEntry.main(LambdaRTEntry.java:114)
END RequestId: 846a2af9-559b-447f-9e47-43e66cda14b9

The behaviour is as expected when starting the project as a normal Micronaut application and requesting that endpoint: [{"id":"1234D","name":"Joe"},{"id":"2345C","name":"Lewis"}]

Multipart file uploads do not work with AWS API Gateway

I have a route for a multipart file upload which works fine when running the service as a standalone application:

    @Post("/attachments", consumes = [MediaType.MULTIPART_FORM_DATA])
    fun uploadImage(file: CompletedFileUpload) : HttpResponse<Any> {
        ...
        return HttpResponse.created("Created")
    }

When testing the route with curl -v -X POST http://localhost:8080/attachments -H 'Content-type: multipart/form-data' -F file=@/path/image.jpg everything works fine.

When I deploy the service as a Lambda with API Gateway access, the file does not seem to make it to the controller: io.micronaut.web.router.exceptions.UnsatisfiedRouteException: Required argument [CompletedFileUpload file] not specified.

All other routes in my application work correctly even if deployed to AWS Lambda + API Gateway so I suspect there might be an issue with parsing the API Gateway input in the Micronaut AWS Proxy Handler.

BuildInfoSource incompatible with functions/API Gateway

Steps to Reproduce

  1. Configure a RequestStreamHandler Lambda with MicronautLambdaContainerHandler.getAwsProxyHandler() in a serverless or CloudFormation environment. An example is here.
  2. include io.micronaut:micronaut-management
  3. add to application.yml:
endpoints:
  info:
    enabled: true
    sensitive: false
  1. Navigate to the /info endpoint, relative to the API Gateway endpoint

Expected Behaviour

Expected an info endpoint result.

Actual Behaviour

An exception is logged in CloudWatch and the endpoint returns a 502 error.

io.micronaut.context.exceptions.DependencyInjectionException: Failed to inject value for parameter [refreshScope] of class: io.micronaut.runtime.context.scope.refresh.RefreshInterceptor
Message: No bean of type [io.micronaut.runtime.context.scope.refresh.RefreshScope] exists. Make sure the bean is not disabled by bean requirements (enable trace logging for 'io.micronaut.context.condition' to check) and if the bean is enabled then ensure the class is declared a bean and annotation processing is enabled (for Java and Kotlin the 'micronaut-inject-java' dependency should be configured as an annotation processor).
Path Taken: new InfoEndpoint(InfoAggregator infoAggregator,[InfoSource[] infoSources]) --> new $BuildInfoSourceDefinition$Intercepted(ResourceResolver resourceResolver,String buildPropertiesPath,BeanContext beanContext,[Interceptor[] interceptors]) --> new RefreshInterceptor([RefreshScope refreshScope])

All AWS functions (with or without API Gateway) run with the Environment.FUNCTION environment. The built-in BuildInfoSource is a @Refreshable bean and RefreshScope is disabled when running in Environment.FUNCTION. Therefore this could probably be easily fixed by creating an abstract base class of the BuildInfoSource bean and two concrete versions, one that's @Refreshable and @Requires(notEnv = Environment.FUNCTION) and the other @Requires(notEnv = Environment.FUNCTION) and NOT @Refreshable.

Example Application

https://github.com/micronaut-projects/micronaut-aws/tree/master/examples/api-gateway-example

Lambda with proxy integration fails with Execution failed due to configuration error: Malformed Lambda proxy response

A sample project is available here using micronaut-aws-lambda-proxy 1.1.0.RC1: https://github.com/codependent/micronaut-aws-lambda-proxy

The problem is with a controller like this:

@Controller("/ping")
class PingController {

    private val logger = LoggerFactory.getLogger(javaClass)

    @Post("/")
    @Status(HttpStatus.CREATED)
    fun createPing(@Body ping: Ping): Ping {
        logger.info("ping {}", ping)
        return ping
    }
}

The Ping argument is correctly unmarshalled (as seen in the logs)...

[36m15:07:27.873[0;39m [1;30m[pool-1-thread-5][0;39m [34mINFO [0;39m [35mc.c.m.awslambda.web.PingController[0;39m - ping Ping(value=myval)

... and returned from the controller, but AWS API Gateway shows this error:

Thu Feb 21 15:41:31 UTC 2019 : Endpoint response body before transformations: {"statusCode":201,"statusDescription":"Created","multiValueHeaders":{"Content-Type":["application/json"]},"body":"{\"value\":\"myval\"}","isBase64Encoded":false}
Thu Feb 21 15:41:31 UTC 2019 : Endpoint response headers: {Date=Thu, 21 Feb 2019 15:41:31 GMT, Content-Type=application/json, Content-Length=161, Connection=keep-alive, x-amzn-RequestId=1d9becec-16b4-42fe-bde6-4dcec2f0d86c, x-amzn-Remapped-Content-Length=0, X-Amz-Executed-Version=$LATEST, X-Amzn-Trace-Id=root=1-5c6ec6ab-faea1670ec1ce53b5d0b5b6e;sampled=0}
Thu Feb 21 15:41:31 UTC 2019 : Execution failed due to configuration error: Malformed Lambda proxy response

For some reason the response doesn't follow the expected format
https://aws.amazon.com/premiumsupport/knowledge-center/malformed-502-api-gateway/

Docker build for custom GraalVM native runtimes fails.

When I tried Custom GraalVM Native Runtimes on this page, I got a warning, and the generated binary didn't contain Java Runtime.
https://micronaut-projects.github.io/micronaut-aws/latest/guide/#customRuntimes

The warning message is as follows.

[server:6]    classlist:  18,170.22 ms
[server:6]        (cap):   1,760.69 ms
[server:6]        setup:   4,722.97 ms
[server:6]     analysis:  44,020.50 ms
Warning: Aborting stand-alone image build. No instances are allowed in the image heap for a class that is initialized or reinitialized at image runtime: com.amazonaws.serverless.proxy.model.ContainerConfig. Try marking this class for build-time initialization with --initialize-at-build-time=com.amazonaws.serverless.proxy.model.ContainerConfig
Detailed message:
Trace: 	field io.micronaut.function.aws.proxy.AbstractLambdaContainerHandler.config

Warning: Use -H:+ReportExceptionStackTraces to print stacktrace of underlying exception
[server:67]    classlist:   6,628.29 ms
[server:67]        (cap):   1,597.73 ms
[server:67]        setup:   4,403.42 ms
[server:67]   (typeflow):   6,819.44 ms
[server:67]    (objects):   1,793.49 ms
[server:67]   (features):     253.99 ms
[server:67]     analysis:   9,047.10 ms
[server:67]     (clinit):     261.85 ms
[server:67]     universe:     845.08 ms
[server:67]      (parse):   1,915.63 ms
[server:67]     (inline):   2,603.30 ms
[server:67]    (compile):  15,898.98 ms
[server:67]      compile:  20,901.04 ms
[server:67]        image:     731.63 ms
[server:67]        write:     244.38 ms
[server:67]      [total]:  43,122.48 ms
Warning: Image 'server' is a fallback image that requires a JDK for execution (use --no-fallback to suppress fallback image generation).

When I added --initialize-at-build-time=com.amazonaws.serverless.proxy.model to native-image.properties and built again, native-image command succeeded.

Environment

java version "1.8.0_202"
Java(TM) SE Runtime Environment (build 1.8.0_202-b08)
Java HotSpot(TM) 64-Bit Server VM (build 25.202-b08, mixed mode)

GraalVM 19.0.0 and 19.0.2

Docker Desktop Community 2.0.0.3

macOS Mojave 10.14.5

AWS Lambda Custom Runtimes problem

I create an app using CLI command:
mn create-app my-app --features aws-api-gateway-graal --build maven

After I build a jar file, I'm trying to run it using generated deploy.sh file.

Trying to call a Lambda i'm constantly got:

No bin/java and no environment variable JAVA_HOME

FunctionInitializer does not parse @JsonProperty

while using micronaut version 1.1

When using the FunctionInitializer the Pojo that is parsed with jackson does not read the @jsonproperties annotation.

Json

{
    "Records": ["test1", "test2"]
}

Pojo

@Introspected
public class SqsEvent {

   @JsonProperty("Records")
    private List<String> records;

    public List<String> getRecords() {
        return records;
    }

    public void setRecords(List<String> records) {
        this.records = records;
    }
}

function

@Singleton
public class SqsFunction extends FunctionInitializer {
    
    public void execute(SqsEvent event) {
       event.getRecords(); // is always empty
    }
}

while using ObjectMapper directly it works

SqsEvent event = mapper.readValue(json, SqsEvent.class);
event.getRecords(); // is filled

GraalVM native generated app is not working in AWS

I am using mn version 1.1.0.M1
Created app using mn create-app my-app --features aws-api-gateway-graal

Trying to deploy it and it not working, gives error in CloudWatch:

START RequestId: 6ed53036-dc55-4c60-ae7a-ba91ad8f988c Version: $LATEST
io.micronaut.http.client.exceptions.ReadTimeoutException: Read Timeout
Request loop failed with: Read Timeout
END RequestId: 6ed53036-dc55-4c60-ae7a-ba91ad8f988c
REPORT RequestId: 6ed53036-dc55-4c60-ae7a-ba91ad8f988c  Duration: 15015.13 ms   Billed Duration: 15000 ms Memory Size: 128 MB   Max Memory Used: 95 MB  
2019-02-13T09:29:19.172Z 6ed53036-dc55-4c60-ae7a-ba91ad8f988c Task timed out after 15.02 seconds

Example project here: https://github.com/huksley/micronaut-aws-api-gateway-graal

No way to set skill id for Alexa skill builder in AlexaFunction

For security Amazon recommends the user set the skill ID on their skill so the SDK will match that ID with the incoming request and reject it if it doesn't match. You can force disable this to make it work in the AWS Developer Console, but it's not recommended. Need to add a configuration value to the application.yml and have the

set this on the builder of the skill.

Will send a PR soon.

Exception Handlers not run in AWS API Gateway

Exception Handlers are not run when Micronaut is run through API Gateway integration. Any exceptions that occur return a 502 Gateway Timeout to the client.

This affects custom error handlers as well as @Valid annotations

Example project at https://github.com/rnielsen/micronaut-aws-apiproxy-test

curl -i http://localhost:8080/test/exception
HTTP/1.1 200 OK

Exception Handled
curl -i https://3kf8ik2za4.execute-api.ap-southeast-2.amazonaws.com/dev/test/exception
HTTP/2 502 

{"message":"Gateway timeout"}

Tested against io.micronaut.aws:micronaut-function-aws-api-proxy:1.1.0.RC3"

415 error returned on methods with multiple @Consumes annotations in AWS API Gateway

When a method has multiple media types in it's @consumes annotation eg. @Consumes({MediaType.APPLICATION_FORM_URLENCODED, MediaType.APPLICATION_JSON}), it always returns a 415 response when deployed through the AWS API Gateway integration.

This specifically affects the default /login and /oauth/token endpoints when using Micronaut Authentication (along with Issue #22)

Problem seems to be MicronautLambdaContainerHandler.java assuming only one MediaType.

Example project at https://github.com/rnielsen/micronaut-aws-apiproxy-test

curl -i -H "Content-Type: application/json" -X POST -d '{"name":"Test"}' http://localhost:8080/test/multipleConsumes
HTTP/1.1 200 OK

{"name":"Test"}
curl -i -H "Content-Type: application/json" -X POST -d '{"name":"Test"}' https://3kf8ik2za4.execute-api.ap-southeast-2.amazonaws.com/dev/test/multipleConsumes
HTTP/2 415 

Tested against io.micronaut.aws:micronaut-function-aws-api-proxy:1.1.0.RC3"

HttpResponse not working properly inside lambda environment using graalvm

Task List

  • Steps to reproduce provided
  • Stacktrace (if present) provided
  • Example that reproduces the problem uploaded to Github
  • Full description of the issue provided (see below)

Steps to Reproduce

Follow steps from https://bitbucket.org/traycho/micronaut-examples/src/master/

  1. Build application
  2. Run it in sam local environment
  3. Execute curl -G http://localhost:3000/ping

Expected Behaviour

Application should behave same running standard jar or graalvm compiled binary.
Executing curl -G http://localhost:3000/ping should result into { "message": "ping"}

Actual Behaviour

Executing curl -G http://localhost:3000/ping results into {}
Using HttpResponse returned by controller methods results into {} empty body.

Environment Information

  • Operating System: MacOs Sierra
  • Micronaut Version: 1.2.4
  • JDK Version: 1.8.0_222

Example Application

Checkout code from
https://bitbucket.org/traycho/micronaut-examples/src/master/

Add SQS support

Adding SQS support: queue configuration, annotations for producers and consumers, ...

URL encoding is not propagating

Steps to Reproduce

  1. Create project: mn create-app aws-api-gateway-test --features aws-api-gateway
  2. Add a controller, with an endpoint that waits for a path param
import io.micronaut.http.annotation.Controller;
import io.micronaut.http.annotation.Get;
import io.micronaut.http.annotation.QueryValue;

@Controller
public class TestController {

    @Get("/books/{book}")
    public String book(String book) {
        return "{\"book\": \"" + book + "\"}";
    }
}
  1. Run ./gradlew clean build && sam local start-api --template sam.yaml
  2. Call http://127.0.0.1:3000/books/The%20Name%20of%20the%20Wind or http://127.0.0.1:3000/books/The Name of the Wind

Example project can be checked out from here: https://github.com/lkonya/micronaut-aws-api-gateway-test.git

Expected Behaviour

HTTP 200 - successfully decode URL path

{
    "book": "The Name of the Wind"
}

Actual Behaviour

HTTP 500 - Internal Server Error
Server:

com.amazonaws.serverless.exceptions.InvalidRequestEventException: Invalid Request: Illegal character in path at index 61: https://1234567890.execute-api.eu-central-1.amazonaws.com/The Name of the Wind
        at io.micronaut.function.aws.proxy.MicronautRequestReader.readRequest(MicronautRequestReader.java:123)
        at io.micronaut.function.aws.proxy.MicronautRequestReader.readRequest(MicronautRequestReader.java:48)
        at io.micronaut.function.aws.proxy.AbstractLambdaContainerHandler.proxy(AbstractLambdaContainerHandler.java:204)
        at io.micronaut.function.aws.proxy.AbstractLambdaContainerHandler.proxyStream(AbstractLambdaContainerHandler.java:239)
        at aws.api.gateway.test.StreamLambdaHandler.handleRequest(StreamLambdaHandler.java:24)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:498)
        at lambdainternal.EventHandlerLoader$StreamMethodRequestHandler.handleRequest(EventHandlerLoader.java:350)
        at lambdainternal.EventHandlerLoader$2.call(EventHandlerLoader.java:888)
        at lambdainternal.AWSLambda.startRuntime(AWSLambda.java:293)
        at lambdainternal.AWSLambda.<clinit>(AWSLambda.java:64)
        at java.lang.Class.forName0(Native Method)
        at java.lang.Class.forName(Class.java:348)
        at lambdainternal.LambdaRTEntry.main(LambdaRTEntry.java:114)
Caused by: java.lang.IllegalArgumentException: Illegal character in path at index 61: https://1234567890.execute-api.eu-central-1.amazonaws.com/The Name of the Wind
        at java.net.URI.create(URI.java:852)
        at io.micronaut.function.aws.proxy.MicronautAwsProxyRequest.getUri(MicronautAwsProxyRequest.java:174)
        at io.micronaut.http.HttpRequest.getPath(HttpRequest.java:85)
        at io.micronaut.function.aws.proxy.MicronautRequestReader.readRequest(MicronautRequestReader.java:79)
        ... 15 more
Caused by: java.net.URISyntaxException: Illegal character in path at index 61: https://1234567890.execute-api.eu-central-1.amazonaws.com/The Name of the Wind
        at java.net.URI$Parser.fail(URI.java:2848)
        at java.net.URI$Parser.checkChars(URI.java:3021)
        at java.net.URI$Parser.parseHierarchical(URI.java:3105)
        at java.net.URI$Parser.parse(URI.java:3053)
        at java.net.URI.<init>(URI.java:588)
        at java.net.URI.create(URI.java:850)
        ... 18 more
END RequestId: 65a9e328-1710-402a-ad10-f3515714416b
REPORT RequestId: 65a9e328-1710-402a-ad10-f3515714416b  Duration: 186.98 ms     Billed Duration: 200 ms Memory Size: 512 MB     Max Memory Used: 34 MB  
[2019-04-19 09:32:28.966] " + NO_REQUEST_ID + " INFO i.m.f.a.p.AbstractLambdaContainerHandler - Starting Lambda Container Handler 
[2019-04-19 09:32:29.086] " + NO_REQUEST_ID + " INFO i.m.c.e.DefaultEnvironment - Established active environments: [function] 
com.amazonaws.serverless.exceptions.InvalidRequestEventException: Invalid Request: Illegal character in path at index 61: https://1234567890.execute-api.eu-central-1.amazonaws.com/The Name of the Windr    at io.micronaut.function.aws.proxy.MicronautRequestReader.readRequest(MicronautRequestReader.java:123)r at io.micronaut.function.aws.proxy.MicronautRequestReader.readRequest(MicronautRequestReader.java:48)r       at io.micronaut.function.aws.proxy.AbstractLambdaContainerHandler.proxy(AbstractLambdaContainerHandler.java:204)r       at io.micronaut.function.aws.proxy.AbstractLambdaContainerHandler.proxyStream(AbstractLambdaContainerHandler.java:239)r      at aws.api.gateway.test.StreamLambdaHandler.handleRequest(StreamLambdaHandler.java:24)r at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)r      at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)r       at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)r    at java.lang.reflect.Method.invoke(Method.java:498)r    at lambdainternal.EventHandlerLoader$StreamMethodRequestHandler.handleRequest(EventHandlerLoader.java:350)r     at lambdainternal.EventHandlerLoader$2.call(EventHandlerLoader.java:888)r    at lambdainternal.AWSLambda.startRuntime(AWSLambda.java:293)r   at lambdainternal.AWSLambda.<clinit>(AWSLambda.java:64)r        at java.lang.Class.forName0(Native Method)r  at java.lang.Class.forName(Class.java:348)r     at lambdainternal.LambdaRTEntry.main(LambdaRTEntry.java:114)rCaused by: java.lang.IllegalArgumentException: Illegal character in path at index 61: https://1234567890.execute-api.eu-central-1.amazonaws.com/The Name of the Windr   at java.net.URI.create(URI.java:852)r   at io.micronaut.function.aws.proxy.MicronautAwsProxyRequest.getUri(MicronautAwsProxyRequest.java:174)r       at io.micronaut.http.HttpRequest.getPath(HttpRequest.java:85)r  at io.micronaut.function.aws.proxy.MicronautRequestReader.readRequest(MicronautRequestReader.java:79)r       ... 15 common frames omittedrCaused by: java.net.URISyntaxException: Illegal character in path at index 61: https://1234567890.execute-api.eu-central-1.amazonaws.com/The Name of the Windr  at java.net.URI$Parser.fail(URI.java:2848)r     at java.net.URI$Parser.checkChars(URI.java:3021)r       at java.net.URI$Parser.parseHierarchical(URI.java:3105)r     at java.net.URI$Parser.parse(URI.java:3053)r    at java.net.URI.<init>(URI.java:588)r   at java.net.URI.create(URI.java:850)r   ... 18 common frames omittedr
com.amazonaws.serverless.exceptions.InvalidRequestEventException: Invalid Request: Illegal character in path at index 61: https://1234567890.execute-api.eu-central-1.amazonaws.com/The Name of the Windr    at io.micronaut.function.aws.proxy.MicronautRequestReader.readRequest(MicronautRequestReader.java:123)r at io.micronaut.function.aws.proxy.MicronautRequestReader.readRequest(MicronautRequestReader.java:48)r       at io.micronaut.function.aws.proxy.AbstractLambdaContainerHandler.proxy(AbstractLambdaContainerHandler.java:204)r       at io.micronaut.function.aws.proxy.AbstractLambdaContainerHandler.proxyStream(AbstractLambdaContainerHandler.java:239)r      at aws.api.gateway.test.StreamLambdaHandler.handleRequest(StreamLambdaHandler.java:24)r at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)r      at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)r       at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)r    at java.lang.reflect.Method.invoke(Method.java:498)r    at lambdainternal.EventHandlerLoader$StreamMethodRequestHandler.handleRequest(EventHandlerLoader.java:350)r     at lambdainternal.EventHandlerLoader$2.call(EventHandlerLoader.java:888)r    at lambdainternal.AWSLambda.startRuntime(AWSLambda.java:293)r   at lambdainternal.AWSLambda.<clinit>(AWSLambda.java:64)r        at java.lang.Class.forName0(Native Method)r  at java.lang.Class.forName(Class.java:348)r     at lambdainternal.LambdaRTEntry.main(LambdaRTEntry.java:114)rCaused by: java.lang.IllegalArgumentException: Illegal character in path at index 61: https://1234567890.execute-api.eu-central-1.amazonaws.com/The Name of the Windr   at java.net.URI.create(URI.java:852)r   at io.micronaut.function.aws.proxy.MicronautAwsProxyRequest.getUri(MicronautAwsProxyRequest.java:174)r       at io.micronaut.http.HttpRequest.getPath(HttpRequest.java:85)r  at io.micronaut.function.aws.proxy.MicronautRequestReader.readRequest(MicronautRequestReader.java:79)r       ... 15 common frames omittedrCaused by: java.net.URISyntaxException: Illegal character in path at index 61: https://1234567890.execute-api.eu-central-1.amazonaws.com/The Name of the Windr  at java.net.URI$Parser.fail(URI.java:2848)r     at java.net.URI$Parser.checkChars(URI.java:3021)r       at java.net.URI$Parser.parseHierarchical(URI.java:3105)r     at java.net.URI$Parser.parse(URI.java:3053)r    at java.net.URI.<init>(URI.java:588)r   at java.net.URI.create(URI.java:850)r   ... 18 common frames omittedr
2019-04-19 11:32:31 No Content-Type given. Defaulting to 'application/json'.
2019-04-19 11:32:31 127.0.0.1 - - [19/Apr/2019 11:32:31] "GET /The%20Name%20of%20the%20Wind HTTP/1.1" 500 -

Environment Information

  • Operating System: MacOs Mojava version: 10.14.4
  • Micronaut Version: 1.1.0
  • JDK Version: 1.8.0_202

aws custom runtime throw exception

I write very simple demo java project with aws custom runtime. (micronaut.version: 1.1.0.M1)
It has just one controller

@Controller
public class HelloController {
    @Get("/hello")
    public String sayHello() {
        return "hello";
    }
}

project: https://github.com/eisig/lambda-demo2

When invoked from AWS API Gateway. The first call will return as exptected.
Then invoke it again a few minutes later, the api return {"message": "Internal server error"}.

Logs:

10:17:44.149 [main]INFO i.m.f.a.p.AbstractLambdaContainerHandler - Starting Lambda Container Handler
10:17:44.282 [main]INFO i.m.context.env.DefaultEnvironment - Established active environments: [function]
START RequestId: f3689953-f4f9-43a6-96b7-a5ebef02b48f Version: $LATEST
END RequestId: f3689953-f4f9-43a6-96b7-a5ebef02b48f
REPORT RequestId: f3689953-f4f9-43a6-96b7-a5ebef02b48f  Init Duration: 2325.18 ms   Duration: 553.63 ms Billed Duration: 2900 ms Memory Size: 704 MB    Max Memory Used: 118 MB 
START RequestId: 10754fbd-1cf2-4963-8392-fb10d6aed231 Version: $LATEST
io.reactivex.exceptions.UndeliverableException: The exception could not be delivered to the consumer because it has already canceled/disposed the flow or the exception has nowhere to go to begin with. Further reading: https://github.com/ReactiveX/RxJava/wiki/What's-different-in-2.0#error-handling | io.micronaut.http.client.exceptions.ReadTimeoutException: Read Timeout
at io.reactivex.plugins.RxJavaPlugins.onError(RxJavaPlugins.java:367)
at io.reactivex.internal.operators.flowable.FlowableCreate$BaseEmitter.onError(FlowableCreate.java:275)
at io.micronaut.http.client.DefaultHttpClient$10.exceptionCaught(DefaultHttpClient.java:1816)
at io.netty.channel.AbstractChannelHandlerContext.invokeExceptionCaught(AbstractChannelHandlerContext.java:285)
at io.netty.channel.AbstractChannelHandlerContext.invokeExceptionCaught(AbstractChannelHandlerContext.java:264)
at io.netty.channel.AbstractChannelHandlerContext.fireExceptionCaught(AbstractChannelHandlerContext.java:256)
at io.netty.channel.ChannelInboundHandlerAdapter.exceptionCaught(ChannelInboundHandlerAdapter.java:131)
at io.netty.channel.AbstractChannelHandlerContext.invokeExceptionCaught(AbstractChannelHandlerContext.java:285)
at io.netty.channel.AbstractChannelHandlerContext.invokeExceptionCaught(AbstractChannelHandlerContext.java:264)
at io.netty.channel.AbstractChannelHandlerContext.fireExceptionCaught(AbstractChannelHandlerContext.java:256)
at io.netty.channel.ChannelInboundHandlerAdapter.exceptionCaught(ChannelInboundHandlerAdapter.java:131)
at io.netty.channel.AbstractChannelHandlerContext.invokeExceptionCaught(AbstractChannelHandlerContext.java:285)
at io.netty.channel.AbstractChannelHandlerContext.invokeExceptionCaught(AbstractChannelHandlerContext.java:264)
at io.netty.channel.AbstractChannelHandlerContext.fireExceptionCaught(AbstractChannelHandlerContext.java:256)
at io.netty.channel.ChannelInboundHandlerAdapter.exceptionCaught(ChannelInboundHandlerAdapter.java:131)
at io.netty.channel.AbstractChannelHandlerContext.invokeExceptionCaught(AbstractChannelHandlerContext.java:285)
at io.netty.channel.AbstractChannelHandlerContext.invokeExceptionCaught(AbstractChannelHandlerContext.java:264)
at io.netty.channel.AbstractChannelHandlerContext.fireExceptionCaught(AbstractChannelHandlerContext.java:256)
at io.netty.channel.CombinedChannelDuplexHandler$DelegatingChannelHandlerContext.fireExceptionCaught(CombinedChannelDuplexHandler.java:426)
at io.netty.channel.ChannelHandlerAdapter.exceptionCaught(ChannelHandlerAdapter.java:87)
at io.netty.channel.CombinedChannelDuplexHandler$1.fireExceptionCaught(CombinedChannelDuplexHandler.java:147)
at io.netty.channel.ChannelInboundHandlerAdapter.exceptionCaught(ChannelInboundHandlerAdapter.java:131)
at io.netty.channel.CombinedChannelDuplexHandler.exceptionCaught(CombinedChannelDuplexHandler.java:233)
at io.netty.channel.AbstractChannelHandlerContext.invokeExceptionCaught(AbstractChannelHandlerContext.java:285)
at io.netty.channel.AbstractChannelHandlerContext.invokeExceptionCaught(AbstractChannelHandlerContext.java:264)
at io.netty.channel.AbstractChannelHandlerContext.fireExceptionCaught(AbstractChannelHandlerContext.java:256)
at io.netty.handler.timeout.ReadTimeoutHandler.readTimedOut(ReadTimeoutHandler.java:98)
at io.netty.handler.timeout.ReadTimeoutHandler.channelIdle(ReadTimeoutHandler.java:90)
at io.netty.handler.timeout.IdleStateHandler$ReaderIdleTimeoutTask.run(IdleStateHandler.java:494)
at io.netty.handler.timeout.IdleStateHandler$AbstractIdleTask.run(IdleStateHandler.java:466)
at io.netty.util.concurrent.PromiseTask$RunnableAdapter.call(PromiseTask.java:38)
at io.netty.util.concurrent.ScheduledFutureTask.run(ScheduledFutureTask.java:127)
at io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java:163)
at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:404)
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:462)
at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:897)
at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
at java.lang.Thread.run(Thread.java:748)
Caused by: io.micronaut.http.client.exceptions.ReadTimeoutException: Read Timeout
at io.micronaut.http.client.exceptions.ReadTimeoutException.<clinit>(ReadTimeoutException.java:26)
at io.micronaut.http.client.DefaultHttpClient.lambda$null$25(DefaultHttpClient.java:1055)
at io.reactivex.internal.operators.flowable.FlowableOnErrorNext$OnErrorNextSubscriber.onError(FlowableOnErrorNext.java:103)
at io.micronaut.reactive.rxjava2.InstrumentedSubscriber.lambda$onError$1(InstrumentedSubscriber.java:96)
at io.micronaut.reactive.rxjava2.InstrumentedSubscriber.onError(InstrumentedSubscriber.java:100)
at io.reactivex.internal.operators.flowable.FlowableTimeoutTimed$TimeoutSubscriber.onTimeout(FlowableTimeoutTimed.java:139)
at io.reactivex.internal.operators.flowable.FlowableTimeoutTimed$TimeoutTask.run(FlowableTimeoutTimed.java:170)
at io.reactivex.internal.schedulers.ScheduledRunnable.run(ScheduledRunnable.java:66)
at io.reactivex.internal.schedulers.ScheduledRunnable.call(ScheduledRunnable.java:57)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:180)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
... 1 more
Exception in thread "nioEventLoopGroup-1-3" io.reactivex.exceptions.UndeliverableException: The exception could not be delivered to the consumer because it has already canceled/disposed the flow or the exception has nowhere to go to begin with. Further reading: https://github.com/ReactiveX/RxJava/wiki/What's-different-in-2.0#error-handling | io.micronaut.http.client.exceptions.ReadTimeoutException: Read Timeout
at io.reactivex.plugins.RxJavaPlugins.onError(RxJavaPlugins.java:367)
at io.reactivex.internal.operators.flowable.FlowableCreate$BaseEmitter.onError(FlowableCreate.java:275)
at io.micronaut.http.client.DefaultHttpClient$10.exceptionCaught(DefaultHttpClient.java:1816)
at io.netty.channel.AbstractChannelHandlerContext.invokeExceptionCaught(AbstractChannelHandlerContext.java:285)
at io.netty.channel.AbstractChannelHandlerContext.invokeExceptionCaught(AbstractChannelHandlerContext.java:264)
at io.netty.channel.AbstractChannelHandlerContext.fireExceptionCaught(AbstractChannelHandlerContext.java:256)
at io.netty.channel.ChannelInboundHandlerAdapter.exceptionCaught(ChannelInboundHandlerAdapter.java:131)
at io.netty.channel.AbstractChannelHandlerContext.invokeExceptionCaught(AbstractChannelHandlerContext.java:285)
at io.netty.channel.AbstractChannelHandlerContext.invokeExceptionCaught(AbstractChannelHandlerContext.java:264)
at io.netty.channel.AbstractChannelHandlerContext.fireExceptionCaught(AbstractChannelHandlerContext.java:256)
at io.netty.channel.ChannelInboundHandlerAdapter.exceptionCaught(ChannelInboundHandlerAdapter.java:131)
at io.netty.channel.AbstractChannelHandlerContext.invokeExceptionCaught(AbstractChannelHandlerContext.java:285)
at io.netty.channel.AbstractChannelHandlerContext.invokeExceptionCaught(AbstractChannelHandlerContext.java:264)
at io.netty.channel.AbstractChannelHandlerContext.fireExceptionCaught(AbstractChannelHandlerContext.java:256)
at io.netty.channel.ChannelInboundHandlerAdapter.exceptionCaught(ChannelInboundHandlerAdapter.java:131)
at io.netty.channel.AbstractChannelHandlerContext.invokeExceptionCaught(AbstractChannelHandlerContext.java:285)
at io.netty.channel.AbstractChannelHandlerContext.invokeExceptionCaught(AbstractChannelHandlerContext.java:264)
at io.netty.channel.AbstractChannelHandlerContext.fireExceptionCaught(AbstractChannelHandlerContext.java:256)
at io.netty.channel.CombinedChannelDuplexHandler$DelegatingChannelHandlerContext.fireExceptionCaught(CombinedChannelDuplexHandler.java:426)
at io.netty.channel.ChannelHandlerAdapter.exceptionCaught(ChannelHandlerAdapter.java:87)
at io.netty.channel.CombinedChannelDuplexHandler$1.fireExceptionCaught(CombinedChannelDuplexHandler.java:147)
at io.netty.channel.ChannelInboundHandlerAdapter.exceptionCaught(ChannelInboundHandlerAdapter.java:131)
at io.netty.channel.CombinedChannelDuplexHandler.exceptionCaught(CombinedChannelDuplexHandler.java:233)
at io.netty.channel.AbstractChannelHandlerContext.invokeExceptionCaught(AbstractChannelHandlerContext.java:285)
at io.netty.channel.AbstractChannelHandlerContext.invokeExceptionCaught(AbstractChannelHandlerContext.java:264)
at io.netty.channel.AbstractChannelHandlerContext.fireExceptionCaught(AbstractChannelHandlerContext.java:256)
at io.netty.handler.timeout.ReadTimeoutHandler.readTimedOut(ReadTimeoutHandler.java:98)
at io.netty.handler.timeout.ReadTimeoutHandler.channelIdle(ReadTimeoutHandler.java:90)
at io.netty.handler.timeout.IdleStateHandler$ReaderIdleTimeoutTask.run(IdleStateHandler.java:494)
at io.netty.handler.timeout.IdleStateHandler$AbstractIdleTask.run(IdleStateHandler.java:466)
at io.netty.util.concurrent.PromiseTask$RunnableAdapter.call(PromiseTask.java:38)
at io.netty.util.concurrent.ScheduledFutureTask.run(ScheduledFutureTask.java:127)
at io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java:163)
at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:404)
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:462)
at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:897)
at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
at java.lang.Thread.run(Thread.java:748)
Caused by: io.micronaut.http.client.exceptions.ReadTimeoutException: Read Timeout
at io.micronaut.http.client.exceptions.ReadTimeoutException.<clinit>(ReadTimeoutException.java:26)
at io.micronaut.http.client.DefaultHttpClient.lambda$null$25(DefaultHttpClient.java:1055)
at io.reactivex.internal.operators.flowable.FlowableOnErrorNext$OnErrorNextSubscriber.onError(FlowableOnErrorNext.java:103)
at io.micronaut.reactive.rxjava2.InstrumentedSubscriber.lambda$onError$1(InstrumentedSubscriber.java:96)
at io.micronaut.reactive.rxjava2.InstrumentedSubscriber.onError(InstrumentedSubscriber.java:100)
at io.reactivex.internal.operators.flowable.FlowableTimeoutTimed$TimeoutSubscriber.onTimeout(FlowableTimeoutTimed.java:139)
at io.reactivex.internal.operators.flowable.FlowableTimeoutTimed$TimeoutTask.run(FlowableTimeoutTimed.java:170)
at io.reactivex.internal.schedulers.ScheduledRunnable.run(ScheduledRunnable.java:66)
at io.reactivex.internal.schedulers.ScheduledRunnable.call(ScheduledRunnable.java:57)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:180)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
... 1 more
io.micronaut.http.client.exceptions.ReadTimeoutException: Read Timeout
at io.micronaut.http.client.exceptions.ReadTimeoutException.<clinit>(ReadTimeoutException.java:26)
at io.micronaut.http.client.DefaultHttpClient.lambda$null$25(DefaultHttpClient.java:1055)
at io.reactivex.internal.operators.flowable.FlowableOnErrorNext$OnErrorNextSubscriber.onError(FlowableOnErrorNext.java:103)
at io.micronaut.reactive.rxjava2.InstrumentedSubscriber.lambda$onError$1(InstrumentedSubscriber.java:96)
at io.micronaut.reactive.rxjava2.InstrumentedSubscriber.onError(InstrumentedSubscriber.java:100)
at io.reactivex.internal.operators.flowable.FlowableTimeoutTimed$TimeoutSubscriber.onTimeout(FlowableTimeoutTimed.java:139)
at io.reactivex.internal.operators.flowable.FlowableTimeoutTimed$TimeoutTask.run(FlowableTimeoutTimed.java:170)
at io.reactivex.internal.schedulers.ScheduledRunnable.run(ScheduledRunnable.java:66)
at io.reactivex.internal.schedulers.ScheduledRunnable.call(ScheduledRunnable.java:57)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:180)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
Request loop failed with: Read Timeout
END RequestId: 10754fbd-1cf2-4963-8392-fb10d6aed231
REPORT RequestId: 10754fbd-1cf2-4963-8392-fb10d6aed231  Duration: 2199.86 ms    Billed Duration: 2200 ms Memory Size: 704 MB    Max Memory Used: 120 MB 
RequestId: 10754fbd-1cf2-4963-8392-fb10d6aed231 Error: Runtime exited without providing a reason
Runtime.ExitError
10:20:17.201 [main]INFO i.m.f.a.p.AbstractLambdaContainerHandler - Starting Lambda Container Handler
10:20:17.341 [main]INFO i.m.context.env.DefaultEnvironment - Established active environments: [function]
START RequestId: 5c454603-1575-4cfe-8a1e-426e5c4eb154 Version: $LATEST

MicronautRequestStreamHandler function name not retrieved from Lambda Context

I feel like I must be misunderstanding something. MicronautRequestStreamHandler is a Lambda-specific stream handler that takes a lambda Context object. The Context object contains a functionName property which specifies the declared name of the lambda function. Confusingly, this value is never referenced when the RequestStreamHandler is attempting to map its current execution context to a @FunctionBean function name.

Is there a reason why MicronautRequestStreamHandler does not out-of-the-box override AbstractExecutor.resolveFunctionName and return Context.getFunctionName()? It's straightforward enough for me to do myself, but I don't understand why it's not the default behaviour.

MicronautAwsProxyRequest.AwsParameters.getAll() does not return values properly

The MicronautAwsProxyRequest.AwsParameters.getAll() method does not return parameter values but instead returns the parameter name. I believe the following:

return strings.stream().map(v -> decodeValue(name,name.toString())).collect(Collectors.toList());

Should be:

return strings.stream().map(v -> decodeValue(name,v.toString())).collect(Collectors.toList());

(AWS Lambda) Exception Handler invocation is non-deterministic

Task List

  • Steps to reproduce provided
  • Stacktrace (if present) provided
  • Example that reproduces the problem uploaded to Github
  • Full description of the issue provided (see below)

Steps to Reproduce

  1. Implement a class derived from RuntimeException and a corresponding exception handler for the specific subclass.
  2. Also implement an exception handler for RuntimeException
  3. Throw the derived class in an HTTP request handler
  4. Deploy to AWS Lambda (using the Lambda proxy from Micronaut)
  5. Invoke the HTTP request handler

Expected Behaviour

The exception handler for the derived exception is always invoked.

Actual Behaviour

Sometimes, apparently "at random" the RuntimeException handler is invoked.

Environment Information

AWS Lambda (Java 8, standard AWS runtime)

Example Application

https://github.com/alexwilbur/mn-issues

S3Event as input to MicronautRequestHandler does not work

Having com.amazonaws.services.lambda.runtime.events.S3Event as input to the MicronautRequestHandler like below causes an ClassCastException when the execute method is invoked from the handler.

public class MyFunction extends MicronautRequestHandler<S3Event, String> { ... }
... 
@Override
public String execute(S3Event event) { ... }

Error

{
  "errorMessage": "java.util.LinkedHashMap cannot be cast to com.amazonaws.services.lambda.runtime.events.S3Event",
  "errorType": "java.lang.ClassCastException",
  "stackTrace": [
    "test.package.MyFunction.execute(MyFunction.java:40)",
    "io.micronaut.function.aws.MicronautRequestHandler.handleRequest(MicronautRequestHandler.java:37)",
    "sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)",
    "sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)",
    "sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)",
    "java.lang.reflect.Method.invoke(Method.java:498)"
  ]
}

No bean of type [io.micronaut.jackson.codec.JsonMediaTypeCodec] exists

Trying to use the example: micronaut-aws/examples/api-proxy-graal-custom-runtime-example/

I am forced to use micronautVersion=1.1.0.M2

if not I get the error - Could not find or load main class io.micronaut.graal.reflect.GraalClassLoadingAnalyzer

But with 1.1.0.M2 deployed to Lambda I get below error
{
"errorMessage": "Error starting Micronaut container: No bean of type [io.micronaut.jackson.codec.JsonMediaTypeCodec] exists. Ensure the class is declared a bean and if you are using Java or Kotlin make sure you have enabled annotation processing."
}

Test friendly StreamLambdaHandler

The suggested StreamLambdaHandler is not very friendly to testing. @MicronautTest doesn't seem to be compatible with testing the handler. I'm using Gru for AWS API Gateway Proxy for testing to ensure the API Gateway integration works.

I had to come up with the following implementation to be able to reset the application context stored statically.

public class StreamLambdaHandler implements RequestStreamHandler {

    private static final Logger LOGGER = LoggerFactory.getLogger(StreamLambdaHandler.class);

    private static MicronautLambdaContainerHandler handler;

    static {
        reset();
    }

    /**
     * Resets the current handler. For testing purposes only.
     */
    public static void reset() {
        reset(b -> {});
    }

    /**
     * Resets the current handler. For testing purposes only.
     *
     * @param configuration builder customizer
     */
    public static void reset(Consumer<ApplicationContextBuilder> configuration) {
        try {
            ApplicationContextBuilder builder = ApplicationContext.build();
            configuration.accept(builder);
            handler = MicronautLambdaContainerHandler.getAwsProxyHandler(builder);
        } catch (ContainerInitializationException e) {
            // if we fail here. We re-throw the exception to force another cold start
            if (LOGGER.isErrorEnabled()) {
                LOGGER.error("Exception in container initialization", e);
            }
            throw new IllegalStateException("Could not initialize Micronaut", e);
        }
    }
     /**
     * Return the application context. For testing purposes only.
     */
    public static ApplicationContext getApplicationContext() {
        if (handler == null) {
            reset();
        }
        return handler.getApplicationContext();
    }

    @Override
    public void handleRequest(InputStream inputStream, OutputStream outputStream, Context context)
            throws IOException {
        handler.proxyStream(inputStream, outputStream, context); 
    }
}

Then I am able to test the handler as follows:

    void setup() {
        MicronautHandler.reset()
        MicronautHandler.applicationContext.with { ApplicationContext context ->
            context.environment.addPropertySource('test.properties', [
                'app.server.url': SOME_APP_SERVER_URL,
            ])
            context.registerSingleton(CaptchaService, captchaService)
            context.registerSingleton(AuthTokenService, managerTokenService, Qualifiers.byName('managerTokenService'))
        }
    }

Server side rendering not working when using function-aws-api-proxy

Given the below controller action:

@Get("/render-html")
@Produces(MediaType.TEXT_HTML)
public ModelAndView getHtmlFromRenderEngine(Context context) {
        ModelAndView mav = new ModelAndView("home", CollectionUtils.mapOf("firstname", "Luke", "lastname", "Skywalker"));
        return mav;
}

When executing the action through AWS API Gateway (via the micronaut function-aws-api-proxy) the result will be:

{"view":"home","model":{"firstname":Luke,"lastname":"Skywalker"}}

The correct result should be rendered "home" template using the configured render engine.

AWS Custom domain support custom runtime

Created an application using the aws-api-gateway-graal feature following the link
https://micronaut-projects.github.io/micronaut-aws/latest/guide/#customRuntimes
I used the following fix to build
#49

Micronaut version 1.2.1

After this i deploy to an aws lambda with an api gateway, call the ping endpoint and response is 200. Calling the same endpoint after adding a custom domain in AWS that uses the api gateway causes a 502 status along with the following error in the lambda logs which gets repeated seemingly until the lambda times out.

11:40:34 WARNING: The sunec native library, required by the SunEC provider, could not be loaded. This library is usually shipped as part of the JDK and can be found under <JAVA_HOME>/jre/lib//libsunec.so. It is loaded at run time via System.loadLibrary("sunec"), the first time services from SunEC are accessed. To use this provider's services the java.library.path system property needs to be set a
11:40:34 START RequestId: 54b57a52-049a-4303-aeb3-60763a20944b Version: $LATEST
11:40:34 END RequestId: 54b57a52-049a-4303-aeb3-60763a20944b
11:40:34 REPORT RequestId: 54b57a52-049a-4303-aeb3-60763a20944b Duration: 18.89 ms Billed Duration: 300 ms Memory Size: 3008 MB Max Memory Used: 77 MB Init Duration: 264.85 ms XRAY TraceId: 1-5d80c631-77a3481d1600ee0d1c4ebba9 SegmentId: 14e6aa5d6d1cebaf Sampled: true
11:40:38 START RequestId: 667ef73d-b2a7-4bc4-8423-9517dbbe294c Version: $LATEST
11:40:38 Invocation with requestId [667ef73d-b2a7-4bc4-8423-9517dbbe294c] failed: com.amazonaws.serverless.proxy.internal.LambdaContainerHandler.getContainerConfig()java.lang.NoSuchMethodError: com.amazonaws.serverless.proxy.internal.LambdaContainerHandler.getContainerConfig()
11:40:38 at com.amazonaws.serverless.proxy.internal.SecurityUtils.isValidHost(SecurityUtils.java:63)
11:40:38 at io.micronaut.function.aws.proxy.MicronautAwsProxyRequest.getUri(MicronautAwsProxyRequest.java:167)
11:40:38 at io.micronaut.http.HttpRequest.getPath(HttpRequest.java:85)
11:40:38 at io.micronaut.function.aws.proxy.MicronautRequestReader.readRequest(MicronautRequestReader.java:79)
11:40:38 at io.micronaut.function.aws.proxy.MicronautRequestReader.readRequest(MicronautRequestReader.java:48)
11:40:38 at io.micronaut.function.aws.proxy.AbstractLambdaContainerHandler.proxy(AbstractLambdaContainerHandler.java:204)
11:40:38 at io.micronaut.function.aws.runtime.MicronautLambdaRuntime.startRuntimeApiEventLoop(MicronautLambdaRuntime.java:129)
11:40:38 at io.micronaut.function.aws.runtime.MicronautLambdaRuntime.main(MicronautLambdaRuntime.java:75)

URI query parameters are not propagated

Steps to Reproduce

  1. Create project: mn create-app aws-api-gateway-test --features aws-api-gateway
  2. Add a controller, with endpoints that is waiting for optional or mandatory query params
import io.micronaut.http.annotation.Controller;
import io.micronaut.http.annotation.Get;
import io.micronaut.http.annotation.QueryValue;

import javax.annotation.Nullable;

@Controller
public class BookController {

    @Get("/optional/books{?max,offset}")
    public String booksWithOptionalQueryParams(@Nullable String max, @Nullable Integer offset) {
        return "{\"max\": " + max + ", \"offset\": " + offset + "}";
    }

    @Get("/mandatory/books")
    public String booksWithQueryParams(@QueryValue String max, @QueryValue Integer offset) {
        return "{\"max\": " + max + ", \"offset\": " + offset + "}";
    }
}
  1. Run ./gradlew clean build && sam local start-api --template sam.yaml
  2. Call http://127.0.0.1:3000/optional/books?max=10&offset=10 or http://127.0.0.1:3000/mandatory/books?max=10&offset=10

Example project can be checked out from here: https://github.com/lkonya/micronaut-aws-api-gateway-test.git

Expected Behaviour

HTTP 200 - successfully parsed URI query strings into query params

{
    "max": 10,
    "offset": 10
}

Actual Behaviour

HTTP 400 - Bad Request
Client:

{
    "_links": {
        "self": {
            "href": "https://1234567890.execute-api.eu-central-1.amazonaws.com/books",
            "templated": false
        }
    },
    "message": "Required argument [String max] not specified",
    "path": "/max"
}

Server:

[2019-04-19 09:08:10.813] " + NO_REQUEST_ID + " INFO i.m.f.a.p.AbstractLambdaContainerHandler - Starting Lambda Container Handler 
[2019-04-19 09:08:10.917] " + NO_REQUEST_ID + " INFO i.m.c.e.DefaultEnvironment - Established active environments: [function] 
[2019-04-19 09:08:12.759] aa14e611-63d3-4b9e-8a6e-e75dba87e94a ERROR i.m.h.s.n.c.UnsatisfiedRouteHandler - io.micronaut.function.aws.proxy.MicronautAwsProxyRequest@415e0bcb (Bad Request): Required argument [String max] not specified 
2019-04-19 11:08:13 No Content-Type given. Defaulting to 'application/json'.
2019-04-19 11:08:13 127.0.0.1 - - [19/Apr/2019 11:08:13] "GET /books?max=10&offset=10 HTTP/1.1" 400 -

Environment Information

  • Operating System: MacOs Mojava version: 10.14.4
  • Micronaut Version: 1.1.0
  • JDK Version: 1.8.0_202

Lambda with proxy integration doesn't unmarshal the JSON body into de @Body annotated controller parameters

There may be a problem with the unmarshalling process in annotated controllers running as lambdas with proxy integration. The full description of the problem can be found in Stackoverflow: https://stackoverflow.com/questions/54769250/micronaut-lambda-with-proxy-cant-unmarshal-object-from-json-body-io-micronaut-w

A Sample project is available here: https://github.com/codependent/micronaut-aws-lambda-proxy

Extremely slow cold starts for a micronaut functions deployed on AWS Lambda

This issue refers to the following function: https://github.com/codependent/micronaut-aws-authentication-function

It's a basic function that generates a JWT token:

@FunctionBean("micronaut-aws-authentication-function")
class MicronautAwsAuthenticationFunction : Function<Credentials, AuthenticationResponse> {

    private val logger = LoggerFactory.getLogger(javaClass)

    override fun apply(t: Credentials): AuthenticationResponse {
        logger.info("Authenticating {} - {}", t.user, t.password)
        return if (t.user == "jose" && t.password == "MyPassword") {
            //HMAC
            val algorithm = Algorithm.HMAC256("secret")
            val token = JWT.create()
                    .withIssuer("MicronautAwsAuthenticationFunction")
                    .withSubject(t.user)
                    .sign(algorithm)
            logger.info("Generated token {}", token)
            AuthenticationResponse(token)
        } else {
            logger.info("Incorrect user/password")
            AuthenticationResponse()
        }
    }
}

Normally (warm behaviour) this AWS executes really fast (~5ms):

Duration
2.05 ms
Billed duration
100 ms
Resources configured
320 MB
Max memory used
153 MB

However the cold start is extremely slow ~20s. I was expecting that Micronaut-based java8 lambdas start way faster than normal Java applications but this shows there's no improvement at all.

The function is invoked directly in the Lambda web console, through the io.micronaut.function.aws.MicronautRequestStreamHandler handler and has 320MB RAM assigned. Also, there's no VPC configured:

Duration
19475.13 ms
Billed duration
19500 ms
Resources configured
320 MB
Max memory used
154 MB

I wonder if there may be something wrong about my setup/implementation or this is the expected behaviour and you guys have found similar times for the cold start. In this case, do you have a way to improve this horrible cold start times??

Incoming Cookies not available in AWS API Gateway

Incoming Cookies are not available via httpRequest.getCookies() when Micronaut is run through API Gateway integration. Outgoing cookies are added to the response correctly and the cookies are available via httpRequest.getHeaders().get("Cookie")

The specific issue affecting me is that Micronaut JWT authentication via Cookies is not allowing access to secured pages after login.

Example project at https://github.com/rnielsen/micronaut-aws-apiproxy-test

curl -i --cookie test=value http://localhost:8080/test/checkCookies
HTTP/1.1 200 OK

{"cookieHeader":"test=value","cookies":[{"nettyCookie":{"secure":false,"httpOnly":false},"name":"test","value":"value","secure":false,"maxAge":-9223372036854775808,"httpOnly":false}]}
curl -i --cookie test=value https://3kf8ik2za4.execute-api.ap-southeast-2.amazonaws.com/dev/test/checkCookies
HTTP/2 200 

{"cookieHeader":"test=value"}

Tested against io.micronaut.aws:micronaut-function-aws-api-proxy:1.1.3.BUILD-SNAPSHOT"

UnsatisfiedRouteException

Thanks for reporting an issue for Micronaut, please review the task list below before submitting the
issue. Your issue report will be closed if the issue is incomplete and the below tasks not completed.

NOTE: If you are unsure about something and the issue is more of a question a better place to ask questions is on Stack Overflow (http://stackoverflow.com/tags/micronaut) or Gitter (https://gitter.im/micronautfw/). DO NOT use the issue tracker to ask questions.

Task List

  • Steps to reproduce provided
  • Stacktrace (if present) provided
  • Example that reproduces the problem uploaded to Github
  • Full description of the issue provided (see below)

Steps to Reproduce

  1. @validated controller with base URI, like @controller(value = "/users")
  2. @post request that accepts JSON and serializes it to an object
  3. Pass a POJO as a parameters pre-seeded by @Valid and @Body

Expected Behaviour

Validate the POJO and either return a 400 Bad request or 201 for Created.

Actual Behaviour

The controller works fine when I run it stand alone or via test but it fails when I deploy it with AWS and invoke it via API Gateway. I get the following error:

io.micronaut.web.router.exceptions.UnsatisfiedRouteException: Required argument [BrandRepresentation brand] not specified at io.micronaut.web.router.AbstractRouteMatch.execute(AbstractRouteMatch.java:279) at io.micronaut.web.router.RouteMatch.execute(RouteMatch.java:122) at io.micronaut.function.aws.proxy.MicronautLambdaContainerHandler.executeRoute(MicronautLambdaContainerHandler.java:312) at io.micronaut.function.aws.proxy.MicronautLambdaContainerHandler.lambda$null$1(MicronautLambdaContainerHandler.java:233) at io.reactivex.internal.operators.flowable.FlowableDefer.subscribeActual(FlowableDefer.java:35) at io.reactivex.Flowable.subscribe(Flowable.java:14805) at io.reactivex.Flowable.subscribe(Flowable.java:14752) at io.micronaut.reactive.rxjava2.RxInstrumentedFlowable.subscribeActual(RxInstrumentedFlowable.java:68) at io.reactivex.Flowable.subscribe(Flowable.java:14805) at io.reactivex.Flowable.subscribe(Flowable.java:14755) at io.micronaut.http.context.ServerRequestTracingPublisher.lambda$subscribe$0(ServerRequestTracingPublisher.java:52) at io.micronaut.http.context.ServerRequestContext.with(ServerRequestContext.java:52) at io.micronaut.http.context.ServerRequestTracingPublisher.subscribe(ServerRequestTracingPublisher.java:52) at io.reactivex.internal.operators.flowable.FlowableFromPublisher.subscribeActual(FlowableFromPublisher.java:29) at io.reactivex.Flowable.subscribe(Flowable.java:14805) at io.reactivex.Flowable.subscribe(Flowable.java:14752) at io.micronaut.reactive.rxjava2.RxInstrumentedFlowable.subscribeActual(RxInstrumentedFlowable.java:68) at io.reactivex.Flowable.subscribe(Flowable.java:14805) at io.reactivex.internal.operators.flowable.FlowableOnErrorNext.subscribeActual(FlowableOnErrorNext.java:40) at io.reactivex.Flowable.subscribe(Flowable.java:14805) at io.reactivex.Flowable.subscribe(Flowable.java:14752) at io.micronaut.reactive.rxjava2.RxInstrumentedFlowable.subscribeActual(RxInstrumentedFlowable.java:68) at io.reactivex.Flowable.subscribe(Flowable.java:14805) at io.reactivex.Flowable.blockingFirst(Flowable.java:5607) at io.micronaut.function.aws.proxy.MicronautLambdaContainerHandler.lambda$handleRequest$5(MicronautLambdaContainerHandler.java:274) at io.micronaut.http.context.ServerRequestContext.with(ServerRequestContext.java:52) at io.micronaut.function.aws.proxy.MicronautLambdaContainerHandler.handleRequest(MicronautLambdaContainerHandler.java:206) at io.micronaut.function.aws.proxy.MicronautLambdaContainerHandler.handleRequest(MicronautLambdaContainerHandler.java:73) at io.micronaut.function.aws.proxy.AbstractLambdaContainerHandler.proxy(AbstractLambdaContainerHandler.java:207) at io.micronaut.function.aws.proxy.AbstractLambdaContainerHandler.proxyStream(AbstractLambdaContainerHandler.java:239) at com.identityguard.config.StreamLambdaHandler.handleRequest(StreamLambdaHandler.java:36) at lambdainternal.EventHandlerLoader$2.call(EventHandlerLoader.java:888) at lambdainternal.AWSLambda.startRuntime(AWSLambda.java:293) at lambdainternal.AWSLambda.<clinit>(AWSLambda.java:64) at java.lang.Class.forName0(Native Method) at java.lang.Class.forName(Class.java:348) at lambdainternal.LambdaRTEntry.main(LambdaRTEntry.java:114)

Environment Information

  • Operating System: Lambda + Api gateway
  • Micronaut Version: io.micronaut:micronaut-bom:1.1.2
  • JDK Version: Java8

Example Application

-N/A

helper scripts lacks gradle build command

the scripts from api-gateway-proxy-graal feature lack the initial line to build the application. it would make more sense to me if each of the script starts with ./gradlew build.

Improve the access to multiple request parameters in Lambdas with proxy integration

This improvement request is related to this question from stackoverflow: https://stackoverflow.com/questions/54768208/is-it-possible-to-access-the-whole-request-information-in-a-micronaut-lambda-wit

The point is sometimes it may be necessary to access multiple values from the request, headers, query params, body...

In a controller like this:

fun postPing(@Header("Host") host: String): String {
        logger.info("PARAM {}", host)
        return "{\"pong\":true}"
}

if we wanted to access a bunch of headers, plus a body, etc... we could end up with a method with too many parameters.

Could you consider allowing us to use some kind of class that gives us access to all the request information?

Spring Cloud Function solved this by means of a Message class, that encapsulates all the request info and gives access to the unmarshaled body: http://cloud.spring.io/spring-cloud-static/spring-cloud-function/2.0.1.RELEASE/single/spring-cloud-function.html#_java_8_function_support

If the user writes a function using Message (from spring-messaging) it will receive and transmit headers from any adapter that supports key-value metadata (e.g. HTTP headers). Here are the details.

AWSLambdaAsyncClientFactory throws DependencyInjectionException

I tried to upgrade our app to Micronaut 1.2 (from 1.0.4), but our AWS lambda functions stopped working. Here is the Exception I get:

Failed to inject value for parameter [refreshScope] of class: io.micronaut.runtime.context.scope.refresh.RefreshInterceptor

Message: No bean of type [io.micronaut.runtime.context.scope.refresh.RefreshScope] exists. Make sure the bean is not disabled by bean requirements (enable trace logging for 'io.micronaut.context.condition' to check) and if the bean is enabled then ensure the class is declared a bean and annotation processing is enabled (for Java and Kotlin the 'micronaut-inject-java' dependency should be configured as an annotation processor).
Path Taken: DispatcherFunction.setTaskProcessor([TaskProcessor taskProcessor]) 
--> TaskProcessor.setWorkerServices([WorkerService[] workerServices]) 
--> BrandWorkerService.setBrandComputationService([BrandComputationService brandComputationService]) 
--> BrandComputationService.setServicesClient([ServicesClient servicesClient]) 
--> new ServicesClient$Intercepted(BeanContext beanContext,Qualifier qualifier,[Interceptor[] interceptors]) 
--> new FunctionClientAdvice(FunctionDiscoveryClient discoveryClient,[FunctionInvokerChooser functionInvokerChooser]) 
--> new DefaultFunctionInvokerChooser([FunctionInvokerChooser[] choosers]) 
--> new AWSLambdaFunctionExecutor([AWSLambdaAsync asyncClient],ByteBufferFactory byteBufferFactory,JsonMediaTypeCodec jsonMediaTypeCodec,ExecutorService ioExecutor) 
--> new $AWSLambdaAsyncClientFactory$AwsLambdaAsyncClient0Definition$Intercepted(BeanContext beanContext,Qualifier qualifier,[Interceptor[] interceptors]) 
--> new RefreshInterceptor([RefreshScope refreshScope]): io.micronaut.context.exceptions.DependencyInjectionException
io.micronaut.context.exceptions.DependencyInjectionException: Failed to inject value for parameter [refreshScope] of class: io.micronaut.runtime.context.scope.refresh.RefreshInterceptor

I did a quick search and found #45 which looks similar, but we don't have the micronaut-management module configured for our AWS functions. Still, it gave me a hint that this might be the problem:

public class AWSLambdaAsyncClientFactory {
(...)
    @Refreshable
    @Requires(beans = AWSLambdaConfiguration.class)
    AWSLambdaAsync awsLambdaAsyncClient() {

Maybe the @Refreshable annotation is causing this? If not, please can you let me know how to get AWS functions working again? This is a blocker to our upgrade.

Docker build fails for examples/api-proxy-graal-custom-runtime-example

Followed the README for examples/api-proxy-graal-custom-runtime-example, but it failed on the generation of reflect.json step because "Could not find or load main class io.micronaut.graal.reflect.GraalClassLoadingAnalyzer" from the fat jar.

What would prevent the dependency for io.micronaut.graal.reflect.GraalClassLoadingAnalyzer from being included in the fat jar?

docker build . -t example-micronaut-runtime
Sending build context to Docker daemon 101.4kB
Step 1/23 : FROM gradle:5.1.1-jdk-alpine as builder
---> 5c0d09610520
Step 2/23 : COPY --chown=gradle:gradle . /home/application
---> 66174f284cf3
Step 3/23 : WORKDIR /home/application
---> Running in 5022a517fe3b
Removing intermediate container 5022a517fe3b
---> 46df1fe4052d
Step 4/23 : RUN gradle build --no-daemon
---> Running in 040019a2a7a4

Welcome to Gradle 5.1.1!

Here are the highlights of this release:

  • Control which dependencies can be retrieved from which repositories
  • Production-ready configuration avoidance APIs

For more details see https://docs.gradle.org/5.1.1/release-notes.html

To honour the JVM settings for this build a new JVM will be forked. Please consider using the daemon: https://docs.gradle.org/5.1.1/userguide/gradle_daemon.html.
Daemon will be stopped at the end of the build stopping after processing

Task :compileJava
Note: Creating bean classes for 1 type elements

Task :processResources
Task :classes
Task :jar
Task :startScripts
Task :distTar
Task :distZip
Task :buildZip
Task :shadowJar
Task :startShadowScripts
Task :shadowDistTar
Task :shadowDistZip SKIPPED
Task :assemble
Note: Creating bean classes for 1 type elements

Task :compileTestJava

Task :processTestResources NO-SOURCE
Task :testClasses
Task :test
Task :check
Task :build

Deprecated Gradle features were used in this build, making it incompatible with Gradle 6.0.
Use '--warning-mode all' to show the individual deprecation warnings.
See https://docs.gradle.org/5.1.1/userguide/command_line_interface.html#sec:command_line_warnings

BUILD SUCCESSFUL in 1m 3s
12 actionable tasks: 12 executed
Removing intermediate container 040019a2a7a4
---> 0c38484359aa
Step 5/23 : FROM amazonlinux:2017.03.1.20170812 as graalvm
---> 28b6d09fbbe4
Step 6/23 : ENV LANG=en_US.UTF-8
---> Using cache
---> 7398562eec93
Step 7/23 : RUN yum install -y gcc gcc-c++ libc6-dev zlib1g-dev curl bash zlib zlib-devel zip && rm -rf /var/cache/yum
---> Using cache
---> 81d6ebb3a4cc
Step 8/23 : ENV GRAAL_VERSION 1.0.0-rc11
---> Using cache
---> 9b97ba12f988
Step 9/23 : ENV GRAAL_FILENAME graalvm-ce-${GRAAL_VERSION}-linux-amd64.tar.gz
---> Using cache
---> 55b1ea6c8754
Step 10/23 : RUN curl -4 -L https://github.com/oracle/graal/releases/download/vm-${GRAAL_VERSION}/${GRAAL_FILENAME} -o /tmp/${GRAAL_FILENAME}
---> Using cache
---> 3b7018178301
Step 11/23 : RUN tar -zxvf /tmp/${GRAAL_FILENAME} -C /tmp && mv /tmp/graalvm-ce-${GRAAL_VERSION} /usr/lib/graalvm
---> Using cache
---> bc1aee2930e6
Step 12/23 : RUN rm -rf /tmp/*
---> Using cache
---> 368abba502e1
Step 13/23 : CMD ["/usr/lib/graalvm/bin/native-image"]
---> Using cache
---> 4298fc3e16f3
Step 14/23 : FROM graalvm
---> 4298fc3e16f3
Step 15/23 : COPY --from=builder /home/application/ /home/application/
---> f82f11a2ac51
Step 16/23 : WORKDIR /home/application
---> Running in d7756549dc4c
Removing intermediate container d7756549dc4c
---> add59665ea7a
Step 17/23 : RUN /usr/lib/graalvm/bin/java -cp build/libs/.jar io.micronaut.graal.reflect.GraalClassLoadingAnalyzer reflect.json
---> Running in c1b3d24d9497
Error: Could not find or load main class io.micronaut.graal.reflect.GraalClassLoadingAnalyzer
The command '/bin/sh -c /usr/lib/graalvm/bin/java -cp build/libs/
.jar io.micronaut.graal.reflect.GraalClassLoadingAnalyzer reflect.json' returned a non-zero code: 1

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.