-
1. Re: RichFaces Datascroller with Seam EntityQuery
hapacur Apr 15, 2009 5:48 PM (in response to sandman202)Yes, that works just fine.
- In your view make sure that datatable and datascroller are enclosed in a form.
- Don't use setMaxResults instead use the rows attribute in datatable.
-
2. Re: RichFaces Datascroller with Seam EntityQuery
sandman202 Apr 15, 2009 6:45 PM (in response to sandman202)Thanks Björn! It is working.
-
3. Re: RichFaces Datascroller with Seam EntityQuery
choilee May 28, 2009 4:45 AM (in response to sandman202)when i have more than 1000 records to display, the getResultList method takes very long time to retrieve the records. so, do u have any idea to solve this problem?
-
4. Re: RichFaces Datascroller with Seam EntityQuery
sandman202 May 29, 2009 3:22 PM (in response to sandman202)My suggestion would be to check your indexes and possibly adjust them. Right now, I do not have 1000 records to be displayed.
-
5. Re: RichFaces Datascroller with Seam EntityQuery
sburgula1 Oct 23, 2009 8:30 PM (in response to sandman202)Could someone please post a sample code here. I am trying to display rich:dataScroller. I am able to display it on top of the table, but I am not able to go through the pages. If sample code is posted, I can cross verify with it.
-
6. Re: RichFaces Datascroller with Seam EntityQuery
sandman202 Oct 23, 2009 10:40 PM (in response to sandman202)Here is how I am using dataScroller.
<a4j:form id="phoneTableForm"> <div class="association" id="phones"> <h:outputText value="No phone number exists" rendered="#{newUzer ? true : empty phoneList.resultList}"/> <rich:dataTable id="phoneList" var="_phone" value="#{phoneList.resultList}" rendered="#{newUzer ? false : not empty phoneList.resultList}" rows="#{optionsCache.load().maxTableRows}"> <rich:column rendered="#{phoneFrom eq '/role/admin/PhoneList'}"> <f:facet name="header"> <s:decorate template="/layout/sort.xhtml"> <ui:param name="entityListName" value="phoneList"/> <ui:param name="entityList" value="#{phoneList}"/> <ui:param name="propertyLabel" value="Name"/> <!-- doesn't support two sort fields --> <ui:param name="propertyPath" value="uzer.name"/> </s:decorate> </f:facet> <s:link id="view" value="#{_phone[1].name}" view="/role/admin/Uzer.xhtml" propagation="none"> <f:param name="uzerFrom" value="/role/admin/PhoneList"/> <f:param name="selectedTab" value="PhoneTab"/> <f:param name="phoneListSort" value="phone.type"/> <f:param name="uzerId" value="#{_phone[1].id}"/> </s:link> </rich:column> <rich:column> <f:facet name="header"> <s:decorate template="/layout/sort.xhtml"> <ui:param name="entityListName" value="phoneList"/> <ui:param name="entityList" value="#{phoneList}"/> <ui:param name="propertyLabel" value="Type"/> <!-- doesn't support two sort fields --> <ui:param name="propertyPath" value="phone.type"/> </s:decorate> </f:facet> #{_phone[0].type} </rich:column> <rich:column> <f:facet name="header"> <s:decorate template="/layout/sort.xhtml"> <ui:param name="entityListName" value="phoneList"/> <ui:param name="entityList" value="#{phoneList}"/> <ui:param name="propertyLabel" value="Number"/> <!-- doesn't support two sort fields --> <ui:param name="propertyPath" value="phone.phoneNumber"/> </s:decorate> </f:facet> #{_phone[0].phoneNumber} </rich:column> <rich:column> <f:facet name="header"> <s:decorate template="/layout/sort.xhtml"> <ui:param name="entityListName" value="phoneList"/> <ui:param name="entityList" value="#{phoneList}"/> <ui:param name="propertyLabel" value="Ext"/> <!-- doesn't support two sort fields --> <ui:param name="propertyPath" value="uzer.ext"/> </s:decorate> </f:facet> #{_phone[0].ext} </rich:column> <rich:column> <f:facet name="header">Action</f:facet> <s:link view="#{empty from ? '/role/admin/Phone' : from}.xhtml" value="Select" id="phoneSelect"> <!-- Do not use propagation="none", because it will turn off the lookups --> <f:param name="phoneFrom" value="/role/admin/PhoneList"/> <f:param name="phoneId" value="#{_phone[0].id}"/> </s:link> </rich:column> <f:facet name="footer"> <rich:datascroller pageIndexVar="pageIndex" pagesVar="pages" maxPages="25"/> <ui:remove> <rich:datascroller pageIndexVar="pageIndex" pagesVar="pages" boundaryControls="hide" stepControls="hide" fastControls="show"> <f:facet name="pages"> <h:outputText style="whitespace: nowrap" value="Page #{pageIndex} of #{pages}"></h:outputText> </f:facet> </rich:datascroller> </ui:remove> </f:facet> </rich:dataTable> </div> </a4j:form>
-
7. Re: RichFaces Datascroller with Seam EntityQuery
blabno Oct 26, 2009 11:55 PM (in response to sandman202)Problem with rich datascroller and EntityQuery is that datamodel provided by Seam causes entityQuery to fetch all entities and pagination happens on datascroller component. This is why your app gets slow. You need database pagination. I've written very usefull datamodel to solve this.
import javax.faces.model.DataModel; import javax.persistence.EntityManager; import java.lang.reflect.Type; import java.lang.reflect.ParameterizedType; import java.lang.reflect.TypeVariable; public class EntityQuery<T> extends org.jboss.seam.framework.EntityQuery<T> { private EntityQueryDataModel entityQueryDataModel; private Integer currentPage; @Override public DataModel getDataModel() { if (entityQueryDataModel == null) { entityQueryDataModel = EntityQueryDataModel.getInstance(this); } return entityQueryDataModel; } @Override public void clearDataModel() { entityQueryDataModel = null; } public Integer getCurrentPage() { return currentPage; } public void setCurrentPage(Integer page) { if (getMaxResults() != null) { setFirstResult(page * getMaxResults()); } this.currentPage = page; } }
public class EntityQueryDataModel<T, K> extends ExtendedDataModel { private K rowKey; private EntityQuery<T> dataProvider; private Field idField; private Method idGetter; private Map<K, T> wrappedData = new HashMap<K, T>(); private Class<T> itemClass; private int rowCount = -1; protected Log log = Logging.getLog(EntityQueryDataModel.class); public static EntityQueryDataModel getInstance(EntityQuery query) { return new EntityQueryDataModel(query); } @SuppressWarnings("unchecked") public EntityQueryDataModel(EntityQuery<T> query) { dataProvider = query; this.itemClass = (Class) ((ParameterizedType) dataProvider.getClass().getGenericSuperclass()).getActualTypeArguments()[0]; Class iClass = itemClass; do { for (Field field : iClass.getDeclaredFields()) { if (field.getAnnotation(Id.class) != null) { idField = field; break; } } iClass = iClass.getSuperclass(); } while (idField == null && iClass.getSuperclass() != null); if (idField == null) { for (Method method : itemClass.getMethods()) { if (method.getAnnotation(Id.class) != null) { idGetter = method; break; } } } else if (!Modifier.isPublic(idField.getModifiers())) { String idGetterName = "get" + idField.getName().substring(0, 1).toUpperCase() + idField.getName().substring(1); try { idGetter = itemClass.getMethod(idGetterName); } catch (NoSuchMethodException e) { throw new IllegalArgumentException("@Id annotated field " + idField.getName() + " is not public and there is no public accessor " + idGetterName); } } if (idField == null && idGetter == null) { throw new IllegalArgumentException("Entity must have @Id annotated property."); } } @SuppressWarnings("unchecked") public void setRowKey(Object o) { rowKey = (K) o; } public Object getRowKey() { return rowKey; } public void walk(FacesContext facesContext, DataVisitor dataVisitor, Range range, Object o) throws IOException { int firstRow = ((SequenceRange) range).getFirstRow(); int numberOfRows = ((SequenceRange) range).getRows(); log.trace("Walking over #1 rows from #0", firstRow, numberOfRows); List<K> wrappedKeys = new ArrayList<K>(); if (dataProvider.getFirstResult() == null || dataProvider.getFirstResult() != firstRow) { dataProvider.setFirstResult(firstRow); } if (dataProvider.getMaxResults() == null || dataProvider.getMaxResults() != numberOfRows) { dataProvider.setMaxResults(numberOfRows); } int i = 0; for (T item : dataProvider.getResultList()) { log.trace("Retrived item #0", i++); K id = getId(item); wrappedKeys.add(id); wrappedData.put(id, item); dataVisitor.process(facesContext, id, o); } log.trace("Walking done"); } public boolean isRowAvailable() { if (getRowKey() == null) { return false; } else { log.trace("Checking if row with id #0 is available", getRowKey()); return null != wrappedData.get(getRowKey()); } } public int getRowCount() { log.trace("Getting results count"); if (rowCount == -1) { rowCount = dataProvider.getResultCount().intValue(); } log.trace("Results count is #0", rowCount); return rowCount; } public Object getRowData() { if (getRowKey() == null) { return null; } else { T item = wrappedData.get(getRowKey()); if (item == null) { log.trace("Row data for key #0 not found in cache. Retriving from data provider.", getRowKey()); item = getCurrentItem(); wrappedData.put((K) getRowKey(), item); return item; } else { log.trace("Row data found in cache as #0", item); return item; } } } public int getRowIndex() { throw new UnsupportedOperationException(); } public void setRowIndex(int i) { throw new UnsupportedOperationException(); } public Object getWrappedData() { throw new UnsupportedOperationException(); } public void setWrappedData(Object o) { throw new UnsupportedOperationException(); } @SuppressWarnings("unchecked") private K getId(T item) { try { return (K) (idGetter != null ? idGetter.invoke(item) : idField.get(item)); } catch (Exception e) { throw new RuntimeException(e); } } private T getCurrentItem() { log.trace("Fetching current row item for key #0", getRowKey()); return dataProvider.getEntityManager().find(itemClass, getRowKey()); } }
Now you can use it like this :
<rich:dataTable value="#{query.dataModel}" var="item" rows="#{personsVotes.maxResults}"> ... <rich:datascroller page="#{query.currentPage}"/>
-
8. Re: RichFaces Datascroller with Seam EntityQuery
hitcurst Feb 16, 2010 9:33 PM (in response to sandman202)Thansk for solution, very good !
-
9. Re: RichFaces Datascroller with Seam EntityQuery
sandman202 Mar 20, 2010 3:07 AM (in response to sandman202)Bernard, I implemented the code you provided and came across something strange. When I have a listing that spans multiple pages and click next to go from page 1 to page 2, it works fine. However, when I click next again to go from page 2 to page 3, it takes me back to page 1.
Have you run across this problem?
Scott
-
10. Re: RichFaces Datascroller with Seam EntityQuery
sandman202 Mar 23, 2010 3:29 AM (in response to sandman202)I did a little more investigation and found that the individual page number buttons are working correctly. It is the
next
button that is causing the problems.Scott
-
11. Re: RichFaces Datascroller with Seam EntityQuery
blabno Mar 24, 2010 9:21 AM (in response to sandman202)No, I haven't come across anything like it. Maybe there is a problem with scopes?
-
12. Re: RichFaces Datascroller with Seam EntityQuery
sandman202 Mar 24, 2010 6:42 PM (in response to sandman202)The strange thing is on another listing where I did not make the changes above, the paging, first, last, next and previous works fine. On the listing where I was testing the above changes, the only parts not working are the next and previous. So, the reason I asked if you had noticed the same problems was I was wondering if I needed to change the next and previous code like you did to the page code.
My listings are using the event scope. I will try later other scope types to see if it starts working.
Do you think it might have to do with the version of Richfaces or Seam? I am using 2.1.1.GA Seam and 3.3.0.GA Richfaces.
-
13. Re: RichFaces Datascroller with Seam EntityQuery
blabno Mar 25, 2010 8:56 AM (in response to sandman202)Absolutely not a version problem. Try using broader scope first.
-
14. Re: RichFaces Datascroller with Seam EntityQuery
sandman202 Mar 25, 2010 2:23 PM (in response to sandman202)I changed the scope from EVENT to CONVERSATION and the results are the same.