Tony
Tony

Reputation: 2406

EL-Conditional operator ?: in composite component unexpected behavior

Wildfly 8, Jsf 2.2

If conditional operator ? : in composite component is used with a list in a c:foreach loop, its behavior is not correct.

Output of example file is

eng germ ital

and not as expected

eng eng germ germ ital ital

If the composite component is rewritten as ui:include or taglib then the expected result comes.

File (test.xhtml):

<html 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:fn="http://java.sun.com/jsp/jstl/functions" xmlns:my="http://java.sun.com/jsf/composite/myComp"
    xmlns:c="http://java.sun.com/jsp/jstl/core">

<h:body>
   <my:testConditionalOperator languagesList="#{['eng', 'germ', 'ital']}"></my:testConditionalOperator>
</h:body>
</html>

Composite component (testConditionalOperator.xhtml):

<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml" xmlns:a="http://xmlns.jcp.org/jsf/passthrough"
    xmlns:of="http://omnifaces.org/functions" xmlns:f="http://xmlns.jcp.org/jsf/core"
    xmlns:c="http://java.sun.com/jsp/jstl/core" xmlns:o="http://omnifaces.org/ui" xmlns:h="http://xmlns.jcp.org/jsf/html"
    xmlns:ui="http://xmlns.jcp.org/jsf/facelets" xmlns:fn="http://xmlns.jcp.org/jsp/jstl/functions"
    xmlns:cc="http://java.sun.com/jsf/composite">
    <cc:interface>
        <cc:attribute name="languagesList"></cc:attribute>
    </cc:interface>
    <cc:implementation>
        <c:forEach var="language" items="#{cc.attrs.languagesList}" >
            #{fn:length(cc.attrs.languagesList) gt 1 ?  language : "a"}
            <c:if test="#{fn:length(cc.attrs.languagesList) gt 1}">
                #{language}
            </c:if>
        </c:forEach>
    </cc:implementation>
</html>

Upvotes: 2

Views: 451

Answers (1)

BalusC
BalusC

Reputation: 1108642

This appears to be a Mojarra bug which doesn't manifest in MyFaces.

The work around is, set the size in end attribute and make use of varStatus to obtain it.

<cc:implementation>
    <c:forEach var="language" items="#{cc.attrs.languagesList}" end="#{cc.attrs.languagesList.size()}" varStatus="loop">
        #{loop.end gt 1 ?  language : "a"}
        <c:if test="#{loop.end gt 1}">
            #{language}
        </c:if>
    </c:forEach>
</cc:implementation>

Note the EL 2.2 ability to just use size() instead of fn:length()

Upvotes: 2

Related Questions