Basic Question
Is this a bug in Mojarra or am I trying to do something that is not supported by the spec?
Overview
I have a composite component "outerComposite" that ui:include
s a facelet with another composite component "innerComposite". I want to pass the client id of the outer composite to the inner composite using <ui:param>
. Depending on how the EL expression looks like, this works or fails on Wildfly 10/11 but works in all cases on Websphere Liberty 17.0.0.1.
Basic Code
outerCompositeUsingPage.xhtml
<h:head />
<h:body>
<h:form id="form">
<app:outerComposite id="outer" value="Test" />
</h:form>
</h:body>
outerComposite.xhtml that includes a facelet with innerComposite:
<cc:implementation>
<c:set var="clientIdViaSet" value="#{cc.clientId}" />
<div id="#{cc.clientId}">
<ui:include src="innerCompositeInclude.xhtml">
<ui:param name="clientIdDirect" value="#{cc.clientId}" /> <-- WORKS
<ui:param name="clientIdViaMethod" value="#{compositeHelperBean.getClientId(cc)}" /> <-- FAILS
<ui:param name="clientIdViaSet" value="#{clientIdViaSet}" /> <-- WORKS
</ui:include>
</div>
innerCompositeInclude.xhtml
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:app="http://xmlns.jcp.org/jsf/composite/components/app" >
<app:innerComposite id="inner"
value1Key="Direct"
value1Value="#{clientIdDirect}"
value2Key="Via Method"
value2Value="#{clientIdViaMethod}"
value3Key="Via c:set"
value3Value="#{clientIdViaSet}"
/>
</ui:composition>
innerComposite.xhtml
<cc:interface>
<cc:attribute name="value1Key" type="java.lang.String" />
<cc:attribute name="value2Key" type="java.lang.String" />
<cc:attribute name="value3Key" type="java.lang.String" />
<cc:attribute name="value1Value" type="java.lang.String" />
<cc:attribute name="value2Value" type="java.lang.String" />
<cc:attribute name="value3Value" type="java.lang.String" />
</cc:interface>
<cc:implementation>
<div id="#{cc.clientId}">
<h:panelGrid columns="2">
<h:outputText value="#{cc.attrs.value1Key}" />
<h:outputText value="#{cc.attrs.value1Value}" />
<h:outputText value="#{cc.attrs.value2Key}" />
<h:outputText value="#{cc.attrs.value2Value}" />
<h:outputText value="#{cc.attrs.value3Key}" />
<h:outputText value="#{cc.attrs.value3Value}" />
</h:panelGrid>
</div>
</cc:implementation>
ComponentHelperBean.java
@ApplicationScoped
@Named
public class CompositeHelperBean {
public String getClientId(UIComponent comp) {
return comp.getClientId();
}
}
Observation
Because #{cc.clientId}
is passed as a parameter to an include file, I expect #{cc.clientId}
to be the value of the outer composite. This indeed works.
Because #{compositeHelperBean(cc)}
just calls cc.getClientId()
, I expect this to yield the same result as the direct EL expression #{cc.clientId}
. This is not the case; instead, it resolves to the client id of the inner composite component.
The result looks as follows in Wildfly 10/11:
Direct form:outer <--- OK
Via Method form:outer:inner <--- WRONG
Via c:set form:outer <--- OK
The result looks as follows in Websphere Liberty Profile 17.0.0.1
Direct form:outer <--- OK
Via Method form:outer <--- OK
Via c:set form:outer <--- OK
Research
I have looked into the code of Mojarra as well as MyFaces. Both have a TagHandlerImpl that create a ValueExpression. In there, they use a regular expression to determine if the EL has something to do with cc
. Both expressions are different which could explain why the behaviour is different.