Pregunta

I'm facing a problem with ICEFaces. It seems like it's unable to properly refresh a view.
I'll provide you with the view, the flow, the bean and the details of the strange behaviour I found thanks to some debugging sessions.

Basically, I'm dealing with a lazy loaded ace:DataTable.

<ace:dataTable id="blocchiTable" [..] />

I select some rows and click on a button labeled with "Modifica" (the Italian for "Edit"):

<ace:menuItem id="modificaBloccoButton" value="Modifica" action="modificaBlocco" icon="ui-icon ui-icon-pencil" />`

As you will see in the flow, the related click event leads the flow to a decision-state:

<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>

and, afterwards, another view-state, associated to the same view of the initial state. While entering the new view-state, the flow asks the bean to enable the cellEditor for the proper rows, so that, when the view is re-rendered, the selected rows will be editable.

<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>

Unfortunaly, while re-rendering the view (I already checked that the method specified in the <on-entry> section is actually invoked), the following exception is raised:

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)

This is the complete view:

<?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>  

This is the complete flow:

<?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>

I tried to understand which UI component was causing such an exception and, luckily, I was able to isolate it by launching the webapp on a debugging-mode server. Basically, it is a <script> node with 22 textElement children. The third child is causing the exception:

<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 ..]

I also inspected the content of the writer object, which is the object containing the output stream that is gradually filled with the content of the response. The portion generated by rendering this element is:

<script>ice.setupBridge('null_icefaces_config

Have you ever faced a similar problem? Do you think I should report this case to the ICEFaces staff, so that they can check whether it's a bug?

¿Fue útil?

Solución

There's an issue with the way the Webflow navigation model integrates with JSF. The ICEFaces code uses a phase listener to extract bits of information from the request and this phase listener isn't executed in the GET portion of the POST-Redirect-GET Spring navigation model. There is a workaround, which is to implement a FlowExecutionListener which takes the place of the PhaseListener in those circumstances. See the tutorial and example implementation of the Listener here:

http://wiki.icesoft.org/display/ICE/Spring+Web+Flow+2.3.1

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top