voyent
Page doesn't show current dataModel  XML
Forum Index -> Components
Author Message
Newlukai

Joined: 29/Nov/2006 00:00:00
Messages: 125
Offline


Hi,

I've a problem with the ice:dataTable in conjuction with ice:selectOneMenus. I use ice:selectOneMenus to filter the shown ice:dataTable.
Imagine a list of cars including their names, colors and prices. On top of this list are 2 selectOneMenus containing colors and prizes. When the page is shown for the first time, all the selectOneMenus are set to a dummy value which tells the list to ignore this filter.

A sample (I know, it's far away from reality ;)):
Code:
All colors    All prizes
 red           < $1000
 blue          < $5000
 black         < $10000
               > $10000
 
 Car A      red      $500
 Car A      blue     $1500
 Car B      black    $500
 Car C      blue     &7500


The problem now is, that whenever I change a filter the ice:dataModel shows the list from the request before. For example:

[list=1]
[*]The page is shown for the first time: the dataTable shows all entries. OK.
[*]User selects "red" from the color filter: the dataTable shows still all entries. NOT OK.
[*]User selects "blue": dataTable shows all red cars. NOT OK.
[*]User selects "black": dataTable shows all blue cars. NOT OK.
[/list]

I debugged the code which applies the filters on the list, but the filtering works fine. The bean returns the correct list. So I think it might be a problem with ICEfaces.

Here's the coe of the page:
Code:
...
 <ice:selectOneMenu value="#{prioritySelector.selectedPriorityNumber}"
     valueChangeListener="#{prioritySelector.valueChanged}" partialSubmit="true">
   <f:selectItems value="#{prioritySelector.priorityItems}" />
 </ice:selectOneMenu>
 
 ...
 
 <ice:dataTable var="testaction_var" value="#{testactionsForDeveloper}"
     sortColumn="#{testactionDeveloper.column}"
     sortAscending="#{testactionDeveloper.ascending}">
   <f:facet name="header">
     <h:outputText value="#{ares_messages.label_ResultCount}:
         #{testactionsForDeveloper.rowCount}" />
   </f:facet>
   <h:column>
     <f:facet name="header">
       <ice:commandSortHeader columnName="id">
         <h:outputText value="#{ares_messages.label_testaction_ID}" />
       </ice:commandSortHeader>
     </f:facet>
     <ice:commandLink value="#{testaction_var.ID}"
         action="#{testactionDeveloper.select}" styleClass="rightAlignment" />
   </h:column>
 ...
 </ice:dataTable>


The "releaseSelector" bean:
Code:
@Stateful
 @Scope(ScopeType.SESSION)
 @LoggedIn
 @Name("prioritySelector")
 public class PrioritySelection implements PrioritySelector, Serializable {
   @PersistenceContext(unitName = "aresDatabase")
   private transient EntityManager em;
 
   @In(required=false) @Out(required=false, scope=ScopeType.SESSION)
   private Priorityclass selectedPriority; 
 
   private List<Priorityclass> priorities;
 
 
   public void valueChanged(ValueChangeEvent event) {
     setSelectedPriorityNumber((String) event.getNewValue());
 }
 
   public SelectItem[] getPriorityItems() {
     initPriorities();
 
     SelectItem[] result = new SelectItem[priorities.size() + 1];
     result[0] = new SelectItem(AdditionalPriorities.UNFILTERED.getID(),
         AdditionalPriorities.UNFILTERED.getDescr());
 
     for(int i = 0; i < priorities.size(); i++) {
       Priorityclass priority = priorities.get(i);
       result[i+1] = new SelectItem(priority.getID(),
           priority.getDescr() + " (" + priority.getID() + ")");
     }
     return result;
   }
 
   public String getSelectedPriorityNumber() {
     return (AdditionalPriorities.isNull(selectedPriority)) ?
         "" : selectedPriority.getID();
   }
 
   public void setSelectedPriorityNumber(String priorityID) {
     if(priorityID == null ||
         priorityID.equals(AdditionalPriorities.UNFILTERED.getDescr())) {
       selectedPriority = AdditionalPriorities.UNFILTERED.value();
     } else {
       selectedPriority = (Priorityclass) EMHelper.execQuerySingleResult(
           em.createQuery("from Priorityclass where PRIO_ID=:prioID"
           ).setParameter("prioID", priorityID));
     }
   }
 
   private void initPriorities() {
     if(priorities != null) {
       return;
     }
     priorities = EMHelper.execQuery(em,
         "from Priorityclass order by PRIO_ID asc");
   }
 
   @Remove @Destroy
   public void destroy() {
   }
 }


Yes, I use Seam ;)

