Filter-enable Lazy DataTable FilterValues all in LowerCase!?

UI Components for JSF
kman
Posts: 57
Joined: 03 Nov 2010, 09:21
Location: Hong Kong

23 Dec 2010, 10:27

I've an DataTable with lazy="true" and implemented its required "load()" method properly.
However, I found that all the "filterValues" are in LowerCase letter no matter what have been inputted at the filter textbox.

After looking into the PrimeFaces Source Code, I found that it arises from the following line at the "org.primefaces.component.datatable.DataHelper.decodeFilterRequest()":

Code: Select all

String filterValue = params.get(filterName).toLowerCase();
Source of "org.primefaces.component.datatable.DataHelper.decodeFilterRequest(FacesContext context, DataTable table)":

Code: Select all

void decodeFilterRequest(FacesContext context, DataTable table) {
    String clientId = table.getClientId(context);
    Map<String,String> params = context.getExternalContext().getRequestParameterMap();

    //Reset state
    table.setFirst(0);
    table.setPage(1);

    if(table.isLazy()) {
        Map<String,String> filters = new HashMap<String, String>();
        Map<String,Column> filterMap = table.getFilterMap();

        for(String filterName : filterMap.keySet()) {
            Column column = filterMap.get(filterName);
            String filterValue = params.get(filterName).toLowerCase();

            if(!isValueBlank(filterValue)) {
                String filterField = resolveField(column.getValueExpression("filterBy"));
                
                filters.put(filterField, filterValue);
            }
        }

        table.setFilters(filters);

        table.loadLazyData();

        //Metadata for callback
        if(table.isPaginator()) {
            RequestContext.getCurrentInstance().addCallbackParam("totalRecords", table.getRowCount());
        }
        
    }
    else {
        Map<String,Column> filterMap = table.getFilterMap();
        List filteredData = new ArrayList();
        table.setValue(null);    //Always work with user data

        String globalFilter = params.get(clientId + UINamingContainer.getSeparatorChar(context) + "globalFilter");
        boolean hasGlobalFilter = !isValueBlank(globalFilter);
        if(hasGlobalFilter) {
            globalFilter = globalFilter.toLowerCase();
        }

        for(int i = 0; i < table.getRowCount(); i++) {
            table.setRowIndex(i);
            boolean localMatch = true;
            boolean globalMatch = false;

            for(String filterName : filterMap.keySet()) {
                Column column = filterMap.get(filterName);
                String columnFilter = params.get(filterName).toLowerCase();
                String columnValue = String.valueOf(column.getValueExpression("filterBy").getValue(context.getELContext()));

                if(hasGlobalFilter && !globalMatch) {
                    if(columnValue != null && columnValue.toLowerCase().contains(globalFilter))
                        globalMatch = true;
                }

                if(isValueBlank(columnFilter)) {
                    localMatch = true;
                }
                else if(columnValue == null || !column.getFilterConstraint().applies(columnValue.toLowerCase(), columnFilter)) {
                    localMatch = false;
                    break;
                }

            }

            boolean matches = localMatch;
            if(hasGlobalFilter) {
                matches = localMatch && globalMatch;
            }

            if(matches) {
                filteredData.add(table.getRowData());
            }
        }

        table.setRowIndex(-1);    //cleanup

        table.setValue(filteredData);

        //Metadata for callback
        if(table.isPaginator()) {
            RequestContext.getCurrentInstance().addCallbackParam("totalRecords", filteredData.size());
        }

    }
}

Here's the test code:

Code: Select all

public LazyDataModel<MyEntity> getMyDatatableValue()
{
    if( myDatatableValue == null )
    {
        myDatatableValue = new LazyDataModel<MyEntity>()
        {
            public List<MyEntity> load( int first, int pageSize, String sortField, boolean sortOrder,
                    Map<String, String> filters )
            {
                // all FilterValues, "filters", here are always been converted to LowerCase!!?
                return getMyEntityDbService().findAll( first, pageSize, sortField, sortOrder, filters );
            }
        };
    }

    myDatatableValue.setRowCount( getMyEntityService().findAllRowCount() );
    return myDatatableValue;
}


