Request parameter accent on JSF page

5

I have a JSF page that receives as a parameter, in the URL, the error message to be displayed. Ex: http://example.com/application_error.jsf?exception=Não+permitido

On the page, the parameter is displayed as follows:

#{param['exception']}

However, the accented characters are wrong.

I'm using the Demoiselle framework and the Tomcat 7 server. My pages are UTF-8.

The page in question is the application_error page, for which Demoiselle redirects when a ApplicationException is posted.

How do I correct the accent problem without changing the character encoding I'm using on my pages?

    
asked by anonymous 11.12.2013 / 17:23

2 answers

4

Tomcat considers the entire request to be ISO-8859-1 by default "factory".

The direct and specific solution for tomcat is to change the server configuration ( server.xml ):

<Server port="8105" shutdown="SHUTDOWN">
...
    <Service name="Catalina">
        <Connector port="8180" URIEncoding="UTF-8" />
        <Engine name="Catalina" defaultHost="localhost">
            <Host name="localhost" appBase="webapps" />
        </Engine>
    </Service>
....
</Server>

However, I do not consider this an ideal solution because when you need to deploy deploy from your application in a third-party environment you probably will not have access to this change.

A solution that can be implemented in the application itself divides (at least) into: encoding in the body of requests, parameters, and headers.

To solve the problem for data in the request body, I usually add a filter to the application in web.xml which forces the encoding to be of a certain type. In a project where I use Spring, the following excerpt solves the problem:

<filter>
    <filter-name>encoding-filter</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>encoding-filter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

If you do not use Spring, you can use the apache library code and place the class in your own project.

For data in headers or parameters, we can encapsulate HttpServletRequest through a filter. I did the implementation below, but I do not have an application on hand to test, so any problem give me a feedback :

public class ParametersEncodingFilter implements Filter {

    private String charset = "UTF-8";

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        String charsetParam = filterConfig.getInitParameter("charset");
        if (charsetParam != null && !charsetParam.isEmpty()) {
            this.charset = charsetParam;
        }
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        chain.doFilter(new FilteredRequest(charset, request), response);
    }

    @Override
    public void destroy() {
        //nothing to clean up
    }

    final private static class FilteredRequest extends HttpServletRequestWrapper {

        public FilteredRequest(String charset, ServletRequest request) {
            super((HttpServletRequest)request);

            //convert encoding params
            Map<String, String[]> originalParams = super.getParameterMap();
            for(Object key : originalParams.keySet()) {

                String[] entry = originalParams.get(key);
                for (int i = 0; i < entry.length; i++) {

                    try {
                        entry[i] = new String(entry[i].getBytes("ISO-8859-1"), charset);
                    } catch (UnsupportedEncodingException e) {
                        return; //if can't convert one, it cannot convert any of them
                    }

                }

            }

        }        

    }

}

Note: This implementation considers that the filter has a parameter with the desired encoding, as in the Spring filter configuration above.

And one last comment: If it is possible to encode URL parameters, for example N%C3%A3o%2Bpermitido instead of Não+Permitido , it might solve the parameter-specific problem without additional implementations.

    
12.12.2013 / 17:08
1

As I understand it, Tomcat decodes GET parameters using ISO-8859-1. Since I do not have access to the server configuration, I have adopted a contour solution. I created a convert to UTF-8:

@Named
public class EncodingConverter implements Converter {

  @Override
  public Object getAsObject(FacesContext context, UIComponent component,
      String value) {
    return null;
  }

  @Override
  public String getAsString(FacesContext context, UIComponent component, Object value) {
    String result = null;

    if (value != null) {
      String string = (String)value;
      Charset toCharset = Charset.forName("ISO-8859-1");
      Charset fromCharset = Charset.forName("UTF-8");
      result = new String(string.getBytes(toCharset), fromCharset);
    }

    return result;
  }
}

When displaying the value on the xhtml page, I step through the convert.

<h:outputText value="#{param['exception']}" converter="#{encodingConverter}" />
    
12.12.2013 / 16:57