我正面临 ICEFaces 的问题。似乎无法正确刷新视图。
我将为您提供视图、流程、bean 和我发现的奇怪行为的详细信息,这要归功于一些调试会话。
基本上,我正在处理一个延迟加载的 ace:DataTable。
<ace:dataTable id="blocchiTable" [..] />
我选择了一些行并单击标有“Modifica”(意大利语为“编辑”)的按钮:
<ace:menuItem id="modificaBloccoButton" value="Modifica" action="modificaBlocco" icon="ui-icon ui-icon-pencil" />`
正如您将在流程中看到的,相关的点击事件将流程引导至决策状态:
<view-state id="creablocco" view="creablocco.xhtml">
[.. other stuff ..]
<transition on="modificaBlocco" to="decidiModifica">
<evaluate expression="flowScope.blocchiBean.getRigheSelezionate()" result="flowScope.righeSelezionate"/>
</transition>
</view-state>
<decision-state id="decidiModifica">
<if test="!(flowScope.righeSelezionate).isEmpty()" then="modificaBlocco" else="fine" />
</decision-state>
然后,另一个视图状态,与初始状态的相同视图相关联。在进入新的视图状态时,流程会要求 bean 为正确的行启用 cellEditor,以便在重新呈现视图时,选定的行将是可编辑的。
<view-state id="modificaBlocco" view="creablocco.xhtml">
<on-entry>
<evaluate expression="flowScope.blocchiBean.abilitaModifica()"/>
</on-entry>
<transition on="salvaModificheBlocco" to="fine">
<evaluate expression="flowScope.blocchiBean.salvaBlocchi()"/>
</transition>
</view-state>
不幸的是,在重新渲染视图时(我已经检查过该<on-entry>
部分中指定的方法是否被实际调用),引发了以下异常:
AVVERTENZA: queued exception
java.lang.NullPointerException
at org.icefaces.impl.util.DOMUtils.isWhitespaceText(DOMUtils.java:394)
at org.icefaces.impl.util.DOMUtils.printNode(DOMUtils.java:351)
at org.icefaces.impl.util.DOMUtils.printNode(DOMUtils.java:355)
at org.icefaces.impl.util.DOMUtils.printNode(DOMUtils.java:355)
at org.icefaces.impl.util.DOMUtils.printNode(DOMUtils.java:355)
at org.icefaces.impl.util.DOMUtils.printNode(DOMUtils.java:306)
at org.icefaces.impl.util.DOMUtils.printNode(DOMUtils.java:290)
at org.icefaces.impl.context.DOMResponseWriter.endDocument(DOMResponseWriter.java:225)
at com.sun.faces.application.view.FaceletViewHandlingStrategy.renderView(FaceletViewHandlingStrategy.java:410)
at com.sun.faces.application.view.MultiViewHandler.renderView(MultiViewHandler.java:131)
at org.springframework.faces.webflow.FlowViewHandler.renderView(FlowViewHandler.java:99)
at com.sun.faces.lifecycle.RenderResponsePhase.execute(RenderResponsePhase.java:121)
at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
at com.sun.faces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:139)
at org.springframework.faces.webflow.FlowLifecycle.render(FlowLifecycle.java:80)
at org.springframework.faces.webflow.JsfView.render(JsfView.java:89)
at org.springframework.webflow.engine.ViewState.render(ViewState.java:296)
at org.springframework.webflow.engine.ViewState.refresh(ViewState.java:243)
at org.springframework.webflow.engine.ViewState.resume(ViewState.java:221)
at org.springframework.webflow.engine.Flow.resume(Flow.java:545)
at org.springframework.webflow.engine.impl.FlowExecutionImpl.resume(FlowExecutionImpl.java:258)
at org.springframework.webflow.executor.FlowExecutorImpl.resumeExecution(FlowExecutorImpl.java:169)
at org.springframework.webflow.mvc.servlet.FlowHandlerAdapter.handle(FlowHandlerAdapter.java:183)
at org.springframework.faces.webflow.JsfFlowHandlerAdapter.handle(JsfFlowHandlerAdapter.java:48)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:900)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:827)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:882)
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:778)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:621)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:311)
at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:116)
at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:83)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:323)
at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:113)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:323)
at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:113)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:323)
at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:101)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:323)
at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:113)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:323)
at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:54)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:323)
at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:45)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:323)
at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:182)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:323)
at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:105)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:323)
at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:87)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:323)
at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:173)
at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346)
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:259)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:88)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:224)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:169)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:168)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:98)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:927)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
at com.springsource.insight.collection.tcserver.request.HttpRequestOperationCollectionValve.traceNextValve(HttpRequestOperationCollectionValve.java:112)
at com.springsource.insight.collection.tcserver.request.HttpRequestOperationCollectionValve.invoke(HttpRequestOperationCollectionValve.java:94)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:407)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:987)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:579)
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:309)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
at java.lang.Thread.run(Thread.java:662)
这是完整的视图:
<?xml version="1.0"?>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:ace="http://www.icefaces.org/icefaces/components"
xmlns:ice="http://www.icesoft.com/icefaces/component"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
template="/resources/includes/templates/template.xhtml">
<ui:param name="pageTitle" value="Crea blocco" />
<ui:define name="page-content">
<ace:panel id="personalInfoInputPanel" header="Crea blocco">
<div class="div_creablocco">
<h:form id="creabloccoform">
<h:panelGrid id="creabloccoInputGrid" columns="1" styleClass="table_creablocco">
<ace:textEntry id="numeroFile" value="#{creaBloccoBean.numeroFile}" label="Numero file:" labelPosition="left" required="true" requiredIndicator="(*)" indicatorPosition="right">
</ace:textEntry>
<ace:textEntry id="numeroColonne" value="#{creaBloccoBean.numeroColonne}" label="Numero colonne:" labelPosition="left" required="true" requiredIndicator="(*)" indicatorPosition="right">
</ace:textEntry>
<ace:textEntry id="posizioneX" value="#{creaBloccoBean.posizioneX}" label="Coordinata X:" labelPosition="left" required="true" requiredIndicator="(*)" indicatorPosition="right">
</ace:textEntry>
<ace:textEntry id="posizioneY" value="#{creaBloccoBean.posizioneY}" label="Coordinata Y:" labelPosition="left" required="true" requiredIndicator="(*)" indicatorPosition="right">
</ace:textEntry>
<ace:pushButton id="pushBttnCreaBlocco" value="Crea blocco" action="creaBlocco"/>
</h:panelGrid>
</h:form>
</div>
</ace:panel>
<ace:panel id="blocchiPanel" header="Blocchi">
<h:form id="blocchiTableForm">
<ace:menuBar id="iconeBloccoMenu" rendered="#{!blocchiBean.modificaInCorso}">
<ace:menuItem id="dettagliBloccoButton" value="Dettagli" action="dettagliBlocco" icon="ui-icon ui-icon-search" />
<ace:menuItem id="modificaBloccoButton" value="Modifica" action="modificaBlocco" icon="ui-icon ui-icon-pencil" />
<ace:menuItem id="cancellaBloccoButton" value="Cancella" action="cancellaBlocco" icon="ui-icon ui-icon-closethick" />
</ace:menuBar>
<ace:menuBar id="iconeModificaBloccoMenu" rendered="#{flowScope.blocchiBean.modificaInCorso}">
<ace:menuItem id="annullaModificheButton" value="Annulla" action="annullaModificheBlocco" icon="ui-icon ui-icon-arrow-1-w" />
<ace:menuItem id="salvaModifiche" value="Salva" action="salvaModificheBlocco" icon="ui-icon ui-icon-disk" />
</ace:menuBar>
<ace:dataTable id="blocchiTable" value="#{blocchi}"
binding="#{flowScope.blocchiBean.table}" stateMap="#{flowScope.blocchiBean.stateMap}"
selectionMode="multiple" doubleClickSelect="false"
rowSelectListener="#{flowScope.blocchiBean.selectListener}"
rowUnselectListener="#{flowScope.blocchiBean.deselectListener}" var="blocco"
lazy="true" rows="10" paginator="true" paginatorPosition="bottom">
<ace:column id="idBloccoColumn" headerText="ID" styleClass="id">
<h:outputText id="idBloccoText" value="#{blocco.id}" />
</ace:column>
<ace:column id="numeroFileBloccoColumn" headerText="Numero file"
styleClass="numFile">
<ace:cellEditor>
<f:facet name="output">
<h:outputText id="numeroFileBloccoText"
value="#{blocco.numeroFile}" />
</f:facet>
<f:facet name="input">
<h:inputText id="numeroFileBloccoInput"
value="#{blocco.numeroFile}" />
</f:facet>
</ace:cellEditor>
</ace:column>
<ace:column id="numeroColonneBloccoColumn"
headerText="Numero colonne" styleClass="numColonne">
<ace:cellEditor>
<f:facet name="output">
<h:outputText id="numeroColonneBloccoText"
value="#{blocco.numeroColonne}" />
</f:facet>
<f:facet name="input">
<h:inputText id="numeroColonneBloccoInput"
value="#{blocco.numeroColonne}" />
</f:facet>
</ace:cellEditor>
</ace:column>
<ace:column id="posizioneXBloccoColumn" headerText="Posizione X"
styleClass="posX">
<ace:cellEditor>
<f:facet name="output">
<h:outputText id="posizioneXBloccoText"
value="#{blocco.posizioneX}" />
</f:facet>
<f:facet name="input">
<h:inputText id="posizioneXBloccoInput"
value="#{blocco.posizioneX}" />
</f:facet>
</ace:cellEditor>
</ace:column>
<ace:column id="posizioneYBloccoColumn" headerText="Posizione Y"
styleClass="posY">
<ace:cellEditor>
<f:facet name="output">
<h:outputText id="posizioneYBloccoText"
value="#{blocco.posizioneY}" />
</f:facet>
<f:facet name="input">
<h:inputText id="posizioneYBloccoInput"
value="#{blocco.posizioneY}" />
</f:facet>
</ace:cellEditor>
</ace:column>
</ace:dataTable>
</h:form>
</ace:panel>
</ui:define>
</ui:composition>
这是完整的流程:
<?xml version="1.0" encoding="UTF-8"?>
<flow xmlns="http://www.springframework.org/schema/webflow"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/webflow
http://www.springframework.org/schema/webflow/spring-webflow-2.0.xsd">
<var name="creaBloccoBean" class="com.infoone.siglo.viewbeans.CreaBloccoBean" />
<var name="blocchiBean" class="com.infoone.siglo.viewbeans.BlocchiBean" />
<view-state id="creablocco" view="creablocco.xhtml">
<on-entry>
<evaluate expression="flowScope.blocchiBean.getBlocchi()" result="flowScope.blocchi" />
</on-entry>
<transition on="creaBlocco" to="fine">
<evaluate expression="gestoreBlocchiCtr.creaBlocco(creaBloccoBean)" />
</transition>
<transition on="cancellaBlocco" to="decidiCancellazione">
<evaluate expression="flowScope.blocchiBean.getRigheSelezionate()" result="flowScope.righeSelezionate"/>
</transition>
<transition on="modificaBlocco" to="decidiModifica">
<evaluate expression="flowScope.blocchiBean.getRigheSelezionate()" result="flowScope.righeSelezionate"/>
</transition>
</view-state>
<decision-state id="decidiCancellazione">
<if test="!(flowScope.righeSelezionate).isEmpty()" then="cancellaBlocco" else="fine" />
</decision-state>
<decision-state id="decidiModifica">
<if test="!(flowScope.righeSelezionate).isEmpty()" then="modificaBlocco" else="fine" />
</decision-state>
<action-state id="cancellaBlocco">
<evaluate expression="gestoreBlocchiCtr.rimuoviBlocchi(flowScope.righeSelezionate)" />
<transition to="fine"/>
</action-state>
<view-state id="modificaBlocco" view="creablocco.xhtml">
<on-entry>
<evaluate expression="flowScope.blocchiBean.abilitaModifica()"/>
</on-entry>
<transition on="salvaModificheBlocco" to="fine">
<evaluate expression="flowScope.blocchiBean.salvaBlocchi()"/>
</transition>
</view-state>
<end-state id="fine" />
</flow>
我试图了解哪个 UI 组件导致了这种异常,幸运的是,我能够通过在调试模式服务器上启动 webapp 来隔离它。基本上,它是一个<script>
有 22 个 textElement 子节点的节点。第三个孩子导致异常:
<script>
|------ null_icefaces_config
|------ ', '
|------ null <<===== (This is the node which causes the exception. I mean exactly the null value associated to the "NULL type", here)
|------ ', '
|------ unknownWindow
|------ [.. other children ..]
我还检查了writer对象的内容,该对象是包含逐渐填充响应内容的输出流的对象。渲染这个元素生成的部分是:
<script>ice.setupBridge('null_icefaces_config
你有没有遇到过类似的问题?你认为我应该将这个案例报告给ICEFaces的工作人员,以便他们检查它是否是一个错误吗?