Any way to preserve original text lettercase for filtering to be picked up at the back-end bean?
PrimeFaces 3.0M1, Sun Mojarra 2.0.4 FCS, Sun GlassFish JSTL 1.2,
Apache Log4J 1.2.16, EclipseLink 2.1.1.v20100817-r8050,
Eclipse Helios

kman
Posts: 57
Joined: 03 Nov 2010, 09:21
Location: Hong Kong

31 Dec 2010, 09:07

hi, does anyone gives an insight?
PrimeFaces 3.0M1, Sun Mojarra 2.0.4 FCS, Sun GlassFish JSTL 1.2,
Apache Log4J 1.2.16, EclipseLink 2.1.1.v20100817-r8050,
Eclipse Helios

kman
Posts: 57
Joined: 03 Nov 2010, 09:21
Location: Hong Kong

07 Jan 2011, 04:56

still looking forward to hearing from expert here...
PrimeFaces 3.0M1, Sun Mojarra 2.0.4 FCS, Sun GlassFish JSTL 1.2,
Apache Log4J 1.2.16, EclipseLink 2.1.1.v20100817-r8050,
Eclipse Helios

action
Posts: 8
Joined: 22 Aug 2010, 13:08

07 Mar 2011, 12:02

Hi, I have the same problems. Have you solved this problem? If yes, could you please reply here?

kman
Posts: 57
Joined: 03 Nov 2010, 09:21
Location: Hong Kong

11 Apr 2011, 04:23

sorry to tell you that still didn't, the forum here is "silent all these years"......
who to break through the silence? pls help!!!
PrimeFaces 3.0M1, Sun Mojarra 2.0.4 FCS, Sun GlassFish JSTL 1.2,
Apache Log4J 1.2.16, EclipseLink 2.1.1.v20100817-r8050,
Eclipse Helios

srt
Posts: 7
Joined: 05 Aug 2011, 00:38

08 Aug 2011, 15:23

Hm seems the only option is to patch it ;)

srt
Posts: 7
Joined: 05 Aug 2011, 00:38

09 Aug 2011, 04:13


sebasrock
Posts: 5
Joined: 03 Nov 2011, 16:31

16 Nov 2011, 16:46

MMMM any idea for this problem. i am use PrimeFaces version
2.2.1, 3.0.M1, 3.0.M2 , 3.0M3 Y 3.0M4

but all have the problem

Help...!!!! :cry:

smithh032772
Posts: 6144
Joined: 10 Sep 2011, 21:10

17 Nov 2011, 01:15

I have been using LazyDataModel to select data from large tables in database, but I had issues with the filterBy columns on my JSF pages/facelets (i forgot the exact behavior, so I cannot state that now at this time), so I developed my own version of the filterBy columns, which are basically p:inputText, getter/setters on the bean, and a filterBy() retrieval method on my Facade EJB which took the values of filterBy bean attributes, and customized SELECT statements in the Facade EJB based on the values of the filterBy bean attributes. You asked for a solution, so i'm giving my solution/workaround.

JSF

Code: Select all

                    <p:column>
                        <f:facet name="header">
                            <h:panelGrid columns="1">
                                <h:outputText value="Customer Name" />
                                <p:inputText value="#{pf_customerController.filterCustomerName}" size="20" onkeypress="disableEnterKey(event)" />

                            </h:panelGrid>
                        </f:facet>
                        <h:outputText value="#{customer.customerName}" />
                    </p:column>
bean

Code: Select all

    public LazyDataModel<Customer> getLazyModel() {

        try {
            /* *** MAY NEED TO REMOVE if (lazyModel == null) *** */
            if (lazyModel == null) {

                // filter by
                if (filterCustomerName.length() > 0) {

                    lazyModel = new LazyCustomerDataModel(getFacade().filterBy(filterCustomerName));
                }
                // first approach for lazy datatable; filterBy and sortBy columns don't work
                else {
                    lazyModel = new LazyCustomerDataModel(getFacade().findAll());
                }

            } // lazyModel == null
        } catch (Exception e) {
            e.printStackTrace();
            messages.addFormErrorMsg("Error retrieving list of Customers", (e.getMessage() != null) ? e.getMessage() : "");
        }
        return lazyModel;
    }

    public void setLazyModel(LazyDataModel<Customer> lazyModel) {
        this.lazyModel = lazyModel;
    }

    public String getFilterCustomerName() {
        return filterCustomerName;
    }

    public void setFilterCustomerName(String filterCustomerName) {
        this.filterCustomerName = filterCustomerName;
    }
