Two months ago I wrote a post on how to deal with a deserialization of immutables in Jackson. The problem there is that, by default, Jackson relies on no-args constructors and setters to construct entities. That requires from developers some workarounds, mainly to apply constructor annotations to explicitly tell Jackson which fields to use. I received a comment from Bertil Muth, who is a creator of the Moonwlker library. He proposed me to try it and now I want to share with you my experience. Basically, Moonwlker is a Jackson module that does exactly same job, we do manually. The library is still in active development, so it may not yet be suitable for production, however it is still a good candidate to look on.

In this post we will see how to configure Moonwlker in Spring Boot applications, how to use it in web layer tests and finally how to setup it without Spring Boot, just with plain Webflux components. Again, the project is on early stage, so things probably will change, and I will keep following it to update this post accordingly.

Do you want to know more about developing modern web apps and microservices with Spring 5, Project Reactor and Spring Webflux? I published the book “Friendly Webflux“, that is a hands-on guide to software engineers and it leads you in all aspects, including reactive architecture, testing, authentication, databases and much more.

Configure Moonwlker with Spring Boot

From a technical point of view, the Moonwlker library is a Jackson module. Therefore, the task of setting it up means to register a custom module. When we use Spring Boot, we could create a configuration class to create a custom object mapper component as a bean. In other words, we initialize a new instance of the ObjectMapper, which serves as an entry point of JSON reader/writer configuration and then register a Moonwlker module. Take a look on the following code snippet below:

@Configuration
public class JacksonConfiguration {

    @Bean
    ObjectMapper getCustomObjectMapper(){
        ObjectMapper mapper = new ObjectMapper();
        MoonwlkerModule moonwlker = MoonwlkerModule.builder().build();
        mapper.registerModule(moonwlker);
        return mapper;
    }
}

When you go with Spring Boot, that is all what you need to do in order to set up things for runtime. If you write unit tests for web layer, you need to explicitly provide a configuration bean for a test. Also, you need to rely on an autowired WebTestClient instead of defining your own. So, to use Moonwlker in unit tests you need to:

@ExtendWith(SpringExtension.class)
@ContextConfiguration(classes = {
    CustomerHandler.class, 
    CustomerRouter.class, 
    JacksonConfiguration.class})
@AutoConfigureWebTestClient
@WebFluxTest
class CustomerRouterTest {

    @MockBean private CustomerService service;

    @Autowired WebTestClient client;

    //.. test

The reason to use an @AutoConfigureWebTestClient annotation and a pre-setted client is that otherwise we have to configure a web client manually (as we will see in the next section). Nothing else is required, and in other aspects a test will work as a normal one.

Configure WebClient manually

Another task may be to set Moonwlker module “hard way” without relying on Spring Boot. That happens when you want to use Spring Webflux components without Spring Boot (which is possible, yet this is a topic for another post). In order to use Moonwlker we need to create a customized instance of a WebClient component and then register configuration. Let separate it into steps:

  1. Create an object mapper
  2. Create an instance of Moonwlker module
  3. Register a module with the object mapper
  4. Initialize a Jackson2JsonDecoder using the object mapper
  5. Provide a decoder with the configurer

Last two steps need more attention. First, about the decoder. This class decode a byte stream into JSON and then deserialize into objects. We provide to it the object mapper to use. Another thing that can confuse is configuring a client. We use a builder pattern in order to initialize and set up an instance. The builder method codecs() helps to define a codecs configurer, which is used for HTTP message reader and writer options. Let now put everything together:

class PostsWebClientTest {

    private WebClient client;

    @BeforeEach
    void setup(){
        MoonwlkerModule module = MoonwlkerModule.builder().build();

        ObjectMapper mapper = new ObjectMapper();

        mapper.registerModule(module);

        Jackson2JsonDecoder decoder = new Jackson2JsonDecoder(mapper);

        client = WebClient.builder()
                .codecs(configurer -> configurer.defaultCodecs()
                        .jackson2JsonDecoder(decoder))
                .build();
    }
}

So, that is all what we need to do here. Then, we can use the client as normal and it will utilize Moonwlker module when doing deserialization.

Source code

Sources of an example project, that uses Moonwlker is available on my github in this repository. Feel free to explore it.

Conclusion

While Moonwlker is a very early stage project, it has a potential. I recommend you to give it a try and see if it fits your goals. What I really enjoyed is that Moonwlker allows to keep Jackson annotations away from model classes and use them as what they expected to be – business entities. This will ensure, that a model layer is separated from a web layer. In this small post we learned how to use Moonwlker module with Spring Boot and Spring Webflux applications. This process is simple, as we can configure a customized Jackson bean to use the extension module.