Функция JSF 2 EL с Tomcat 6.0.x и EL 2.2

В моем приложении JSF 2.0 есть важные части:

functions.taglib.xml:

<?xml version="1.0"?>
<!DOCTYPE facelet-taglib PUBLIC "-//Sun Microsystems, Inc.//DTD Facelet Taglib 1.0//EN" "http://java.sun.com/dtd/facelet-taglib_1_0.dtd">
<facelet-taglib xmlns="http://java.sun.com/JSF/Facelet">
    <namespace>http://marius/components</namespace>
    <function>
       <function-name>empty</function-name>
       <function-class>com.test.ui.function.JsfFunctions</function-class>
       <function-signature>java.util.Boolean empty(java.lang.Object)</function-signature>
    </function>
</facelet-taglib>

Класс JsfFunctions:

package com.test.ui.function.function;

public class JsfFunctions {

    public static boolean empty(Object obj) {
        return obj == null;
    }
}

web.xml:

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

<context-param>
    <param-name>facelets.LIBRARIES</param-name>
    <param-value>/META-INF/functions.taglib.xml</param-value>
</context-param>

pom.xml:

<dependency>
    <groupId>javax.el</groupId>
    <artifactId>el-api</artifactId>
    <version>2.2</version>
</dependency>
<dependency>
    <groupId>org.glassfish.web</groupId>
    <artifactId>el-impl</artifactId>
    <version>2.2</version>
</dependency>

XHTML-файл:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:ui="http://java.sun.com/jsf/facelets"
    xmlns:c="http://java.sun.com/jsp/jstl/core"
    xmlns:t="http://myfaces.apache.org/tomahawk"
    xmlns:func="http://marius/components"
    xmlns:composite="http://java.sun.com/jsf/composite">

<composite:interface>
    <composite:attribute name="rendered" default="#{true}" />
</composite:interface>

<composite:implementation>

    <t:dataScroller id="#{cc.attrs.tableId}Scroller"
            for="#{cc.attrs.tableId}"
            rendered="#{cc.attrs.rendered and !func:empty(cc.attrs.dataModel)}">
    ....

Я получаю эту ошибку:

javax.el.ELException: Error Parsing: #{cc.attrs.rendered and !cl:empty(cc.attrs.dataModel)}
    com.sun.el.lang.ExpressionBuilder.createNodeInternal(ExpressionBuilder.java:171)
    com.sun.el.lang.ExpressionBuilder.build(ExpressionBuilder.java:188)


com.sun.el.parser.ParseException: Encountered ":" at line 1, column 28.
Was expecting one of:
    "}" ...
    "." ...
    "[" ...

Когда я отключаю интеграцию с EL 2.2, все работает нормально. Означает ли это, что EL 2.2 не работает с пользовательскими функциями EL?


person marius    schedule 12.10.2011    source источник


Ответы (2)


Смотри сюда,

xmlns:func="http://marius/components"

...

rendered="#{cc.attrs.rendered and !cl:empty(cc.attrs.dataModel)}"

Вы объявили его в пространстве имен XML func, но вызываете его в пространстве имен cl:. Либо переименуйте пространство имен XML в cl, либо измените префикс cl: на func:.


Не связанные с конкретной проблемой, есть еще несколько вопросов:

  1. Вы объявили taglib Facelets 1.x. Поскольку вы уже используете JSF / Facelets 2.x, вам следует предпочесть объявление taglib Facelets 2.x.

  2. Вы использовали конкретный контекстный параметр Facelets 1.x facelets.LIBRARIES, который существует только в JSF / Facelets 2.x для обратной совместимости. Но его рано или поздно уберут. Вместо этого вы должны использовать java.faces.FACELETS_LIBRARIES.

  3. Почему бы вам просто не использовать стандартное ключевое слово EL empty?

    rendered="#{cc.attrs.rendered and not empty cc.attrs.dataModel}">
    

    Ключевое слово empty проверяет, является ли оно null, и если это массив или коллекция, а также имеет ли он длину / размер 0.

    Если вы просто хотите проверить null, вы также можете просто сделать

    rendered="#{cc.attrs.rendered and cc.attrs.dataModel != null}">
    

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

person BalusC    schedule 12.10.2011
comment
Благодарю за ваш ответ. Я исправил префикс пространства имен XML и проблемы, упомянутые вами под номерами 1 и 2. Но это не помогло, я все еще получаю ту же ошибку. Функцию empty я использовал в качестве примера. Реальная функция будет более сложной. - person marius; 12.10.2011
comment
Очевидно, это противоречит собственному EL 2.1 Tomcat. Я никогда не использовал Maven и GF EL на Tomcat. Я не знаю, что делает Maven, но если Tomcat загрузит собственный EL 2.1 API при наличии EL 2.2 impl, он сломается. Если ваша единственная цель - передать аргументы метода в EL, я рекомендую вместо этого использовать JBoss EL. Тогда вам не понадобится EL 2.2 API. Достаточно просто EL 2.1 по умолчанию, предоставляемого Tomcat. Избавьтесь от зависимостей EL 2.2 и добавьте группу org.jboss.el, артефакт jboss-el версию 2.0.0 в свой pom и, наконец, отредактируйте значение параметра контекста, чтобы оно было org.jboss.el.ExpressionFactoryImpl. - person BalusC; 12.10.2011
comment
Обратите внимание, что у вас есть два параметра контекста: один для Mojarra JSF impl и другой для MyFaces JSF impl. Один из них лишний. - person BalusC; 12.10.2011

Думаю, я нашел причину ошибки. Похоже, возникла ошибка, потому что моя функция имела имя «пусто». Вероятно, это зарезервированное ключевое слово. Все работает после функции переименования.

person marius    schedule 13.10.2011
comment
Это зарезервированное ключевое слово, оно используется для типов коллекций и строк. - person Zoltán; 13.10.2011