java.lang.NumberFormatException Using the JSF2 Resource Management Framework

Last Modified: July 10, 2014

Summary

There is a known issue with the Google App Engine where a java.lang.NumberFormatException is thrown when the JavaServer Faces new Resource Management Framework attempts to load a file.  This is caused by a problem in the underlying Jetty web container which attempts to parse a RFC1123 compatible date value as a long.  This issue is documented in the Google App Engine issue tracker as bug 8415 entitled "Parsing date header as int caused NumberFormatException".

NOTE: As of the 1.9.6 release of the App Engine platform, this problem has been fixed.

Issue Tracker Information

This problem has been documented as issue 8145 in Google's Issue Tracker for the App Engine platform.

Recommended Solution

One solution is to modify the com.sun.faces.application.resource.ResourceImpl class so it catches this error, but that requires you to go in and modify source code belonging to the JavaServer Faces reference implementation each time you upgrade frameworks.  An alternative solution which we will use is to write a javax.servlet.Filter that wraps the HttpServletRequest in a class that hides the If-Modified-Since header from all requests.

  1. In the "Project Explorer" tab, located on the left side of your IDE, expand your project.  Expand the "src" branch and left-click on the package to which you would like to add this class.  For the purpose of this tutorial, we are going to select com.wildstartech.gae.jsf22template.
  2. Right-click on the package, display the "New" menu and then left-click on the "Class" menu item.



  3. Enter "HttpModifiedSinceRequestWrapper" in the "Name:" field.
  4. Enter "javax.servlet.http.HttpServletRequestWrapper" in the "Superclass:" field
  5. Ensure the "Constructors from superclass" option under the "Which method stubs would you like to create?" has a check mark beside it (see figure below).



  6. Replace the source code for the newly created HttpModifiedSinceRequestWrapper Java class that is displayed in the editor window with what is shown below.  Save the file and then close the editor window.

package com.wildstartech.gae.jsf22template;


import java.util.ArrayList;

import java.util.Collections;

import java.util.Enumeration;

import java.util.List;

import java.util.logging.Logger;


import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletRequestWrapper;


/**

 * Request wrapper to hide the If-Modified-Since request header.

 * 

 * @author Derek Berube, Wildstar Technologies, LLC.

 * @version 2014-01-07, 1.0

 * 

 * @see https://code.google.com/p/googleappengine/issues/detail?id=8415

 */

public class HttpModifiedSinceRequestWrapper extends HttpServletRequestWrapper {

    private static final String _CLASS=HttpModifiedSinceRequestWrapper.class.getName();

    private static final Logger logger = Logger.getLogger(_CLASS);


    /**

     * @param request

     */

    public HttpModifiedSinceRequestWrapper(HttpServletRequest request) {

        super(request);

        logger.entering(_CLASS"HttpModifiedSinceRequestWrapper");

        logger.exiting(_CLASS"HttpModifiedSinceRequestWrapper");

    }


    @Override

    /**

     * Returns the header provided it is not the "If-Modified-Since" header.

     */

    public String getHeader(String name) {

        logger.entering(_CLASS"getHeader(String)", name);

        String header = null;

        if (!"If-Modified-Since".equals(name)) {

            header = super.getHeader(name);

        } // END if (!"If-Modified-Since".equals(name))

        logger.exiting(_CLASS"getHeader(String)", header);

        return header;

    }


    @SuppressWarnings("rawtypes")

    @Override

    /**

     * Returns headers stripping out the "If-Modified-Since" header if

     * present.

     */

