Error while displaying the result of a List using MVC and JSF

0

I need to return data from the database to JSF but even before I get to JSF I can not show the searched data.

I have the following error:

Advertência:   #{usuarioBean.pesquisa}: java.lang.ClassCastException: java.lang.Class cannot be cast to java.lang.reflect.ParameterizedType
javax.faces.FacesException: #{usuarioBean.pesquisa}: java.lang.ClassCastException: java.lang.Class cannot be cast to java.lang.reflect.ParameterizedType
at com.sun.faces.application.ActionListenerImpl.processAction(ActionListenerImpl.java:118)
at javax.faces.component.UICommand.broadcast(UICommand.java:315)
at javax.faces.component.UIViewRoot.broadcastEvents(UIViewRoot.java:790)
at javax.faces.component.UIViewRoot.processApplication(UIViewRoot.java:1282)
at com.sun.faces.lifecycle.InvokeApplicationPhase.execute(InvokeApplicationPhase.java:81)
at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:198)
at javax.faces.webapp.FacesServlet.service(FacesServlet.java:646)
at org.apache.catalina.core.StandardWrapper.service(StandardWrapper.java:1682)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:318)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:160)
at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:734)
at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:673)
at com.sun.enterprise.web.WebPipeline.invoke(WebPipeline.java:99)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:174)
at org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:357)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:260)
at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:188)
at org.glassfish.grizzly.http.server.HttpHandler.runService(HttpHandler.java:191)
at org.glassfish.grizzly.http.server.HttpHandler.doHandle(HttpHandler.java:168)
at org.glassfish.grizzly.http.server.HttpServerFilter.handleRead(HttpServerFilter.java:189)
at org.glassfish.grizzly.filterchain.ExecutorResolver$9.execute(ExecutorResolver.java:119)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeFilter(DefaultFilterChain.java:288)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeChainPart(DefaultFilterChain.java:206)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.execute(DefaultFilterChain.java:136)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.process(DefaultFilterChain.java:114)
at org.glassfish.grizzly.ProcessorExecutor.execute(ProcessorExecutor.java:77)
at org.glassfish.grizzly.nio.transport.TCPNIOTransport.fireIOEvent(TCPNIOTransport.java:838)
at org.glassfish.grizzly.strategies.AbstractIOStrategy.fireIOEvent(AbstractIOStrategy.java:113)
at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.run0(WorkerThreadIOStrategy.java:115)
at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.access$100(WorkerThreadIOStrategy.java:55)
at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy$WorkerThreadRunnable.run(WorkerThreadIOStrategy.java:135)
at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:564)
at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.run(AbstractThreadPool.java:544)
at java.lang.Thread.run(Thread.java:744)
Caused by: javax.faces.el.EvaluationException: java.lang.ClassCastException: java.lang.Class cannot be cast to java.lang.reflect.ParameterizedType
at javax.faces.component.MethodBindingMethodExpressionAdapter.invoke(MethodBindingMethodExpressionAdapter.java:101)
at com.sun.faces.application.ActionListenerImpl.processAction(ActionListenerImpl.java:102)
... 34 more
Caused by: java.lang.ClassCastException: java.lang.Class cannot be cast to java.lang.reflect.ParameterizedType
at br.com.atreu.dao.GenericDao.<init>(GenericDao.java:18)
at br.com.atreu.dao.UsuarioDao.retornoUsuarios(UsuarioDao.java:47)
at br.com.atreu.bean.UsuarioBean.pesquisa(UsuarioBean.java:35)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at com.sun.el.parser.AstValue.invoke(AstValue.java:275)
at com.sun.el.MethodExpressionImpl.invoke(MethodExpressionImpl.java:304)
at org.jboss.weld.util.el.ForwardingMethodExpression.invoke(ForwardingMethodExpression.java:40)
at org.jboss.weld.el.WeldMethodExpression.invoke(WeldMethodExpression.java:50)
at com.sun.faces.facelets.el.TagMethodExpression.invoke(TagMethodExpression.java:105)
at javax.faces.component.MethodBindingMethodExpressionAdapter.invoke(MethodBindingMethodExpressionAdapter.java:87)
... 35 more

Follow the code below:

GenericDao:

