Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
700 views
in Technique[技术] by (71.8m points)

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

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 treated as null.

In Tomcat 8, EL 3.0, it is supposed to be the default but it is in fact converting null string to empty string "" on JSF side.

It is supposed to be a bug and it is supposed to be corrected but I'm not able to get it working in TomEE snapshot (Tomcat 8.0.27.0, MyFaces 2.2.8).

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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:


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...