简体   繁体   English

使用bean的方法结果时的PropertyNotFoundException <h:selectBooleanCheckbox/>

[英]PropertyNotFoundException when using bean's method's result for <h:selectBooleanCheckbox/>

Environment : 环境

  • PrimeFaces 5.1 PrimeFaces 5.1
  • Mojarra 2.2.2 Mojarra 2.2.2
  • Spring 4.0.2 春季4.0.2

Current Code : 当前代码

I have the following XHTML page: 我有以下XHTML页面:

<ui:composition xmlns="http://www.w3.org/1999/xhtml"
                xmlns:ui="http://java.sun.com/jsf/facelets"
                xmlns:h="http://java.sun.com/jsf/html"
                xmlns:f="http://java.sun.com/jsf/core"
                xmlns:p="http://primefaces.org/ui"
                xmlns:c="http://java.sun.com/jsp/jstl/core"
                template="/WEB-INF/pages/main/admin.xhtml">

    <ui:define name="contentBody">
        <p:dataTable widgetVar="weekdayTable"
                     value="#{weekdayList.countries}"
                     var="ctr"
                     styleClass="weekdaysManagementDatatable">

            <p:column width="100"
                      sortBy="#{ctr.desc}"
                      headerText="#{msg['page.admin.weekday.list.country']}">
                <h:outputText value="#{ctr.desc}" />
            </p:column>

            <c:forEach items="#{weekdayList.weekdays}" var="day">
                <c:set var="open" value="#{weekdayList.checkOpen(ctr.id, day.date)}"/>
                <p:column width="20" headerText="#{utils.dateToDayWeek(day.date)}">
                    <h:selectBooleanCheckbox value="#{open}">
                        <p:ajax listener="#{weekdayList.handleDay(ctr.id, day.id)}" />
                    </h:selectBooleanCheckbox>
                </p:column>
            </c:forEach>
        </p:dataTable>
    </ui:define>
</ui:composition>

The associated bean is the following : 关联的bean如下:

@Named("weekdayList")
@Scope("session")
public class AdminWeekdayListController implements Serializable {

    ...

    public boolean checkOpen(String ctrId, Date date) {
        Country ctr = countryDao.getById(ctrId);
        List<WeekDay> list = weekdaysMap.get(ctr);

        if (list == null) {
            return true;
        }

        WeekDay day = new WeekDay();
        day.setDate(date);

        for (WeekDay wd : list) {
            if (wd.compareTo(day) == 0) {
                return wd.isOpen();
            }
        }
        return true;
    }
}

I have another bean which maintains the current page to display and the whole the application is made with AJAX. 我还有另一个bean,用于维护要显示的当前页面,整个应用程序都是使用AJAX编写的。 The user is always on the same page and the content is dynamically loaded. 用户总是在同一页面上,并且内容是动态加载的。

The problem : 问题

When I reload (F5) the page, all seems to work correctly. 当我重新加载(F5)页面时,所有内容似乎都能正常工作。 But, if I go trought the normal navigation (AJAX loading), I have got a PropertyNotFoundException ... 但是,如果我进行常规导航(加载AJAX),则会收到PropertyNotFoundException ...

Here is the stack trace: 这是堆栈跟踪:

SEVERE: javax.faces.component.UpdateModelException: javax.el.PropertyNotFoundException: /WEB-INF/pages/main/admin/weekdayList.xhtml @32,47 value="#{open}": /WEB-INF/pages/main/admin/weekdayList.xhtml @29,74 value="#{weekdayList.checkOpen(ctr.id, day.date)}": Property 'checkOpen' not found on type stomac.web.controller.AdminWeekdayListController
    at javax.faces.component.UIInput.updateModel(UIInput.java:867)
    at javax.faces.component.UIInput.processUpdates(UIInput.java:749)
    at org.primefaces.component.api.UIData.process(UIData.java:342)
    at org.primefaces.component.api.UIData.processChildren(UIData.java:323)
    at org.primefaces.component.api.UIData.processPhase(UIData.java:285)
    at org.primefaces.component.api.UIData.processUpdates(UIData.java:271)
    at org.primefaces.component.datatable.DataTable.processUpdates(DataTable.java:651)
    at javax.faces.component.UIComponentBase.processUpdates(UIComponentBase.java:1286)
    at javax.faces.component.UIComponentBase.processUpdates(UIComponentBase.java:1286)
    at javax.faces.component.UIForm.processUpdates(UIForm.java:281)
    at javax.faces.component.UIComponentBase.processUpdates(UIComponentBase.java:1286)
    at javax.faces.component.UIComponentBase.processUpdates(UIComponentBase.java:1286)
    at javax.faces.component.UIViewRoot.processUpdates(UIViewRoot.java:1254)
    at com.sun.faces.lifecycle.UpdateModelValuesPhase.execute(UpdateModelValuesPhase.java:78)
    at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
    at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:198)
    at javax.faces.webapp.FacesServlet.service(FacesServlet.java:646)
    at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:769)
    at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:585)
    at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:143)
    at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:577)
    at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:223)
    at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1125)
    at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:515)
    at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:185)
    at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1059)
    at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141)
    at org.eclipse.jetty.server.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:215)
    at org.eclipse.jetty.server.handler.HandlerCollection.handle(HandlerCollection.java:110)
    at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:97)
    at org.eclipse.jetty.server.Server.handle(Server.java:497)
    at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:311)
    at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:248)
    at org.eclipse.jetty.io.AbstractConnection$2.run(AbstractConnection.java:540)
    at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:610)
    at org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:539)
    at java.lang.Thread.run(Thread.java:745)
