Поведение 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.
Вы можете решить эту проблему двумя способами:
Предоставьте собственный распознаватель 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>
Или переключитесь на 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.