ServletContext#setRequestCharacterEncoding and ServletContext#setResponseCharacterEncoding seem to fail to set the character encoding(WildFly16)
tmk310st May 15, 2019 6:42 PMHello,
Does WildFly-16 support using ServletContext#setRequestCharacterEncoding and ServletContext#setResponseCharacterEncoding?
WildFly-16.0.0.Final supports Java EE 8(https://docs.wildfly.org/) ,
so I am trying to use ServletContext#setRequestCharacterEncoding and ServletContext#setResponseCharacterEncoding
(available in Servlet 4.0).
However, when I created a simple war application and tested them,
they failed to set the character encoding.
[Environment]
- Wildfly-16.0.0.Final (I didn't change any default configuration.)
- jdk11
- Windows 8.1
Here are the application's configuration and components.
[standalone.xml]
(I didn't specify default-encoding for the purpose of testing)
        <subsystem xmlns="urn:jboss:domain:undertow:8.0" default-server="default-server" default-virtual-host="default-host" default-servlet-container="default" default-security-domain="other" statistics-enabled="${wildfly.undertow.statistics-enabled:${wildfly.statistics-enabled:false}}">
            <buffer-cache name="default"/>
            <server name="default-server">
                <http-listener name="default" socket-binding="http" redirect-socket="https" enable-http2="true"/>
                <https-listener name="https" socket-binding="https" security-realm="ApplicationRealm" enable-http2="true"/>
                <host name="default-host" alias="localhost">
                    <location name="/" handler="welcome-content"/>
                    <http-invoker security-realm="ApplicationRealm"/>
                </host>
            </server>
            <servlet-container name="default">
                <jsp-config/>
                <websockets/>
            </servlet-container>
            <handlers>
                <file name="welcome-content" path="${jboss.home.dir}/welcome-content"/>
            </handlers>
        </subsystem>
[pom.xml]
(just one dependency)
<dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>4.0.1</version> <scope>provided</scope> </dependency>
[index.html]
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
</head>
<body>
    <form action="/SimpleWarApp/app/simple" method="post">
        <!-- The value is Japanese character '\u3042' -->
        <input type="text" name="hello" value="あ"/>
        <input type="submit" value="submit!"/>
    </form>
    <button type="button" id="the_button">post</button>
    <script>
        document.getElementById('the_button').addEventListener('click', function() {
            var xhttp = new XMLHttpRequest();
            xhttp.onreadystatechange = function() {
                 if (this.status === 200 && this.readyState === this.DONE) {
                      alert(this.responseText);
                 }
            };
            <!-- Decode the  response body by UTF-8 -->
            xhttp.overrideMimeType('Content-Type: text/plain; charset=UTF-8');
            xhttp.open('POST', '/SimpleWarApp/app/simple');
            <!-- For the purpose of testing, I intentionally omit charset parameter from Content-Type header, -->
            <!-- so I can avoid charset parameter to have an effect on the character encoding of servlets. -->
            <!-- Even when charset parameter is omitted, XMLHttpRequest encodes the request body by UTF-8. -->
            xhttp.setRequestHeader('Content-Type', 'text/plain');
            <!-- The body content is Japanese character '\u3042' -->
            xhttp.send('あ');
        });
    </script>
</body>
</html>
[InitServletContextListener.java]
@WebListener
public class InitServletContextListener implements ServletContextListener {
     @Override
     public void contextInitialized(ServletContextEvent sce) {
          sce.getServletContext().setRequestCharacterEncoding("UTF-8");
          sce.getServletContext().setResponseCharacterEncoding("UTF-8");
     }
}
[SimpleServlet.java]
@WebServlet("/app/simple")
@SuppressWarnings("serial")
public class SimpleServlet extends HttpServlet {
     @Override
     protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
          System.out.println("requestCharacterEncoding : " + req.getServletContext().getRequestCharacterEncoding());
          System.out.println("req.getCharacterEncoding() : " + req.getCharacterEncoding());
          System.out.println("responseCharacterEncoding : " + req.getServletContext().getResponseCharacterEncoding());
          System.out.println("resp.getCharacterEncoding() : " + resp.getCharacterEncoding());
          String hello = req.getParameter("hello");
          if (hello != null) {
               System.out.println("hello( expected:E3 81 82 ) : " + toHexString(req.getParameter("hello")));
          } else {
               System.out.println("body( expected:E3 81 82 ) : " + toHexString(req.getReader().readLine()));
          }
          resp.getWriter().println("あ");
     }
     // To avoid the platform default encoding to affect assertion, I check the text in hexadecimal format.
     private String toHexString(String str) throws UnsupportedEncodingException {
          String ret = "";
          for (int b : str.getBytes("UTF-8")) {
               if (b < 256) {
                    b += 256;
               }
               ret += " ";
               ret += Integer.toHexString(b).toUpperCase();
          }
          return ret;
     }
}
}
It doesn't have any servlet filters, web.xml and jboss-web.xml.
The above three(html, listener and servlet) are all the components of this application.
I checked the application's behavior as follows.
Case 1:
When I submit the form with 'hello' parameter, the value of 'hello' parameter is not successfully decoded.
23:59:39,635 INFO [stdout] (default task-1) requestCharacterEncoding : /SimpleWarApp
23:59:39,637 INFO [stdout] (default task-1) req.getCharacterEncoding() : ISO-8859-1
23:59:39,637 INFO [stdout] (default task-1) responseCharacterEncoding : UTF-8
23:59:39,638 INFO [stdout] (default task-1) resp.getCharacterEncoding() : ISO-8859-1
23:59:39,657 INFO [stdout] (default task-1) hello( expected:E3 81 82 ) : C3 A3 C2 81 C2 82
Case 2:
When I click 'post' button and send text contents, the request body (one Japanese character) is not successfully decoded,
23:55:30,854 INFO [stdout] (default task-1) requestCharacterEncoding : /SimpleWarApp
23:55:30,855 INFO [stdout] (default task-1) req.getCharacterEncoding() : ISO-8859-1
23:55:30,857 INFO [stdout] (default task-1) responseCharacterEncoding : UTF-8
23:55:30,858 INFO [stdout] (default task-1) resp.getCharacterEncoding() : ISO-8859-1
23:55:30,863 INFO [stdout] (default task-1) body( expected:E3 81 82 ) : C3 A3 C2 81 C2 82
In both Case 1 and Case 2, I expected the response body to be encoded by UTF-8 (expected: E3 81 82 0A) but it was not encoded successfully
(I checked the response body in hexadecimal form by using Fiddler).
3F 0A
However, when I remove InitServletContextListener.java from the application and set the character encoding
by using HttpServetRequest#setCharacterEncoding and HttpServletResponse#setCharacterEncoding at the beginning of 'doPost' method,
It seems to work fine as follows.
(In Case 1)
00:05:33,194 INFO [stdout] (default task-1) req.getCharacterEncoding() : UTF-8
00:05:33,197 INFO [stdout] (default task-1) resp.getCharacterEncoding() : UTF-8
00:05:33,199 INFO [stdout] (default task-1) hello( expected:E3 81 82 ) : E3 81 82
(In Case 2)
00:05:27,814 INFO [stdout] (default task-1) req.getCharacterEncoding() : UTF-8
00:05:27,816 INFO [stdout] (default task-1) resp.getCharacterEncoding() : UTF-8
00:05:27,843 INFO [stdout] (default task-1) body( expected:E3 81 82 ) : E3 81 82
(The response body)
E3 81 82 0A
Thanks,
Tomoki
 
     
    





