Bom dia, pessoal.
Me deparei com a seguinte situação-problema: tenho uma classe DAO Genérico e criei um DAOFactory que contém um método anotado com @Produces que retorna o DAO de acordo com o bean que eu informar. Ex:
@Inject
private DAO<Produto> dao;
A injeção ocorre normalmente, inclusive com o EntityManager que eu injeto no DAOFactory:
public class DAOFactory<T extends Serializable> {
@Inject
private EntityManager em;
@SuppressWarnings({ "rawtypes", "unchecked" })
@Produces
public DAO createDAO(InjectionPoint injectionPoint) throws ClassNotFoundException {
ParameterizedType type = (ParameterizedType) injectionPoint.getType();
Class classe = (Class) type.getActualTypeArguments()[0];
return new DAO(classe, em);
}
}
Até aí tudo bem.
Tive que expandir o sistema de modo a ter também um DataModel Genérico (do componente DataModel do Primefaces) para não precisar ficar criando vários DataModel para cada bean do meu sistema.
package br.com.caelum.notasfiscais.datamodel;
import java.io.Serializable;
import java.util.List;
import java.util.Map;
import org.primefaces.model.LazyDataModel;
import org.primefaces.model.SortOrder;
import br.com.caelum.notasfiscais.dao.DAO;
public class DataModelGenerico<T extends Serializable> extends LazyDataModel<T> {
/**
*
*/
private static final long serialVersionUID = 1L;
@SuppressWarnings("unused")
private Class<? extends Serializable> classe;
private DAO<T> dao;
public DataModelGenerico(Class<T> classe, DAO<T> dao) {
this.classe = classe;
this.dao = dao;
}
@Override
public List<T> load(int inicio, int quantidade, String campoOrdenacao,
SortOrder sentidoOrdenacao, Map<String, String> filtros) {
return (List<T>) dao.listaTodosPaginada(inicio, quantidade);
}
}
Por usar CDI, também tive que criar um DataModelFactory (no mesmo estilo do DAOFactory):
package br.com.caelum.notasfiscais.datamodel;
import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import javax.enterprise.inject.Produces;
import javax.enterprise.inject.spi.InjectionPoint;
import javax.inject.Inject;
import br.com.caelum.notasfiscais.dao.DAO;
public class DataModelFactory<T extends Serializable> {
@Inject
private DAO<? extends Serializable> dao;
@Produces
public DataModelGenerico createFactory(InjectionPoint injectionPoint) {
ParameterizedType type = (ParameterizedType) injectionPoint.getType();
Class classe = (Class) type.getActualTypeArguments()[0];
return new DataModelGenerico(classe, dao);
}
}
Tive que fazer uma pequena alteração no método createDAO do DAOFactory para verificar o tipo do objeto que está vindo na injeção:
if (type instanceof ParameterizedType) {
ParameterizedType paramType = (ParameterizedType) type;
if (paramType.getActualTypeArguments()[0] instanceof TypeVariable<?>)
dataType = (Class<T>) paramType.getClass().asSubclass(Serializable.class);
//dataType = Class.forName(paramType.getClass().getName()).asSubclass(Serializable.class);
else
dataType = (Class<T>) paramType.getActualTypeArguments()[0];
} else if (type instanceof Class) {
dataType = (Class<T>) type;
}
Da maneira como está o código até então descrito, me deparo com a seguinte exceção:
java.lang.ClassCastException: sun.reflect.generics.reflectiveObjects.WildcardTypeImpl cannot be cast to java.lang.Class
br.com.caelum.notasfiscais.dao.DAOFactory.createDAO(DAOFactory.java:38)
a linha 38 que fala na exceção acima é esta que está no método createDAO do DAOFactory:
dataType = (Class<T>) paramType.getActualTypeArguments()[0];
Se alguém tiver alguma idéia de como eu poderia resolver isto, ou até mesmo de outra maneira, ficaria grato.
Abraços!