0

There are important parts of my JSF 2.0 application:

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 class:

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 file:

<?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)}">
    ....

I get this error:

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:
    "}" ...
    "." ...
    "[" ...

When I disable EL 2.2 integration everything works OK. Does it mean that EL 2.2 doesn't work with custom EL functions?

marius
  • 49
  • 1
  • 7

2 Answers2

0

Look here,

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

...

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

You declared it on XML namespace func, but you're calling it on cl: namespace. Either rename XML namespace to cl or change the cl: prefix to func:.


Unrelated to the concrete problem, there are several other issues:

  1. You declared a Facelets 1.x taglib. As you're already on JSF/Facelets 2.x, you should prefer a Facelets 2.x taglib declaration.

  2. You used a Facelets 1.x specific context param facelets.LIBRARIES which only exist in JSF/Facelets 2.x for backwards compatibility. But it will be removed sooner or later. You should use java.faces.FACELETS_LIBRARIES instead.

  3. Why don't you just use the EL standard empty keyword?

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

    The empty keyword will check if it is null and if it's an array or a collection also if it has a length/size of 0.

    If you just want to check for null, you could also just do

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

See also:

Community
  • 1
  • 1
BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • Thank you for your response. I fixed XML namespace prefix and issues you mentioned as number 1 and 2. But this doesn't helped, I still receive the same error. Function empty I used as an example. Real function will be more complex. – marius Oct 12 '11 at 16:48
  • 1
    Apparently it's conflicting with Tomcat's own EL 2.1. I've never used Maven, nor used GF EL on Tomcat. I don't know what Maven is doing, but if Tomcat loads own EL 2.1 API while EL 2.2 impl is present, it will break. If your sole purpose being able to pass method arguments in EL, then I recommend using JBoss EL instead. Then you don't need EL 2.2 API. Just EL 2.1 as default provided by Tomcat suffices. Get rid of EL 2.2 dependencies and add group `org.jboss.el`, artifact `jboss-el` version `2.0.0` to your pom and finally edit the context param value to be `org.jboss.el.ExpressionFactoryImpl`. – BalusC Oct 12 '11 at 17:01
  • Note that you've two context params for it, one for Mojarra JSF impl and other for MyFaces JSF impl. One of them is superfluous. – BalusC Oct 12 '11 at 17:01
0

I think I found the reason of the error. It seems as error was thrown because my function had name "empty". Probably it is a reserved keyword. Everything works after renaming function.

marius
  • 49
  • 1
  • 7