[Solucao] PrimeFaces DataTable Problema Com Ordenacao e Selecao

O datatable do PrimeFaces tem um serio Problema quando se usa
Ordenacao com Selecao.

Quando se ordena uma coluna visualmente ela fica em ordem Porem
quando se seleciona uma linha dePois de se realizar a ordenacao ele
nao seleciona a linha correta. Somente visualmente que eh selecionado
a linha correta, Porem quando vamos utilizar o objeto selecionado
ele eh o objeto que estava naquele lugar antes da ordenacao.

Ou Seja, quando ordenamos soh acontece ordenacao visual
a fonte de Dados continua na ordem original selecionando erradamente a linha.

Para resolver isso basta fazer uma modificacao na classe DataHelper

pacote - org.primefaces.component.datatable
classe - DataHelper

Importe a biblioteca do primefaces e faca um pacote com o nome acima
Faca uma classe chamada DataHelper com esse codigo

[code]/*

  • Copyright 2010 Prime Technology.
  • Licensed under the Apache License, Version 2.0 (the “License”);
  • you may not use this file except in compliance with the License.
  • You may obtain a copy of the License at
  • http://www.apache.org/licenses/LICENSE-2.0
  • Unless required by applicable law or agreed to in writing, software
  • distributed under the License is distributed on an “AS IS” BASIS,
  • WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  • See the License for the specific language governing permissions and
  • limitations under the License.
    */
    package org.primefaces.component.datatable;

import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.el.ValueExpression;
import javax.faces.component.UIColumn;
import javax.faces.component.UIComponent;
import javax.faces.component.UINamingContainer;
import javax.faces.component.ValueHolder;
import javax.faces.context.FacesContext;
import javax.faces.event.PhaseId;
import org.primefaces.component.column.Column;
import org.primefaces.context.RequestContext;
import org.primefaces.event.SelectEvent;
import org.primefaces.event.UnselectEvent;
import org.primefaces.model.BeanPropertyComparator;
import org.primefaces.model.Cell;

class DataHelper {

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

	String firstParam = params.get(clientId + "_first");
	String rowsParam = params.get(clientId + "_rows");
	String pageParam = params.get(clientId + "_page");

	table.setFirst(Integer.valueOf(firstParam));
	table.setRows(Integer.valueOf(rowsParam));
	table.setPage(Integer.valueOf(pageParam));

    if(table.isLazy()) {
        table.loadLazyData();
    }
}

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

	String sortKey = params.get(clientId + "_sortKey");
	boolean asc = Boolean.valueOf(params.get(clientId + "_sortDir"));
    Column sortColumn = null;

    for(Column column : table.getColumns()) {
        if(column.getClientId(context).equals(sortKey)) {
            sortColumn = column;
            break;
        }
    }

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

    if(table.isLazy()) {
        table.setSortField(resolveField(sortColumn.getValueExpression("sortBy")));
        table.setSortOrder(asc);

        table.loadLazyData();

    } else {
        List sortData = new ArrayList();
        List list = (List) table.getValue();
        sortData.addAll(list);
        Collections.sort(sortData, new BeanPropertyComparator(sortColumn, table.getVar(), asc));
        table.setRowIndex(-1);      //cleanup
        table.setValue(sortData);

    }
}

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());
        }

    }

}

public boolean isValueBlank(String value) {
	if(value == null)
		return true;

	return value.trim().equals("");
}

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

	String selection = params.get(clientId + "_selection");

	if(table.isSingleSelectionMode())
		decodeSingleSelection(table, selection);
	else
		decodeMultipleSelection(table, selection);

    table.setRowIndex(-1);	//clean

    //Instant selection and unselection
    queueInstantSelectionEvent(context, table, clientId, params);

	table.setRowIndex(-1);	//clean
}

void queueInstantSelectionEvent(FacesContext context, DataTable table, String clientId, Map<String,String> params) {

	if(table.isInstantSelectionRequest(context)) {
        int selectedRowIndex = Integer.parseInt(params.get(clientId + "_instantSelectedRowIndex"));
        table.setRowIndex(selectedRowIndex);
        SelectEvent selectEvent = new SelectEvent(table, table.getRowData());
        selectEvent.setPhaseId(PhaseId.INVOKE_APPLICATION);
        table.queueEvent(selectEvent);
    }
    else if(table.isInstantUnselectionRequest(context)) {
        int unselectedRowIndex = Integer.parseInt(params.get(clientId + "_instantUnselectedRowIndex"));
        table.setRowIndex(unselectedRowIndex);
        UnselectEvent unselectEvent = new UnselectEvent(table, table.getRowData());
        unselectEvent.setPhaseId(PhaseId.INVOKE_APPLICATION);
        table.queueEvent(unselectEvent);
    }
}

