Tomcat 8 (and 9) coerce behaviour, null strings are incorrectly set as empty strings

前端 未结 1 838
清酒与你
清酒与你 2020-12-06 13:12

I have just migrated to Tomcat 8. I used to work with system property org.apache.el.parser.COERCE_TO_ZERO=false so empty strings, numbers, booleans etc. are tre

相关标签:
1条回答
  • 2020-12-06 13:42

    This is a bug in the EL 3.0 specification. Since EL 3.0, as consequence of overzealous fix of JSP spec issue 184, null will be coerced back to empty string before the model value setter is invoked. Basically, the javax.faces.INTERPRET_EMPTY_STRING_SUBMITTED_VALUES_AS_NULL doesn't have any affect anymore. See also JSF issue 3071 and EL spec issue 18.

    Basically, to solve this problem you need to provide either a custom EL resolver, or to replace/upgrade the EL implementation (or simply the whole server as it's the one actually providing EL out the box) to a version with the bugfix. The Tomcat issue 57309 which you linked is not related to this particular EL 3.0 issue of unnecessary coercion from null to empty string, it's only related to Tomcat's ignorance of the custom EL resolver.

    You can solve this problem in two ways:

    1. Provide a custom EL resolver like below. Make sure that you use Tomcat 8.0.16 or newer, as specified in the Tomcat issue report you found.

       public class EmptyToNullStringELResolver extends ELResolver {
      
           @Override
           public Class<?> getCommonPropertyType(ELContext context, Object base) {
               return String.class;
           }
      
           @Override
           public Object convertToType(ELContext context, Object value, Class<?> targetType) {
               if (value == null && targetType == String.class) {
                   context.setPropertyResolved(true);
               }
      
               return value;
           }
      
           @Override
           public Iterator<FeatureDescriptor> getFeatureDescriptors(ELContext context, Object base) {
               return null;
           }
      
           @Override
           public Class<?> getType(ELContext context, Object base, Object property) {
               return null;
           }
      
           @Override
           public Object getValue(ELContext context, Object base, Object property) {
               return null;
           }
      
           @Override
           public boolean isReadOnly(ELContext context, Object base, Object property) {
               return true;
           }
      
           @Override
           public void setValue(ELContext context, Object base, Object property, Object value) {
               // NOOP.
           }
      
       }
      

      In order to get it to run, register as below in faces-config.xml:

       <application>
           <el-resolver>com.example.EmptyToNullStringELResolver</el-resolver>
       </application>
      

    2. Or, switch to Oracle EL. They already fixed it in version 3.0.1 b05 which has been available since 7 July 2014 (just pick the newest one which is 3.0.1-b10 as of today).

      Just drop javax.el.jar file in /WEB-INF/lib and add the below context param to web.xml in order to instruct MyFaces to use the Oracle EL implementation instead:

       <context-param>     
           <param-name>org.apache.myfaces.EXPRESSION_FACTORY</param-name>
           <param-value>com.sun.el.ExpressionFactoryImpl</param-value>   
       </context-param>
      

      In case you're using Mojarra, use param name com.sun.faces.expressionFactory.

    As I got momentarily confused myself too, I blogged to get it all right: The empty String madness.

    ###See also:

    • javax.faces.INTERPRET_EMPTY_STRING_SUBMITTED_VALUES_AS_NULL does not work anymore since Java EE 7 / EL 3.0
    0 讨论(0)
提交回复
热议问题