Caused by: javax.el.PropertyNotFoundException: /WEB-INF/pages/main/admin/weekdayList.xhtml @32,47 value="#{open}": /WEB-INF/pages/main/admin/weekdayList.xhtml @29,74 value="#{weekdayList.checkOpen(ctr.id, day.date)}": Property 'checkOpen' not found on type stomac.web.controller.AdminWeekdayListController
    at com.sun.faces.facelets.el.TagValueExpression.setValue(TagValueExpression.java:133)
    at javax.faces.component.UIInput.updateModel(UIInput.java:832)
    ... 36 more
Caused by: javax.el.PropertyNotFoundException: /WEB-INF/pages/main/admin/weekdayList.xhtml @29,74 value="#{weekdayList.checkOpen(ctr.id, day.date)}": Property 'checkOpen' not found on type stomac.web.controller.AdminWeekdayListController
    at com.sun.faces.facelets.el.TagValueExpression.setValue(TagValueExpression.java:133)
    at org.apache.el.parser.AstIdentifier.setValue(AstIdentifier.java:129)
    at org.apache.el.ValueExpressionImpl.setValue(ValueExpressionImpl.java:260)
    at com.sun.faces.facelets.el.TagValueExpression.setValue(TagValueExpression.java:131)
    ... 37 more
Caused by: javax.el.PropertyNotFoundException: Property 'checkOpen' not found on type stomac.web.controller.AdminWeekdayListController
    at javax.el.BeanELResolver$BeanProperties.get(BeanELResolver.java:245)
    at javax.el.BeanELResolver$BeanProperties.access$300(BeanELResolver.java:222)
    at javax.el.BeanELResolver.property(BeanELResolver.java:332)
    at javax.el.BeanELResolver.getType(BeanELResolver.java:82)
    at com.sun.faces.el.DemuxCompositeELResolver._getType(DemuxCompositeELResolver.java:215)
    at com.sun.faces.el.DemuxCompositeELResolver.getType(DemuxCompositeELResolver.java:242)
    at org.apache.el.parser.AstValue.setValue(AstValue.java:199)
    at org.apache.el.ValueExpressionImpl.setValue(ValueExpressionImpl.java:260)
    at com.sun.faces.facelets.el.TagValueExpression.setValue(TagValueExpression.java:131)
    ... 40 more

But what make me think that the problem does not come from my bean is, if I remove the #{open} from the value of the <h:selectBooleanCheckbox/> it perfectly works (except that the checkboxes are not checked the way I want): 但是,让我认为问题并非出自我的bean的原因是,如果我从<h:selectBooleanCheckbox/>的值中删除#{open} ,它就可以正常工作(除非未按照我想要的方式检查复选框):

<c:forEach items="#{weekdayList.weekdays}" var="day">
    <c:set var="open" value="#{weekdayList.checkOpen(ctr.id, day.date)}"/>
    <p:column width="20" headerText="#{utils.dateToDayWeek(day.date)}">
        #{open}
        <h:selectBooleanCheckbox value="true">
            <p:ajax listener="#{weekdayList.handleDay(ctr.id, day.id)}" />
        </h:selectBooleanCheckbox>
    </p:column>
</c:forEach>

As you can see I keep using #{open} but not inside the value attibute. 如您所见,我一直使用#{open}但不在value attibute中使用。

Questions : 问题

What did I wrong? 我怎么了 Am I missing something? 我想念什么吗? Is there a bug? 有错误吗?

Thanks. 谢谢。

So... I have found a "solution", and respond to my own question. 所以...我找到了一个“解决方案”,然后回答我自己的问题。

I added fakes getter and setter for the method checkOpen. 我为checkOpen方法添加了伪造的getter和setter方法。 So the bean looks like this: 因此,bean看起来像这样:

@Named("weekdayList")
@Scope("session")
public class AdminWeekdayListController implements Serializable {

    ...

    public boolean getCheckOpen() {
        return true;
    }

    public void setCheckOpen(boolean b) {
    }

    public boolean checkOpen(String ctrId, Date date) {
        Country ctr = countryDao.getById(ctrId);
        List<WeekDay> list = weekdaysMap.get(ctr);

        if (list == null) {
            return true;
        }

        WeekDay day = new WeekDay();
        day.setDate(date);

        for (WeekDay wd : list) {
            if (wd.compareTo(day) == 0) {
                return wd.isOpen();
            }
        }
        return true;
    }
}

This way JSF thinks checkOpen is a valid (read/write) attribute, BUT calls checkOpen(String ctrId, Date date) . 这样,JSF认为checkOpen是有效的(读/写)属性, 但会调用checkOpen(String ctrId, Date date) It never calls the getter or the setter... 它从不调用getter或setter。

If someone can explain this, I will be gratefull. 如果有人可以解释这一点,我将不胜感激。 And if someone has a better solution, I am listening. 如果有人有更好的解决方案,我在听。

its the LifeCycle of Taghandlers and UI components. 其Taghandlers和UI组件的生命周期。

JSTL-Tags in JSF do not represent components and never become part of the component tree once the view has been built. 一旦构建了视图,JSF中的JSTL-Tags不会代表组件,也永远不会成为组件树的一部分。

TagHandlers are responsible for building the tree, "Once they have done their job, they expire". TagHandlers负责构建树,“一旦完成工作,它们就会过期”。 this means, they are available only in the View Building Phase. 这意味着它们仅在视图构建阶段可用。 at the other hand UI-Components run in View Rendering Phase. 另一方面,UI组件在视图渲染阶段中运行。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM