Skip to content

Avoid overriding of supported media types in Thymeleaf reactive auto-configuration #9134

@danielfernandez

Description

@danielfernandez

The new support for Thymeleaf + Spring WebFlux auto-configuration (#8124) works great, but there is one point in ThymeleafAutoConfiguration where now this is done:

@Bean
@ConditionalOnMissingBean(name = "thymeleafReactiveViewResolver")
public ThymeleafReactiveViewResolver thymeleafViewResolver(
		ISpringWebFluxTemplateEngine templateEngine) {
	ThymeleafReactiveViewResolver resolver = new ThymeleafReactiveViewResolver();
        ...
	resolver.setSupportedMediaTypes(
			this.properties.getReactive().getMediaTypes());
        ...
	return resolver;
}

So the Thymeleaf auto-configuration mechanism always overwrites the supported media types with whatever comes from the ThymeleafProperties.Reactive object. But in that class, such supported media types are initialised like this:

private List<MediaType> mediaTypes = new ArrayList<>(
            Collections.singletonList(MediaType.TEXT_HTML));

So unless specifically configured by the user, text/html will always be the only media type that Thymeleaf is allowed to run for.

This was fine until Thymeleaf 3.0.3. But Thymeleaf 3.0.4 introduced support for text/event-stream in Thymeleaf's WebFlux support, and now Thymeleaf 3.0.6 introduces a series of improvements to the way content negotiation is integrated into Thymeleaf's view resolution (and linked with template resolution and template modes themselves) that allow Thymeleaf to be more easily used for processing dynamic CSS, JAVASCRIPT or XML templates with the same configuration setup. Ideally, with no additional configuration at all.

In fact, the list of supported media types at ThymeleafReactiveViewResolver has grown quite a lot in 3.0.6:

private static final List<MediaType> SUPPORTED_MEDIA_TYPES =
        Arrays.asList(new MediaType[] {
                MediaType.TEXT_HTML, MediaType.APPLICATION_XHTML_XML, // HTML
                MediaType.APPLICATION_XML, MediaType.TEXT_XML,        // XML
                MediaType.APPLICATION_RSS_XML,                        // RSS
                MediaType.APPLICATION_ATOM_XML,                       // ATOM
                new MediaType("application", "javascript"),           // JAVASCRIPT
                new MediaType("application", "ecmascript"),           //
                new MediaType("text", "javascript"),                  //
                new MediaType("text", "ecmascript"),                  //
                MediaType.APPLICATION_JSON,                           // JSON
                new MediaType("text", "css"),                         // CSS
                MediaType.TEXT_PLAIN,                                 // TEXT
                MediaType.TEXT_EVENT_STREAM});                        // SERVER-SENT EVENTS (SSE)

I'm not a huge expert in how WebFlux's content negotiation mechanism works, so I might be missing some reason why giving direct support for this in Spring Boot's auto-configuration would be a bad idea… but if not, it would be great if ThymeleafAutoConfiguration and ThymeleafProperties.Reactive didn't overwrite all these values.

This could be easily achieved by making the default value for mediaTypes in ThymeleafProperties.Reactive be null, and also making this bit of configuration optional at ThymeleafAutoConfiguration, like:

@Bean
@ConditionalOnMissingBean(name = "thymeleafReactiveViewResolver")
public ThymeleafReactiveViewResolver thymeleafViewResolver(
		ISpringWebFluxTemplateEngine templateEngine) {
	ThymeleafReactiveViewResolver resolver = new ThymeleafReactiveViewResolver();
        ...
        final List<MediaType> mediaTypes = this.properties.getReactive().getMediaTypes();
        if (mediaTypes != null) {
            resolver.setSupportedMediaTypes(mediaTypes);
        }
        ...
	return resolver;
}

Finally, note that this does not affect the non-reactive version, because in such case the equivalent contentType property works as a sort of default value for the HTTP header, instead of a comprehensive list of all the media types for which Thymeleaf will be actually allowed to run for once content negotiation takes place.

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions