简单地说,我的问题是我有一个指定了componentType的复合组件。当我单独在页面上使用复合组件时,它可以正常工作。当我将它嵌套到另一个复合组件(也在ui:repeat中)中时,我会得到一个异常,试图在UINamingContainer中找到我在componentType类上定义的属性--这是错误的类。我发现我可以通过用cc.whatever代替component.parent.parent.parent.whatever来解决这个问题,但是我发现这是一个很严重的问题。我想我是在做一些让JSF困惑的愚蠢的事情,但我不确定它是什么,或者我应该做什么不同的事情。
现在,在令人痛苦的细节中,我有以下复合组件:
<?xml version='1.0' encoding='UTF-8' ?>
<ui:component xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:cc="http://java.sun.com/jsf/composite"
xmlns:ice="http://www.icesoft.com/icefaces/component"
xmlns:f="http://java.sun.com/jsf/core">
<cc:interface componentType="edu.nrao.sss.tools.resrccat.ui.support.LinearVelocityUIComponent">
<cc:attribute name = "value"
class = "edu.nrao.sss.measure.LinearVelocity"
required = "true"
shortDescription = "The LinearVelocity value to show or edit."/>
<cc:attribute name = "separate-units"
type = "boolean"
default = "true"
shortDescription = "If true, provide a drop-box to edit the units separately from the value."/>
</cc:interface>
<cc:implementation>
<ice:inputText id="velocity" value="#{cc.attrs.value}" rendered="#{not cc.attrs['separate-units']}"/>
<ui:fragment rendered="#{cc.attrs['separate-units']}">
<ice:inputText id="velocityDecimal" value="#{cc.velocityDecimal}"/>
<ice:selectOneMenu id="velocityUnits" value="#{cc.velocityUnits}">
<f:selectItems value="#{siFactory.linearVelocityUnits}"/>
</ice:selectOneMenu>
</ui:fragment>
</cc:implementation>
</ui:component>支持部分如下:
@FacesComponent("edu.nrao.sss.tools.resrccat.ui.support.LinearVelocityUIComponent")
public class LinearVelocityUIComponent extends UIInput implements NamingContainer {
@Override public String getFamily() {
return UINamingContainer.COMPONENT_FAMILY;
}
public LinearVelocity getVelocity() {
return (LinearVelocity) getValueExpression("value").getValue(FacesContext.getCurrentInstance().getELContext());
}
public void setVelocity(LinearVelocity newVelocity) {
getValueExpression("value").setValue(FacesContext.getCurrentInstance().getELContext(), newVelocity);
}
public BigDecimal getVelocityDecimal() {
return getVelocity().getValue();
}
public LinearVelocityUnits getVelocityUnits() {
return getVelocity().getUnits();
}
public void setVelocityDecimal(BigDecimal newVelocity) {
setVelocity(new LinearVelocity(newVelocity, getVelocityUnits()));
}
public void setVelocityUnits(LinearVelocityUnits units) {
setVelocity(new LinearVelocity(getVelocityDecimal(), units));
}
}当我单独在页面上使用这个组件时,一切都很好:
<p>Your linear velocity is <rct:linear-velocity value="#{test.velocity}"/></p>当我将它嵌套到另一个复合组件中时,如下所示:
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<ui:component xmlns="http://www.w3.org/1999/xhtml"
xmlns:ice="http://www.icesoft.com/icefaces/component"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:cc="http://java.sun.com/jsf/composite"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:rct="http://java.sun.com/jsf/composite/components/rct">
<cc:interface>
<cc:attribute name="specs" required="true"/>
<cc:attribute name="type" default="line"/>
</cc:interface>
<cc:implementation>
<table class="iceDatTbl">
<thead>
<tr>
...
<th class="iceDatTblColHdr2">Minimum<br/>Span</th>
...
</tr>
</thead>
<tbody>
<ui:repeat var="spec" value="#{cc.attrs.specs}" varStatus="stat">
<tr class="#{stat.even ? 'iceDatTblRow1' : 'iceDatTblRow2'}">
...
<td class="iceDatTblCol2">
Req: <rct:linear-velocity value="#{spec.minimumSpan}"/><br/>
Sug: #{spec.suggestedMinimumSpan}
</td>
...
</tr>
</ui:repeat>
</tbody>
</table>
</cc:implementation>
</ui:component>我明白这一例外:
Nov 19, 2012 4:10:37 PM org.icefaces.impl.application.ExtendedExceptionHandler handle
WARNING: queued exception
javax.el.PropertyNotFoundException: /resources/components/rct/linear-velocity.xhtml @20,113 value="#{cc.velocityDecimal}": Property 'velocityDecimal' not found on type javax.faces.component.UINamingContainer
at com.sun.faces.facelets.el.TagValueExpression.getValue(TagValueExpression.java:111)
at javax.faces.component.ComponentStateHelper.eval(ComponentStateHelper.java:194)
at javax.faces.component.ComponentStateHelper.eval(ComponentStateHelper.java:182)
at javax.faces.component.UIOutput.getValue(UIOutput.java:169)
at com.sun.faces.facelets.component.UIRepeat$SavedState.populate(UIRepeat.java:823)
at com.sun.faces.facelets.component.UIRepeat.saveChildState(UIRepeat.java:369)
at com.sun.faces.facelets.component.UIRepeat.saveChildState(UIRepeat.java:375)
at com.sun.faces.facelets.component.UIRepeat.saveChildState(UIRepeat.java:375)
at com.sun.faces.facelets.component.UIRepeat.saveChildState(UIRepeat.java:355)
at com.sun.faces.facelets.component.UIRepeat.setIndex(UIRepeat.java:440)
at com.sun.faces.facelets.component.UIRepeat.visitTree(UIRepeat.java:613)
at javax.faces.component.UIComponent.visitTree(UIComponent.java:1601)
at javax.faces.component.UIComponent.visitTree(UIComponent.java:1601)
at javax.faces.component.UINamingContainer.visitTree(UINamingContainer.java:163)
at javax.faces.component.UIComponent.visitTree(UIComponent.java:1601)
at org.icefaces.impl.component.UISeriesBase.visitRows(UISeriesBase.java:1174)
at org.icefaces.impl.component.UISeriesBase.visitTree(UISeriesBase.java:1065)
at javax.faces.component.UIComponent.visitTree(UIComponent.java:1601)
at javax.faces.component.UIComponent.visitTree(UIComponent.java:1601)
at javax.faces.component.UIComponent.visitTree(UIComponent.java:1601)
at javax.faces.component.UIForm.visitTree(UIForm.java:344)
at javax.faces.component.UIComponent.visitTree(UIComponent.java:1601)
at javax.faces.component.UIComponent.visitTree(UIComponent.java:1601)
at org.icefaces.impl.event.RestoreResourceDependencies.processEvent(RestoreResourceDependencies.java:24)
at javax.faces.event.SystemEvent.processListener(SystemEvent.java:106)
at com.sun.faces.application.ApplicationImpl.processListeners(ApplicationImpl.java:2168)
at com.sun.faces.application.ApplicationImpl.invokeListenersFor(ApplicationImpl.java:2144)
at com.sun.faces.application.ApplicationImpl.publishEvent(ApplicationImpl.java:302)
at com.sun.faces.application.ApplicationImpl.publishEvent(ApplicationImpl.java:246)
at javax.faces.component.UIComponentBase.encodeBegin(UIComponentBase.java:812)
at javax.faces.component.UIViewRoot.encodeBegin(UIViewRoot.java:962)
at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1755)
at com.sun.faces.application.view.FaceletViewHandlingStrategy.renderView(FaceletViewHandlingStrategy.java:402)
at com.sun.faces.application.view.MultiViewHandler.renderView(MultiViewHandler.java:131)
at com.ocpsoft.pretty.faces.application.PrettyViewHandler.renderView(PrettyViewHandler.java:163)
at com.sun.faces.lifecycle.RenderResponsePhase.execute(RenderResponsePhase.java:121)
at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
at com.sun.faces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:139)
at javax.faces.webapp.FacesServlet.service(FacesServlet.java:594)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at com.ocpsoft.pretty.PrettyFilter.doFilter(PrettyFilter.java:145)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:749)
at org.apache.catalina.core.ApplicationDispatcher.processRequest(ApplicationDispatcher.java:487)
at org.apache.catalina.core.ApplicationDispatcher.doForward(ApplicationDispatcher.java:412)
at org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:339)
at com.ocpsoft.pretty.PrettyFilter.doFilter(PrettyFilter.java:137)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at edu.nrao.sss.webapp.LookupUserFilter.doFilter(LookupUserFilter.java:57)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.jasig.cas.client.util.HttpServletRequestWrapperFilter.doFilter(HttpServletRequestWrapperFilter.java:50)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.jasig.cas.client.validation.AbstractTicketValidationFilter.doFilter(AbstractTicketValidationFilter.java:167)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.jasig.cas.client.authentication.AuthenticationFilter.doFilter(AuthenticationFilter.java:111)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:168)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:99)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:929)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:407)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1002)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:585)
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:310)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
at java.lang.Thread.run(Thread.java:722)我所能做的使它能够工作的替代方法是:
<ui:fragment rendered="#{cc.attrs['separate-units']}">
<ice:inputText id="velocityDecimal" value="#{component.parent.parent.parent.velocityDecimal}"/>
<ice:selectOneMenu id="velocityUnits" value="#{component.parent.parent.parent.velocityUnits}">
<f:selectItems value="#{siFactory.linearVelocityUnits}"/>
</ice:selectOneMenu>
</ui:fragment>这感觉很不对,从历史上看,每当我试图让JSF在几个月后通过这样的黑客攻击时,它就会毁了我的生活。我将非常感谢任何帮助!我喜欢JSF,我非常喜欢使用复合组件来构造东西,但是我真的需要能够嵌套复合组件。
编辑:我已经发现,在Glassfish中,组件根本不会孤立地呈现。它会产生嵌套在另一个组件中的相同错误(UINamingContainer不具有LinearVelocityUIComponent具有的这个属性)。
发布于 2012-11-20 02:47:57
我能够在Tomcat7.0.30上使用mojarra2.1.14(并使用那些<h:xxx>组件的标准JSF ICEfaces等效项)来重现您的问题。这是由于Mojarra中嵌套<ui:repeat>的状态保存机制中断所致。老实说,我不确定“嵌套ui:重复”上哪个Mojarra bug报告涵盖了您的特定问题,有太多的报告,而您的特定的报告对我来说是新的。
在MyFaces 2.1.9中,完全相同的代码对我来说很好。当我至少用<h:dataTable>或<p:dataList>替换外部<h:dataTable>时,它也工作得很好。
所以你有两个选择来解决这个问题:
<ui:repeat>替换为一个完全合适的UIData实现,例如<h:dataTable>或<p:dataList>或任何我无法从头上分辨出来的ICEfaces等效物。这可能不会生成您想要的HTML,但是它可以工作,使用CSS您可以做很多事情。发布于 2019-05-16 14:04:57
如果它对任何人都有帮助,我就解决了一个类似的问题,我在另一个复合组件中嵌套了一个复合组件(cc)。一个实例是正常的,一个页面中的两个实例是有问题的,试图查找属于嵌套cc的类字段,但是在主机cc中查找它们。问题是,我对两个ccs都使用了相同的名称变量。所以,EL表达式"cc.attrs.bean“让JSF感到困惑.我通过在CCs中保留不同的参数名来解决这个问题。我花了一段时间才发现这个。
https://stackoverflow.com/questions/13457989
复制相似问题