我定义了一个JSF复合组件,相关部分如下所示。 更新:改进了使用Kukeltje推荐的JSF 2.2命名空间声明的示例,但问题仍然存在。
/resources/functiontest/functiontest.xhtml
<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html
xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
xmlns:composite="http://xmlns.jcp.org/jsf/composite"
xmlns:fn="http://xmlns.jcp.org/jsp/jstl/functions"
>
<composite:interface>
<composite:attribute name="value" type="java.util.Date"/>
<composite:attribute name="timeZone" type="java.util.TimeZone"/>
<composite:attribute name="update" type="java.lang.String"/>
</composite:interface>
<composite:implementation>
<div id="#{cc.clientId}">
clientId class=#{cc.clientId['class'].name}<br/>
clientId=#{cc.clientId}<br/>
value=#{cc.attrs.value}<br/>
timeZone=#{cc.attrs.timeZone}<br/>
update=#{cc.attrs.update}<br/>
<br/>
WORKS - fn:toLowerCase - #{fn:toLowerCase("hellOOOOOO")}<br/>
WORKS - whoName = #{myBean.user}<br/>
WORKS - fn:toUpperCase1 = #{fn:toUpperCase(myBean.user)}<br/>
WORKS - fn:toUpperCase2 = #{fn:toUpperCase(myBean.toString())}<br/>
WORKS - fn:toUpperCase3 = #{fn:toUpperCase(myBean['class'].simpleName)}<br/>
FAILS - fn:toUpperCase4 = #{fn:toUpperCase(cc.clientId['class'].name)}<br/>
FAILS - fn:toUpperCase5 = #{fn:toUpperCase(cc.clientId)}<br/>
FAILS - fn:toUpperCase6 = #{fn:toUpperCase(cc.attrs.value.toString())}<br/>
FAILS - fn:toUpperCase7 = #{fn:toUpperCase(cc.attrs.update)}<br/>
</div>
</composite:implementation>
</html>
/src/FunctionTestBean.java
import java.util.Date;
import java.util.TimeZone;
import javax.faces.bean.ManagedBean;
@ManagedBean(name="myBean")
public class FunctionTestBean
{
public String getUser() { return "UserX"; }
@Override public String toString() { return "toString method output"; }
private Date now = new Date();
public Date getNow() { return now; }
public TimeZone getTimeZone() { return TimeZone.getDefault(); }
}
/testFunctionPage.xhtml (使用模板 - 从JSF 2.2.5开始不工作)
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html
xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
xmlns:composite="http://xmlns.jcp.org/jsf/composite"
xmlns:fn="http://xmlns.jcp.org/jsp/jstl/functions"
xmlns:fntest="http://xmlns.jcp.org/jsf/composite/functiontest"
>
<ui:composition template="/template/PublicPageTemplate.xhtml">
<ui:define name="body">
Function test:<br/>
<ui:repeat var="loopVar" value='#{"a,b,c".split(",")}'>
LoopVar=#{loopVar}<br/>
<fntest:functiontest id="tst2" value="#{myBean.now}" timeZone="#{myBean.timeZone}" update="UpdateOrDontUpdate"/>
</ui:repeat>
</ui:define>
</ui:composition>
</html>
/template/PublicPageTemplate.xhtml
<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://xmlns.jcp.org/jsf/core"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:c="http://xmlns.jcp.org/jsp/jstl/core"
xmlns:ui="http://xmlns.jcp.org/jsf/facelets">
<h:head>
</h:head>
<h:body>
<div style="padding-left:5%; padding-right:5%;">
<ui:insert name="body">DEFAULT BODY!</ui:insert>
</div>
</h:body>
</html>
/testFunctionPageWithHBody.xhtml (使用h:body - WORKS!)
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html
xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
xmlns:composite="http://xmlns.jcp.org/jsf/composite"
xmlns:fn="http://xmlns.jcp.org/jsp/jstl/functions"
xmlns:fntest="http://xmlns.jcp.org/jsf/composite/functiontest"
>
<h:head>
</h:head>
<h:body>
Function test:<br/>
<ui:repeat var="loopVar" value='#{"a,b,c".split(",")}'>
LoopVar=#{loopVar}<br/>
<fntest:functiontest id="tst2" value="#{myBean.now}" timeZone="#{myBean.timeZone}" update="UpdateOrDontUpdate"/>
</ui:repeat>
</h:body>
</html>
似乎尝试将cc。*的任何部分传递给函数失败,即使它们显然只是打印出值。我已经尝试过JSTL函数和我自己的函数。这是错误:
javax.el.ELException: Function 'fn:toUpperCase' not found
我最好的猜测是使用我没有学到的cc有限制,我希望有人可以阐明它们是什么以及发生了什么。这似乎已在JSF 2.2.5中引入;所有变体都适用于JSF 2.2.1到2.2.4。
这是一些额外的奇怪行为。如果我先加载testFunctionPage.xhtml
,则会失败。如果我加载testFunctionPageWithHBody.xhtml
,它会成功(如预期的那样)。然后,如果我加载testFunctionPage.xhtml
,它现在将成功,并将继续这样做,直到重新启动Web服务器(Tomcat)!
修改: 我运行的环境是Windows 7,Java 1.7.0_80,Tomcat 7.0.68及其版本的EL,JSF Mojarra 2.2.8-14,jstl 1.2,Eclipse Mars.2(4.5.2)。< / p>