Поведение Tomcat 8 в принудительном порядке, нулевые строки неправильно заданы как пустые строки

Я только что перешел на Tomcat 8. Раньше я работал с системным свойством org.apache.el.parser.COERCE_TO_ZERO=false поэтому пустые строки, числа, логические значения и т. д. рассматриваются как null,

В Tomcat 8, EL 3.0, он должен быть по умолчанию, но на самом деле он конвертирует null строка в пустую строку "" на стороне JSF.

Предполагается, что это ошибка, и она должна быть исправлена, но я не могу заставить ее работать в снимке TomEE (Tomcat 8.0.27.0, MyFaces 2.2.8).

1 ответ

Решение

Это ошибка в спецификации EL 3.0. Начиная с EL 3.0, как следствие чрезмерного усердия исправления проблемы спецификации JSP 184, null будет принудительно возвращен к пустой строке перед вызовом установщика значения модели. В основном, javax.faces.INTERPRET_EMPTY_STRING_SUBMITTED_VALUES_AS_NULL больше не влияет. См. Также выпуск 3071 JSF и выпуск 18 спецификации EL.

По сути, для решения этой проблемы вам необходимо предоставить либо собственный распознаватель EL, либо заменить / обновить реализацию EL (или просто весь сервер, так как он фактически предоставляет EL из коробки) до версии с исправлением ошибки. Проблема Tomcat 57309, с которой вы столкнулись, не связана с этой конкретной проблемой EL 3.0 о ненужном приведении от пустой к пустой строке, она связана только с незнанием Tomcat пользовательского распознавателя EL.

Вы можете решить эту проблему двумя способами:

  1. Предоставьте собственный распознаватель EL, как показано ниже. Убедитесь, что вы используете Tomcat 8.0.16 или новее, как указано в найденном вами отчете о проблемах Tomcat.

    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.
        }
    
    }
    

    Чтобы запустить его, зарегистрируйтесь как ниже faces-config.xml:

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

  2. Или переключитесь на Oracle EL. Они уже исправили это в версии 3.0.1 b05, которая была доступна с 7 июля 2014 года (просто выберите самую новую версию 3.0.1-b10 на сегодняшний день).

    Просто бросьте javax.el.jar файл в /WEB-INF/lib и добавьте следующий контекстный параметр в web.xml чтобы поручить MyFaces использовать реализацию Oracle EL вместо:

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

    Если вы используете Mojarra, используйте имя параметра com.sun.faces.expressionFactory,

Когда я тоже на мгновение запутался, я написал в блоге, чтобы все было в порядке: пустое безумие String.

Смотрите также:

Другие вопросы по тегам