EJB Strange ClassCastException
jjmargon Aug 19, 2005 7:36 AMHi.
I have a very strange ClassCastException that I'm going to try to explain in detail.
I have an EAR application, with a WAR, an EJB JAR and some other JARs.
The structure is like that:
App.EAR:
WebApp.war (struts files and jsps)
App.jar (business objects and business rules)
EJBApp.jar (bridge to access App.jar remotely)
otherjar1.jar
otherjar2.jar
..............
The project evolved in this way. I had a web application, and possibly, they told me that another application could call this application remotely through an EJB. So, I made an EAR application with a WAR (with struts and jsps) and a JAR with all my business code. In this way, the action classes of the WAR call the business Java classes of the App.JAR.
By the way, the MANIFEST.MF of the WAR file has a list of all the jars used in the application,i.e., App.jar and the rest of the other tools jars. In this way, these classes would be visibles from any part of the application.
The next step, was that I had to create and EJB for the other application. The functionality would be the same between both applications (my original web application and the remote application). In this way, my web application gives the same functionality that the remote Swing application that access through the EJB.
Web Application ->(access) Business Rules (App.jar through WAR)
Swing Application -> (access) Business Rules (App.jar through EJB)
For the EJB I use the Command Pattern. This is (basically) the code of the EJB:
public Command executeCommand(Command comando) throws EJBException { try { comando.execute(); } catch (AppException ex) { throw new EJBException(ex); } return comando; }
So, to make a functionality, I use the next Command class (I only show the execute method code) that I pass to the EJB as the Command argument:
public void execute() throws AppException { Session session = null; JbpmSession jbpmSession = null; try { session = PersistenceUtil.getSession(); jbpmSession = PersistenceUtil.getJbpmSession(); if(getTercero().getDni() != null && !"".equals(getTercero().getDni())){ UsuarioDAOHibernateImpl usuarioDAO = new UsuarioDAOHibernateImpl(); if(usuarioDAO.getTerceroByDNI(new Long(getTercero().getDni()).longValue()) != null){ this.setTercero(usuarioDAO.getTerceroByDNI(new Long(getTercero().getDni()).longValue(), session)); ProcessInstanceDAOHibernateImpl processInstanceDAO = new ProcessInstanceDAOHibernateImpl(); setTramitesTercero(processInstanceDAO.getTramitesTercero(usuarioDAO.getTerceroByDNI(new Long(getTercero().getDni()).longValue()).getDni(), session, jbpmSession)); } } } catch (Exception e) { throw new AppException(e); }finally{ try { PersistenceUtil.closeJbpmSession(jbpmSession); PersistenceUtil.closeSession(session); } catch (InfrastructureException e) { throw new AppException("Error al intentar cerrar las sesiones de Hibernate (Session y JbpmSession)", e); } } }
Note: As you can see, my application uses Hibernate and Jbpm.
Well. When I try to execute the functionality through the web tier all goes well.But when I try to test the EJB through a JUnit Test (a standalone application from my Eclipse IDE), I get a ClassCastExcpetion in the next point. When the execute code shown earlier is in
usuarioDAO.getTerceroByDNI(new Long(getTercero().getDni()).longValue(), session)
I get the ClassCastException.
The UsuarioDAOHibernateImpl is a business plain java class that resides in the App.jar.
The UsuarioDAOHibernateImpl.getTerceroByDNI method code is as follows:
public Tercero getTerceroByDNI(long dni, Session session){ // Se crea la query con los parametros Tercero tercero = null; Query q = session.createQuery("from Tercero t where t.dni=:dni"); q.setLong("dni",dni); tercero = (Tercero)q.uniqueResult(); return tercero; }
The ClassCastException is thrown in this line
tercero = (Tercero)q.uniqueResult();
Note: The Tercero class is a POJO class that resides in the App.jar.
I don't understand this ClassCastException.
I thought that as I have specified in the MANIFEST.MF, the classes in the App.jar would be shared by all the application (in classloading terms).
My unique suspicion was that the Session (org.hibernate.Session) parameter object in the above code was obtained in different way from the web application (all works well in the web application) that through the EJB. But I've debugged the application, I've used the jmx-console to observe the UCL used to load all the objects involved in the execution and in both cases (through the web and through the EJB) I get the same UCLs for all the classes, but only through the EJB I obtain the ClassCastException.
Any help or suggestion will be very very welcome!!
I'm getting crazy!!!
Thanks to all.