Make JSF 2.0 execute methods as they are assigned to params, not store reference to method?

夙愿已清 提交于 2020-01-02 18:36:50

问题


Before I begin, my apologies if the wording of this question's title is confusing. I hope my explanation here will make it much clearer.

In a JSF template of my application, I want to include another template and pass a parameter to it that holds the results of an application method. In this parent template, I have:

<ui:repeat var="loopObject" value="#{ApplicationBean.objectList}">
    <ui:include src="anotherTemplate.xhtml">
        <ui:param name="firstParam" 
            value="#{ApplicationBean.initForOtherTemplate(loopObject)}" />
    </ui:include>
</ui:repeat>

It turns out, though, that initForOtherTemplate is not executed at this point and firstParam contains a reference to that method, rather than its return value, as I expected.

Actually, while initForOtherTemplate does have a return value, anotherTemplate.xhtml doesn't need it. However,the method does set up some other objects in ApplicationBean that this new template will use. For example, it sets values for importantInfo and importantInfoToo, which the other template needs.

anotherTemplate.xhtml contains:

<ui:remove>
    <!-- 
    When a parameter contains a method call, the method isn't executed until
    the parameter is referenced.  So we reference the parameter here and ignore
    the results.  There must be a better way.
    -->
</ui:remove>
<h:outputText value="#{firstParam}" style="display: none;" />
<h:outputText value="#{ApplicationBean.importantInfo}" />
<h:outputText value="#{ApplicationBean.importantInfoToo}" />

If this template didn't reference firstParam, then importantInfo and importantInfoToo wouldn't be set or have unpredictable values. This is very disappointing, because I expected initForOtherTemplate to be executed in the parent template, rather than here, which feels messy.

How can I get the assignment of the parameter to actually execute the method immediately rather than store a reference to it?


回答1:


The <ui:repeat> is an UIComponent which runs during view render time. The <ui:include> is a TagHandler (like JSTL) which runs during view build time. So at the moment <ui:include> runs, the <ui:repeat> isn't running and thus the #{loopObject} isn't available in the EL scope at all.

Replacing <ui:repeat> by <c:forEach> should solve this particular problem.

<c:forEach var="loopObject" items="#{ApplicationBean.objectList}">
    <ui:include src="anotherTemplate.xhtml">
        <ui:param name="firstParam" 
            value="#{ApplicationBean.initForOtherTemplate(loopObject)}" />
    </ui:include>
</c:forEach>

See also:

  • JSTL in JSF2 Facelets... makes sense? - Substitute "JSTL" with "ui:include".


来源:https://stackoverflow.com/questions/11802782/make-jsf-2-0-execute-methods-as-they-are-assigned-to-params-not-store-reference

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!