javax.el.PropertyNotFoundException 提交 ui:repeat 时有条件渲染不同子类的属性 [英] javax.el.PropertyNotFoundException when submitting ui:repeat with conditionally rendered properties of different subclasses

查看:20
本文介绍了javax.el.PropertyNotFoundException 提交 ui:repeat 时有条件渲染不同子类的属性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我的 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.
}

以及由 add1add2 方法添加的以下 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:commandLinks 我可以随意添加和删除 Type1 对象.如果我添加 Type2 对象,它们会按预期呈现.但是,当我尝试删除 Type2 对象之一时,我在渲染响应阶段遇到异常(尽管列表中是否有其他元素):

Using the h:commandLinks 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 实例时,我们也遇到了这个问题ImageBlockTextBlockFeedBlock).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屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