voyent
'Target Unreachable, identifier 'row' resolved to null' after removing a dataTable row  XML
Forum Index -> General Help
Author Message
mlewter

Joined: 08/Apr/2008 00:00:00
Messages: 3
Offline


Hello everyone,

I've been wrestling with something all day and I thought it was about time I tried the forum. Any insight into handling this would be greatly appreciated.

I'm currently working with a dataTable. Each row in the dataTable consists of multiple selectOneMenu components. The available values in one of the selectOneMenu components may be driven by the selection made in another selectOneMenu component.

To accomplish this, some of the selectOneMenu components are bound to valueChangeListeners in my bean. This is all working without issue.

However, my users also need the ability to add/remove rows from this table as they see fit. I can add rows without a problem, but removing is a different story.

Here's an example of how my dataTable is layed out:

Code:
 
 <ice:dataTable  value="#{myBean.rows}"
 	        var="row"
 	        binding="#{myBean.dataTable}">
 
     <ice:column>
         <f:facet name="header">
             <ice:outputText value="Select some value"/>
         </f:facet>
         <ice:selectOneMenu id="slct" 
 		      partialSubmit="true"
 		      value="#{row.myVal}"
 		      valueChangeListener="{myBean.slctListener}">
             <f:selectItems id="items" value="#{myBean.items}"/>
         </ice:selectOneMenu>
      </ice:column>
 
     <ice:column>
         <f:facet name="header">
             <ice:outputText value="Action"/>
         </f:facet>
            <ice:commandButton id="removeRow"
                                           value="Remove" 
 	    	          actionListener="#{myBean.removeRow}"/>
      </ice:column>
 
 ...etc...
 
 </ice:dataTable>	            
 
 


removeRow looks something like this:

Code:
 
     public void removeRow(ActionEvent event) {
         int row = dataTable.getRowIndex();
         removedRows.add(rows.get(row)); //keeping track of removed rows
         rows.remove(row);
     }
 
 


and finally, my valueChangeListener(s) look something like this:

