Error showing List output using MVC and JSF

Asked

Viewed 194 times

0

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

I Have Next Mistake:

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

User:

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

    GenericDao dao = new GenericDao();

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

    return lista;
}
.......

User:

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

        }



    }
    .........

Listausuario.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>
  • I believe the main problem is only in the cast between the java.lang.Class and java.lang.reflect.ParameterizedType. It’s not really a matter of JSF, Java-EE. I am still firm on the answer, but I see that the impossibility of this conversion only.

  • @Cold I did not understand your placement can detail better? But I wanted to specify that I am using JSF and MVC because I didn’t rule out the possibility of being something of a problem when calling the method.

  • For what I observed in the stacktrace the error occurs only in the type conversion and not properly in the presentation layer. Not this (in)directly related to JSF.

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 something very insecure. In the scenario in question, it will not work.

Type Erasure

First, it is necessary to understand that the generic type information of a variable is removed at runtime.

For example:

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

The compiler "ensures" that you can only add objects of the type String of that list, but when its class is run in the JVM, there is no verification as to the type.

Yes, you can give one cast insecure of List<String> for List and then add another object. The compiler will accept, after all he "trusts" you.

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

I read once that keep the Type Safety would imply a overhead too large for the virtual machine, as Java would need to practically create a copy of the class List for each generic type used in the program.

When it is possible to recover 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.

Look at the method getGenericSuperclass(). It returns the types that the current class defines for the generic parameters of the immediate superclass. Something analogous occurs with the getGenericInterfaces().

It means that if you have a subclass like this:

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

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

But as you instantiate directly the GenericDao, there is no Generic superclass and therefore the exception being cast.

Just use inheritance?

Use the example with extends above is a way out, but many do not recommend because there are chances of code "break" with strange new mistakes.

This is a possibility, as the documentation of the method itself getGenericSuperclass() 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.

Recommending

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

Example:

public class GenericDao<T extends Serializable> {

    private final Class<T> persistentClass;

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

    .....
}

Much simpler, all right?

The biggest drawback is the call verbose class creation:

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

Avoiding redundancy

To solve this, you can create a method Factory. 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 stays like this:

GenericDao<Usuario> usuarioDao = GenericDao.getInstance(Usuario.class);
  • 1

    Thank you so much for the beautiful explanation above, besides helping me with my problem helped me understand some details that were not very clear.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.