micronaut-projects / micronaut-aws

Projects specific to integrating Micronaut and Amazon Web Services (AWS)
Apache License 2.0
87 stars 80 forks source link

Micronaut does not use Jackson custom serializer / deserializer for Serverless #817

Open blazejkarmelita opened 3 years ago

blazejkarmelita commented 3 years ago

Custom Jackson serializers / deserializers configured with the ObjectMapper are working in Micronaut test but not working when testing with AWS SAM.

The enclosed sample is a working example generated from Micronaut Launcher that has been modified to make it easier to reproduce issue. Changes made are:

  1. Book POJO class does not have a public constructor but the static factory method instead

@Introspected public class Book {

... // public Book() { // }

... public static Book ofName(String name) { return new Book(name); } }

  1. There is custom Book deserializer introduced @Singleton public class CustomBookDeserializer extends JsonDeserializer {

    public CustomBookDeserializer() { super(); }

    @Override public Book deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException { return Book.ofName("Mabe not Serverless"); }

}

  1. The sample test is changed so it shows that the custom deserializer is taken to deserialize book payload @Test public void testHandler() throws JsonProcessingException { final String json = "{ name: \"An old book\"}"; final ObjectMapper objectMapper = bookRequestHandler.getApplicationContext().getBean(ObjectMapper.class); final Book book = objectMapper.readValue(json, Book.class);

    BookSaved bookSaved = bookRequestHandler.execute(book);
    assertEquals(bookSaved.getName(), book.getName());
    assertNotNull(bookSaved.getIsbn());

    }

Steps to Reproduce

  1. Run BookRequestHandlerTest
    • see that custom Book deserializer is properly created in Micronaut context
    • see that JacksonMapper uses it to deserialize Book json
  2. Configure AWS SAM locally and run enclosed cloudformation.yaml and see that it does not work anymore

Expected Behaviour

When testing with AWS SAM the standard Jackson ObjectMapper configured with custom deserialized is picked to deserialize the Book json payload.

Actual Behaviour

An error occurred during JSON parsing: java.lang.RuntimeException java.lang.RuntimeException: An error occurred during JSON parsing Caused by: java.io.UncheckedIOException: com.fasterxml.jackson.databind.JsonMappingException: No suitable constructor found for type [simple type, class com.example.Book]: can not instantiate from JSON object (missing default constructor or creator, or perhaps need to add/enable type information?) at [Source: lambdainternal.util.NativeMemoryAsInputStream@61799544; line: 2, column: 3] Caused by: com.fasterxml.jackson.databind.JsonMappingException: No suitable constructor found for type [simple type, class com.example.Book]: can not instantiate from JSON object (missing default constructor or creator, or perhaps need to add/enable type information?) at [Source: lambdainternal.util.NativeMemoryAsInputStream@61799544; line: 2, column: 3] at com.fasterxml.jackson.databind.JsonMappingException.from(JsonMappingException.java:148) at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromObjectUsingNonDefault(BeanDeserializerBase.java:1106) at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:296) at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:133) at com.fasterxml.jackson.databind.ObjectReader._bindAndClose(ObjectReader.java:1511) at com.fasterxml.jackson.databind.ObjectReader.readValue(ObjectReader.java:1102)

Environment Information

Example Application

https://bitbucket.org/blazejkarmelita/micronaut-jackson-issue/src/master/

blazejkarmelita commented 3 years ago

Just for your notice. If I go an old way with @FunctionBean than it works:

@FunctionBean("MyFunction") public class BookFunction implements Consumer { @Override public void accept(Book book) { book.getName(); } public class BookHandler extends MicronautRequestStreamHandler { @Override protected String resolveFunctionName(Environment env) { return "MyFunction"; } } }