5 Replies Latest reply on Jan 21, 2011 11:04 AM by Shriharsh Mishra

    Issue while using Extended Data Model in Data Table

    TV Ramprasadh Newbie

      As part of the implementation of our own datamodel, extending ScrollableTableDataModel, we implemented an enhancement, i.e. storing the objectid as rowkey instead of the row index.

      This in order to facilitate retrieving objects efficiently after operations on the table such as sorting. This rowkeyvar is sent to the client, rendered as part of the clientid of each row.

      This seems to be working properly right after search and when navigating between the pages. However, as soon as the tables gets sorted there seems to go something wrong in the dataTable:

      the rowkeyvar rendered as part of the clientid in the datatable is no longer the objecid but again the rowindex, which makes any context menu operation on that row fail as as part of the action, we need to get the object based on the String object id but we get the row index instead

        • 1. Re: Issue while using Extended Data Model in Data Table
          TV Ramprasadh Newbie

          Missed to add the stak trace we get:

          java.lang.ClassCastException: java.lang.Integer
          at com.approach.view.arval.jsf.util.MyDataModel.setRowKey(MyDataModel.java:57)
          at org.richfaces.model.ModifiableModel.setRowKey(ModifiableModel.java:99)
          at org.ajax4jsf.component.UIDataAdaptor.setRowKey(UIDataAdaptor.java:356).

          • 2. Re: Issue while using Extended Data Model in Data Table
            Maksim Kaszynski Apprentice

            Ramprasadh TV,
            which component are you using this model for?
            If it is scrollableDataTable then I wonder how ModifiableModel got into stack trace.
            If it is dataTable than why ScrollabletableDataModel.

            It will be very nice if you post page snippet where you have this problem, and MyDataModel class declaration (I mean superclass and interfaces)
            Thank you

            • 3. Re: Issue while using Extended Data Model in Data Table- Sor
              TV Ramprasadh Newbie

              Thanks

              We are using Rich Data table.
              We tried extending SerializableDataModel as well as ScrollableTableData Model.

              Initially we used Scrollable model. We did not know that it is meant only for scrollable data table and also the load data has a min and max.

              However, In both cases we faced the issue after sorting. the row key variable gets the row index (type integer) and not the actual object id of type String that we set before sorting.

              Request your help

              Attaching code for both cases:

              First one is for ScrollableTableData and second is for SerializableData Model

              -------------------------------------------------------
              Code:
              Extending ScrollableTableDataModel
              public class MyDataModel extends ScrollableTableDataModel {

              private List data;
              private Map<String, IListable> wrappedData = new HashMap<String, IListable>();
              private List wrappedKeys = null;
              private String currentPk;
              private boolean detached = false;
              //private SortOrder currentSortOrder;
              @Override
              public List loadData(int arg0, int arg1, SortOrder arg2) {
              List fieldList = new ArrayList();
              for (SortField field : arg2.getFields()) {
              fieldList.add(field.getIndex(), field);
              }
              return getData().subList(arg0, arg1);

              }

              @Override
              public Object getRowKey() {
              return currentPk;
              }

              /**
              * This method normally called by Visitor before request Data Row.
              */
              @Override
              public void setRowKey(Object key) {
              if(key instanceof Integer){
              this.currentPk=key.toString();
              }else
              this.currentPk = (String) key;

              }

              @Override
              public int getRowCount() {
              if (getData() != null) {
              return getData().size();
              } else {
              return 0;
              }
              }

              @Override
              public Object getWrappedData() {
              throw new UnsupportedOperationException("Not supported yet.");
              }

              @Override
              public void walk(FacesContext context, DataVisitor visitor, Range range, Object argument) throws IOException {
              //super.walk(arg0, arg1, arg2, arg3);

              int firstRow = ((SequenceRange) range).getFirstRow();
              int rows = ((SequenceRange) range).getRows();

              if (rows <= 0) rows = getRowCount();

              if (detached) {
              for (String key : wrappedKeys) {
              setRowKey(key);
              visitor.process(context, key, argument);
              }
              } else {
              wrappedKeys = new ArrayList();
              if(getData() != null){
              for (IListable item : getData().subList(firstRow, Math.min(firstRow + rows, getData().size()))) {
              wrappedKeys.add(item.getObjectId());
              wrappedData.put(item.getObjectId(), item);
              visitor.process(context, item.getObjectId(), argument);
              }
              }
              }


              }

              @Override
              public Object getRowData() {
              if (getCurrentPk() == null) {
              return null;
              } else {
              IListable ret = wrappedData.get(getCurrentPk());
              if (ret == null) {
              ret = (IListable) getObjectById(getCurrentPk());
              wrappedData.put(getCurrentPk(), ret);
              return ret;
              } else {
              return ret;
              }
              }
              }

              @Override
              public Object getObjectById(Object id) {

              for (IListable current : getData()) {
              if (current.getObjectId().equals(id)) {
              return current;
              }
              }

              return null;

              }

              @Override
              public void setWrappedData(Object arg0) {
              throw new UnsupportedOperationException("Not supported yet.");
              }

              public List getData() {
              return data;
              }

              public void setData(List data) {
              this.data = data;
              }

              public String getCurrentPk() {
              return currentPk;
              }

              public void setCurrentPk(String currentPk) {
              this.currentPk = currentPk;
              }

              @Override
              public boolean isRowAvailable() {
              if (currentPk == null) {
              return false;
              } else {
              return getObjectById(currentPk) != null;
              }
              }
              /**
              *
              * @param objectId
              * @return
              */
              public int getRowKeyIndex(String objectId){
              return wrappedKeys.indexOf(objectId);
              }
              /**
              *
              * @param index
              * @return
              */
              public String getRowDataByIndex(int index){
              return wrappedKeys.get(index);
              }


              -------------------------------------------------------------------------------

              -------------------------------------------------------
              Code:
              Extending SerializableDataModel

              /**
              * This method suppose to produce SerializableDataModel that will be serialized into View State and used on a post-back.
              * In current implementation we just mark current model as serialized. In more complicated cases we may need to
              * transform data to actually serialized form.
              */
              public SerializableDataModel getSerializableModel(Range range) {
              if (wrappedKeys != null) {
              detached = true;
              //Some activity to detach persistent data from wrappedData map may be taken here.
              //In that specific case we are doing nothing.
              return this;
              } else {
              return null;
              }
              }

              /* (non-Javadoc)
              * @see org.ajax4jsf.model.SerializableDataModel#update()
              */
              @Override
              public void update() {

              }

              /**
              * 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) {
              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 {
              int firstRow = ((SequenceRange) range).getFirstRow();
              int numberOfRows = ((SequenceRange) range).getRows();
              if (detached) { // Is this serialized model
              // Here we just ignore current Rage and use whatever data was saved in serialized model.
              // Such approach uses much more getByPk() operations, instead of just one request by range.
              // Concrete case may be different from that, so you can just load data from data provider by range.
              // We are using wrappedKeys list only to preserve actual order of items.
              for (String key : wrappedKeys) {
              setRowKey(key);
              visitor.process(context, key, argument);
              }
              } else { // if not serialized, than we request data from data provider
              wrappedKeys = new ArrayList();
              for (IListable item : getData().subList(firstRow,
              Math.min(firstRow + numberOfRows, getData().size()))) {
              //for (AuctionItem item : dataProvider.getItemsByrange(new Integer(firstRow),numberOfRows, null, true)) {
              wrappedKeys.add(item.getObjectId());
              wrappedData.put(item.getObjectId(), item);
              visitor.process(context, item.getObjectId(), 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(getData().size());
              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 {
              IListable ret = wrappedData.get(currentPk);
              if (ret == null) {
              ret = getObjectById(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 hasObjectById(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();
              }

              /**
              * @return the currentPk
              */
              public String getCurrentPk() {
              return this.currentPk;
              }

              /**
              * @param currentPk the currentPk to set
              */
              public void setCurrentPk(String currentPk) {
              this.currentPk = currentPk;
              }

              /**
              * @return the data
              */
              public List getData() {
              return this.data;
              }

              /**
              * @param data the data to set
              */
              public void setData(List data) {
              this.data = data;
              }

              /**
              * @return the detached
              */
              public boolean isDetached() {
              return this.detached;
              }

              /**
              * @param detached the detached to set
              */
              public void setDetached(boolean detached) {
              this.detached = detached;
              }

              /**
              * @return the wrappedKeys
              */
              public List getWrappedKeys() {
              return this.wrappedKeys;
              }

              /**
              * @param wrappedKeys the wrappedKeys to set
              */
              public void setWrappedKeys(List wrappedKeys) {
              this.wrappedKeys = wrappedKeys;
              }

              /**
              * @param wrappedData the wrappedData to set
              */
              public void setWrappedData(Map<String, IListable> wrappedData) {
              this.wrappedData = wrappedData;
              }

              public IListable getObjectById(String pk) {
              for (IListable item : getData()) {
              if (item.getObjectId().equals(pk)) {
              return item;
              }
              }
              return null;
              //throw new RuntimeException("Object Item pk=" + pk.toString() + " not found");
              }

              public boolean hasObjectById(String pk) {
              for (IListable item : getData()) {
              if (item.getObjectId().equals(pk)) {
              return true;
              }
              }
              return false;

              }

              /**
              *
              * @param objectId
              * @return
              */

              public int getRowKeyIndex(String objectId) {
              return wrappedKeys.indexOf(objectId);
              }

              /**
              *
              * @param index
              * @return
              */

              public String getRowDataByIndex(int index) {
              return wrappedKeys.get(index);
              }

              public List loadData(int arg0, int arg1, SortOrder arg2) {
              List fieldList = new ArrayList();
              for (SortField field : arg2.getFields()) {
              fieldList.add(field.getIndex(), field);
              }
              return getData().subList(arg0, arg1);

              }

              • 4. Sorting Issue - Re: Issue while using Extended Data Model in
                TV Ramprasadh Newbie

                Hi

                Can you please help.

                Is there any chance that when rendering the data table after sorting the rowkey variable is set the row no instead of the object id we set initially. This is when you extend using the Serializable or Scrollable Table data model.

                Appreciate your inputs. Code snippet and other details in the below thread.

                • 5. Re: Issue while using Extended Data Model in Data Table
                  Shriharsh Mishra Newbie

                  Hi Ramprasadh,

                   

                  Were you able to extend ScrollableTableDataModel successfully?

                   

                   

                  Thanks,

                  Shriharsh