LazyCustomerDataModel

Code: Select all

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package jsf.customer;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import jpa.entities.Customer;
import org.primefaces.model.LazyDataModel;
import org.primefaces.model.SortOrder;

/**
 *
 * @author Administrator
 */
public class LazyCustomerDataModel extends LazyDataModel<Customer> {

    private List<Customer> datasource;

    public LazyCustomerDataModel(List<Customer> datasource) {
        this.datasource = datasource;
        setRowCount(this.datasource.size());
    }

    @Override
    public Customer getRowData(String rowKey) {
        for(Customer customer : datasource) {
            if(customer.getCustomerId().toString().equals(rowKey))
                return customer;
        }
        return null;
    }

    @Override
    public Object getRowKey(Customer customer) {
        return customer.getCustomerId();
    }

    @Override
    public void setRowIndex(int rowIndex) {
        /*
         * The following is in ancestor (LazyDataModel):
         * this.rowIndex = rowIndex == -1 ? rowIndex : (rowIndex % pageSize);
         */
        if (rowIndex == -1 || getPageSize() == 0) {
            super.setRowIndex(-1);
        }
        else
            super.setRowIndex(rowIndex % getPageSize());
    }

   @Override
    public List<Customer> load(int first, int pageSize, String sortField, SortOrder sortOrder, Map<String,String> filters) {
        List<Customer> data = new ArrayList<Customer>();

        //filter
        for(Customer Customer : datasource) {
            boolean match = true;

            for(Iterator<String> it = filters.keySet().iterator(); it.hasNext();) {
                try {
                    String filterProperty = it.next();
                    String filterValue = filters.get(filterProperty);
                    String fieldValue = String.valueOf(Customer.getClass().getField(filterProperty).get(Customer));

                    if(filterValue == null || fieldValue.startsWith(filterValue)) {
                        match = true;
                    }
                    else {
                        match = false;
                        break;
                    }
                } catch(Exception e) {
                    match = false;
                }
            }

            if(match) {
                data.add(Customer);
            }
        }

        //sort
        if(sortField != null) {
            Collections.sort(data, new CustomerLazySorter(sortField, sortOrder));
        }

        //rowCount
        int dataSize = data.size();
        this.setRowCount(dataSize);

        //paginate
        
        /*
         * IndexOutOfBoundsException thrown under the following conditions:
         * 
         * fromIndex < 0 || toIndex > size || fromIndex > toIndex
         * 
         * http://docs.oracle.com/javase/6/docs/api/java/util/List.html#subList%28int%2C%20int%29
         */
        if (first < 0 || first > dataSize) {
            //System.out.println(this.getClass().toString() + ".load(): paginate: first < 0 || first > dataSize; dataSize=" + dataSize + "; first=" + first);
        }

        if(dataSize > pageSize && first >= 0) {
            //System.out.println(this.getClass().toString() + ".load(): paginate: dataSize > pageSize; dataSize=" + dataSize + "; pageSize=" + pageSize + "; first=" + first);
            try {
                /*
                 * first > dataSize can occur when previous dataSize > current dataSize
                 * return the last page of the current dataSize
                 */
                if (first > dataSize) {
                    Integer lastPageSize = (dataSize % pageSize);
                    first = dataSize - lastPageSize;
                    pageSize = lastPageSize;
                    //System.out.println(this.getClass().toString() + ".load(): paginate: first > dataSize; RECALCULATED first=" + first + "; pageSize=" + pageSize);
                }
                if (first < 0) 
                    return data;
                else
                    return data.subList(first, first + pageSize);
            }
            catch(IndexOutOfBoundsException e) {
                //System.out.println(this.getClass().toString() + ".load(): paginate: caught IndexOutOfBoundsException e.getLocalizedMessage()=" + e.getLocalizedMessage() + "; e.getMessage()=" + e.getMessage());
                return data.subList(first, first + (dataSize % pageSize));
            }
        }
        else {
            //System.out.println(this.getClass().toString() + ".load(): paginate: dataSize <= pageSize && first < 0; dataSize=" + dataSize + "; pageSize=" + pageSize);
            return data;
        }
    }
}
CustomerLazySorter

