4 Replies Latest reply on Feb 15, 2008 7:13 AM by martin.ahrer

    scrollableDataTable sort-property

    klaus.viehboeck

      I am using a scrollableDatatable to loop through a list of offices that have a certain enterprise, and an enterprise has a description (string).

      so my datatable code looks like this:

      <rich:scrollableDataTable rowKeyVar="rkv" value="#{teilnehmerVerfahrenHandler.geeigneteTeilnehmer}"
       id="tableBieterwahlDB" height="140" width="740px" var="office" sortMode="single"
       headerClass="scrollableListHeader">
      ...
      
       <rich:column id="enterprise" width="300px">
       <f:facet name="header"><h:outputText value="Unternehmen"/></f:facet>
       <h:outputText value="#{office.enterprise.description}" styleClass="standard" />
       </rich:column>
      </rich:scrollableDataTable>
      


      as far as I have found out, the property that is used to sort the table is defined by the id of the row, in this case "enterprise".

      Is there a way to order the table by the "description" property of the enterprise? I tried to use "enterprise.description" in the id,

      <rich:column id="enterprise.description" width="300px">


      which - of course - doesn't work.

        • 1. Re: scrollableDataTable sort-property
          klaus.viehboeck

          I forgot to say that I also experimented with the sortExpression Attribute of the "rich:column" tag, but no luck.

          something like

          <rich:column id="enterprise" width="300px" sortExpression="#{office.enterprise.description}">
          


          • 2. Re: scrollableDataTable sort-property
            maksimkaszynski

            Klaus,
            example 2 and example 3 both look correct.

            Component first tries to get expression string of sortExpression, and if it's not set, it uses id instead.

            Sorting SHOULD work with these attributes. If it doesnt, then it may be something around or something within the component.

            Does scrolling work?
            Do you have a form around the component?

            • 3. Re: scrollableDataTable sort-property
              klaus.viehboeck

              The scrolling works, and the component is in an a4j:Form.

              I always get a property not found exception.

              <rich:scrollableDataTable value="#{handler.geeigneteTeilnehmer}"
               id="tableBieterwahlDB" var="office" sortMode="single">
              
               <rich:column id="enterprise" width="300px" sortExpression="#{office.enterprise.description}">
               <f:facet name="header"><h:outputText value="Unternehmen"/></f:facet>
               <h:outputText value="#{office.enterprise.description}" styleClass="standard" />
               </rich:column>
              </rich:scrollableDataTable>
              


              Here is what i found out during debugging:

              This is the method that was active when I watched the instance variables and the parameters below.

              FacesCompositeELResolver.getValue(ELContext context, Object base, Object property)
              


              The following resolvers were available:

              resolvers:
               com.sun.faces.el.ImplicitObjectELResolver@5b267f
               com.sun.faces.el.VariableResolverChainWrapper@3c6543
               com.sun.faces.el.ManagedBeanELResolver@11c2137
               javax.el.ResourceBundleELResolver@1c8a9a0
               com.sun.faces.el.FacesResourceBundleELResolver@f888ea
               javax.el.MapELResolver@e4e327
               javax.el.ListELResolver@fd2549
               javax.el.ArrayELResolver@19aff01
               javax.el.BeanELResolver@dbbf61
               com.sun.faces.el.ScopedAttributeELResolver@f181ec
              


              the parameters were

              base= an instance of Office
              property=#{office.enterprise.description}
              


              the BeanELREsolver is selected to handle the expression but it fails of course, because it is not suitable for this kind of expression

              I also tried richfaces version 3.1.3 with the same result (in the project i use 3.1.2)

              • 4. Re: scrollableDataTable sort-property
                martin.ahrer

                After experiencing the same problem, my investigations lead to the resullt that it can't work this way.
                The expression you are using (#{office.enterprise.description}) is never evaluated as a EL expression.

                The SimpleGridDataModel is using the Comparator PropertyResolverComparator which is using the application property resolver for resolving properties

                public PropertyResolverComparator(SortOrder sortOrder) {
                 ApplicationFactory factory = (ApplicationFactory) FactoryFinder.getFactory(FactoryFinder.APPLICATION_FACTORY);
                 Application application = factory.getApplication();
                 resolver = application.getPropertyResolver();
                 this.sortOrder = sortOrder;
                }

                Unless you have registered a custom property resolver this gets you the com.sun.faces.el.PropertyResolverImpl resolver.

                This resolver in turn uses context.getApplication().getELResolver().getValue to resolve the property. Now this resolver is the FacesCompositeELResolver which consults a list of resolvers (the list that was posted by the previous posting). And none of these resolvers is able to resolve neither an expression like #{bean.property.nestedproperty} nor the property name property.nestedproperty.

                I have implemented a workaround - I don't believe it should be done this way. I would think that a more elegant solution would try to implement a resolver that is registerd with the application!
                Anyway with this you can specify a sortExpression="propertyname.nestedpropertyname"!

                // this creates the data model for the scrollable table
                new ListDataModel() {
                 @Override
                 protected Comparator createComparator(SortOrder sortOrder) {
                 Comparator comparator = new NestedPropertyResolverComparator(sortOrder, new NestedPropertyResolver());
                 return comparator;
                 }
                };
                
                
                class NestedPropertyResolverComparator implements Comparator {
                
                 private static SortField[] EMPTY = {};
                
                 private final PropertyResolver resolver;
                
                 private final SortOrder sortOrder;
                
                 public NestedPropertyResolverComparator(SortOrder sortOrder, PropertyResolver resolver) {
                 this.resolver = resolver;
                 this.sortOrder = sortOrder;
                 }
                
                 public int compare(Object o1, Object o2) {
                 int result = 0;
                
                 SortField[] fields = sortOrder == null ? EMPTY : sortOrder.getFields();
                
                 for (int i = 0; i < fields.length && result == 0; i++) {
                 SortField field = fields;
                 String name = field.getName();
                 Boolean asc = field.getAscending();
                
                 if (name != null && asc != null) {
                 Object property1 = resolver.getValue(o1, name);
                 Object property2 = resolver.getValue(o2, name);
                 if (property1 instanceof Comparable && property2 instanceof Comparable) {
                 result = ((Comparable) property1).compareTo(property2);
                 }
                 if (!asc.booleanValue()) {
                 result = -result;
                 }
                 }
                 }
                 return result;
                 }
                
                 }
                
                 class NestedPropertyResolver extends PropertyResolver {
                
                 @Override
                 public Class getType(Object base, Object property) throws EvaluationException, PropertyNotFoundException {
                 // TODO Auto-generated method stub
                 return null;
                 }
                
                 @Override
                 public Class getType(Object base, int index) throws EvaluationException, PropertyNotFoundException {
                 // TODO Auto-generated method stub
                 return null;
                 }
                
                 @Override
                 public Object getValue(Object base, Object property) throws EvaluationException, PropertyNotFoundException {
                 try {
                 return PropertyUtils.getNestedProperty(base, (String) property);
                 } catch (Exception e) {
                 throw new PropertyNotFoundException(e);
                 }
                 }
                
                 @Override
                 public Object getValue(Object base, int index) throws EvaluationException, PropertyNotFoundException {
                 // TODO Auto-generated method stub
                 return null;
                 }
                
                 @Override
                 public boolean isReadOnly(Object base, Object property) throws EvaluationException, PropertyNotFoundException {
                 // TODO Auto-generated method stub
                 return false;
                 }
                
                 @Override
                 public boolean isReadOnly(Object base, int index) throws EvaluationException, PropertyNotFoundException {
                 // TODO Auto-generated method stub
                 return false;
                 }
                
                 @Override
                 public void setValue(Object base, Object property, Object value) throws EvaluationException,
                 PropertyNotFoundException {
                 // TODO Auto-generated method stub
                
                 }
                
                 @Override
                 public void setValue(Object base, int index, Object value) throws EvaluationException, PropertyNotFoundException {
                 // TODO Auto-generated method stub
                
                 }
                
                 }