void decodeSingleSelection(DataTable table, String selection) {
	if(isValueBlank(selection)) {
		table.setSelection(null);
        table.setEmptySelected(true);
	} else {
        if(table.isCellSelection()) {
			table.setSelection(buildCell(table, selection));
		}
        else {
            table.setRowIndex(Integer.parseInt(selection));
            Object data = table.getRowData();

            table.setSelection(data);
        }
	}
}

void decodeMultipleSelection(DataTable table, String selection) {
	Class<?> clazz = table.getValueExpression("selection").getType(FacesContext.getCurrentInstance().getELContext());

	if(isValueBlank(selection)) {
		Object data = Array.newInstance(clazz.getComponentType(), 0);
		table.setSelection(data);

	} else {
        if(table.isCellSelection()) {
			String[] cellInfos = selection.split(",");
			Cell[] cells = new Cell[cellInfos.length];

			for(int i = 0; i < cellInfos.length; i++) {
				cells[i] = buildCell(table, cellInfos[i]);
				table.setRowIndex(-1);	//clean
			}

			table.setSelection(cells);
		}
         else {
            String[] rowSelectValues = selection.split(",");
            Object data = Array.newInstance(clazz.getComponentType(), rowSelectValues.length);

            for(int i = 0; i < rowSelectValues.length; i++) {
                table.setRowIndex(Integer.parseInt(rowSelectValues[i]));

                Array.set(data, i, table.getRowData());
            }

            table.setSelection(data);
        }
	}
}

String resolveField(ValueExpression expression) {
    String expressionString = expression.getExpressionString();
    expressionString = expressionString.substring(2, expressionString.length() - 1);      //Remove #{}

    return expressionString.substring(expressionString.indexOf(".") + 1);                //Remove var
}

Cell buildCell(DataTable dataTable, String value) {
	String[] cellInfo = value.split("#");

	//Column
    int rowIndex = Integer.parseInt(cellInfo[0]);
	UIColumn column = dataTable.getColumns().get(Integer.parseInt(cellInfo[1]));

	//RowData
	dataTable.setRowIndex(rowIndex);
	Object rowData = dataTable.getRowData();

	//Cell value
	Object cellValue = null;
	UIComponent columnChild = column.getChildren().get(0);
	if(columnChild instanceof ValueHolder) {
		cellValue = ((ValueHolder) columnChild).getValue();
	}

	return new Cell(rowData, column.getId(), cellValue);
}

}

O que muda eh o metodo decodeSortRequest
no trecho

else {
List sortData = new ArrayList();
List list = (List) table.getValue();
sortData.addAll(list);
Collections.sort(sortData, new BeanPropertyComparator(sortColumn, table.getVar(), asc));
table.setRowIndex(-1); //cleanup
table.setValue(sortData);

    }[/code]

soh isso.

postei essa solucao pois peskisei muito sobre ela e nao encontrei nada.

Espero que gostem.

Olá elbesh

essa dica será muito útil, pois estou com este problema.
Não consegui entender sua solução. Basta criar este pacote e uma classe chamada DataHelper substituindo o código?

Você poderia me detalhar um poiuco mais a solução?

Agradeço

amigo, comigo funcionou normal…sem fazer nada disso.

nao sei se é porque o PrimeFaces foi atualizado, mas nao precisei fazer nada disso ai.

no meu caso utilizei LazyDataModel.

Segue o código

[code]package dao;

import java.util.ArrayList;

import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Expression;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;

import model.Pessoa;

import org.primefaces.model.LazyDataModel;
import org.primefaces.model.SortOrder;

