小编典典

弄清楚为什么我不希望调用JSF getters的原因

java

我正在与我合作,却jsf 2遇到一些难以解释或理解的行为。

我有几个独立的h:formS。

其中之一看起来像这样:

<h:form>
    <h:commandButton value="#{text.General_Wipe_Now}" action="#{bean.doThate}" >
        <f:ajax execute="@form" render="@form" />
    </h:commandButton>
    <h:selectBooleanCheckbox value="#{bean.ignoreErrors}">Ignore Errors</h:selectBooleanCheckbox>
</h:form>

我的问题/问题是,每当按下上述按钮时,我都会看到其他不相关的bean成员getter(属于其他形式的一部分)被调用。(通过记录)

任何获取方法都没有业务逻辑,但是我 了解其原因。通过打印,stacktrace我确保JSF确实是调用它们的人。

您如何建议我遵循JSF以了解为什么要调用它们?可能是什么原因?

谢谢!本

更新

这是由正在运行且不应该运行的getter之一打印的stacktrace。正如评论中所讨论的那样,在这个问题中包含所有相关的细节将是极其复杂的,因此我宁愿获得有关工具的帮助,以自己找到答案。

java.lang.Exception
    at com.aCompanyName.applicationName.beans.aBean.getSomethingFromBean(CurrentDevice.java:382)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at javax.el.BeanELResolver.getValue(BeanELResolver.java:302)
    at javax.el.CompositeELResolver.getValue(CompositeELResolver.java:175)
    at org.apache.myfaces.el.unified.resolver.FacesCompositeELResolver.getValue(FacesCompositeELResolver.java:142)
    at com.sun.el.parser.AstValue.getValue(AstValue.java:116)
    at com.sun.el.parser.AstValue.getValue(AstValue.java:163)
    at com.sun.el.ValueExpressionImpl.getValue(ValueExpressionImpl.java:219)
    at org.apache.myfaces.view.facelets.el.TagValueExpression.getValue(TagValueExpression.java:85)
    at org.apache.myfaces.view.facelets.component.UIRepeat.getValue(UIRepeat.java:248)
    at org.apache.myfaces.view.facelets.component.UIRepeat.getDataModel(UIRepeat.java:211)
    at org.apache.myfaces.view.facelets.component.UIRepeat._validateAttributes(UIRepeat.java:530)
    at org.apache.myfaces.view.facelets.component.UIRepeat.visitTree(UIRepeat.java:763)
    at javax.faces.component.UIComponent.visitTree(UIComponent.java:797)
    at javax.faces.component.UIComponentBase.visitTree(UIComponentBase.java:992)
    at javax.faces.component.UIComponent.visitTree(UIComponent.java:797)
    at javax.faces.component.UIComponentBase.visitTree(UIComponentBase.java:992)
    at javax.faces.component.UIComponent.visitTree(UIComponent.java:797)
    at javax.faces.component.UIComponentBase.visitTree(UIComponentBase.java:992)
    at javax.faces.component.UIComponent.visitTree(UIComponent.java:797)
    at javax.faces.component.UIComponentBase.visitTree(UIComponentBase.java:992)
    at javax.faces.component.UIComponent.visitTree(UIComponent.java:797)
    at javax.faces.component.UIComponentBase.visitTree(UIComponentBase.java:992)
    at javax.faces.component.UIComponent.visitTree(UIComponent.java:797)
    at javax.faces.component.UIComponentBase.visitTree(UIComponentBase.java:992)
    at javax.faces.component.UIComponent.visitTree(UIComponent.java:797)
    at javax.faces.component.UIComponentBase.visitTree(UIComponentBase.java:992)
    at javax.faces.component.UIComponent.visitTree(UIComponent.java:797)
    at javax.faces.component.UIComponentBase.visitTree(UIComponentBase.java:992)
    at javax.faces.component.UIComponent.visitTree(UIComponent.java:797)
    at javax.faces.component.UIComponentBase.visitTree(UIComponentBase.java:992)
    at javax.faces.component.UIComponent.visitTree(UIComponent.java:797)
    at javax.faces.component.UIComponentBase.visitTree(UIComponentBase.java:992)
    at javax.faces.component.UIComponent.visitTree(UIComponent.java:797)
    at javax.faces.component.UIComponentBase.visitTree(UIComponentBase.java:992)
    at javax.faces.component.UIComponent.visitTree(UIComponent.java:797)
    at javax.faces.component.UIComponentBase.visitTree(UIComponentBase.java:992)
    at org.apache.myfaces.view.facelets.tag.ui.DebugPhaseListener._doTreeVisit(DebugPhaseListener.java:310)
    at org.apache.myfaces.view.facelets.tag.ui.DebugPhaseListener.afterPhase(DebugPhaseListener.java:286)
    at org.apache.myfaces.lifecycle.PhaseListenerManager.informPhaseListenersAfter(PhaseListenerManager.java:111)
    at org.apache.myfaces.lifecycle.LifecycleImpl.executePhase(LifecycleImpl.java:185)
    at org.apache.myfaces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:118)
    at javax.faces.webapp.FacesServlet.service(FacesServlet.java:189)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
    at org.apache.openejb.tomcat.catalina.OpenEJBValve.invoke(OpenEJBValve.java:45)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:298)
    at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:852)
    at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:588)
    at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489)
    at java.lang.Thread.run(Thread.java:662)

