6 Replies Latest reply on Feb 3, 2009 1:21 AM by atulkc

    a4j push related problem

    atulkc

      Hi,

      In our project we are using a4j:push tag to dynamically refresh certain portions of our web page depending upon events generated on server side. The problem that I am seeing is that some times (not always!) a4j push does not reRender the target id specified even though PushEventListener is notified of an Event.

      Here is my xhtml that uses a4j:push tag:

      <a4j:push reRender="myTableId" eventProducer="#{myBean.addListener}" interval="10000"
       ignoreDupResponses="true" action="#{mybean.populateViewModel}" enabled="false"/>
      <rich:dataTable id="myTableId" value="#{myBean.data}" var="_data">
      <rich:column>
      <h:outputText value="#{_data.name}" />
      </rich:column>
      </rich:dataTable>
      

      Note that I have simplified the table definition for this post (in reality it consists of lot more columns)

      Backing bean definition is as follows:
      @Stateful
      @Local( {
       MyBeanLocal.class
      })
      @Name("myBean")
      @Scope(ScopeType.SESSION)
      @Restrict("#{identity.loggedIn}")
      public class MyBean implements MyBeanLocal, Serializable {
      
       @EJB
       private MyEJB ejb;
      
       private MyBeanListener eventListener;
      
       /**
       * DataModel
       */
       private List<Data> data;
      
       public List<Data> getData() {
       return this.data;
       }
      
      @Create
       public void create() {
       this.data = new ArrayList<Data>();
       populateViewModel();
       }
      
      // destroy method de-registers the listener from DataModel
       @Remove
       @Destroy
       public void destroy() {
       DataModel dataModel = ejb.getDataModel();
       if (dataModel != null) {
       dataModel.removeChangeListener(eventListener);
       }
       }
      
      /**
       * Adds listener for conveying AJAX events.
       *
       * @param listener
       */
       public void addListener(EventListener listener) {
       DataModel dataModel = ejb.getDataModel();
       eventListener = new MyBeanListener();
       eventListener.addListener(listener);
       dataModel.addChangeListener(eventListener);
       }
      
       /**
       * Constructs the view data model required for the link utilization widget on dashboard
       */
       public void populateViewModel() {
       data.clear();
       DataModel dataModel = ejb.getDataModel();
       data = dataModel.getData();
       }
      
      }


      public class MyBeanListener implements Serializable {
      
       private PushEventListener listener;
      
       public void addListener(EventListener l) {
       this.listener = (PushEventListener)l;
       }
      
       public void dataChanged() {
       listener.onEvent(new EventObject(this));
       }
      
      }
      


      public class DataModel {
      
       private List<MyBeanListener> listeners;
      
       public void addChangeListener(MyBeanListener l) {
       listeners.add(l);
       }
      
       public void removeChangeListener(MyBeanListener l) {
       listeners.remove(l);
       }
      
       public void fireEvent() {
       for (MyBeanListener l: listeners) {
       l.dataChanged();
       }
       }
      
       // This method is called on JMS message
       public void onMessage(Message message) {
       // update internal data structure and then notify listeners
       fireEvent();
       }
      
      }


      So what is happening here is that class MyBean is SFSB and registers MyBeanListener with DataModel when addListener is called (by virtue of eventProducer attribute of a4j:push). DataModel is a JMS listener and upon receiving JMS message it notifies the registered listener of change in data.

      What I am seeing here is that all the above described flow happens and a4j:push gets notified of the event (I verified this by checking that populateViewData method of MyBean gets called) but the reRender of 'myTableId' component does not happen. I debugged it using a4j:log component and found that sometimes the ajax response does not contain the component with id 'myTableId'.

      I am not really sure what I am doing wrong here. If anyone could shed some light on why I would face this issue (intermittent failure to reRender the target component) it would be of great help. Just a note: Upon encountering the failure to reRender; if I refresh the web page using browser's refresh button then the table shows correct (updated) values - which means the SFSB (MyBean) has been update properly.


      My environment is as follows:
      JBoss AS: 4.2.2 GA
      JBoss Seam: 2.1.1GA
      JBoss RichFaces: 3.3.0 GA


      Regards,
      Atul