Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve documentation regarding encoding in FreeMarker support #33071

Closed
Etienne522 opened this issue Jun 19, 2024 · 4 comments
Closed

Improve documentation regarding encoding in FreeMarker support #33071

Etienne522 opened this issue Jun 19, 2024 · 4 comments
Assignees
Labels
in: web Issues in web modules (web, webmvc, webflux, websocket) type: documentation A documentation task
Milestone

Comments

@Etienne522
Copy link

Etienne522 commented Jun 19, 2024

Hello! I found an issue with Freemarker support.

The following configuration will use the platform encoding instead of UTF-8 like I expected :

package test.springFreemarker;

import java.nio.charset.StandardCharsets;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer;
import org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver;

@Configuration
public class FreeMarkerConfig {

    @Bean
    public FreeMarkerViewResolver freemarkerViewResolver() {
        FreeMarkerViewResolver resolver = new FreeMarkerViewResolver();
        resolver.setSuffix(".ftl");
        return resolver;
    }

    @Bean
    public FreeMarkerConfigurer freemarkerConfig() {
        FreeMarkerConfigurer freeMarkerConfigurer = new FreeMarkerConfigurer();
        freeMarkerConfigurer.setDefaultEncoding(StandardCharsets.UTF_8.name());
        freeMarkerConfigurer.setTemplateLoaderPath("classpath:/templates");
        return freeMarkerConfigurer;
    }
}

The resulting HTML page had the line :

<meta http-equiv="content-type" content="text/html; charset=windows-1252">

even though my template had no meta tag.

I had to add

        resolver.setContentType("text/html;charset=UTF-8");

to make it work.

It seems FreeMarkerConfigurer default encoding is ignored because FreeMarkerViewResolver overrides it, even if it was left empty.

The Javadoc of FreeMarkerConfigurer#setDefaultEncoding mentions it will be ignored if it is explicitly specified by FreeMarkerViewResolver, but if it was not explicitly specified, it just uses the default.

Either the behavior needs to be changed, or the Javadoc updated to state that FreeMarkerViewResolver will always override it.

I am using spring-boot-starter-freemarker with Spring Boot 3.2.5.

Thanks again for the great framework, I hope this issue report helps.

@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged or decided on label Jun 19, 2024
@sbrannen sbrannen added the in: web Issues in web modules (web, webmvc, webflux, websocket) label Jun 19, 2024
@sbrannen sbrannen self-assigned this Jun 19, 2024
@sbrannen sbrannen added type: documentation A documentation task and removed status: waiting-for-triage An issue we've not yet triaged or decided on labels Jun 20, 2024
@sbrannen sbrannen modified the milestones: 6.1.11, 6.2.0-M5 Jun 20, 2024
@sbrannen sbrannen added type: enhancement A general enhancement and removed type: documentation A documentation task labels Jun 21, 2024
@sbrannen
Copy link
Member

sbrannen commented Jun 22, 2024

Hi @Etienne522,

Congratulations on opening your first GitHub issue ever! 👍

The following configuration will use the platform encoding instead of UTF-8 like I expected

Based on my analysis, the default encoding you have configured is used to read the template file.

The resulting HTML page had the line :

<meta http-equiv="content-type" content="text/html; charset=windows-1252">

even though my template had no meta tag.

I am not sure how that <meta> tag ends up in the rendered HTML. Perhaps your application has a component (or template include) that automatically adds that based on some heuristics.

I had to add

resolver.setContentType("text/html;charset=UTF-8");

to make it work.

That's currently to be expected. If you don't specify the content type via the FreeMarkerViewResolver, "text/html;charset=ISO-8859-1" will be used, which is the default set in AbstractView.

Though, since I do not have access to your application, I cannot explain the contents of the <meta> tag you've mentioned.

It seems FreeMarkerConfigurer default encoding is ignored because FreeMarkerViewResolver overrides it, even if it was left empty.

The Javadoc of FreeMarkerConfigurer#setDefaultEncoding mentions it will be ignored if it is explicitly specified by FreeMarkerViewResolver, but if it was not explicitly specified, it just uses the default.

Either the behavior needs to be changed, or the Javadoc updated to state that FreeMarkerViewResolver will always override it.

If you explicitly configure the default encoding via FreeMarkerConfigurer, that encoding will be used to read the template file. If you explicitly configure the encoding via FreeMarkerViewResolver, that encoding will in fact override the default encoding in the FreeMarker Configuration (configured via the FreeMarkerConfigurer).

What can be confusing is the difference between the configured (or default) encoding and the Content-Type header of the HTTP response (and consequently the character encoding used to render the body of the response).

Spring currently does not update the charset of the Content-Type header of the HTTP response to reflect the actual type of encoding used to read the template file and render the body of the response. I will create a new GitHub issue to address that in Spring Framework 6.2 (based on support for checking whether an explicit default encoding has been set, which is available since FreeMarker 2.3.26).

Another potential issue is that Spring does not set the output_encoding in the FreeMarker processing Environment (supported since FreeMarker 2.3.1), and I will create a separate GitHub issue to address that in Spring Framework 6.2 as well.

As for the Javadoc in FreeMarkerConfigurer and FreeMarkerView, I agree that the discussion of encoding is a bit confusing and perhaps misleading. Thus, I will repurpose this issue to improve that documentation in Spring Framework 6.1.x.

@sbrannen sbrannen added type: documentation A documentation task and removed type: enhancement A general enhancement labels Jun 22, 2024
@sbrannen sbrannen modified the milestones: 6.2.0-M5, 6.1.11 Jun 22, 2024
@sbrannen sbrannen changed the title FreeMarkerConfigurer#setDefaultEncoding is ignored Improve documentation for encoding support in FreeMarkerConfigurer and FreeMarkerViewResolver Jun 22, 2024
@sbrannen

This comment was marked as outdated.

@sbrannen sbrannen changed the title Improve documentation for encoding support in FreeMarkerConfigurer and FreeMarkerViewResolver Improve documentation regarding encoding in FreeMarker support Jun 23, 2024
sbrannen added a commit to sbrannen/spring-framework that referenced this issue Jun 25, 2024
sbrannen added a commit that referenced this issue Jun 27, 2024
According to the official FreeMarker documentation, Spring's
FreeMarkerView implementations should be configuring the
output_encoding for template rendering.

To address that, this commit modifies the FreeMarkerView
implementations in Web MVC and WebFlux to explicitly set the
output_encoding for template rendering.

See https://freemarker.apache.org/docs/pgui_misc_charset.html#autoid_53
See gh-33071
Closes gh-33106
@sbrannen
Copy link
Member

Another potential issue is that Spring does not set the output_encoding in the FreeMarker processing Environment (supported since FreeMarker 2.3.1), and I will create a separate GitHub issue to address that in Spring Framework 6.2 as well.

@sbrannen
Copy link
Member

Hi @Etienne522 (and anyone else interested),

I overhauled our FreeMarker documentation regarding encoding in d133ab6.

I had to add

        resolver.setContentType("text/html;charset=UTF-8");

Please note that as of Spring Framework 6.2, that workaround will no longer be required. For details see:

And thanks to #33102, freeMarkerConfigurer.setDefaultEncoding(StandardCharsets.UTF_8.name()) from your example can now be replaced with freeMarkerConfigurer.setDefaultCharset(StandardCharsets.UTF_8).

Feel free to check out the updated documentation or try out any of the new features and let us know if you run into any issues.

Thanks,

Sam

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in: web Issues in web modules (web, webmvc, webflux, websocket) type: documentation A documentation task
Projects
None yet
Development

No branches or pull requests

3 participants