javax.el.PropertyNotFoundException 提交 ui:repeat 时有条件渲染不同子类的属性 [英] javax.el.PropertyNotFoundException when submitting ui:repeat with conditionally rendered properties of different subclasses
问题描述
在我的 backing-bean 中,我有一组不同子类的对象共享一个公共接口.在视图内部,一个 ui:repeat
迭代这个集合.在这个循环中,必须根据接口的具体实现来呈现不同的属性.
In my backing-bean I have a collection of objects of different subclasses sharing a common interface. Inside the view, an ui:repeat
iterates over this collection. Inside this loop, different properties have to be rendered depending on the concrete implementation of the interface.
我将问题简化为以下支持 bean:
I reduced the problem to the following backing bean:
@Named
@SessionScoped
public class DummyBean implements Serializable {
private List<Type> objects = new ArrayList<Type>();
public void add1() {
objects.add(new Type1());
}
public void add2() {
objects.add(new Type2());
}
public void remove(Type o) {
objects.remove(o);
}
// Getter.
}
以及由 add1
和 add2
方法添加的以下 Type
实现.它们有一些共同的属性,但也可能有不同的属性,例如以下示例中的 getType1OnlyMethod()
:
And the following Type
implementations which are added by the methods add1
and add2
. They have some common properties, but they may also have different ones, such as getType1OnlyMethod()
in below example:
public class Type1 implements Type {
@Override
public String getType() { return "1"; }
public List<String> getType1OnlyMethod() {
return Arrays.asList("only1", "only2");
}
// ...
}
public class Type2 implements Type {
@Override
public String getType() { return "2"; }
// ...
}
在视图中,我想遍历存储在 DummyBean
中的所有对象并显示它们的内容.根据对象的具体类型,可以使用 rendered
属性调用仅在类 Type1
中实现的方法以进行条件渲染:
In the view I want to iterate over all objects which are stored in the DummyBean
and display their contents. Depending on the concrete type of the object, the method which is only implemented in the class Type1
may be called using the rendered
-attribute for conditional rendering:
<h:form id="dummyForm">
<ui:repeat value="#{dummyBean.objects}" var="_obj" >
<h:outputText value="Type of the Object is #{_obj.type}." />
<h:panelGroup rendered="#{_obj.type eq '1'}">
<ui:repeat value="#{_obj.type1OnlyMethod}" var="_oneOnlyObject" varStatus="_status" >
<h:outputText value="#{_oneOnlyObject}" />
</ui:repeat>
</h:panelGroup>
<h:commandLink value="remove" action="#{dummyBean.remove(_obj)}">
<f:ajax render="dummyForm" />
</h:commandLink>
<br/>
</ui:repeat>
<h:commandLink value="add1" action="#{dummyBean.add1}">
<f:ajax render="dummyForm" />
</h:commandLink>
<br/>
<h:commandLink value="add2" action="#{dummyBean.add2}">
<f:ajax render="dummyForm" />
</h:commandLink>
</h:form>
使用页面上的 h:commandLink
s 我可以随意添加和删除 Type1
对象.如果我添加 Type2
对象,它们会按预期呈现.但是,当我尝试删除 Type2
对象之一时,我在渲染响应阶段遇到异常(尽管列表中是否有其他元素):
Using the h:commandLink
s on the page I can add and remove Type1
objects at will. If I add Type2
objects, they are rendered as expected. But when I try to remove one of the Type2
objects, I get an exception in the render-response phase (nevertheless if there are other elements in the list or not):
2014-03-24 15:42:46,754 SEVERE [javax.enterprise.resource.webcontainer.jsf.application] (default task-11) Error Rendering View[/transition/beginTestSite.xhtml]:
javax.el.PropertyNotFoundException: /transition/beginTestSite.xhtml @23,96 value="#{_obj.type1OnlyMethod}": The class 'at.co.xss.Type2' does not have the property 'type1OnlyMethod'.
at com.sun.faces.facelets.el.TagValueExpression.getValue(TagValueExpression.java:111) [jsf-impl-2.2.5-jbossorg-3.jar:]
at com.sun.faces.facelets.component.UIRepeat.getValue(UIRepeat.java:279) [jsf-impl-2.2.5-jbossorg-3.jar:]
at com.sun.faces.facelets.component.UIRepeat.getDataModel(UIRepeat.java:255) [jsf-impl-2.2.5-jbossorg-3.jar:]
at com.sun.faces.facelets.component.UIRepeat.setIndex(UIRepeat.java:523) [jsf-impl-2.2.5-jbossorg-3.jar:]
at com.sun.faces.facelets.component.UIRepeat.doVisitChildren(UIRepeat.java:790) [jsf-impl-2.2.5-jbossorg-3.jar:]
at com.sun.faces.facelets.component.UIRepeat.visitTree(UIRepeat.java:748) [jsf-impl-2.2.5-jbossorg-3.jar:]
at javax.faces.component.UIComponent.visitTree(UIComponent.java:1700) [jboss-jsf-api_2.2_spec-2.2.5.jar:2.2.5]
at com.sun.faces.facelets.component.UIRepeat.visitTree(UIRepeat.java:754) [jsf-impl-2.2.5-jbossorg-3.jar:]
at javax.faces.component.UIComponent.visitTree(UIComponent.java:1700) [jboss-jsf-api_2.2_spec-2.2.5.jar:2.2.5]
at javax.faces.component.UIForm.visitTree(UIForm.java:371) [jboss-jsf-api_2.2_spec-2.2.5.jar:2.2.5]
at javax.faces.component.UIComponent.visitTree(UIComponent.java:1700) [jboss-jsf-api_2.2_spec-2.2.5.jar:2.2.5]
at javax.faces.component.UIComponent.visitTree(UIComponent.java:1700) [jboss-jsf-api_2.2_spec-2.2.5.jar:2.2.5]
at com.sun.faces.application.view.FaceletPartialStateManagementStrategy.saveView(FaceletPartialStateManagementStrategy.java:472) [jsf-impl-2.2.5-jbossorg-3.jar:]
at com.sun.faces.application.StateManagerImpl.saveView(StateManagerImpl.java:89) [jsf-impl-2.2.5-jbossorg-3.jar:]
at javax.faces.application.StateManager.getViewState(StateManager.java:593) [jboss-jsf-api_2.2_spec-2.2.5.jar:2.2.5]
at com.sun.faces.context.PartialViewContextImpl.renderState(PartialViewContextImpl.java:486) [jsf-impl-2.2.5-jbossorg-3.jar:]
at com.sun.faces.context.PartialViewContextImpl.processPartial(PartialViewContextImpl.java:328) [jsf-impl-2.2.5-jbossorg-3.jar:]
at javax.faces.context.PartialViewContextWrapper.processPartial(PartialViewContextWrapper.java:219) [jboss-jsf-api_2.2_spec-2.2.5.jar:2.2.5]
at org.primefaces.context.PrimePartialViewContext.processPartial(PrimePartialViewContext.java:57) [primefaces-4.0.jar:4.0]
at org.richfaces.context.ExtendedPartialViewContextImpl.processPartial(ExtendedPartialViewContextImpl.java:218) [richfaces-core-impl-4.3.5.Final.jar:4.3.5.Final]
at javax.faces.component.UIViewRoot.encodeChildren(UIViewRoot.java:1004) [jboss-jsf-api_2.2_spec-2.2.5.jar:2.2.5]
at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1856) [jboss-jsf-api_2.2_spec-2.2.5.jar:2.2.5]
at com.sun.faces.application.view.FaceletViewHandlingStrategy.renderView(FaceletViewHandlingStrategy.java:435) [jsf-impl-2.2.5-jbossorg-3.jar:]
at com.sun.faces.application.view.MultiViewHandler.renderView(MultiViewHandler.java:133) [jsf-impl-2.2.5-jbossorg-3.jar:]
at javax.faces.application.ViewHandlerWrapper.renderView(ViewHandlerWrapper.java:337) [jboss-jsf-api_2.2_spec-2.2.5.jar:2.2.5]
at javax.faces.application.ViewHandlerWrapper.renderView(ViewHandlerWrapper.java:337) [jboss-jsf-api_2.2_spec-2.2.5.jar:2.2.5]
at javax.faces.application.ViewHandlerWrapper.renderView(ViewHandlerWrapper.java:337) [jboss-jsf-api_2.2_spec-2.2.5.jar:2.2.5]
at javax.faces.application.ViewHandlerWrapper.renderView(ViewHandlerWrapper.java:337) [jboss-jsf-api_2.2_spec-2.2.5.jar:2.2.5]
at com.sun.faces.lifecycle.RenderResponsePhase.execute(RenderResponsePhase.java:120) [jsf-impl-2.2.5-jbossorg-3.jar:]
at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101) [jsf-impl-2.2.5-jbossorg-3.jar:]
at com.sun.faces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:219) [jsf-impl-2.2.5-jbossorg-3.jar:]
at javax.faces.webapp.FacesServlet.service(FacesServlet.java:647) [jboss-jsf-api_2.2_spec-2.2.5.jar:2.2.5]
at io.undertow.servlet.handlers.ServletHandler.handleRequest(ServletHandler.java:85) [undertow-servlet-1.0.0.Final.jar:1.0.0.Final]
at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:130) [undertow-servlet-1.0.0.Final.jar:1.0.0.Final]
at org.apache.shiro.web.servlet.AbstractShiroFilter.executeChain(AbstractShiroFilter.java:449) [shiro-web-1.2.2.jar:1.2.2]
at org.apache.shiro.web.servlet.AbstractShiroFilter$1.call(AbstractShiroFilter.java:365) [shiro-web-1.2.2.jar:1.2.2]
at org.apache.shiro.subject.support.SubjectCallable.doCall(SubjectCallable.java:90) [shiro-core-1.2.2.jar:1.2.2]
at org.apache.shiro.subject.support.SubjectCallable.call(SubjectCallable.java:83) [shiro-core-1.2.2.jar:1.2.2]
at org.apache.shiro.subject.support.DelegatingSubject.execute(DelegatingSubject.java:383) [shiro-core-1.2.2.jar:1.2.2]
at org.apache.shiro.web.servlet.AbstractShiroFilter.doFilterInternal(AbstractShiroFilter.java:362) [shiro-web-1.2.2.jar:1.2.2]
at org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:125) [shiro-web-1.2.2.jar:1.2.2]
at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:56) [undertow-servlet-1.0.0.Final.jar:1.0.0.Final]
at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:132) [undertow-servlet-1.0.0.Final.jar:1.0.0.Final]
at io.undertow.servlet.handlers.FilterHandler.handleRequest(FilterHandler.java:85) [undertow-servlet-1.0.0.Final.jar:1.0.0.Final]
at io.undertow.servlet.handlers.security.ServletSecurityRoleHandler.handleRequest(ServletSecurityRoleHandler.java:61) [undertow-servlet-1.0.0.Final.jar:1.0.0.Final]
at io.undertow.servlet.handlers.ServletDispatchingHandler.handleRequest(ServletDispatchingHandler.java:36) [undertow-servlet-1.0.0.Final.jar:1.0.0.Final]
at org.wildfly.extension.undertow.security.SecurityContextAssociationHandler.handleRequest(SecurityContextAssociationHandler.java:78)
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:25) [undertow-core-1.0.0.Final.jar:1.0.0.Final]
at io.undertow.servlet.handlers.security.SSLInformationAssociationHandler.handleRequest(SSLInformationAssociationHandler.java:113) [undertow-servlet-1.0.0.Final.jar:1.0.0.Final]
at io.undertow.security.handlers.AuthenticationCallHandler.handleRequest(AuthenticationCallHandler.java:52) [undertow-core-1.0.0.Final.jar:1.0.0.Final]
at io.undertow.security.handlers.AbstractConfidentialityHandler.handleRequest(AbstractConfidentialityHandler.java:45) [undertow-core-1.0.0.Final.jar:1.0.0.Final]
at io.undertow.servlet.handlers.security.ServletConfidentialityConstraintHandler.handleRequest(ServletConfidentialityConstraintHandler.java:61) [undertow-servlet-1.0.0.Final.jar:1.0.0.Final]
at io.undertow.servlet.handlers.security.CachedAuthenticatedSessionHandler.handleRequest(CachedAuthenticatedSessionHandler.java:70) [undertow-servlet-1.0.0.Final.jar:1.0.0.Final]
at io.undertow.security.handlers.SecurityInitialHandler.handleRequest(SecurityInitialHandler.java:76) [undertow-core-1.0.0.Final.jar:1.0.0.Final]
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:25) [undertow-core-1.0.0.Final.jar:1.0.0.Final]
at org.wildfly.extension.undertow.security.jacc.JACCContextIdHandler.handleRequest(JACCContextIdHandler.java:61)
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:25) [undertow-core-1.0.0.Final.jar:1.0.0.Final]
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:25) [undertow-core-1.0.0.Final.jar:1.0.0.Final]
at io.undertow.servlet.handlers.ServletInitialHandler.handleFirstRequest(ServletInitialHandler.java:240) [undertow-servlet-1.0.0.Final.jar:1.0.0.Final]
at io.undertow.servlet.handlers.ServletInitialHandler.dispatchRequest(ServletInitialHandler.java:227) [undertow-servlet-1.0.0.Final.jar:1.0.0.Final]
at io.undertow.servlet.handlers.ServletInitialHandler.access$000(ServletInitialHandler.java:73) [undertow-servlet-1.0.0.Final.jar:1.0.0.Final]
at io.undertow.servlet.handlers.ServletInitialHandler$1.handleRequest(ServletInitialHandler.java:146) [undertow-servlet-1.0.0.Final.jar:1.0.0.Final]
at io.undertow.server.Connectors.executeRootHandler(Connectors.java:168) [undertow-core-1.0.0.Final.jar:1.0.0.Final]
at io.undertow.server.HttpServerExchange$1.run(HttpServerExchange.java:687) [undertow-core-1.0.0.Final.jar:1.0.0.Final]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) [rt.jar:1.7.0_45]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) [rt.jar:1.7.0_45]
at java.lang.Thread.run(Thread.java:744) [rt.jar:1.7.0_45]
Caused by: javax.el.PropertyNotFoundException: The class 'at.co.xss.Type2' does not have the property 'type1OnlyMethod'.
at javax.el.BeanELResolver.getBeanProperty(BeanELResolver.java:730) [javax.el-3.0.0.jar:3.0.0]
at javax.el.BeanELResolver.getValue(BeanELResolver.java:351) [javax.el-3.0.0.jar:3.0.0]
at com.sun.faces.el.DemuxCompositeELResolver._getValue(DemuxCompositeELResolver.java:176) [jsf-impl-2.2.5-jbossorg-3.jar:]
at com.sun.faces.el.DemuxCompositeELResolver.getValue(DemuxCompositeELResolver.java:203) [jsf-impl-2.2.5-jbossorg-3.jar:]
at com.sun.el.parser.AstValue.getValue(AstValue.java:140) [javax.el-3.0.0.jar:3.0.0]
at com.sun.el.parser.AstValue.getValue(AstValue.java:204) [javax.el-3.0.0.jar:3.0.0]
at com.sun.el.ValueExpressionImpl.getValue(ValueExpressionImpl.java:226) [javax.el-3.0.0.jar:3.0.0]
at org.jboss.weld.el.WeldValueExpression.getValue(WeldValueExpression.java:50) [weld-core-impl-2.1.2.Final.jar:2014-01-09 09:23]
at org.jboss.weld.el.WeldValueExpression.getValue(WeldValueExpression.java:50) [weld-core-impl-2.1.2.Final.jar:2014-01-09 09:23]
at com.sun.faces.facelets.el.TagValueExpression.getValue(TagValueExpression.java:109) [jsf-impl-2.2.5-jbossorg-3.jar:]
... 66 more
似乎在渲染响应阶段,嵌套的 ui:repeat
是为当前删除的 Type2
对象执行"的.
It seems that in the render-response phase the nested ui:repeat
is "executed" for the currently deleted Type2
object.
如果我删除第二个(嵌套的)ui:repeat
并添加一些普通的 h:outputText
来访问仅在 Type1中可用的属性代码>,当我添加或删除元素时,一切都会再次正常工作:
If I remove the second (nested) ui:repeat
and add some plain h:outputText
to access the property which is only available in Type1
, everything works again without exception when I add or remove elements:
<h:form id="dummyForm">
<ui:repeat value="#{dummyBean.objects}" var="_obj" >
<!-- ... -->
<h:panelGroup rendered="#{_obj.type eq '1'}">
<h:outputText value="#{_obj.type1OnlyMethod.size()}" />
</h:panelGroup>
<!-- ... -->
</h:form>
有人对这个话题有任何想法吗?
Does anyone have any idea on this topic?
(在JEE7应用服务器上运行(Wildfly 8.0.0.Final))
(Running on JEE7 application server (Wildfly 8.0.0.Final))
推荐答案
这是由 Mojarra 的 <ui:repeat>
状态管理中的错误引起的,该错误已根据 issue 3215 正如我的同事 Arjan Tijms 所报告的那样.在 zeef.com (LinkBlock) 上迭代不同的
、Block
实例时,我们也遇到了这个问题ImageBlock
、TextBlock
和 FeedBlock
).Mojarra 2.2.7 和JSF 2.0/2.1 向后移植到 Mojarra 2.1.29 根据 issue 3221.所以至少升级到那个版本(或者只是根据 Mojarra homepage 提供的最新版本)应该可以做到.
This is caused by a bug in state management of Mojarra's <ui:repeat>
which is fixed as per issue 3215 as reported by my fellow Arjan Tijms. We also faced this problem when iterating over different Block
instances at zeef.com (LinkBlock
, ImageBlock
, TextBlock
and FeedBlock
). The fix is available in Mojarra 2.2.7 and for JSF 2.0/2.1 backported to Mojarra 2.1.29 as per issue 3221. So upgrading to at least that version (or just the latest available as per Mojarra homepage) should do it.
否则,最好的办法是将 <ui:repeat>
替换为 <c:forEach>
.
Otherwise, your best bet is to replace <ui:repeat>
by <c:forEach>
.
这篇关于javax.el.PropertyNotFoundException 提交 ui:repeat 时有条件渲染不同子类的属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!