69

At the moment I'm trying to get started with Spring MVC. While trying things out I ran into an encoding issue.

I want to display UTF-8 characters on my JSP-Pages so I added a String with UTF-8 characters to my ModelAndView. It looks like this:

@Controller
public class HomeController {

    private static final Logger logger = LoggerFactory.getLogger(HomeController.class);

    @RequestMapping(value="/", method=RequestMethod.GET)
    public ModelAndView home() {
        logger.info("Welcome home!");
        return new ModelAndView("home", "utftest", "ölm");
    }

}

On the JSP page I just want to display the String with UTF-8 characters like this:

<%@ page language="java" pageEncoding="UTF-8"%>
<%@ page contentType="text/html;charset=UTF-8" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ page session="false" %>
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <title>Home</title>
</head>
<body>
    <h1>Hello world!</h1>
    <p><c:out value="ö" /></p>
    <p><c:out value="${utftest}"></c:out></p>
</body>
</html>

As result I get following:

Hello world!

ö

ölm

Note that following code <c:out value="ö" /> was displayed without encoding error. I also set the default encoding to UTF-8 in Springsource Tool Suite but I'm still getting wrong characters.

Edit:

Maybe I should have mentioned that I'm using a Mac with OS X 10.6. For Spring development I use the Springsource Tool Suite from Spring (http://www.springsource.com/developer/sts). Hope this helps to find out what is wrong with my setting.

Edit 2:

Thanks to McDwell, I just tried out using "\u00f6lm" instead of "ölm" in my controller and the encoding issue on the JSP page is gone.

Does that mean my .java files are encoded with wrong character set? Where can I change this in Eclipse?

Thank you.