Code: Select all

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package jsf.customer;

import java.util.Comparator;
import jpa.entities.Customer;
import org.primefaces.model.SortOrder;

/**
 *
 * @author Administrator
 */
public class CustomerLazySorter implements Comparator<Customer> {
    
    private String sortField;
    private SortOrder sortOrder;
    
    public CustomerLazySorter(String sortField, SortOrder sortOrder) {
        this.sortField = sortField;
        this.sortOrder = sortOrder;
    }
    
    @Override
    public int compare(Customer customer1, Customer customer2) {
        try {
            Object value1 = Customer.class.getField(this.sortField).get(customer1);
            Object value2 = Customer.class.getField(this.sortField).get(customer2);

            int value = ((Comparable)value1).compareTo(value2);
            
            return SortOrder.ASCENDING.equals(sortOrder) ? value : -1 * value;
        }
        catch(Exception e) {
            throw new RuntimeException();
        }
    }    
}
Facade EJB

Code: Select all

@Stateless
public class CustomerFacade extends AbstractFacade<Customer> {
    @PersistenceContext(unitName = "mcmsPU")
    private EntityManager em;

    protected EntityManager getEntityManager() {
        return em;
    }

    public CustomerFacade() {
        super(Customer.class);
    }
    
    public List<Customer> filterBy(String customerName)  throws Exception {
        
        List<Customer> customerList = null;
        Query q;
        
        /*
         * The percent (%) wildcard character represents zero or more characters.
         * address.phone LIKE '12%3'
         *    TRUE:  '123', '12993'
         *    FALSE: '1234'
         * http://download.oracle.com/javaee/6/tutorial/doc/bnbuf.html#bnbvg
         * 
         * contains = LIKE '%MOTOR%' 
         * startsWith = LIKE 'MOTOR%'
         * endsWith = LIKE '%MOTOR'
         */
        
        
        String queryStr = "";
        if (customerName.length() > 0) {
            queryStr += "LOWER(c.customerName) LIKE LOWER('%" + customerName + "%')";
        }
        
        queryStr = "SELECT c FROM Customer c WHERE " + queryStr + " ORDER BY c.customerName";
        
        try {
            q = getEntityManager().createQuery(queryStr);
            customerList = q.getResultList();
        } catch(Exception ex) {
            throw ex;
        }
        return customerList;
    }
    
    // override AbstractFacade.findAll() and used NamedQuery
    @Override
    public List<Customer> findAll() {
        return getEntityManager().createNamedQuery("Customer.findAll").getResultList();
    }
    
}
Howard

PrimeFaces 6.0, Extensions 6.0.0, Push (Atmosphere 2.4.0)
TomEE+ 1.7.4 (Tomcat 7.0.68), MyFaces Core 2.2.9, JDK8
JUEL 2.2.7 | OmniFaces | EclipseLink-JPA/Derby | Chrome

Java EE 6 Tutorial|NetBeans|Google|Stackoverflow|PrimeFaces|Apache

senthil_sss
Posts: 32
Joined: 20 Feb 2013, 09:13

27 Feb 2013, 13:50

Need to know whether, it is possible to make the lazy load call, after a minimum of 3 characters entered in the filter data input field
and also
need to know whether, it is possible to popup a calendar onclick inside the filter data input field

if possible, how can it be...?

plz reply it would be more helpfull, thanks in advance.
PrimeFaces v_3.5,
JSF v_2
Server name : JBOSS , Version : 7.1.1

Post Reply

Return to “PrimeFaces”

  • Information
  • Who is online

    Users browsing this forum: No registered users and 6 guests