Code:
 
     public void slctListener(ValueChangeEvent event) {
         if (!event.getPhaseId().equals(PhaseId.INVOKE_APPLICATION)) {
              event.setPhaseId(PhaseId.INVOKE_APPLICATION);
              event.queue();
         }
         else {
           //assign the values for some other selectOneMenu component
         }
 
 


So...all I'm doing is removing a row from the 'rows' ArrayList. When I do this however, I get the following exception:

Target Unreachable, identifier 'row' resolved to null

After stepping through the code, I found that at least one of the valueChangeListeners on my table is being called AFTER the call to 'removeRow' (the phase on both the remove and valueChange events is INVOKE_APPLICATION).

I'm guessing that the dataTable is still holding a reference to the removed row, even though it's no longer in the ArrayList?

The interesting thing (to me anyway) is that it works if I first select an item in any of my selectOneMenu components first (which obviously fires off a valueChangeListener) before trying to remove a row.

Is this something I can correct by evaluating the current phase of the lifecycle? Again, any ideas/suggestions would be greatly appreciated.

Thanks!

-Matt



Knuckle

Joined: 22/Nov/2008 00:00:00
Messages: 93
Offline


Hi wlewter

I to have a similar problem as it occurs in my app after deleting a row then selecting the last row in the table.

Although I have been unable to solve the problem I found this as it might help.


Have a look at http://www.icefaces.org/main/resources/tutorials.iface
-> CRUD Applications with ICEfaces and NetBeans

Check out point #3
"One last thing you need to do is ensure that the table view on the data is refreshed before the render occurs to ensure it is up to date. This is done in the prerender() member function as shown below.
"

Unfortunatly, my app users fragments which do not have the pre-render method.

Cheers
Wayne

mlewter

Joined: 08/Apr/2008 00:00:00
Messages: 3
Offline



Hi Wayne,

Thanks for the reply!

I was actually able to find a way around my issue a little earlier today.

I ended up replacing this:

Code:
 if (!event.getPhaseId().equals(PhaseId.INVOKE_APPLICATION)) {
      event.setPhaseId(PhaseId.INVOKE_APPLICATION);
      event.queue();
 }
 


with this:

Code:
 if (!event.getPhaseId().equals(PhaseId.UPDATE_MODEL_VALUES)) {
      event.setPhaseId(PhaseId.UPDATE_MODEL_VALUES);
      event.queue();
 }
 


...and everything seems to be working fine now. It looks like the UPDATE_MODEL_VALUES phase comes directly before INVOKE_APPLICATION, but to be completely honest...I'm not exactly sure why this works.

Could it be because all of the events had previously been executing during INVOKE_APPLICATION, so the table had not been updated prior to the execution of the other ValueChangeEvent's?

Can anyone offer any insight into this?

Thanks again,

-Matt

caioformiga

Joined: 12/Oct/2009 00:00:00
Messages: 9
Offline


Unfortunately, I haven't just doubts about this behavior, indeed I`m passing through similar problem.

Code:
 <ice:form>
      <ice:selectOneListbox id="institutionSelected"   size="1"                       					                                           
                                         value="#{monitorController.institutionSelected}"                                                                                                                            
                                         valueChangeListener="#{monitorController.institutionChanged}"
                                         partialSubmit="true">                                            
                         <f:selectItems id="cbInstituitionsSelectItems"
                                        value="#{monitorController.instituitionsSelectItems}"/>
       </ice:selectOneListbox>        				   
       <p>#{pageMsg.eventHandlerDesc}</p>
       <ice:dataTable value="#{monitorController.progressBarList}" var="progress">	
                         <ice:column rendered="#{progress.isRendered}" colspan="2">
 		                    <f:facet name="header">
 		                        <ice:outputText value="#{pageMsg.lbColInstitutionName}"/>
 		                    </f:facet>		                 													
 		                    <ice:outputText value="#{progress.name}"/>		               		                   
 		         </ice:column>
 		         <ice:column rendered="#{progress.isRendered}">
 		                    <f:facet name="header">
 		                        <ice:outputText value="#{pageMsg.lbColPercent}"/>
 		                    </f:facet>
 		                    <ice:outputProgress value="#{progress.percent}" />
 		          </ice:column>
      </ice:dataTable>   	                	                	               	            		
 </ice:form>
 


I have a </ice:selectOneListbox> component populated with a list of Institutions like INST 1 and INST 2. Then after selectOneListBox changes its value the method institutionChanged is invoked.

Code:
 public void institutionChanged(ValueChangeEvent event) {						
 		if ((event.getPhaseId().equals(PhaseId.UPDATE_MODEL_VALUES)) && 
    		   ((! "".equals(institutionSelected)) && (institutionSelected != null))) {			
 			System.out.println("Creating ProgressBar List ====================>");		
 			createProgressBarList();											
 		} else {
 			event.setPhaseId(PhaseId.UPDATE_MODEL_VALUES);
 			event.queue();
 			return;
 		}
 	}
 


This method is responsible to populate my progressBarList, that is the datamodel associated to <ice:dataTable>, but during this Exception is throw:


08:02:09,207 ERROR [ReceiveSendUpdates:80] Exception occured during rendering on http://192.168.1.152:8080/ProgressMonitor/block/send-receive-updates [/pages/monitorTest.jspx]
javax.faces.FacesException: Exception while calling broadcast on component : {Component-Path : [Class: com.icesoft.faces.application.SettableLocaleViewRoot,ViewId: /pages/monitorTest.jspx][Class: com.icesoft.faces.component.portlet.Portlet,Id: _BankProcessMonitor_WAR_ProgressMonitor_INSTANCE_Bt4F_][Class: com.icesoft.faces.component.ext.HtmlForm,Id: _BankProcessMonitor_WAR_ProgressMonitor_INSTANCE_Bt4F_j_id6][Class: com.icesoft.faces.component.ext.HtmlSelectOneListbox,Id: institutionSelected]}
at javax.faces.component.UIComponentBase.broadcast(UIComponentBase.java:494)
at javax.faces.component.UIInput.broadcast(UIInput.java:196)
at javax.faces.component.UIViewRoot._broadcastForPhase(UIViewRoot.java:292)
at javax.faces.component.UIViewRoot.process(UIViewRoot.java:209)
at javax.faces.component.UIViewRoot.processUpdates(UIViewRoot.java:105)
at org.apache.myfaces.lifecycle.UpdateModelValuesExecutor.execute(UpdateModelValuesExecutor.java:33)
at org.apache.myfaces.lifecycle.LifecycleImpl.executePhase(LifecycleImpl.java:103)
at org.apache.myfaces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:76)
at com.icesoft.faces.webapp.http.core.JsfLifecycleExecutor.apply(JsfLifecycleExecutor.java:18)
at com.icesoft.faces.webapp.http.core.ReceiveSendUpdates.renderCycle(ReceiveSendUpdates.java:132)
at com.icesoft.faces.webapp.http.core.ReceiveSendUpdates.service(ReceiveSendUpdates.java:74)
at com.icesoft.faces.webapp.http.core.RequestVerifier.service(RequestVerifier.java:31)
at com.icesoft.faces.webapp.http.common.standard.PathDispatcherServer.service(PathDispatcherServer.java:24)
at com.icesoft.faces.webapp.http.servlet.BasicAdaptingServlet.service(BasicAdaptingServlet.java:16)
at com.icesoft.faces.webapp.http.servlet.PathDispatcher.service(PathDispatcher.java:23)
at com.icesoft.faces.webapp.http.servlet.SessionDispatcher.service(SessionDispatcher.java:53)
at com.icesoft.faces.webapp.http.servlet.SessionVerifier.service(SessionVerifier.java:26)
at com.icesoft.faces.webapp.http.servlet.PathDispatcher.service(PathDispatcher.java:23)
at com.icesoft.faces.webapp.http.servlet.MainServlet.service(MainServlet.java:131)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
at com.icesoft.faces.webapp.xmlhttp.BlockingServlet.service(BlockingServlet.java:56)
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.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:433)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128)
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:286)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:845)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:583)
at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:447)
at java.lang.Thread.run(Thread.java:619)
Caused by: javax.faces.event.AbortProcessingException: javax.el.ELException: /pages/monitorTest.jspx @23,64 valueChangeListener="#{monitorController.institutionChanged}": java.lang.NullPointerException
at javax.faces.event.MethodExpressionValueChangeListener.processValueChange(MethodExpressionValueChangeListener.java:48)
at javax.faces.event.ValueChangeEvent.processListener(ValueChangeEvent.java:59)
at javax.faces.component.UIComponentBase.broadcast(UIComponentBase.java:489)
... 33 more
Caused by: javax.el.ELException: /pages/monitorTest.jspx @23,64 valueChangeListener="#{monitorController.institutionChanged}": java.lang.NullPointerException
at com.sun.facelets.el.TagMethodExpression.invoke(TagMethodExpression.java:74)
at javax.faces.event.MethodExpressionValueChangeListener.processValueChange(MethodExpressionValueChangeListener.java:46)
... 35 more
Caused by: java.lang.NullPointerException
at com.vsoftcorp.watchmen.controller.MonitorController.createProgressBarList(MonitorController.java:94)
at com.vsoftcorp.watchmen.controller.MonitorController.institutionChanged(MonitorController.java:126)
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 org.apache.el.parser.AstValue.invoke(AstValue.java:172)
at org.apache.el.MethodExpressionImpl.invoke(MethodExpressionImpl.java:276)
at com.sun.facelets.el.TagMethodExpression.invoke(TagMethodExpression.java:68)
... 36 more
 


Through the code-line Sstem.out.println("Creating ProgressBar List ====================>"); I have sure that until this point everything is ok, and I also have sure that my progressBarList and its DAO are ok, cause I tested the MODEL layer before start the integration with VIEW layer.

What should I do?
Shags

Joined: 11/Aug/2010 16:08:41
Messages: 1
Offline


I was having a similar issue. I’m not real happy with my solution (it feels a little hackish) but it does work:

Code:
 <ice:rowSelector value="#{not empty row ? row.iceSelected : editor.nothing}" 
 selectionListener="#{editor.rowSelection}"  
 immediate="false" />
 


Here if row is null we simply call editor.nothing instead of trying to access the null row. Editor.setNothing and Editor.getNothing do absolutely nothing.

So it work, but I still feel like I must be doing something wrong, or not doing something right… either way I wish the iceFaces guys would popup and comment on this.

Oh, and to add to the weirdness, with my list the null row only appeared if I first deleted a row under the next row I selected (i.e. I delete row 2 and then select row 1). The other way worked just fine.

-Shags
 
Forum Index -> General Help
Go to:   
Powered by JForum 2.1.7ice © JForum Team