Tuesday 14 May 2013

JSF Beginners Tips #1: request parameter encoding and date/times

As a habitual visitor to the PrimeFaces Forums I and other expert members often have to answer questions related to problems related to request parameter encoding and date/times.

Without further rambling from me an example of the first problem.


Typically a web application will use UTF-8 encoding for pages, requests and responses. Unfortunately this can lead to unexpected problems as illustrated by the following observations.

The poster had discovered that a JSF page which uses PrimeFaces for a partial submit will submit request parameters as expected

However when the same page used a non-AJAX request (full form post submit) the same parameters become garbled.
I was able to reproduce this behaviour with a simple form like this

<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:tst="http://java.sun.com/jsf/composite/composites"
      xmlns:f="http://java.sun.com/jsf/core"
      xmlns:p="http://primefaces.org/ui">
    <f:view contentType="text/html" encoding="UTF-8">
        <h:head>
            <meta content="text/html; charset=UTF-8" http-equiv="Content-Type" />
            <title>Facelet Title</title>
        </h:head>
        <h:body>
            <h:form>
                <tst:buttonFacet labelText="Press me!">
                    <f:facet name="commandButton">
                        <p:commandButton ajax="false" value="Waiting to be pressed!"/>
                    </f:facet>
                </tst:buttonFacet>
                <p>
                    <h:panelGroup>
                        <p:inputText id="myInput" value="#{inputCapture.input}" required="true" requiredMessage="Required">
                            <p:ajax event="blur" listener="#{inputCapture.inputListener()}" update="myMsg"/>
                        </p:inputText>
                        <p:messages id="myMsg" globalOnly="false"/>
                    </h:panelGroup>
                </p>
            </h:form>
        </h:body>
    </f:view>
</html>

The composite component and backing bean don't actually play a role in this, I used an existing page to see if I could reproduce the posters findings and was successful. Starting with the failure case any "special" characters like Ö and ü were recieved in a garbled state and by the look of things they were being decoded as if they were ISO-8859-1 when they are actually UTF-8.
Ajaxifying the p:commandButton results in a partial submit with the values not being incorrectly decoded.
Using Glassfish I observed the following being logged.

WARNING: PWC4011: Unable to set request character encoding to utf-8 from context /XXX, because request parameters have already been read, or ServletRequest.getReader() has already been called
An old friend indeed.
Glassfish is expected to behave as the spec says and in this case it actually does. If a form POST does not specify an encoding it is assumed that the request is encoded using ISO-8859-1 and decodes request parameters accordingly.
To correct this for Glassfish simply add a glassfish-web.xml with the following contents

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE glassfish-web-app PUBLIC "-//GlassFish.org//DTD GlassFish Application Server 3.1 Servlet 3.0//EN" "http://glassfish.org/dtds/glassfish-web-app_3_0-1.dtd">
<glassfish-web-app error-url="">
  <class-loader delegate="true"/>
  <jsp-config>
    <property name="keepgenerated" value="true">
      <description>Keep a copy of the generated servlet class' java code.</description>
    </property>
  </jsp-config>
  <parameter-encoding default-charset="UTF-8"/>
</glassfish-web-app>

Other servers will have other ways of fixing this, Tomcat for instance.
For a more in-depth explanation of this try here courtesy of Omnifaces.org.

Problem #2


Dates causes chaos! Simply adding a calender type widget or even a simple h:outputText where the output is a Date will often result in the date being displayed with a different, unexpected, value where often the time is out by an hour or even the date being out by a day or more. The actual value is still correct however.
This infuriating behaviour has probably caused quite a lot of premature balding in devs over the years however a simple fix is available.
Add the following to your web.xml.
<context-param>
        <param-name>javax.faces.DATETIMECONVERTER_DEFAULT_TIMEZONE_IS_SYSTEM_TIMEZONE</param-name>
        <param-value>true</param-value>
    </context-param>

At least this means that all the other date problems you have are less likely to be caused by the JSF container.

For a more complete explanation of why this is so try here.

No comments:

Post a Comment