public class GenericDao<T extends Serializable> {

private final Session session;
private final Class<T> persistentClass;

public GenericDao() {
    this.session = ConexaoUtil.getSession();
    this.persistentClass = (Class<T>) ((ParameterizedType)
        getClass().getGenericSuperclass()).getActualTypeArguments()[0];
}

public Session getSession() {
    return session;
}

protected void save(T entity) {
    try {
        getSession().getTransaction().begin();
        getSession().save(entity);
        getSession().getTransaction().commit();
    } catch (Throwable t) {
        getSession().getTransaction().rollback();
        t.printStackTrace();
    } finally {
        close();
    }
}

protected void update(T entity) {
    try {
        getSession().getTransaction().begin();
        getSession().update(entity);
        getSession().getTransaction().commit();
    } catch (Throwable t) {
        getSession().getTransaction().rollback();
        t.printStackTrace();
    } finally {
        close();
    }
}

protected void delete(T entity) {
    try {
        getSession().getTransaction().begin();
        getSession().delete(entity);
        getSession().getTransaction().commit();
    } catch (Throwable t) {
        getSession().getTransaction().rollback();
        t.printStackTrace();
    } finally {
        close();
    }
}

public List<T> findAll() throws Exception {
    return getSession().createCriteria(persistentClass).list();
}

public T findByName(String nome) {
    return (T) getSession().createCriteria(persistentClass)
            .add(Restrictions.eq("nome", nome).ignoreCase()).uniqueResult();
}

public T findById(long id) {
    return (T) getSession().createCriteria(persistentClass)
            .add(Restrictions.eq("id", id)).uniqueResult();
}

private void close() {
    if (getSession() != null && getSession().isOpen()) {
        getSession().close();
    }
}
}

UserDao:

......
public List retornoUsuarios() throws Exception{

    GenericDao dao = new GenericDao();

    List<Usuario> lista = dao.findAll();

    return lista;
}
.......

UserBean:

.......
public void pesquisa() throws Exception{

        UsuarioDao user = new UsuarioDao();
         List<Usuario> listaDeUsuario = user.retornoUsuarios();

        for (int i = 0; i < listaDeUsuario.size(); i++) {
            Usuario usuario = listaDeUsuario.get(i);

            System.out.println(usuario.getNome());

        }



    }
    .........

User List.xhtml

<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org   /TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
  xmlns:h="http://xmlns.jcp.org/jsf/html"
  xmlns:p="http://primefaces.org/ui"   
  xmlns:f="http://xmlns.jcp.org/jsf/core">
<h:head>
    <title>Atreu System</title>
</h:head>
<h:body>
    <h:form> 

        <h:commandButton value="Gravar" action="#{usuarioBean.pesquisa}"/>

    </h:form>
</h:body>

</html>
    
asked by anonymous 03.10.2014 / 17:22

1 answer

1

Consider the following code snippet:

this.persistentClass = (Class<T>) ((ParameterizedType)
        getClass().getGenericSuperclass()).getActualTypeArguments()[0];

This is available in several Stack Overflow responses, but it is very unsafe. In the scenario in question, it will not work.

Type erasure

First, you have to understand that the generic type information for a variable is removed at runtime.

For example:

List<String> lista = new ArrayList<String>();

The compiler "ensures" that you can only add objects of type String from this list, but when your class runs in the JVM, there is no type checking.

Yes, you can give an cast unsafe from List<String> to List and then add another object. The compiler will accept, after all it "trusts" you.

We conclude that it is impossible for instance lista to know its own generic type, since in the end there is only a single class ArrayList , the generic type is only a type of security for the developer.

I have read that keeping Type Safety would mean a very large overhead for the virtual machine, since Java would almost need to create a copy of the List class for each generic type used in the program.

When it is possible to retrieve the generic type

There are scenarios where the code quoted at the beginning of the answer will work, but we need to pay attention to the details.

Notice the method getGenericSuperclass() . It returns the types that the current class defines for the generic parameters of the immediate superclass. Something similar happens with getGenericInterfaces() .

This means that if you have a subclass like this:

class UsuarioDao extends GenericDao<Usuario> { ... }

The code would work perfectly because you are defining a type for the generic parameter of the superclass. This works because the generic type is not just in a variable, but statically declaring (fixed) the class definition itself.

But since you directly instantiate the GenericDao , there is no generic superclass and hence the exception being thrown.

Just use inheritance?

Using the example with extends above is an output, but many do not recommend because there is a chance the code will "break" with new strange errors.

This is a possibility, because as the documentation itself of the getGenericSuperclass() method states, it only returns the implemented generic type of the immediate superclass of the class. So if you have a hierarchy other than exactly two levels, the code will fail.

Recommendation

The recommendation that will work most simply and directly is to pass the desired class by parameter to the GenericDao constructor.

Example:

public class GenericDao<T extends Serializable> {

    private final Class<T> persistentClass;

    public GenericDao(Class<T> persistentClass) {
        this.persistentClass = persistentClass;
    }

    .....
}

Much simpler, right?

The biggest drawback is the verbose class creation:

GenericDao<Usuario> usuarioDao = new GenericDao<Usuario>(Usuario.class);

Avoiding redundancy

To resolve this, you can create a factory method. Example:

public class GenericDao<T extends Serializable> {

    final private Class<T> persistentClass;

    public static <X extends Serializable> GenericDao<X> getInstance(Class<X> persistentClass) {
        return new GenericDao<X>(persistentClass);
    }

    private GenericDao(Class<T> persistentClass) {
        this.persistentClass = persistentClass;
    }

    ...

}

And the creation of the class looks like this:

GenericDao<Usuario> usuarioDao = GenericDao.getInstance(Usuario.class);
    
03.10.2014 / 19:58