我正在与我合作,却jsf 2遇到一些难以解释或理解的行为。
jsf 2
我有几个独立的h:formS。
h:form
其中之一看起来像这样:
<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确实是调用它们的人。
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代码,可以说明此问题:
<ui:repeat>
<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
为什么要运行列表?这不是多余的吗?
我不使用MyFaces,因此不会详细介绍它。但是为了值钱,在莫哈拉(Mojarra)也需要使用吸气剂<ui:repeat>。但是,堆栈更清楚地说明了正在发生的事情。这里是Thread#dumpStack()直到FacesServlet#service():
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
根据UIRepeat#doVisitChildren()来源,行索引设置为-1。最终目标是仅访问树中的子级,而不是遍历模型值或渲染任何东西。它只需要DataModel为了能够设置行索引。数据模型的值是您看到正在调用getter的列表。如果一切正常,则在还原视图阶段仅应调用一次此getter。但是,如果在例如渲染响应阶段也调用了它,那么您可能会为此担心,因为它完全是不必要的。
UIRepeat#doVisitChildren()
-1
DataModel