Skip to content

Commit

Permalink
Merge branch '4.1.x'
Browse files Browse the repository at this point in the history
  • Loading branch information
sdelamo committed Dec 22, 2023
2 parents 9016807 + 6a3152f commit f634bb1
Show file tree
Hide file tree
Showing 3 changed files with 202 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -55,15 +55,9 @@ public class MicronautRequestStreamHandler extends StreamFunctionExecutor<Contex
* Lambda deployment.
*/
public MicronautRequestStreamHandler() {
// initialize the application context in the constructor
// this is faster in Lambda as init cost is giving higher processor priority
// see https://github.com/micronaut-projects/micronaut-aws/issues/18#issuecomment-530903419
try {
buildApplicationContext(null);
} catch (Exception e) {
LOG.error("Exception initializing handler: " + e.getMessage(), e);
throw e;
}
buildApplicationContext(null);
startEnvironment(applicationContext);
injectIntoApplicationContext();
}

/**
Expand All @@ -72,6 +66,12 @@ public MicronautRequestStreamHandler() {
*/
public MicronautRequestStreamHandler(ApplicationContext applicationContext) {
this.applicationContext = applicationContext;
startEnvironment(applicationContext);
injectIntoApplicationContext();
}

private void injectIntoApplicationContext() {
applicationContext.inject(this);
}

@Override
Expand All @@ -91,7 +91,12 @@ public void handleRequest(InputStream input, OutputStream output, Context contex

@Override
protected ApplicationContext buildApplicationContext(Context context) {
return super.buildApplicationContext(context);
try {
return super.buildApplicationContext(context);
} catch (Exception e) {
LOG.error("Exception initializing handler: " + e.getMessage(), e);
throw e;
}
}

@NonNull
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package io.micronaut.function.aws

import com.amazonaws.services.lambda.runtime.ClientContext
import com.amazonaws.services.lambda.runtime.CognitoIdentity
import com.amazonaws.services.lambda.runtime.LambdaLogger
import com.amazonaws.services.lambda.runtime.Context

final class ContextUtils {
private ContextUtils() {
}

static Context mock() {
new Context() {
@Override
String getAwsRequestId() {
null
}

@Override
String getLogGroupName() {
null
}

@Override
String getLogStreamName() {
null
}

@Override
String getFunctionName() {
return "foo";
}

@Override
String getFunctionVersion() {
null
}

@Override
String getInvokedFunctionArn() {
null
}

@Override
CognitoIdentity getIdentity() {
null
}

@Override
ClientContext getClientContext() {
null
}

@Override
int getRemainingTimeInMillis() {
return 0;
}

@Override
int getMemoryLimitInMB() {
return 0;
}

@Override
LambdaLogger getLogger() {
null
}
};
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
package io.micronaut.function.aws

import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent
import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent
import io.micronaut.context.ApplicationContext
import io.micronaut.context.env.Environment
import io.micronaut.function.FunctionBean
import io.micronaut.http.HttpMethod
import io.micronaut.json.JsonMapper
import jakarta.inject.Inject
import jakarta.inject.Singleton
import spock.lang.Specification

import java.util.function.Function

class MicronautRequestStreamHandlerStartsContextSpec extends Specification {

void "MicronautRequestStreamHandler starts application context"() throws IOException {
given:
String expectation = '{"message":"Hello World"}'
FunctionRequestHandler handler = new FunctionRequestHandler()

when:
JsonMapper jsonMapper = handler.getApplicationContext().getBean(JsonMapper.class)
APIGatewayProxyRequestEvent request = createRequest(HttpMethod.GET, "/")
APIGatewayProxyResponseEvent response = execute(handler, jsonMapper, request)

then: 'application context is started'
200 == response.getStatusCode().intValue()
expectation == response.body
and: "bean injection works in class extending MicronautRequestStreamHandler"
"HELLO WORLD" == handler.getUppercaser().uppercase("Hello World")

when:
handler.close()
handler = new FunctionRequestHandler(ApplicationContext.builder().build().stop())
jsonMapper = handler.getApplicationContext().getBean(JsonMapper.class)
request = createRequest(HttpMethod.GET, "/")
response = execute(handler, jsonMapper, request)

then: 'application context is started'
200 == response.getStatusCode().intValue()
expectation == response.body

and: "bean injection works in class extending MicronautRequestStreamHandler"
"HELLO WORLD" == handler.getUppercaser().uppercase("Hello World")

cleanup:
handler.close()
}

private static APIGatewayProxyRequestEvent createRequest(HttpMethod method, String path) {
APIGatewayProxyRequestEvent request = new APIGatewayProxyRequestEvent();
request.setHttpMethod(method.name());
request.setPath(path);
return request;
}

private static APIGatewayProxyResponseEvent execute(MicronautRequestStreamHandler handler,
JsonMapper jsonMapper,
APIGatewayProxyRequestEvent request) throws IOException {
ByteArrayInputStream inputStream = new ByteArrayInputStream(jsonMapper.writeValueAsBytes(request))
ByteArrayOutputStream output = new ByteArrayOutputStream()
handler.handleRequest(inputStream, output, ContextUtils.mock())
return jsonMapper.readValue(output.toByteArray(), APIGatewayProxyResponseEvent.class)
}

static class FunctionRequestHandler extends MicronautRequestStreamHandler {
public static final String FUNCTION_NAME = "apiHandler"

@Inject
UpperCaseString uppercaser

FunctionRequestHandler() {
}

FunctionRequestHandler(ApplicationContext applicationContext) {
super(applicationContext)
}

UpperCaseString getUppercaser() {
return uppercaser
}

@Override
protected String resolveFunctionName(Environment env) {
return FUNCTION_NAME
}
}

@FunctionBean(FunctionRequestHandler.FUNCTION_NAME)
static class ApiHandler implements Function<APIGatewayProxyRequestEvent, APIGatewayProxyResponseEvent> {
@Inject
JsonMapper jsonMapper

@Override
APIGatewayProxyResponseEvent apply(APIGatewayProxyRequestEvent apiGatewayProxyRequestEvent) {
APIGatewayProxyResponseEvent response = new APIGatewayProxyResponseEvent()
try {
String json = new String(jsonMapper.writeValueAsBytes([message: "Hello World"]))
response.setStatusCode(200)
response.setBody(json)
} catch (IOException e) {
response.setStatusCode(500)
}
return response;
}
}

@Singleton
static class UpperCaseString {
String uppercase(String str) {
str.toUpperCase()
}
}

}

0 comments on commit f634bb1

Please sign in to comment.