    public Enumeration getHeaderNames() {

logger.entering(_CLASS"getHeaderNames()");

Enumeration headerNames = null;

Enumeration<?> enu = null;

List<String> names;

String name = null;


names = new ArrayList<String>();

enu = super.getHeaderNames();


while (enu.hasMoreElements()) {

    name = enu.nextElement().toString();

    if (!"If-Modified-Since".equals(name)) {

        names.add(name);

    // END if (!"If-Modified-Since".equals(name))

// END while (enu.hasMoreElements())

headerNames = Collections.enumeration(names);

logger.exiting(_CLASS"getHeaderNames()", headerNames);

        return headerNames;

    }

}

We will use a javax.servlet.Filter to intercept requests to our web application to wrap incoming requests with the HttpRequestWrapper listed above.

  1. In the "Project Explorer" tab, located on the left side of your IDE, expand your project.  Expand the "src" branch and left-click on the package to which you would like to add this class.  For the purpose of this tutorial, we are going to select com.wildstartech.gae.jsf21template.
  2. Right-click on the package, display the "New" menu and then left-click on the "Class" menu item.



  3. Enter "HttpIfModifiedSinceFix" in the "Name:" field.
  4. Left-click on the "Add..." button that appears to the right of the "Interfaces" field.
  5. When the "Implemented Interfaces Selection" dialog is displayed, enter "javax.servlet.Filter" in the "Choose interfaces:" field.  Ensure the "Filter - Javax.servlet" option is selected from the list of items found in the "Matching items:" field as depicted in the screenshot below.



  6. Left-click on the "OK" button to return to the "New Java Class" dialog.  Ensure the "Inherited abstract methods" option in the "Which method stubs would you like to create?" has a check mark beside it as shown in the figure below.



  7. Left-click on the "Finish" button.
  8. Replace the source code for the newly created HttpIfModifiedSinceFix Java class that is displayed in the editor window with what is shown below.  Save the file and then close the editor window.

package com.wildstartech.gae.jsf22template;


import java.io.IOException;

import java.util.logging.Logger;


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 javax.servlet.http.HttpServletRequestWrapper;


/**

 * Replaces the If-Modified-Since header until Google App Engine bug 8415 is

 * resolved.

 * 

 * @see http://code.google.com/p/googleappengine/issues/detail?id=8415

 * 

 * @author Derek Berube, Wildstar Technologies

 */

public class HttpIfModifiedSinceFix implements Filter {

    private static final String _CLASS = HttpIfModifiedSinceFix.class.getName();

    private static final Logger logger = Logger.getLogger(_CLASS);


    /**

     * Called by the web container to indicate to a filter that it is being

     * taken out of service.

     */

    @Override

    public void destroy() {

logger.entering(_CLASS"destroy()");

logger.exiting(_CLASS"destroy()");

    }


    /**

     * The <code>doFilter</code> method of the Filter is called by the container

     * each time a request/response pair is passed through the chain due to a

     * client request for a resource at the end of the chain.

     */

    @Override

    public void doFilter(ServletRequest request, ServletResponse response,

        FilterChain chain) throws IOException, ServletException {

        logger.entering(_CLASS,

           "doFilter(ServletRequest,ServletResponse,FilterChain)",

    new Object[] { request, response, chain });

        HttpServletRequest httpRequest = null;

        HttpServletRequestWrapper requestWrapper = null;


        httpRequest = (HttpServletRequest) request;

        requestWrapper = new HttpModifiedSinceRequestWrapper(httpRequest);

        chain.doFilter(requestWrapper, response);


        logger.exiting(_CLASS,

            "doFilter(ServletRequest,ServletResponse,FilterChain)");

    }


    /**

     * Called by the web container to indicate to a filter that it is being

     * placed into service.

     */

    @Override

    public void init(FilterConfig config) throws ServletException {

        logger.entering(_CLASS"init(FilterConfig)", config);

        logger.exiting(_CLASS"init(FilterConfig)");

    }

}

The final step in addressing this bug is to define the filter and its corresponding filter-mapping entries in the web.xml configuration file located in the WEB-INF directory of our web application.

<!-- ***** Filter Definitions ***** -->

<filter>

    <display-name>AppEngine Bug 8145 Work Around</display-name>

    <description>

    Suppresses the If Modified Since header until GAE bug 8145 is fixed.

    </description>

    <filter-name>GAEBug8145WorkAround</filter-name>

    <filter-class>com.wildstartech.gae.jsf22template.HttpIfModifiedSinceFix</filter-class>

</filter>

<filter-mapping>

    <filter-name>GAEBug8145WorkAround</filter-name>

    <url-pattern>/*</url-pattern>

</filter-mapping>


In our example application, the above text was added just before the following line in the template web.xml file.

<!-- ***** Load the JavaServer Faces Servlet ***** -->


Copyright © 2013-2014, Wildstar Technologies, LLC.

Comments