@EnableWebFlux on a WebFluxConfigurer does autoconfigure a ThymeleafViewResolver as expected

1.8k Views Asked by At

I'm building a REST api starting with spring-boot-starter-webflux, but I'd also like the app to serve a swagger UI using a webjar. I need to tweak how the swagger UI initializes, so I've made a @Controller that returns a Mono to trigger rendering the view. The REST api also needs a customized jackson ObjectMapper with the snake case naming strategy enabled, among other things.

The Spring Boot Docs say that to accomplish this I should provide a @Configuration class that extends WebFluxConfigurer, but I should leave @EnableWebflux off. Here is what I have so far (Kotlin):

Config

@Configuration
@ComponentScan
class CommonConfig : WebFluxConfigurer {

    override fun configureHttpMessageCodecs(configurer: ServerCodecConfigurer) {
        configurer.defaultCodecs().jackson2JsonDecoder(
                Jackson2JsonDecoder(objectMapper())
        )
        configurer.defaultCodecs().jackson2JsonEncoder(
                Jackson2JsonEncoder(objectMapper())
        )
    }

    private fun objectMapper() = Jackson2ObjectMapperBuilder
            .json()
            .propertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE)
            .featuresToDisable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
            .build<ObjectMapper>().also {
                it.configOverride(BigDecimal::class.java).format = JsonFormat.Value.forShape(JsonFormat.Shape.STRING)
            }
}

Controller

@Controller
class SwaggerController(
        val swaggerConfig: SwaggerConfig
) {
    @GetMapping("/swagger-ui")
    fun swagger(model: Model): Mono<String> {

        model.addAttribute("docUrl", swaggerConfig.docUrl)
        return Mono.just("swagger-ui")
    }
}

With this configuration, the swagger view renders fine, but when I try to post to one of my api endpoints, it complains about missing required properties (which is resolved by sending data with camel case instead of the snake case that I want). If I add @EnableWebFlux to my CommonConfig class, the custom object mapper gets picked up and I can send snake case data, but then the swagger view does not render. I get:

java.lang.IllegalStateException: Could not resolve view with name 'swagger-ui'.
    at org.springframework.web.reactive.result.view.ViewResolutionResultHandler.lambda$resolveViews$3(ViewResolutionResultHandler.java:278) ~[spring-webflux-5.2.5.RELEASE.jar:5.2.5.RELEASE]
    Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException:

This is presumably because there is no thymeleaf ViewResolver registered.

The docs do say that if I want to "take complete control of Spring WebFlux, you can add your own @Configuration annotated with @EnableWebFlux", which explains why there's no ViewResolver. But this isn't what I want. I want most of the webflux autoconfiguration, but I want to provide my own customized ObjectMapper. What is the correct way to do this?

1

There are 1 best solutions below

0
On BEST ANSWER

I ended up 1) switching to FreeMarker and 2) needing to expose my custom ObjectMapper as a bean, though this came with its own problems.