Search code examples
amazon-web-servicesspring-bootaws-lambdaspring-cloudspring-cloud-function

Spring Cloud function cannot read function definition from Message header


I've created an AWS Lambda based Spring Cloud Function with multiple functions and it works fine when I define exactly one "spring_cloud_function_definition" environment variable in the AWS Lambda Configuration panel. These functions' input and output is a Message<?>, so the payload and http headers can be accessed runtime as well.

I'd like to use this AWS Lambda function in different API Gateway methods, so for example:

  • /item [POST] -> saveItem should be called
  • /item [DELETE] -> deleteItem should be called
  • ... and so on...

https://cloud.spring.io/spring-cloud-static/spring-cloud-function/3.0.0.RC1/reference/html/spring-cloud-function.html#_function_catalog_and_flexible_function_signatures

I found this documentation on Spring.io which says it's feasible:

If the input argument is of type Message<?>, you can communicate routing instruction by setting one of spring.cloud.function.definition or spring.cloud.function.routing-expression Message headers. For more static cases you can use spring.cloud.function.definition header which allows you to provide the name of a single function (e.g., …​definition=foo) or a composition instruction (e.g., …​definition=foo|bar|baz)

So the following test event should run in AWS Lambda without any failure:

{ "method": "POST", "body": "{ "key" : "value" }", "headers": { "spring.cloud.function.definition": "saveItem" } }

but of course it throws an exception:

 No function defined: java.lang.IllegalStateException
 java.lang.IllegalStateException: No function defined
    at org.springframework.cloud.function.context.AbstractSpringFunctionAdapterInitializer.apply(AbstractSpringFunctionAdapterInitializer.java:187)
    at org.springframework.cloud.function.adapter.aws.SpringBootRequestHandler.handleRequest(SpringBootRequestHandler.java:51)
    at org.springframework.cloud.function.adapter.aws.SpringBootApiGatewayRequestHandler.handleRequest(SpringBootApiGatewayRequestHandler.java:140)
    at org.springframework.cloud.function.adapter.aws.SpringBootApiGatewayRequestHandler.handleRequest(SpringBootApiGatewayRequestHandler.java:43)

I've tried many configurations (application.properties, AWS Lambda env property, header, etc.) but nothing happened:

  • spring.cloud.function.routing-expression=headers.function_name
  • setting spring.cloud.function.definition=saveItem

What could be the problem? What is the best configuration in this case? Any help would be appreciated!

Used technologies:

  • Cloud: AWS
  • Cloud components: Lambda + API Gateway
  • AWS Lambda handler class: org.springframework.cloud.function.adapter.aws.SpringBootApiGatewayRequestHandler
  • AWS Lambda input and output events: APIGatewayProxyRequestEvent, APIGatewayProxyResponseEvent
  • Java: 8
  • Spring Cloud Function version: 3.0.6.RELEASE

Solution

  • I've updated to v3.1.3 and switched to FunctionInvoker and I've added the function definition to the request template mapping header, and it worked fine.

    Anyways, thanks for the help. :)