Search code examples
jsfeltomcat9tomee-8

Blank input String fields submitted as Empty Strings vs Null - JSF 2.3 MyFaces - Tomcat (TomEE)/9.0.12 (8.0.0-M1)


Empty form input fields bound to bean String type are received as empty strings ("") when the expected value is NULL.

This is an old problem that seems to get recreated with each version of Oracle EL or Apache EL or Tomcat.

@BalusC has addressed it many times. Empty String Madness, Tomcat 8 (and 9) coerce behaviour, null strings are incorrectly set as empty strings are a couple of examples.

I have tried all previous workarounds without success.

someform.xhtml

<h:form>
  <h:outputText value="Some Input: " />
  <p:inputText value="#{someBean.stringVariable}" />

  <p:commandButton id="search-button"
                    value="Search"
                    actionListener="#{someBean.doSearch}" />
</form>

SomeBean.java

private String stringVariable;
// Setter & Getter
public void doSearch()
{
    if(stringVariable == null)
    {
       System.out.println("Input is NULL");
    }
    else if(stringVariable.equals(""))
    {
       System.out.println("Input is EMPTY STRING");    
    }
}

faces-config.xml

<?xml version="1.0" encoding="UTF-8"?>
<faces-config
    xmlns="http://xmlns.jcp.org/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-facesconfig_2_3.xsd"
    version="2.3">
        <application>
        <el-resolver>com.example.EmptyToNullStringELResolver</el-resolver>
    </application> 
    <application>
        <resource-handler>org.jepsar.primefaces.theme.jepsar.FontAwesomeResourceHandler</resource-handler>
        <resource-handler>org.omnifaces.resourcehandler.UnmappedResourceHandler</resource-handler>
    </application>  
    <application>
        <el-resolver>
           org.primefaces.application.exceptionhandler.PrimeExceptionHandlerELResolver
        </el-resolver>
    </application>
    <factory>
           <exception-handler-factory>
                 org.primefaces.application.exceptionhandler.PrimeExceptionHandlerFactory
           </exception-handler-factory>
    </factory> 
 </faces-config>

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1">
  <context-param>
    <param-name>javax.faces.INTERPRET_EMPTY_STRING_SUBMITTED_VALUES_AS_NULL</param-name>
    <param-value>true</param-value>
  </context-param> 
  <context-param>     
    <param-name>org.apache.myfaces.EXPRESSION_FACTORY</param-name>
    <param-value>com.sun.el.ExpressionFactoryImpl</param-value>   
  </context-param>
</web-app>

When I use the custom EmptyToNullStringELResolver method, a NPE is thrown.

java.lang.NullPointerException
    at org.apache.myfaces.shared.resource.ValueExpressionFilterInputStream.read(ValueExpressionFilterInputStream.java:130)
    at java.io.InputStream.read(InputStream.java:179)
    at java.nio.channels.Channels$ReadableByteChannelImpl.read(Channels.java:385)
    at org.omnifaces.util.Utils.stream(Utils.java:397)
    at org.omnifaces.resourcehandler.UnmappedResourceHandler.handleResourceRequest(UnmappedResourceHandler.java:176)
    at javax.faces.webapp.FacesServlet.service(FacesServlet.java:196)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at ...

Dropping the most recent EL jar from Oracle into WEB/lib seems to have no effect. (javax.el-3.0.1-b11.jar)

Thank you, Ted S


Solution

  • As per The Empty String Madness article, The EmptyToNullStringELResolver and Oracle EL doesn't need to be done simultaneously. For Tomcat 8.0.16 or newer the following is listed:

    JF: add javax.faces.INTERPRET_EMPTY_STRING_SUBMITTED_VALUES_AS_NULL=true context param.
    ER: register EmptyToNullStringELResolver, or alternatively, just do UE.
    UE: migrate/upgrade to Oracle EL implementation version 3.0.1-b05 or newer.

    Note the "alternatively" word. Thus it's fine to do only one or the other.

    As to the observed NullPointerException, it's thus happening when a ResourceHandler needs to stream a resource which could possibly contain EL expressions. This by default only happens on CSS resources in order to be able to support How to reference JSF image resource as CSS background image url. The ValueExpressionFilterInputStream represents MyFaces' internal class which is being used to evaluate EL expressions while reading an InputStream. However, it has apparently a bug whereby it doesn't expect EL expressions which return null instead of a concrete object. That problem is in turn actually unrelated to the solutions for "The Empty String Madness". It would have occurred nonetheless. You should at least scan your custom CSS files for EL expressions which incorrectly return null and fix them.