public class LazyPessoaDataModel extends LazyDataModel {

/**
 * 
 */
private static final long serialVersionUID = 1L;

private List<Pessoa> datasource;  
  
public LazyPessoaDataModel(List<Pessoa> datasource) {  
    this.datasource = datasource;  
} 
  
@Override  
public Pessoa getRowData(String rowKey) {  
	
	 Integer id = Integer.valueOf(rowKey);
	 
    for(Pessoa pessoa : datasource) {  
    	 if(id.equals(pessoa.getCodigo())){
            return pessoa;  
    	 }
    }  

    return null;  
}  

@Override  
public Object getRowKey(Pessoa pessoa) {  
    return pessoa.getCodigo();  
}  


@SuppressWarnings({ "unchecked", "rawtypes" })
@Override
public List load(int first, int pageSize, String sortField, SortOrder sortOrder, Map filters) {
	    List data = new ArrayList();
	    
	    System.out.println("Executando Load()");
	    EntityManagerFactory emf = Persistence.createEntityManagerFactory("projetoSistema");
	    EntityManager em = emf.createEntityManager();
	
	    // CRITERIA
	    CriteriaBuilder criteriaBuilder = em.getCriteriaBuilder();
	    CriteriaQuery accountQuery = criteriaBuilder.createQuery(Pessoa.class);
	
	    
	    // FROM
	    Root from = accountQuery.from(Pessoa.class);
	
	    
	    //SORT
	    if(sortField != null) {
		    if (sortOrder == SortOrder.ASCENDING) {
		    	accountQuery.orderBy(criteriaBuilder.asc(from.get(sortField)));
		    }
		    else {
		    	accountQuery.orderBy(criteriaBuilder.desc(from.get(sortField)));
		    }
	    }
	
	    // FILTROS
	    List predicates = new ArrayList();
	    for(Iterator it = filters.keySet().iterator(); it.hasNext();) {
			    String filterProperty = (String) it.next(); // table column name = field name
			    String filterValue = (String) filters.get(filterProperty);
			
			    Expression literal = criteriaBuilder.literal((String)filterValue);
			    predicates.add(criteriaBuilder.like(from.get(filterProperty), literal));
	    }
	    accountQuery.where((Predicate[]) predicates.toArray(new Predicate[predicates.size()]));
	
	    
	    
	    // PAGINATE
	    data = em.createQuery(accountQuery).setFirstResult(first).setMaxResults(getPageSize()).getResultList();
	
	    
	    
	    // ROW COUNT
	    CriteriaQuery countQuery = criteriaBuilder.createQuery(Long.class);
	    countQuery.select(criteriaBuilder.count(countQuery.from(Pessoa.class)));
	    countQuery.where((Predicate[]) predicates.toArray(new Predicate[predicates.size()]));
	   
	    
	    
	    int rowCount = Integer.parseInt(em.createQuery(countQuery).getSingleResult().toString());
	    setRowCount(rowCount);
	
	    return data;
}

}
[/code]

package bean;

import java.io.Serializable;
import java.util.List;

import javax.annotation.PostConstruct;
import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.faces.context.FacesContext;

import org.primefaces.model.LazyDataModel;



import dao.LazyPessoaDataModel;
import dao.PessoaDAO;

import model.Pessoa;


@ManagedBean
@ViewScoped // SESSION OU VIEW SCOPED PARA CONSEGUIR ORDENAR
public class PessoaBean implements Serializable {

	private static final long serialVersionUID = 1L;
	
	
	private LazyDataModel<Pessoa> lazyModel;
    private Pessoa selectedPessoa;  
  
    private List<Pessoa> listaPessoas;  
    
    
   	private Pessoa pessoa = new Pessoa();
   	PessoaDAO pessoaDAO = new PessoaDAO();
   	
   	
    @PostConstruct 
    protected void init() {  
			
		System.out.println("Executando INIT()");
	      listaPessoas = pessoaDAO.exibirPessoas();
	      lazyModel = new LazyPessoaDataModel(listaPessoas); // DATA SOURCE
 	
    }  
	
	public LazyDataModel<Pessoa> getLazyModel() {  
    	System.out.println("Executando getLazyModel()");
    	
    	
         return lazyModel;  
    }  
    
	

   	public Pessoa getSelectedPessoa() {  
        return selectedPessoa;  
    }  
  
    public void setSelectedPessoa(Pessoa selectedPessoa) {  
        this.selectedPessoa = selectedPessoa;  
    }  
      
    
	



	public List<Pessoa> getListaPessoas(){
   		
			System.out.println("Retornou Consulta em Cache");
	        return listaPessoas;
   	}
   	

  
   

}