5 Replies Latest reply on Mar 16, 2009 1:01 PM by konstantin.mishin

    Please help on rich:scrollableDataTable / ScrollableTableDat

    unlud

      Hi,

      I try to have such a component for pagination with a table which has a primary key of type string.

      My issue for the moment is that when the setRowKey method of ScrollableTableDataModel extended class is called, I get such an exception:

      java.lang.ClassCastException: org.richfaces.model.ScrollableTableDataModel$SimpleRowKey cannot be cast to java.lang.String
       at org.unludo.iknow.jsf.beans.ObjectObjectDataModel.setRowKey(ObjectObjectDataModel.java:72)
       at org.richfaces.model.DataModelCache.setRowKey(DataModelCache.java:185)
       at org.ajax4jsf.component.UIDataAdaptor.setRowKey(UIDataAdaptor.java:351)
      


      I searched but don't knw what to try next.

      I post the code:

      1/ the xhtml piece:
       <rich:scrollableDataTable
       height="400px" width="700px" rows="10"
       value="#{objectObjectDataModel}" columnClasses="col1" var="objectObjectVO">
       <rich:column id="object">
       <f:facet name="header">Object</f:facet>
       <h:outputText value="#{objectObjectVO.id}" />
       </rich:column>
       </rich:scrollableDataTable>
      


      2/ The model:
      public class ObjectObjectDataModel extends ScrollableTableDataModel {
      
       private String currentPk;
       private Map<String,ObjectObjectVO> wrappedData = new HashMap<String,ObjectObjectVO>();
       private List<String> wrappedKeys = null;
       private ObjectObjectDataProvider dataProvider;
      
       private static Logger logger = Logger.getLogger(ObjectObjectDataModel.class);
      
       /**
       *
       */
       private static final long serialVersionUID = -1956179896875438628L;
      
       public ObjectObjectDataModel()
       {
       logger.info("creation of data provider") ;
       dataProvider = new ObjectObjectDataProvider();
       }
      
       /**
       * This method never called from framework.
       * (non-Javadoc)
       * @see org.ajax4jsf.model.ExtendedDataModel#getRowKey()
       */
       @Override
       public Object getRowKey() {
       return currentPk;
       }
       /**
       * This method normally called by Visitor before request Data Row.
       */
       @Override
       public void setRowKey(Object key) {
       logger.info("setRowKey " + key + key != null ? key.getClass() : "") ;
       this.currentPk = (String) key;
      
       }
       /**
       * This is main part of Visitor pattern. Method called by framework many times during request processing.
       */
       @Override
       public void walk(FacesContext context, DataVisitor visitor, Range range, Object argument) throws IOException {
       logger.info("walk visitor " + visitor) ;
       int firstRow = ((SequenceRange)range).getFirstRow();
       int numberOfRows = ((SequenceRange)range).getRows();
       wrappedKeys = new ArrayList<String>();
       for (ObjectObjectVO item:getDataProvider().getItemsByrange(firstRow, numberOfRows))
       {
       wrappedKeys.add(item.getId());
       wrappedData.put(item.getId(), item);
       visitor.process(context, item.getId(), argument);
       }
       }
       /**
       * This method must return actual data rows count from the Data Provider. It is used by pagination control
       * to determine total number of data items.
       */
       private Integer rowCount; // better to buffer row count locally
       @Override
       public int getRowCount() {
       if (rowCount==null) {
       rowCount = new Integer(getDataProvider().getRowCount());
       return rowCount.intValue();
       } else {
       return rowCount.intValue();
       }
       }
       /**
       * This is main way to obtain data row. It is intensively used by framework.
       * We strongly recommend use of local cache in that method.
       */
       @Override
       public Object getRowData() {
       if (currentPk==null) {
       return null;
       } else {
       ObjectObjectVO ret = wrappedData.get(currentPk);
       if (ret==null)
       {
       ret = (ObjectObjectVO) getDataProvider().getItemByKey(currentPk);
       wrappedData.put(currentPk, ret);
       return ret;
       }
       else
       {
       return ret;
       }
       }
       }
      
       /**
       * Unused rudiment from old JSF staff.
       */
       @Override
       public int getRowIndex() {
       throw new UnsupportedOperationException();
       }
      
       /**
       * Unused rudiment from old JSF staff.
       */
       @Override
       public Object getWrappedData() {
       throw new UnsupportedOperationException();
       }
      
       /**
       * Never called by framework.
       */
       @Override
       public boolean isRowAvailable() {
       if (currentPk==null) {
       return false;
       } else {
       return getDataProvider().hasObjectObjectVOByPk(currentPk);
       }
       }
      
       /**
       * Unused rudiment from old JSF staff.
       */
       @Override
       public void setRowIndex(int rowIndex) {
       throw new UnsupportedOperationException();
       }
      
       /**
       * Unused rudiment from old JSF staff.
       */
       @Override
       public void setWrappedData(Object data) {
       throw new UnsupportedOperationException();
       }
      
       public ObjectObjectDataProvider getDataProvider()
       {
       logger.info("data provider has been accessed") ;
       return dataProvider;
       }
      
       public void setDataProvider(ObjectObjectDataProvider p_o)
       {
       logger.info("data provider has been set") ;
       dataProvider = p_o;
       }
      
      
       @Override
       public
       List loadData(int arg0, int arg1, SortOrder arg2)
       {
       Iterable<ObjectObjectVO> it;
      
       it = getDataProvider().getItemsByrange(arg0, arg1);
      
       if(it == null)
       {
       logger.error("loadData returned null") ;
       return null;
       }
      
       return (List) it;
       }
      
      }


      3/the data provider
      /*
      * To change this template, choose Tools | Templates
      * and open the template in the editor.
      */

      package org.unludo.iknow.jsf.beans.ObjectObject;

      import java.util.List;
      import javax.ejb.EJB;
      import javax.naming.InitialContext;
      import javax.naming.NamingException;
      import org.apache.log4j.Logger;
      import org.richfaces.model.DataProvider;
      import org.unludo.iKnow.ejb.session.ObjectObjectFacadeLocal;
      import org.unludo.iKnow.vo.ObjectObjectVO;

      /**
      *
      * @author Ludovic
      */
      @EJB(name="objectobjectfacaderef", beanInterface=ObjectObjectFacadeLocal.class)
      public class ObjectObjectDataProvider implements DataProvider
      {
      private static Logger logger = Logger.getLogger(ObjectObjectDataProvider.class);

      ObjectObjectFacadeLocal oObjectObjectFacade;

      public ObjectObjectDataProvider()
      {
      try
      {
      InitialContext ic = new InitialContext();
      oObjectObjectFacade = (ObjectObjectFacadeLocal) ic.lookup("java:comp/env/objectobjectfacaderef");
      logger.info("getRowCount oObjectObjectFacade constructor" + oObjectObjectFacade) ;
      }
      catch (NamingException ex)
      {
      logger.error("getRowCount oObjectObjectFacade null " + ex) ;
      }
      }

      public
      Iterable<ObjectObjectVO> getItemsByrange(int firstRow, int numberOfRows)
      {
      List<ObjectObjectVO> lvo =oObjectObjectFacade.getList(firstRow, numberOfRows);

      logger.info("getItemsByrange first row "+ firstRow + "nb rows " + numberOfRows + " -> " + lvo) ;

      return lvo;
      }

      @Override
      public
      int getRowCount()
      {
      Long nbObject = oObjectObjectFacade.count();
      logger.info("getRowCount nb objects" + nbObject);

      return nbObject.intValue();
      }

      public
      int count()
      {

      Long nbObject = oObjectObjectFacade.count();

      return nbObject.intValue();
      }

      @Override
      public
      List getItemsByRange(int arg0, int arg1)
      {
      return oObjectObjectFacade.getList(arg0, arg1);
      }

      @Override
      public
      Object getItemByKey(Object arg0)
      {
      return oObjectObjectFacade.find((String)arg0);
      }

      @Override
      public
      Object getKey(Object arg0)
      {
      return ((ObjectObjectVO)arg0).getId();
      }

      public boolean hasObjectObjectVOByPk(String p_sId)
      {
      return (getItemByKey(p_sId) != null);
      }
      }


      Any help would be greatly appreciated.
      Also if some one knows about a consistent example of this component, I would be interested. If not, I will post something if I find a solution.

      Thank you
      Ludo


        • 1. Re: Please help on rich:scrollableDataTable / ScrollableTabl

          Hi Ludo, maybe getRowKey should be of some numeric type?

          According to API it could be of any type:
          http://www.jboss.org/file-access/default/members/jbossrichfaces/freezone/docs/apidoc_framework/org/richfaces/model/ScrollableTableDataModel.html

          But quick search in qoogle shows, that public implementations use e.g. BigDecimal - maybe String should not be used although the API allow this?

          Just try - replace String with BigDecimal.....maybe this helps

          wfg
          rschoeler

          • 2. Re: Please help on rich:scrollableDataTable / ScrollableTabl
            unlud

            thanks rschoeler,

            The issue is that my table has a PK as string, so using Bigdecimal or Integer for the key does not work for me.

            thanks
            Ludo

            • 3. Re: Please help on rich:scrollableDataTable / ScrollableTabl
              nbelaevski

              Hello Ludo,

              I guess the problem is because rowKeyConverter is not provided. Please declare it (for String case it should be just no-operation convereter).

              • 4. Re: Please help on rich:scrollableDataTable / ScrollableTabl
                unlud

                thanks nbelaevski!

                I still need a little help.
                Here is what I tried (I searched but found nothing strikingly obvious):

                1/ in the xhtml page I declared a converter

                <rich:scrollableDataTable
                height="400px" width="700px" rows="10"
                value="#{objectObjectDataModel}" rowKeyConverter="myConverter" columnClasses="col1" var="objectObjectVO">
                <rich:column id="object">
                <f:facet name="header">Object</f:facet>
                <h:outputText value="#{objectObjectVO.id}" />
                </rich:column>
                </rich:scrollableDataTable>


                2/ I declared the converter into faces-config.xml

                <converter>
                <converter-id>myConverter</converter-id>
                <converter-class>org.unludo.iknow.jsf.beans.ObjectObject.NoOpConverter</converter-class>
                </converter>


                3/ I created my do nothing converter

                public class NoOpConverter implements Converter
                {
                private static Logger logger = Logger.getLogger(NoOpConverter.class);

                @Override
                public
                Object getAsObject(FacesContext arg0, UIComponent arg1, String arg2)
                {
                logger.info("getAsObject") ;
                return arg2;
                }

                @Override
                public
                String getAsString(FacesContext arg0, UIComponent arg1, Object arg2)
                {
                logger.info("getAsString") ;
                return (String) arg2;
                }


                I also tried:
                4/ override the following methods, but they are never called:
                public javax.faces.convert.Converter getRowKeyConverter()
                {
                logger.info("getRowKeyConverter") ;
                return null;
                }

                public void setRowKeyConverter(javax.faces.convert.Converter rowKeyConverter)
                {
                logger.info("setRowKeyConverter") ;

                }


                So I still have the same exception:
                java.lang.ClassCastException: org.richfaces.model.ScrollableTableDataModel$SimpleRowKey cannot be cast to java.lang.String
                at org.unludo.iknow.jsf.beans.ObjectObjectDataModel.setRowKey(ObjectObjectDataModel.java:70)
                at org.richfaces.model.DataModelCache.setRowKey(DataModelCache.java:185)


                Because the key is of type string and the setRowKey is of type
                org.richfaces.model.ScrollableTableDataModel$SimpleRowKey

                with this value: srk0class

                I still miss something.

                Any help would be very appreciated.

                thanks
                Ludo


                • 5. Re: Please help on rich:scrollableDataTable / ScrollableTabl
                  konstantin.mishin

                  Post full stacktrace of exception, please.