Here the filtering code:
Code:
@Stateful
 @Scope(ScopeType.SESSION)
 @LoggedIn
 @Name("testactionDeveloper")
 public class TestactionDeveloperAction extends TestactionHandling
     implements TestactionDeveloper, Serializable {	
   @In(required=false)
   private Release selectedRelease;
 
   @In(required=false)
   private Priorityclass selectedPriority;
 
   @In(required=false)
   private Severityclass selectedSeverity;
 
   @In(required=false)
   private User selectedUser;
 
   private Long lastSelectedReleaseID;
   private String lastSelectedPriorityID;
   private Integer lastSelectedSeverityID;
   private String lastSelectedUserID;
 
   @Factory("testactionsForDeveloper")
   public void initTestactions() {
     if(hasAFilterChanged() || shouldRefresh() || testactions == null) {
       testactions = EMHelper.execQuery(em, "from Testaction where
           (TACT_REV_ID=2 or TACT_REV_ID=9) and
           (TACT_BFV_ID=4 or TACT_BFV_ID=99)" +
         generateFilterStatements() +
         "order by TACT_ID asc"
       );
 
       updateFilterHelpers();
     }
     Collections.sort(testactions, new TestactionComparator(column, ascending));
   }
 
   @DataModel(scope=ScopeType.PAGE)
   public List<Testaction> getTestactionsForDeveloper() {
     initTestactions();
     return testactions;
   }


I hope you can help me. I don't know where the problem could be.

Thanks in advance
Newlukai
Newlukai

Joined: 29/Nov/2006 00:00:00
Messages: 125
Offline


Hi,

I think I know why my app doesn't work as expected. As soon as the user changes the selectOneMenu it fires a partial submit. Therefore ICEfaces doesn't update the dataTable.
Now I ask you for a possibility or best practice how to implement such a feature.

The page now looks like:
Code:
<ice:form>
 ...
  <ice:selectOneMenu value="#{prioritySelector.selectedPriorityNumber}"
      partialSubmit="true">
    <f:selectItems value="#{prioritySelector.priorityItems}" />
  </ice:selectOneMenu>
  
  ...
  
  <ice:dataTable var="testaction_var" value="#{testactionsForDeveloper}"
      sortColumn="#{testactionDeveloper.column}"
      sortAscending="#{testactionDeveloper.ascending}">
    <f:facet name="header">
      <h:outputText value="#{ares_messages.label_ResultCount}:
          #{testactionsForDeveloper.rowCount}" />
    </f:facet>
    <h:column>
      <f:facet name="header">
        <ice:commandSortHeader columnName="id">
          <h:outputText value="#{ares_messages.label_testaction_ID}" />
        </ice:commandSortHeader>
      </f:facet>
      <ice:commandLink value="#{testaction_var.ID}"
          action="#{testactionDeveloper.select}" styleClass="rightAlignment" />
    </h:column>
  ...
  </ice:dataTable>
 </ice:form>


So I could use the valueChangeListener for other things. I just inspected the address demo and saw that there's a PhaseListener updating the values for some components. Would that be a solution or is there another, less complex option?
Newlukai

Joined: 29/Nov/2006 00:00:00
Messages: 125
Offline


I just tried to implement a PhaseListener that updates the dataTable after the INCOKE_APPLICATION phase. But the more I try to realise it (there are a lot of exceptions ;)) the more I'm satisfied that it isn't a good thing in respect of software design.

I just have a page with several filters (selectOneMenus) and a dataTable. Everytime the user changes a filter the new filter value should be applied on that dataTable.
As far as I can see it shouldn't be necessary to introduce a phase listener that is invoked everytime for a feature that only applies in one special case.

The selectOneMenu performs a partial submit, the backing bean changes the model of the dataTable. And I don't know if I'm right in this point: ICEfaces doesn't update the dataTable because it didn't perform the submit but the selectOneMenu.
This decision happens obviously on client side since the getter of that dataTable model is called several times.

Isn't there anybody who implemented such a filtering already? Or somebody with an idea how to implement it?
grief

Joined: 15/Dec/2006 00:00:00
Messages: 6
Offline


hi!

did you find a solution for your problerm?
i'm fasing the same

gernot

zark

Joined: 09/Jun/2006 00:00:00
Messages: 90
Offline


Hi Newlukai and grief

Maybe you must use renderable to resolve this problem.

Read Chapter 5 Advanced Topics of ICEfacesDevelopersGuide.pdf this chapter talk about Server-initiated Rendering API.


