From ff9cb57741febe88339dddb837cce9e4307eedcf Mon Sep 17 00:00:00 2001 From: Oleg Zhurakousky Date: Wed, 12 Jan 2022 10:44:29 +0100 Subject: [PATCH] GH-789 Propagate AWS FunctionInvoker exceptions They will be handled by the AWS runtime and properly reported and recorded. Resolves #789 --- .../function/adapter/aws/FunctionInvoker.java | 27 +++---------------- .../adapter/aws/FunctionInvokerTests.java | 12 ++++++--- .../function-sample-aws/pom.xml | 4 +++ .../java/example/FunctionConfiguration.java | 2 +- 4 files changed, 18 insertions(+), 27 deletions(-) diff --git a/spring-cloud-function-adapters/spring-cloud-function-adapter-aws/src/main/java/org/springframework/cloud/function/adapter/aws/FunctionInvoker.java b/spring-cloud-function-adapters/spring-cloud-function-adapter-aws/src/main/java/org/springframework/cloud/function/adapter/aws/FunctionInvoker.java index d8e31deeb..071a2c6a4 100644 --- a/spring-cloud-function-adapters/spring-cloud-function-adapter-aws/src/main/java/org/springframework/cloud/function/adapter/aws/FunctionInvoker.java +++ b/spring-cloud-function-adapters/spring-cloud-function-adapter-aws/src/main/java/org/springframework/cloud/function/adapter/aws/FunctionInvoker.java @@ -30,7 +30,6 @@ import java.util.Set; import com.amazonaws.services.lambda.runtime.Context; import com.amazonaws.services.lambda.runtime.RequestStreamHandler; -import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.JsonDeserializer; @@ -53,7 +52,6 @@ import org.springframework.cloud.function.utils.FunctionClassUtils; import org.springframework.context.ApplicationContextInitializer; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.core.env.Environment; -import org.springframework.http.HttpStatus; import org.springframework.messaging.Message; import org.springframework.messaging.MessageHeaders; import org.springframework.messaging.support.MessageBuilder; @@ -112,27 +110,10 @@ public class FunctionInvoker implements RequestStreamHandler { .generateMessage(payload, new MessageHeaders(Collections.emptyMap()), function.getInputType(), this.jsonMapper, context); } - try { - Object response = this.function.apply(requestMessage); - byte[] responseBytes = this.buildResult(requestMessage, response); - StreamUtils.copy(responseBytes, output); - } - catch (Exception e) { - logger.error(e); - StreamUtils.copy(this.buildExceptionResult(requestMessage, e, isApiGateway), output); - } - } - - private byte[] buildExceptionResult(Message requestMessage, Exception exception, boolean isApiGateway) throws IOException { - if (isApiGateway) { - APIGatewayProxyResponseEvent event = new APIGatewayProxyResponseEvent(); - event.setStatusCode(HttpStatus.EXPECTATION_FAILED.value()); - event.setBody(exception.getMessage()); - return this.jsonMapper.toJson(event); - } - else { - throw new IllegalStateException(exception); - } + Object response = this.function.apply(requestMessage); + byte[] responseBytes = this.buildResult(requestMessage, response); + StreamUtils.copy(responseBytes, output); + // any exception should propagate } @SuppressWarnings("unchecked") diff --git a/spring-cloud-function-adapters/spring-cloud-function-adapter-aws/src/test/java/org/springframework/cloud/function/adapter/aws/FunctionInvokerTests.java b/spring-cloud-function-adapters/spring-cloud-function-adapter-aws/src/test/java/org/springframework/cloud/function/adapter/aws/FunctionInvokerTests.java index a79230fd4..3b34e8b16 100644 --- a/spring-cloud-function-adapters/spring-cloud-function-adapter-aws/src/test/java/org/springframework/cloud/function/adapter/aws/FunctionInvokerTests.java +++ b/spring-cloud-function-adapters/spring-cloud-function-adapter-aws/src/test/java/org/springframework/cloud/function/adapter/aws/FunctionInvokerTests.java @@ -49,6 +49,7 @@ import org.springframework.messaging.converter.AbstractMessageConverter; import org.springframework.util.MimeType; import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.fail; /** * @@ -914,9 +915,14 @@ public class FunctionInvokerTests { InputStream targetStream = new ByteArrayInputStream(this.apiGatewayEvent.getBytes()); ByteArrayOutputStream output = new ByteArrayOutputStream(); - invoker.handleRequest(targetStream, output, null); - Map result = mapper.readValue(output.toByteArray(), Map.class); - assertThat(((String) result.get("body"))).startsWith("Failed to establish route, since neither were provided:"); + + try { + invoker.handleRequest(targetStream, output, null); + fail(); + } + catch (Exception e) { + // TODO: handle exception + } } @SuppressWarnings("rawtypes") diff --git a/spring-cloud-function-samples/function-sample-aws/pom.xml b/spring-cloud-function-samples/function-sample-aws/pom.xml index 9f7b8ce78..4653b95c5 100644 --- a/spring-cloud-function-samples/function-sample-aws/pom.xml +++ b/spring-cloud-function-samples/function-sample-aws/pom.xml @@ -37,6 +37,10 @@ org.springframework.cloud spring-cloud-function-web + + org.springframework.boot + spring-boot-starter-web + com.amazonaws diff --git a/spring-cloud-function-samples/function-sample-aws/src/main/java/example/FunctionConfiguration.java b/spring-cloud-function-samples/function-sample-aws/src/main/java/example/FunctionConfiguration.java index f44747302..ade13c608 100644 --- a/spring-cloud-function-samples/function-sample-aws/src/main/java/example/FunctionConfiguration.java +++ b/spring-cloud-function-samples/function-sample-aws/src/main/java/example/FunctionConfiguration.java @@ -21,7 +21,7 @@ public class FunctionConfiguration { public Function uppercase() { return value -> { if (value.equals("exception")) { - throw new RuntimeException("Intentional exception which should result in HTTP 417"); + throw new RuntimeException("Intentional exception"); } else { return value.toUpperCase();