OemerA
  • 2,662
  • 7
  • 28
  • 31
  • The Springsource Tool Suite, is that basically Eclipse with some plugin? How exactly did you set the default encoding? – BalusC May 08 '11 at 14:48
  • 1
    Yeah, it's just Eclipse with some pre installed plugins for Spring development (http://www.springsource.com/developer/sts). I changed encoding in Springsource preferences (it's the same as in Eclipse) General > Workspace and General > Content Types to UTF-8 – OemerA May 08 '11 at 15:01
  • 3
    Well, McDowell mentioned in my deleted answer (which basically answers what you've already done) that this is likely caused by the Java compiler reading the source files using the wrong encoding. This is a very reasonable cause. But since I don't use/have a Mac I don't know how to fix it. – BalusC May 08 '11 at 15:03
  • 2
    @OemerA - you can narrow down the issue by replacing `"ölm"` with `"\u00f6lm"`. If this works, you know the issue is with the Java source file and its compilation to bytecode. – McDowell May 08 '11 at 16:10
  • @McDowell Thank you for your tip. I tried it and the encoding issue on the JSP page is gone. Well does that mean my configuration for .java files is messed up? Or does it have something to do with the compiler (options)? – OemerA May 08 '11 at 16:23
  • 3
    @OemerA - I've never installed STS, so I can't say much about it. Given that `ö` is the byte sequence `C3 B6` in UTF-8, I'd say the editor is doing the right thing (you can confirm with an external hex editor). So, whatever reads the file and passes it to the compiler is reading it using the wrong encoding - have a look at the project builders (by right-clicking the project) and maybe go visit their respective bug databases. – McDowell May 08 '11 at 16:53
  • @OemerA: in the `Content Types` preference, did you set both the Java Class File and Java Source File to UTF-8? Is the *General > Workspace > Text File Encoding* also set to UTF-8? – BalusC May 08 '11 at 17:42
  • @BalusC Yes, this what I did (actually in my desperate I changed everything to UTF-8). But I think there must be something wrong with the build process. I will dig into that. – OemerA May 08 '11 at 20:03
  • If you are using third party software then you need to make sure there in your request editor should be set encoding UTF-8. – MasterUZ Dec 05 '14 at 18:52
  • The JSP compiler compiles the JSP in the edited encoding. The _javac compiler_ however seems to compile a UTF-8 java source using some local (default) encoding. Look there. – Joop Eggen Sep 14 '17 at 15:45

10 Answers10

131

Make sure you register Spring's CharacterEncodingFilter in your web.xml (must be the first filter in that file).

<filter>  
    <filter-name>encodingFilter</filter-name>  
    <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>  
    <init-param>  
       <param-name>encoding</param-name>  
       <param-value>UTF-8</param-value>  
    </init-param>  
    <init-param>  
       <param-name>forceEncoding</param-name>  
       <param-value>true</param-value>  
    </init-param>  
</filter>  
<filter-mapping>  
    <filter-name>encodingFilter</filter-name>  
    <url-pattern>/*</url-pattern>  
</filter-mapping> 

If you are on Tomcat you might not have set the URIEncoding in your server.xml. If you don't set it to UTF-8 it won't work. Definitely keep the CharacterEncodingFilter. Nevertheless, here's a concise checklist to follow. It will definitely guide you to make this work.

Angelo Fuchs
  • 9,825
  • 1
  • 35
  • 72
Benjamin Muschko
  • 32,442
  • 9
  • 61
  • 82
  • 10
    The filter only sets the encoding for request parameters of POST requests. The `URIEncoding` does that for GET requests. He has the problem already when just displaying the page by HTTP response, not when processing the submitted data. – BalusC May 08 '11 at 15:01
  • Sorry this didn't work for me. I'm still getting the same wrong characters as before. – OemerA May 08 '11 at 15:14
  • As a Tomcat user, the most important part of this answer was the sentence about setting the URIEncoding in the server.xml file i.e. in the definition of the connector to whatever port you're using (e.g. 8080), you must have the following assignment: URIEncoding="UTF-8" – Sheldon R. May 11 '15 at 14:36
  • As it turns out, the URIEncoding in the server.xml isn't just an important thing to Tomcat users, it's the thing that matters as opposed to the filter definitiion, which doesn't appear to make a difference – Sheldon R. May 11 '15 at 14:56
  • 4
    URIEncoding is set to UTF-8 by default since Tomcat 8 (https://tomcat.apache.org/migration-8.html#URIEncoding), thus for new deployments this is one less problem. The filter is still necessary for handling POST request correctly. – Claudio Venturini Jan 28 '16 at 14:29
  • 3
    Just to explain a bit: We need the `CharacterEncodingFilter` because browsers often do not provide encoding information when submitting post data, and hence the server may use a different encoding than that of the incoming data. So we tell the server the expected encoding in the `CharacterEncodingFilter`. – Markus Pscheidt May 04 '16 at 08:15
  • You may try the following [solution](https://stackoverflow.com/a/54835821/5917460), without filters but with Java-based config. – Andrei Veshtard Feb 22 '19 at 22:26
  • This solved my headache of broken UTF-8(Korean) thru @ModelAttribute used in Spring MVC application. – Park JongBum Mar 03 '23 at 01:20
48

Ok guys I found the reason for my encoding issue.

The fault was in my build process. I didn't tell Maven in my pom.xml file to build the project with the UTF-8 encoding. Therefor Maven just took the default encoding from my system which is MacRoman and build it with the MacRoman encoding.

Luckily Maven is warning you about this when building your project (BUT there is a good chance that the warning disappears to fast from your screen because of all the other messages).

Here is the property you need to set in the pom.xml file:

<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    ...
</properties>

Thank you guys for all your help. Without you guys I wouldn't be able to figure this out!

OemerA
  • 2,662
  • 7
  • 28
  • 31
  • 7
    thanks!! +1. I'm not using maven, I just start to use gradle (but I'm a newbie with it) and this problem starts happening. Specifying the compile encoding for java tasks in gradle: `compileJava.options.encoding = 'UTF-8'` solves the problem. – albciff Mar 25 '15 at 11:44
  • This problem can also happen in other situations, not related to your build problem. – Alex R Feb 01 '18 at 18:40
18

In addition to Benjamin's answer - in case if you are using Spring Security, placing the CharacterEncodingFilter in web.xml might not always work. In this case you need to create a custom filter and add it to the filter chain as the first filter. To make sure it's the first filter in the chain, you need to add it before ChannelProcessingFilter, using addFilterBefore in your WebSecurityConfigurerAdapter:

@Configuration
@EnableWebSecurity 
public class SecurityConfig extends WebSecurityConfigurerAdapter {


    @Override
    protected void configure(HttpSecurity http) throws Exception {

        //add your custom encoding filter as the first filter in the chain
        http.addFilterBefore(new EncodingFilter(), ChannelProcessingFilter.class);

        http.authorizeRequests()
            .and()
            // your code here ...
    }
}

The ordering of all filters in Spring Security is available here: HttpSecurityBuilder - addFilter()

Your custom UTF-8 encoding filter can look like following:

public class EncodingFilter extends GenericFilterBean {

    @Override
    public void doFilter(
            ServletRequest request, 
            ServletResponse response,
            FilterChain chain) throws IOException, ServletException {

        request.setCharacterEncoding("UTF-8");
        response.setCharacterEncoding("UTF-8");

        chain.doFilter(request, response);
    }
}

Don't forget to add in your jsp files:

<%@ page pageEncoding="UTF-8" contentType="text/html; charset=UTF-8" %>

And remove the CharacterEncodingFilter from web.xml if it's there.

Alexey
  • 1,521
  • 1
  • 13
  • 24
15

In addition to Benjamin's answer (which I've only skimmed), you need to make sure that your files are actually stored using the proper encoding (that would be UTF-8 for source code, JSPs etc., but note that Java Properties files must be encoded as ISO 8859-1 by definition).

The problem with this is that it's not possible to tell what encoding has been used to store a file. Your only option is to open the file using a specific encoding, and checking whether or not the content makes sense. You can also try to convert the file from the assumed encoding to the desired encoding using iconv - if that produces an error, your assumption was incorrect. So if you assume that hello.jsp is encoded as UTF-8, run "iconv -f UTF-16 -t UTF-8 hello.jsp" and check for errors.

If you should find out that your files are not properly encoded, you need to find out why. It's probably the editor or IDE you used to create the file. In case of Eclipse (and STS), make sure the Text File Encoding (Preferences / General / Workspace) is set to UTF-8 (it unfortunately defaults to your system's platform encoding).

What makes encoding problems so difficult to debug is that there's so many components involved (text editor, borwser, plus each and every software component in between, in some cases including a database), and each of them has the potential to introduce an error.

otto.poellath
  • 4,129
  • 6
  • 45
  • 60
  • As per the comment on the question, OP has already configured the editor to save files as UTF-8. – BalusC May 08 '11 at 15:27
  • 1
    Yup, and even though the OP's comment was posted before my answer, it wasn't there when I first loaded the page and read the question. – otto.poellath May 08 '11 at 16:01
9

Easiest solution to force UTF-8 encoding in Spring MVC returning String:

In @RequestMapping, use:

produces = MediaType.APPLICATION_JSON_VALUE + "; charset=utf-8"
Alex R
  • 11,364
  • 15
  • 100
  • 180
5

To solve this issue you need below three steps:

  1. Set page encoding to UTF-8 like below:

    <%@ page language="java" pageEncoding="UTF-8"%>
    <%@ page contentType="text/html;charset=UTF-8" %>
    
  2. Set filter in web.xml file as below:

    <filter>
        <filter-name>encodingFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <init-param>
            <param-name>forceEncoding</param-name>
            <param-value>true</param-value>
        </init-param>
        <init-param>
            <param-name>encoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>encodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    
  3. Set resource encoding to UTF-8, in case if you are writing any UTF-8 characters in Java code or JSP directly.

zb226
  • 9,586
  • 6
  • 49
  • 79
user7373275
  • 51
  • 1
  • 1
5

right-click to your controller.java then properties and check if your text file is encoded with utf-8, if not this is your mistake.

storm_buster
  • 7,362
  • 18
  • 53
  • 75
4

Depending on how you render your view, you may also need:

@Bean
public StringHttpMessageConverter stringHttpMessageConverter() {
    return new StringHttpMessageConverter(Charset.forName("UTF-8"));
}
Axel Fontaine
  • 34,542
  • 16
  • 106
  • 137
  • Thanks. I have a controller method that returns a `@ResponseBody String` that was encoding wrong (since the `StringHttpMessageConverter` uses `ISO-8859-1` internally by default). Btw, you can use Java 7's `StandardCharsets.UTF_8`, e.g. `new StringHttpMessageConverter(StandardCharsets.UTF_8)`. – matsev Oct 27 '14 at 12:32
2

Worked for me like here Spring MVC Java config

by added to web initializer

 @Override
      protected Filter[] getServletFilters() {

        CharacterEncodingFilter characterEncodingFilter = new CharacterEncodingFilter();
        characterEncodingFilter.setEncoding("UTF-8");
        return new Filter[] { characterEncodingFilter};
      }
d0wn
  • 121
  • 4
1

Starting servlet spec 4.0, you can set the request character encoding in the servlet context without specifying the filter.

Either in web.xml:

<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
                      http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
  version="4.0">
  <request-character-encoding>UTF-8</request-character-encoding>
  [...]

Or in Java config:

servletContext.setRequestCharacterEncoding("UTF-8");
flup
  • 26,937
  • 7
  • 52
  • 74