you can see and download ICEfacesDevelopersGuide.pdf from: http://icefaces.org/docs/v1_5_3/ICEfacesDevelopersGuide.pdf

Good luck,
zark
Newlukai

Joined: 29/Nov/2006 00:00:00
Messages: 125
Offline


Hi,

in my desparation I removed the @Factory annotation and set the value attribute of the ice:dataTable to #{testactionDeveloper.testactionsForDeveloper} instead of #{testactionsForDeveloper}. This worked for me regarding the filtering of the list.

But this change just causes another problem. The list shows the current data. The user should now have the possibility to click on an ID (see the ice:commandLink in my code) what invokes a method that navigates to another page where the selected testaction is shown. To retrieve the selected item I use an annotation from Seam, @DataModelSelection. But the annotated field doesn't get the correct value any more, it's null.
If I undo the changes that I made to get the filters working the @DataModelSelection gets the correct value.

I'll have a look at the Rendering API, I think. Or perhaps somebody has an idea how the get such a feature to work with Seam and ICEfaces.

Regards
Newlukai
Newlukai

Joined: 29/Nov/2006 00:00:00
Messages: 125
Offline


OK. I modified the bean that populates the list as follows:

Code:
@Stateful
 @Scope(ScopeType.SESSION)
 @LoggedIn
 @Name("testactionDeveloper")
 public class TestactionDeveloperAction extends TestactionHandling implements TestactionDeveloper, Serializable, Renderable {
 	@In(required=false)
 	private Release selectedRelease;
 	
 	@In(required=false)
 	private Priorityclass selectedPriority;
 	
 	@In(required=false)
 	private Severityclass selectedSeverity;
 	
 	@In(required=false)
 	private User selectedUser;
 	
 	private Long lastSelectedReleaseID;
 	private String lastSelectedPriorityID;
 	private Integer lastSelectedSeverityID;
 	private String lastSelectedUserID;
 	
 	[b]private PersistentFacesState state;
 	private RenderManager renderManager;[/b]
 	
 	
 	[b]public TestactionDeveloperAction() {
 		state = PersistentFacesState.getInstance();
 	}[/b]
 
 	[b]@Factory("testactionsForDeveloper")[/b]
 	public void initTestactions() {
 		if(hasAFilterChanged() || shouldRefresh() || testactions == null) {
 			testactions = EMHelper.execQuery(em, "from Testaction where (TACT_REV_ID=2 or TACT_REV_ID=9) and (TACT_BFV_ID=4 or TACT_BFV_ID=99)" +
 					generateFilterStatements() +
 					"order by TACT_ID asc"
 			);
 			
 			updateFilterHelpers();
 			
 			[b]renderManager.requestRender(this);[/b]
 		}
 		Collections.sort(testactions, new TestactionComparator(column, ascending));
 	}
 	
 	@DataModel
 	public List<Testaction> getTestactionsForDeveloper() {
 		initTestactions();
 		return testactions;
 	}
 	
 	[b]public void setRenderManager(RenderManager renderManager) {
 		this.renderManager = renderManager;
 	}
 	
 	public PersistentFacesState getState() {
 		return state;
 	}
 	
 	public void renderingException(RenderingException renderingException) {
 		renderingException.printStackTrace();
 	}[/b]
 
 ...
 


Additionally my .ear now looks like this:

Code:
EAR
   META-INF
     application.xml (icefaces.jar and icefaces-comp.jar as module)
     jboss-app.xml
   JAR
     com (sources)
     META-INF
       ejb-jar.xml
       persistence.xml
     seam.properties
   WAR
     WEB-INF
       lib
         el-api.jar
         el-ri.jar
         icefaces-facelets.jar
         icefaces.jar
         jboss-seam-debug.jar
         jboss-seam-ui.jar
         selectitems-ui.jar
         selectitems.jar
       components.xml (including bean configuration for RenderManager)
       faces-config.xml
       navigation.xml
       web.xml
     pages, css, image and js stuff
   icefaces-comps.jar
   icefaces.jar
   jboss-seam.jar


When I now change a filter the result is still the same: The datModel shows old values. And the console shows many errors:

Code:
11:25:14,625 ERROR [PhaseListenerManager] Exception in PhaseListener RENDER_RESPONSE(6) beforePhase.
 java.lang.IllegalStateException: No active event context
 	at org.jboss.seam.core.Manager.instance(Manager.java:260)
 	at org.jboss.seam.jsf.AbstractSeamPhaseListener.beforeRender(AbstractSeamPhaseListener.java:173)
 	at org.jboss.seam.jsf.SeamPhaseListener.beforePhase(SeamPhaseListener.java:53)
 	at org.apache.myfaces.lifecycle.PhaseListenerManager.informPhaseListenersBefore(PhaseListenerManager.java:70)
 	at org.apache.myfaces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:373)
 	at com.icesoft.faces.webapp.xmlhttp.PersistentFacesState.render(PersistentFacesState.java:180)
 	at com.icesoft.faces.async.render.RunnableRender.run(RunnableRender.java:89)
 	at edu.emory.mathcs.backport.java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:650)
 	at edu.emory.mathcs.backport.java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:675)
 	at java.lang.Thread.run(Thread.java:595)
 11:25:14,625 ERROR [D2DFaceletViewHandler] Problem in renderResponse: No Factories configured for this Application. This happens if the faces-initialization does not work at all - make sure that you properly include all configuration settings necessary for a basic faces application and that all the necessary libs are included. Also check the logging output of your web application and your container for any exceptions!
 If you did that and find nothing, the mistake might be due to the fact that you use some special web-containers which do not support registering context-listeners via TLD files and a context listener is not setup in your web.xml.
 A typical config looks like this;
 <listener>
   <listener-class>org.apache.myfaces.webapp.StartupServletContextListener</listener-class>
 </listener>
 
 java.lang.IllegalStateException: No Factories configured for this Application. This happens if the faces-initialization does not work at all - make sure that you properly include all configuration settings necessary for a basic faces application and that all the necessary libs are included. Also check the logging output of your web application and your container for any exceptions!
 If you did that and find nothing, the mistake might be due to the fact that you use some special web-containers which do not support registering context-listeners via TLD files and a context listener is not setup in your web.xml.
 A typical config looks like this;
 <listener>
   <listener-class>org.apache.myfaces.webapp.StartupServletContextListener</listener-class>
 </listener>
 
 	at javax.faces.FactoryFinder.getFactory(FactoryFinder.java:90)
 	at javax.faces.component.UIComponentBase.getRenderer(UIComponentBase.java:742)
 	at javax.faces.component.UIComponentBase.encodeBegin(UIComponentBase.java:509)
 	at com.icesoft.faces.application.D2DViewHandler.renderResponse(D2DViewHandler.java:579)
 	at com.icesoft.faces.application.D2DViewHandler.renderResponse(D2DViewHandler.java:586)
 	at com.icesoft.faces.facelets.D2DFaceletViewHandler.renderResponse(D2DFaceletViewHandler.java:276)
 	at com.icesoft.faces.application.D2DViewHandler.renderView(D2DViewHandler.java:149)
 	at org.apache.myfaces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:384)
 	at com.icesoft.faces.webapp.xmlhttp.PersistentFacesState.render(PersistentFacesState.java:180)
 	at com.icesoft.faces.async.render.RunnableRender.run(RunnableRender.java:89)
 	at edu.emory.mathcs.backport.java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:650)
 	at edu.emory.mathcs.backport.java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:675)
 	at java.lang.Thread.run(Thread.java:595)
 11:25:14,625 ERROR [STDERR] com.icesoft.faces.webapp.xmlhttp.TransientRenderingException: transient render failure for viewNumber 1
 11:25:14,625 ERROR [STDERR] 	at com.icesoft.faces.webapp.xmlhttp.PersistentFacesState.render(PersistentFacesState.java:194)
 11:25:14,625 ERROR [STDERR] 	at com.icesoft.faces.async.render.RunnableRender.run(RunnableRender.java:89)
 11:25:14,625 ERROR [STDERR] 	at edu.emory.mathcs.backport.java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:650)
 11:25:14,625 ERROR [STDERR] 	at edu.emory.mathcs.backport.java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:675)
 11:25:14,656 ERROR [STDERR] 	at java.lang.Thread.run(Thread.java:595)


Those errors are thrown something about 6 times.

Regards
Newlukai
philip.breau


Joined: 08/May/2006 00:00:00
Messages: 2989
Offline


Hi Newlukai,

You shouldn't have to do server-initiated rendering to get this to work, because there's a client-initiated event involved. This is just convoluting the problem, as we have a bug with AJAX Push + Seam. So...first off...remove the requestRender(). Then I would suggest ruling out any conversion problems by sticking an <ice:messages/> and seeing if there are any error messages.

Thanks,
Philip

.
 
Forum Index -> Components
Go to:   
Powered by JForum 2.1.7ice © JForum Team