0

I've a simple Micronaut AWS lambda request handled using the micronaut-function-aws functionality.

The service that I inject doesn't seem to be created when it's run in AWS.

If I do the whole groovy script function handler and use @Field @Singleton TestService testService it seems to work fine when running locally.

Any idea what I'm doing wrong?

Service:

package testtest

import groovy.transform.CompileStatic

@CompileStatic
@Singleton
class TestService {
    String test = "Test"
}

handler:

package testtest

import com.amazonaws.services.lambda.runtime.Context
import io.micronaut.function.aws.MicronautRequestStreamHandler

import javax.inject.Inject

class TestHandler extends MicronautRequestStreamHandler {

    @Inject TestService testService

    @Override
    protected void execute(InputStream input, OutputStream output, Context context) throws IOException {
        output << testService.test
    }
}

Stack trace from AWS lambda

Cannot get property 'test' on null object: java.lang.NullPointerException
java.lang.NullPointerException: Cannot get property 'test' on null object
    at org.codehaus.groovy.runtime.NullObject.getProperty(NullObject.java:60)
    at org.codehaus.groovy.runtime.InvokerHelper.getProperty(InvokerHelper.java:190)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callGroovyObjectGetProperty(AbstractCallSite.java:304)
    at testtest.TestHandler.execute(TestHandler.groovy:14)
    at testtest.TestHandler.execute(TestHandler.groovy)
    at io.micronaut.function.aws.MicronautRequestStreamHandler.handleRequest(MicronautRequestStreamHandler.java:40)
    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)

1 Answers1

2

So I'm not sure on the correct way to use MicronautRequestStreamHandler but I've found a way around this (or just the right way to do this).

I've created a new Function @FunctionBean and then return the function name from overriding the MicronautRequestStreamHandler resolveFunctionName method.

class AuthHandler  extends MicronautRequestStreamHandler {

@Override
protected String resolveFunctionName(Environment environment) {
    return "auth"
}

}

@FunctionBean('auth')
class AuthFunction implements Function<InputStream, AuthResponse> {

  @Inject
  AuthService authService

  @Override
  AuthResponse  apply(InputStream input) {
    // stuff etc
  }
}

The Function injects the service correctly.

Really just copying how they test MicronautRequestStreamHandler MicronautRequestStreamHandlerSpec.groovy

Hope this helps others...

  • thanks a lot! you saved me a few hours of life :) Do you happen to know how to go about accessing the "context" of the lambda in the function bean? The apply override will processes only the defined input and output (InputStream and AuthResponse) – user375868 Apr 07 '21 at 00:05
  • I got exception while injecting saying no such bean exception "errorType": "io.micronaut.context.exceptions.NoSuchBeanException", – user3769960 Jun 14 '21 at 06:17