I have got a problem with my JSF-rendering. A given condition in Expression Language will not be executed in the right way.
E.g:
Example 1
<f:param name="cat" value="#{product.category.uri}" rendered="#{product.category.parent.uri == null}" />
<f:param name="cat" value="#{product.category.parent.uri}" rendered="#{product.category.parent.uri != null}" />
Example 2
<c:if test="#{product.category.parent.uri == null}">
<f:param name="cat" value="#{product.category.uri}" />
</c:if>
<c:if test="#{product.category.parent.uri != null}">
<f:param name="cat" value="#{product.category.parent.uri}" />
</c:if>
Problem
In both examples, both my parameters will be added to my surrounding h:outputLink.
I am not sure what other code to add, so if you guys need anything else in order to help me, I’ll be happy to provide it.
Thanks in advance.
Example 3 (on request)
<?xml version='1.0' encoding='UTF-8' ?>
<ui:composition template="./WEB-INF/templates/base.xhtml"
xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:c="http://java.sun.com/jsp/jstl/core">
<ui:define name="content">
<c:choose>
<c:when test="#{webshop.productlist.size() > 0}">
<div id="spacer">
<ui:repeat value="#{webshop.productlist}" var="product">
<div id="block">
<p>
<h:outputLink value="product.xhtml">
#{product.name}
<c:choose>
<c:when test="#{product.category.parent.uri == null}">
<f:param name="cat" value="#{product.category.uri}" rendered="" />
</c:when>
<c:otherwise>
<f:param name="cat" value="#{product.category.parent.uri}" />
</c:otherwise>
</c:choose>
<f:param name="product" value="#{product.uri}" />
</h:outputLink>
</p>
</div>
</ui:repeat>
</div>
</c:when>
<c:otherwise>
(...)
</c:otherwise>
</c:choose>
</ui:define>
</ui:composition>
I have cleaned up this example a bit, but the essence is there.
I have replaced the first examples by a when/otherwise construction, whether my product.category.parent.uri is null or not, it will give me the first result in this case.
Your core problem is that you’re completely confusing view build time tags and view render time tags.
The view build time is that moment when a XHTML file is to be converted to a JSF component tree as available by
FacesContext#getViewRoot(). The view render time is that moment when the JSF component tree is about to produce HTML code, as initiated byUIViewRoot#encodeAll().All JSTL
<c:xxx>tags and all JSF<ui:xxx>tags which do not have arenderedattribute run during view build time. All JSF<ui:xxx>tags which do have arenderedattribute and all JSF<h:xxx>tags run during view render time. So, they don’t run in sync as you’d expect from the coding.Coming back to your concrete problem, this is two-fold:
The
<f:param>does as being a tag handler not support therenderedattribute at all.The
#{product}is in your code definied by<ui:repeat var>, which is a view render time tag, but yet you’re trying to let JSTL<c:xxx>view build time tags depend on that. This will of course not work. The#{product}isnullduring the view build time, simply because the<ui:repeat>hasn’t run at that moment.Your concrete problem can only be solved by using the view build time tag
<c:forEach>instead of the view render time tag<ui:repeat>to iterate over products.See also
Unrelated to the concrete problem, the follwing clumsy block
can be replaced by the following simpler approach with help of the conditional operator in EL:
This way you must be able to keep using the
<ui:repeat>.