更新2

制作SSCCE的过程将在我拥有一个时进行更新。

更新3

<ui:repeat>值属性似乎发生了问题。这是一个SSCCE代码,可以说明此问题:

<h:body>
    <ui:repeat var="str" value="#{admin.SList}">
        STRING: #{str}
    </ui:repeat>

    <h:form>
        <h:commandButton value="pressie" action="#{admin.doThat}">
            <f:ajax execute="@form"/>
        </h:commandButton>
    </h:form>
</h:body>

Bean代码:

@PostConstruct
public void init()
{
    slist.add("Testing");
    slist.add("This");
    slist.add("Thing");
}

private List<String> slist = new ArrayList<String>();

public List<String> getSList(){
    logger.trace("Getting LIST");
    return slist;
}

public void doThat(){
    logger.trace("DoThat Was Run");
}

当按下按钮时,这将输出到日志:

2011-08-16 16:55:55,853 TRACE [http-80-2] (AdminBean.java:80) - Getting LIST
2011-08-16 16:55:55,865 TRACE [http-80-2] (AdminBean.java:85) - DoThat Was Run

为什么要运行列表?这不是多余的吗?


阅读 236

收藏
2020-11-26

共1个答案

小编典典

我不使用MyFaces,因此不会详细介绍它。但是为了值钱,在莫哈拉(Mojarra)也需要使用吸气剂<ui:repeat>。但是,堆栈更清楚地说明了正在发生的事情。这里是Thread#dumpStack()直到FacesServlet#service()

java.lang.Exception: Stack trace
    at java.lang.Thread.dumpStack(Thread.java:1249)
    at mypackage.Bean.getList(Bean.java:21)
    at sun.reflect.GeneratedMethodAccessor51.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at javax.el.BeanELResolver.getValue(BeanELResolver.java:302)
    at com.sun.faces.el.DemuxCompositeELResolver._getValue(DemuxCompositeELResolver.java:176)
    at com.sun.faces.el.DemuxCompositeELResolver.getValue(DemuxCompositeELResolver.java:203)
    at com.sun.el.parser.AstValue.getValue(AstValue.java:116)
    at com.sun.el.parser.AstValue.getValue(AstValue.java:163)
    at com.sun.el.ValueExpressionImpl.getValue(ValueExpressionImpl.java:219)
    at com.sun.faces.facelets.el.TagValueExpression.getValue(TagValueExpression.java:109)
    at com.sun.faces.facelets.component.UIRepeat.getValue(UIRepeat.java:272)
    at com.sun.faces.facelets.component.UIRepeat.getDataModel(UIRepeat.java:248)
    at com.sun.faces.facelets.component.UIRepeat.setIndex(UIRepeat.java:442)
    at com.sun.faces.facelets.component.UIRepeat.doVisitChildren(UIRepeat.java:661)
    at com.sun.faces.facelets.component.UIRepeat.visitTree(UIRepeat.java:619)
    at javax.faces.component.UIComponent.visitTree(UIComponent.java:1600)
    at javax.faces.component.UIComponent.visitTree(UIComponent.java:1600)
    at com.sun.faces.application.view.StateManagementStrategyImpl.restoreView(StateManagementStrategyImpl.java:240)
    at com.sun.faces.application.StateManagerImpl.restoreView(StateManagerImpl.java:188)
    at com.sun.faces.application.view.ViewHandlingStrategy.restoreView(ViewHandlingStrategy.java:123)
    at com.sun.faces.application.view.FaceletViewHandlingStrategy.restoreView(FaceletViewHandlingStrategy.java:452)
    at com.sun.faces.application.view.MultiViewHandler.restoreView(MultiViewHandler.java:148)
    at javax.faces.application.ViewHandlerWrapper.restoreView(ViewHandlerWrapper.java:303)
    at com.sun.faces.lifecycle.RestoreViewPhase.execute(RestoreViewPhase.java:189)
    at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
    at com.sun.faces.lifecycle.RestoreViewPhase.doPhase(RestoreViewPhase.java:113)
    at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:118)
    at javax.faces.webapp.FacesServlet.service(FacesServlet.java:409)
    // Remnant omitted for brevity.

因此,在状态管理需要访问整个组件树的还原视图阶段中会发生这种情况。该UIRepeat反过来需要设置的行索引时,其子到会参观。

根据UIRepeat#doVisitChildren()来源,行索引设置为-1。最终目标是仅访问树中的子级,而不是遍历模型值或渲染任何东西。它只需要DataModel为了能够设置行索引。数据模型的值是您看到正在调用getter的列表。如果一切正常,则在还原视图阶段仅应调用一次此getter。但是,如果在例如渲染响应阶段也调用了它,那么您可能会为此担心,因为它完全是不必要的。

2020-11-26