22
votes

This is on GlassFish 3.1, using PrimeFaces over Mojarra and salted with MyFaces CODI. On just about every request the following message appears:

WARNING: PWC4011: Unable to set request character encoding to UTF-8 from context /com.myapp_war_0.1, because request parameters have already been read, or ServletRequest.getReader() has already been called

This has happened ever since I started the project -- so far I have been ignoring it but now I have realized I am wasting a lot of time reading around it. I found an interesting but incomplete work-around here, but I don't understand it.

Can someone suggest how to tamp down this message without suppressing other possible warning messages?

1
From my experience this famous message gets lost after upgrading mojarra version. Which one are you using?andbi
@Osw: there was indeed a related bug in one of the earliest Mojarra 2.0.x versions, but that was caused by a slight different issue and affected Ajax requests only. OP is however using GF 3.1 which bundles JSF 2.1.BalusC
@osw: specifically I am using GF 3.1.1 Build 12. I probably shouldn't but I let both Netbeans and GF download all updates as soon as they become available. I recall this problem at nearly every version level, however. It just got to the point where I was testing a lot of pages, generating enough of those error messages in the process, that I was stimulated to tak action on it. BTW the Mojarra version in this package is 2.1.3 (FCS b02).AlanObject

1 Answers

41
votes

JSF/Facelets uses by default UTF-8 to decode HTTP request parameters. GlassFish itself uses by default ISO-8859-1 do decode HTTP request parameters. HTTP request parameters can be parsed and decoded only once and this happens whenever a request parameter is requested by the code for the first time like so request.getParameter("name"). So, if a request parameter is requested for the first time before JSF has set the request parameter encoding to UTF-8, then it will (incorrectly) be parsed using ISO-8859-1.

When JSF needs to set the request parameter encoding during restore view phase as follows,

request.setCharacterEncoding("UTF-8");

while the request parameters are already parsed, then GlassFish will show exactly this warning.

The unwanted consequence is, all those HTTP request parameters may possibly end up in Mojibake. The form data is originally submitted and encoded using UTF-8. If you decode UTF-8 data using a different charset like ISO-8859-1, then the characters in 8-bit range and beyond (usually, it are those "special characters" like é, à, ö, etc. will be corrupted and end up in é, à, ö, etc.

Technically, the right solution is to not request a HTTP request parameter before JSF has set the right encoding. You basically need to check all the code which runs before JSF's restore view phase, such as servlet filters, phase listeners, etc if they aren't doing that.

If you can't seem to find it, or the code is beyond your control, then you can tell GlassFish to use UTF-8 instead to decode HTTP request parameters, so that it doesn't need to be changed when JSF want to get them. You can do that by adding the following entry to the <glassfish-web-app> of your /WEB-INF/glassfish-web.xml file:

<parameter-encoding default-charset="UTF-8"/>

(note: the file and root entry is previously called sun-web.xml and <sun-web-app> respectively)

Noted should be that this is specific to GlassFish and this all won't work when you deploy the webapp to a different server. The canonical server-independent approach is to create a servlet filter which does basically the following job in doFilter() method:

request.setCharacterEncoding("UTF-8");
chain.doFilter(request, response);

and make sure that it's been mapped before any other filter which needs to collect any HTTP request parameters.


Update: as to why GlassFish has set it beforehand, it's possibly caused by PrimeFaces. See also this related question: Unicode input retrieved via PrimeFaces input components become corrupted.