5 Replies Latest reply on Oct 24, 2007 11:59 AM by pmuir

    Additional filter outside Seam-filter messes up encoding

    toby451

      I added a very innocent looking request timing filter outside the Seam Filter like this:

       <filter>
       <filter-name>Timing Filter</filter-name>
       <filter-class>foo.bar.TimingFilter</filter-class>
       </filter>
      
       <filter>
       <filter-name>Seam Filter</filter-name>
       <filter-class>org.jboss.seam.servlet.SeamFilter</filter-class>
       </filter>
      
       <filter-mapping>
       <filter-name>Timing Filter</filter-name>
       <url-pattern>/*</url-pattern>
       </filter-mapping>
      
       <filter-mapping>
       <filter-name>Seam Filter</filter-name>
       <url-pattern>/*</url-pattern>
       </filter-mapping>
      



      All of a sudden the UTF-8 encoding on our pages is broken. Scandinavian characters looking like "ö" instead of "ö" for instance (double encoded?).

      This is strange since the filter I am using does nothing with the actual content, it merely times the call like this:

       long t0 = System.nanoTime();
       chain.doFilter(req, res);
       long dt = System.nanoTime() - t0;
      



      What is going on here?

      Best Regards,
      Tobias


        • 1. Re: Additional filter outside Seam-filter messes up encoding
          shane.bryzak

          No idea.. could you post the full code for your filter?

          • 2. Re: Additional filter outside Seam-filter messes up encoding
            toby451

            Here it is (I can't see that it interfers with encoding in any way).
            Application is being deployed on JBoss 4.2.1.GA.


            import org.apache.commons.lang.StringUtils;
            
            import javax.servlet.Filter;
            import javax.servlet.FilterChain;
            import javax.servlet.FilterConfig;
            import javax.servlet.ServletException;
            import javax.servlet.ServletRequest;
            import javax.servlet.ServletResponse;
            import javax.servlet.http.HttpServletRequest;
            import java.io.IOException;
            import java.util.ArrayList;
            import java.util.Collections;
            import java.util.List;
            import java.util.Map;
            
            /**
             * TimingFilter messures requests times and should be placed
             * outside (in the filter/servlet chain) the thing to be meassured.
             */
            public class TimingFilter implements Filter {
            
             private FilterConfig config;
             private static final int MAX_ARRAYITEMS_PRINTED = 5;
            
             public void init(FilterConfig config) throws ServletException {
             this.config = config;
             }
            
             public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
             String name = "<non http request>";
             String method = "?";
             if (req instanceof HttpServletRequest) {
             HttpServletRequest servletRequest = (HttpServletRequest) req;
             name = servletRequest.getRequestURI();
             method = servletRequest.getMethod();
             }
             Map requestMap = req.getParameterMap();
            
             long t0 = System.nanoTime();
             chain.doFilter(req, res);
             long dt = System.nanoTime() - t0;
            
             config.getServletContext().log(
             StringUtils.leftPad(formatTime(dt), 10) +
             StringUtils.leftPad(method + " ", 6) +
             StringUtils.rightPad(name, 26) +
             StringUtils.rightPad(prettify(requestMap), 100)
             );
             }
            
            
             /**
             * Will format a nanosecond value as milliseconds with one decimal.
             */
             private String formatTime(long ns) {
             String ms = String.valueOf(ns / 100000);
             int pointPos = ms.length() - 1;
             return ms.substring(0, pointPos) + "." + ms.substring(pointPos) + " ms";
             }
            
            
             /**
             * Will convert the map into something readable
             */
             private String prettify(Map map) {
             StringBuilder sb = new StringBuilder();
            
             //noinspection unchecked
             List<String> keys = new ArrayList(map.keySet());
             Collections.sort(keys);
            
             for (String key : keys)
             sb.append(key).append("=").append(prettifyValue(map.get(key))).append(" ");
            
             return sb.length() > 0 ? sb.toString() : "<no parameters>";
             }
            
            
             /**
             * Will loop through array values and give pretty output.
             * (i.e. some widgets (grouped checkboxes) give multiple values)
             */
             private String prettifyValue(Object o) {
            
             // Non arrays we just convert to String.
             if (!(o instanceof Object[]))
             return o.toString();
            
             // For arrays we build a comma separated list.
             StringBuilder sb = new StringBuilder("");
             Object[] arr = (Object[]) o;
             int itemsToPrint = Math.min(arr.length, MAX_ARRAYITEMS_PRINTED);
             for (int i = 0; i < itemsToPrint; i++)
             sb.append(arr).append(i < (itemsToPrint - 1) ? ", " : "");
            
             if (itemsToPrint == 1)
             return sb.toString();
             else
             return "[" + sb.toString() + "]";
             }
            
             public void destroy() {
             config = null;
             }
             }
            
            


            • 3. Re: Additional filter outside Seam-filter messes up encoding

              How are you UTF-8 encoding your pages? I tried the filter and it didn't mess up the öåä, etc

              • 4. Re: Additional filter outside Seam-filter messes up encoding
                toby451

                Ok ... the scandinavian characters åäöÅÄÖ got scrambled when they where part of a post-data.

                Adding this (below) filter in front of the timing seems to solve it!

                 <filter>
                 <filter-name>Character Encoding</filter-name>
                 <filter-class>
                 org.jboss.seam.servlet.SeamCharacterEncodingFilter
                 </filter-class>
                 <init-param>
                 <param-name>encoding</param-name>
                 <param-value>UTF-8</param-value>
                 </init-param>
                 <init-param>
                 <param-name>overrideClient</param-name>
                 <param-value>true</param-value>
                 </init-param>
                 </filter>
                




                • 5. Re: Additional filter outside Seam-filter messes up encoding
                  pmuir

                  N.B. if you make your filter a Seam filter (see the configuration chapter) you can order the filters using @Filter.