When developing a non-english webapp, you'll probably encounter some issues with special characters as "ñ", "á", etc, ie, when you input some of this characters in a text input field, you get those characters back from the server rendered as "Ö" or something similar.
The best approach is to use UTF-8 enconding all over the application so the response is not encoded differently depending of the place that handles that response.
This approach applies to:
- Tomcat 6
- Java 1.6
- MyFaces 2.1.10
- RichFaces 4.2.3-Final
The places to configure the encoding are:
- server.xml in Tomcat
It's neccesary to get Tomcat to encode GET parameters. This is done by adding the URIEncoding attribute to the HTTP connector.
<Connector port="8080" protocol="HTTP/1.1" URIEncoding="UTF-8"
.... />
- Servlet Filter
Implement a servlet filter to do the UTF-8 encoding of the requests and responses:
public class SetCharacterEncodingFilter implements Filter {
protected String encoding = null;
protected FilterConfig filterConfig = null;
protected boolean ignore = true;
/**
* Take this filter out of service.
*/
public void destroy() {
this.encoding = null;
this.filterConfig = null;
}
/**
* Select and set (if specified) the character encoding to be used to
* interpret request parameters for this request.
* @param request The servlet request we are processing
* @param result The servlet response we are creating
* @param chain The filter chain we are processing
* @exception IOException if an input/output error occurs
* @exception ServletException if a servlet error occurs
*/
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain)
throws IOException, ServletException {
// Conditionally select and set the character encoding to be used
if (ignore || (request.getCharacterEncoding() == null)) {
String encoding = selectEncoding(request);
if (encoding != null)
request.setCharacterEncoding(encoding);
}
response.setContentType("text/html; charset=UTF-8");
response.setCharacterEncoding("UTF-8");
// Pass control on to the next filter
chain.doFilter(request, response);
}
/**
* Place this filter into service.
* @param filterConfig The filter configuration object
*/
public void init(FilterConfig filterConfig) throws ServletException {
this.filterConfig = filterConfig;
this.encoding = filterConfig.getInitParameter("encoding");
String value = filterConfig.getInitParameter("ignore");
if (value == null)
this.ignore = true;
else if (value.equalsIgnoreCase("true"))
this.ignore = true;
else if (value.equalsIgnoreCase("yes"))
this.ignore = true;
else
this.ignore = false;
}
/**
* Select an appropriate character encoding to be used, based on the
* characteristics of the current request and/or filter initialization
* parameters. If no character encoding should be set, return
* null.
* * The default implementation unconditionally returns the value configured
* by the encoding initialization parameter for this
* filter.
*
* @param request The servlet request we are processing
*/
protected String selectEncoding(ServletRequest request) {
return (this.encoding);
}
}
Then you have to reference and map that filter in web.xml:
<filter>
<filter-name>SetCharacterEncodingFilter</filter-name>
<filter-class>com.foo.filters.SetCharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>SetCharacterEncodingFilter</filter-name>
<url-pattern>*.xhtml</url-pattern>
</filter-mapping>
Here I mapped only xhtml files because I'm also encoding the responses to UTF-8, so mapping images and other resources as UTF-8 will probably generate an encoding error.
- .xhtml Files
One final step is neccesary to ensure we have coherent encoding all across the webapp.
The first line in the xhtml files must be:
<?xml version="1.0" encoding="UTF-8"?>
Then, inside the head tag of the xhtml, add the following meta tag:
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
This is a lot less painful if you are using facelet templating technique; if that is the case, you'd only have to add the line mentioned above in the master template instead of in every .xhtml file.
Hope this helps, comment if you have any problem using this aproach.