Search code examples
aws-lambdaspring-cloud

How to apply Spring Cloud Function's "Functional Bean Registration" for SpringBootApiGatewayRequestHandler


I'm trying to deploy a AWS Lambda function, written using Spring Cloud Function 2.1.0, that receives an API Gateway Event. Therefore I setup a ApplicationContextInitializer as shown below as well as a SpringBootApiGatewayRequestHandler. Unfortunately I run into an Exception: com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance oforg.springframework.messaging.Message(no Creators, like default construct, exist): abstract types either need to be mapped to concrete types, have custom deserializer, or contain additional type information.

I looked into spring-cloud-functions test cases and examples, but couldn't find an example for Functional Bean Registration with Message parameter/return value.

@SpringBootConfiguration
public class ServiceConfiguration implements ApplicationContextInitializer<GenericApplicationContext> {

    public static void main(String[] args) {
        FunctionalSpringApplication.run(ServiceConfiguration.class, args);
    }

    public Function<Message<Pojo>,Message<Pojo>> transformMessage() {
        return request -> new GenericMessage<>(new Pojo(request.getPayload().getValue().toUpperCase()));
    }

    @Override
    public void initialize(GenericApplicationContext applicationContext) {
        applicationContext
                .registerBean("transformMessage", FunctionRegistration.class,
                        () -> new FunctionRegistration<>(transformMessage())
                                .type(FunctionType.from(Message.class).to(Message.class)));
    }

}
public class TransformMessageHandler extends SpringBootApiGatewayRequestHandler {
}

Could someone point me out to a working example or give a hint on how to properly register it?


Solution

  • From the specifications I see that SpringBootApiGatewayRequestHandler extends SpringBootRequestHandler<APIGatewayProxyRequestEvent, APIGatewayProxyResponseEvent>.
    Instead of your function returning receiving and returning Message objects it should work with the APIGatewayProxyRequestEvent and APIGatewayResponseEvent.

    The method representing your functions logic would then have a signature like:
    public Function<APIGatewayProxyRequestEvent, APIGatewayProxyResponseEvent> transform()

    Registration during initialisation then looks like:

    @Override
    public void initialize(GenericApplicationContext applicationContext) {
        applicationContext
                .registerBean("transform", FunctionRegistration.class,
                        () -> new FunctionRegistration<>(transform())
                                .type(FunctionType.from(APIGatewayProxyRequestEvent.class).to(APIGatewayProxyResponseEvent.class)));
    }