facebook

Spring-Hibernate: Class-cast exception when retrieving DAO

  1. MyEclipse Archived
  2.  > 
  3. Database Tools (DB Explorer, Hibernate, etc.)
Viewing 15 posts - 1 through 15 (of 19 total)
  • Author
    Posts
  • #245569 Reply

    everbright
    Member

    Hi,

    I’m using MyEclipse 4.1GA with Eclispe 3.1.2.

    I’m now exploring the excellent Spring-Hibernate integration that this version of MyEclipse offers.

    Ran into a ClassCastException error while trying to retrieve a DAO from the Spring factory.

    Here’s what I did:
    1) Added Spring capabilities.
    2) Added Hibernate capabilities. I chose to use a hibernate.cfg.xml, instead of Spring configuration.
    3) Used Reverse Engineering to create Hibernate mapping. I chose to generate all the artifacts (the Java Data Object, the DAO).

    Here’s the relevant sections of my files which were created as a result of the above.

    1. hibernate.cfg.xml

    <hibernate-configuration>
    
        <session-factory>
            <property name="myeclipse.connection.profile">DEV_MYSQL</property>
            <property name="connection.url">jdbc:mysql://$$REMOVED BY ADMIN$$:3306/DEV_MYSQL</property>
            <property name="connection.username">$$REMOVED BY ADMIN$$</property>
            <property name="connection.password">$$REMOVED BY ADMIN$$</property>
            <property name="connection.driver_class">com.mysql.jdbc.Driver</property>
            <property name="dialect">org.hibernate.dialect.MySQLDialect</property>
            <mapping resource="project/hibernate/Users.hbm.xml" />
    
        </session-factory>
    
    </hibernate-configuration>

    2. Spring applicationContext.xml

    <bean id="hibernateSessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
         <property name="configLocation" value="classpath:/hibernate.cfg.xml" />
    </bean>
    <bean id="UsersDAO" class="project.hibernate.UsersDAO">
         <property name="sessionFactory">
              <ref bean="hibernateSessionFactory" />
         </property>
    </bean>

    3. UsersDAO.java

    public class UsersDAO extends HibernateDaoSupport {
    
        private static final Log log = LogFactory.getLog(UsersDAO.class);
    
        protected void initDao() {
            //do nothing
        }
        
        public void save(User transientInstance) {
            log.debug("saving Users instance");
            try {
                getHibernateTemplate().saveOrUpdate(transientInstance);
                log.debug("save successful");
            } catch (RuntimeException re) {
                log.error("save failed", re);
                throw re;
            }
        }
        
        public void delete(User persistentInstance) {
            log.debug("deleting Users instance");
            try {
                getHibernateTemplate().delete(persistentInstance);
                log.debug("delete successful");
            } catch (RuntimeException re) {
                log.error("delete failed", re);
                throw re;
            }
        }
        
        public User findById( java.lang.Integer id) {
            log.debug("getting Users instance with id: " + id);
            try {
                User instance = (User) getHibernateTemplate()
                        .get("project.hibernate.Users", id);
                return instance;
            } catch (RuntimeException re) {
                log.error("get failed", re);
                throw re;
            }
        }
        
        
        public List findByExample(User instance) {
            log.debug("finding Users instance by example");
            try {
                List results = getSession()
                        .createCriteria("project.hibernate.Users")
                        .add(Example.create(instance))
                .list();
                log.debug("find by example successful, result size: " + results.size());
                return results;
            } catch (RuntimeException re) {
                log.error("find by example failed", re);
                throw re;
            }
        }    
        
        public User merge(User detachedInstance) {
            log.debug("merging Users instance");
            try {
                User result = (User) getHibernateTemplate()
                        .merge(detachedInstance);
                log.debug("merge successful");
                return result;
            } catch (RuntimeException re) {
                log.error("merge failed", re);
                throw re;
            }
        }
    
        public void attachDirty(User instance) {
            log.debug("attaching dirty Users instance");
            try {
                getHibernateTemplate().saveOrUpdate(instance);
                log.debug("attach successful");
            } catch (RuntimeException re) {
                log.error("attach failed", re);
                throw re;
            }
        }
        
        public void attachClean(User instance) {
            log.debug("attaching clean Users instance");
            try {
                getHibernateTemplate().lock(instance, LockMode.NONE);
                log.debug("attach successful");
            } catch (RuntimeException re) {
                log.error("attach failed", re);
                throw re;
            }
        }
    
    }

    4. Test.java

    public class Test {
    
        /**
         * @param args
         * @throws Exception 
         */
        public static void main(String[] args) throws Exception {
            ClassPathXmlApplicationContext appContext = new ClassPathXmlApplicationContext(new String[] {"applicationContext.xml"});
            UsersDAO usersDAO = (UsersDAO) appContext.getBean("UsersDAO");
            
            
        }
    
    }

    When I ran Test.java, I got the following error logs.

    2006-01-29 01:44:11,953 INFO  [org.hibernate.cfg.SettingsFactory.buildSettings(SettingsFactory.java:265)]  - Deleted entity synthetic identifier rollback: disabled
    2006-01-29 01:44:11,953 INFO  [org.hibernate.cfg.SettingsFactory.buildSettings(SettingsFactory.java:279)]  - Default entity-mode: pojo
    2006-01-29 01:44:11,984 INFO  [org.hibernate.impl.SessionFactoryImpl.<init>(SessionFactoryImpl.java:152)]  - building session factory
    2006-01-29 01:44:12,015 WARN  [net.sf.ehcache.config.Configurator.configure(Configurator.java:126)]  - No configuration found. Configuring ehcache from ehcache-failsafe.xml found in the classpath: jar:file:/F:/MyEclipse/eclipse/plugins/com.genuitec.eclipse.springframework_4.1.0/data/1.2/lib/dependencies/ehcache/ehcache-1.1.jar!/ehcache-failsafe.xml
    2006-01-29 01:44:12,250 INFO  [org.hibernate.impl.SessionFactoryObjectFactory.addInstance(SessionFactoryObjectFactory.java:82)]  - Not binding factory to JNDI, no JNDI name configured
    2006-01-29 01:44:12,250 INFO  [org.hibernate.impl.SessionFactoryImpl.checkNamedQueries(SessionFactoryImpl.java:379)]  - Checking 0 named queries
    2006-01-29 01:44:12,281 INFO  [project.spring.aop.LoggingAdvice.before(LoggingAdvice.java:16)]  - About to call method: org.springframework.orm.hibernate3.LocalSessionFactoryBean.isSingleton
    2006-01-29 01:44:12,281 INFO  [project.spring.aop.LoggingAdvice.afterReturning(LoggingAdvice.java:22)]  - Successfully returned from method: org.springframework.orm.hibernate3.LocalSessionFactoryBean.isSingleton
    2006-01-29 01:44:12,281 INFO  [project.spring.aop.LoggingAdvice.before(LoggingAdvice.java:16)]  - About to call method: org.springframework.orm.hibernate3.LocalSessionFactoryBean.getObject
    2006-01-29 01:44:12,281 INFO  [project.spring.aop.LoggingAdvice.afterReturning(LoggingAdvice.java:22)]  - Successfully returned from method: org.springframework.orm.hibernate3.LocalSessionFactoryBean.getObject
    2006-01-29 01:44:12,296 INFO  [project.spring.aop.LoggingAdvice.before(LoggingAdvice.java:16)]  - About to call method: org.springframework.orm.hibernate3.LocalSessionFactoryBean.getObject
    2006-01-29 01:44:12,296 INFO  [project.spring.aop.LoggingAdvice.afterReturning(LoggingAdvice.java:22)]  - Successfully returned from method: org.springframework.orm.hibernate3.LocalSessionFactoryBean.getObject
    java.lang.ClassCastException
        at Test.main(Test.java:13)
    Exception in thread "main" 

    I’ve verified that my Hibernate set-up is correct, by indepedently running a Hibernate query via the Hibernate static SessionFactory and that worksed fine. So it seems to be some issue with the Spring-Hibernate mechanism??

    Anyone has any idea what’s wrong here?

    #245572 Reply

    Riyad Kalla
    Member

    I’ll kick this back to the team that worked on the hib-spring integration and see what is wrong.

    Also the problem of *only* UsersDAO getting added to the Spring context is a known bug, they all should be added.

    #245576 Reply

    everbright
    Member

    Hi rkalla,

    Thanks for the quick response on this!

    Just want to clarify one thing as well. The applicationContext.xml that I supplied above is only a fragment of the whole file, which is pretty long and cluttered. I don’t seem to hit the bug of only having the DAO added to the factory.

    According to my Spring logs, I have no problems with the Bean Factory setting up the other beans correctly.

    #245581 Reply

    everbright
    Member

    Hi,

    Just an update. I’ve tried to configure the Spring-Hibernate set-up using entirely Spring configuration, instead of relying on the hibernate.cfg.xml file, and it still fails 😥

    So it looks like a problem with Spring’s integration to Hibernate?

    #245585 Reply

    Brian Fernandes
    Moderator

    everbright,

    Just clarifying for everyone that we don’t do any sort of “integration” at a library / JAR level. The JARs are the standard JARs which are shipped with Hibernate and Spring.
    What we do however, is generate a lot of code and markup for Hibernate which takes advantage of the fact that you’re managing your project using Spring.

    While I haven’t tried out exactly what you mentioned, we did use the DAOs we generated in our Spring-Hibernate projects for data acess, so I know they worked very smoothly for us.

    Could you see *what* object you are actually getting at the end of the getBean(“UsersDAO”) call?
    I know you mentioned this above but are you able to retrieve any other beans (or setup a dummy bean) from your applicationContext.xml file? I think this could be a spring configuration issue.

    I realize you are diving into Spring + Hibernate yourself, we’re happy you like what you see in MyEclipse and would welcome further suggestions 🙂

    Best,
    Brian.

    #245586 Reply

    everbright
    Member

    Hi,

    I think I’ve figured out what the problem is. I had some AOP-related configuration which actually causes a LoggingAdvice to advise all methods for all beans from the Spring Factory.

    The class returned by the Spring Factory is $Proxy3.

    Once I removed the advising, I could instantiate the UsersDAO bean correctly.

    So it seems like I can’t properly retrieve any AOP-advised DAO bean from the Spring Factory??

    I have no problems retrieving another AOP-advised bean correctly.

    #245587 Reply

    Brian Fernandes
    Moderator

    so it seems like I can’t properly retrieve any AOP-advised DAO bean from the Spring Factory??

    This is more of a spring question – my thoughts are that you might have to change the DAO bean definition or maybe the class as well so that it works with your LoggingAdvice.

    Could you give us details of the LoggingAdvice you are using? Is it custom or a part of spring; how is the advice configured to instrument all your beans, are you using some sort of AutoProxying? (pasting the xml here would help)

    Best,
    Brian.

    #245588 Reply

    everbright
    Member

    Yup, I’m using autoproxying.

    Here’s the Spring configuration for the Logging Advice:

    <bean id="autoProxyCreator" class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator" />
    <bean id="loggingAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
         <property name="patterns">
              <value>Config.*\..*</value>
         </property>
         <property name="advice">
              <bean class="project.spring.aop.LoggingAdvice"/>
         </property>
    </bean>

    Here’s the source code for the class:

    LoggingAdvice.java

    package project.spring.aop;
    
    import java.lang.reflect.Method;
    
    import org.apache.log4j.Logger;
    import org.springframework.aop.AfterReturningAdvice;
    import org.springframework.aop.MethodBeforeAdvice;
    import org.springframework.aop.ThrowsAdvice;
    
    public class LoggingAdvice implements MethodBeforeAdvice, AfterReturningAdvice, ThrowsAdvice {
    
        Logger logger = Logger.getLogger("Default logger");
        
        public void before(Method method, Object[] args, Object target) throws Throwable {
            if (logger.isInfoEnabled()) {
                logger.info("About to call method: " + target.getClass().getName() + "." + method.getName());
            }        
        }
    
        public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
            if (logger.isInfoEnabled()) {
                logger.info("Successfully returned from method: " + target.getClass().getName() + "." + method.getName());
            }
        }
    
        public void afterThrowing(Method method, Object[] args, Object target, Throwable throwable) {
            logger.error("Exception of type " + throwable.getClass().getName() + " thrown in method " + target.getClass().getName() + "." + method.getName() + ". Message: " + throwable.getMessage());
        }
    }

    As you can see, this is just basically a very simple logging class that uses Log4J to do generic logging of class methods.

    Agreed that this is more likely a Spring-Hibernate issue. I’ll make a post on the Spring forums instead.

    Thanks for the help with this!

    #245604 Reply

    Brian Fernandes
    Moderator

    everbright,

    The cleanest way to do this (becuase of how ProxyFactoryBean works) is to have your generated DAO class implement an interface, and then cast to that interface instead of UsersDAO.

    
    class UsersDAO extends HibernateDAOSupport implements DAOInterface {
    ...
    }
    
    DAOInterface usersDAO = (DAOInterface)factory.getBean("UsersDAO");
    

    I know this might make things a little tricky becuase we don’t generate a DAOInterface, but since the DAO class doesn’t really change when you change your mappings, you can just generate them once and make the change manually. This is something we didn’t think of and we’ll be looking at this aspect in 4.1.1, so you shouldn’t have this issue.

    If manual editing is going to be a pain, I will post a template workaround until 4.1.1

    Let us know how it turns out,

    Best,
    Brian.

    #245660 Reply

    Brian Fernandes
    Moderator

    everbright,

    I did some more digging and found that you could also solve this problem by declaring your DefaultAdvisorAutoProxyCreator bean like so:

    
    <bean id="autoProxyCreator" class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator">
      <property name = "proxyTargetClass" value = "true"/>
    </bean>
    

    The implications of this can be found at http://www.springframework.org/docs/reference/aop.html – see section 6.5.4

    Does this solve your problem?

    Best,
    Brian.

    #246602 Reply

    smoyer
    Member

    I am using the same code and configs that are shown above.

    This is my applicationContext.xml:
    <beans>

    <bean id=”sessionFactory” class=”org.springframework.orm.hibernate3.LocalSessionFactoryBean”>
    <property name=”configLocation”>
    <value>file:src/dataAccess/hibernate.cfg.xml</value>
    </property>
    </bean>
    <bean id=”UserDAO” class=”dataAccess.UserDAO”>
    <property name=”sessionFactory”>
    <ref bean=”sessionFactory”></ref>
    </property>
    </bean>
    </beans>

    I have my DAO, hibernate mappings, and data object all in the dataAccess package. My applicationContext.xml is under the src directory. I am getting the following error:

    org.springframework.beans.factory.BeanDefinitionStoreException: Error registering bean with name ‘UserDAO’ defined in class path resource [applicationContext.xml]: Class that bean class [dataAccess.UserDAO] depends on not found; nested exception is java.lang.NoClassDefFoundError: org/hibernate/criterion/Criterion

    Can anybody steer me in the right dircection? Or can anybody steer me towards a resource that has a good example of the spring/hibernate config files. I am trying to put this together with the help of myEclipse generators and bits and pieces of samples that I find on the internet. I know that my mapping isn’t right, but I am having difficulties figuring it out.

    Thanks

    #246626 Reply

    Riyad Kalla
    Member

    Have you added Hibernate 2 or HIbernate 3 capabilities to your project? From the error it looks like it wants Hibernate 3 libraries (org.hibernate package instead of net.sf.hibernate package)

    #246630 Reply

    smoyer
    Member

    I have both Hibernate 3.0 Core Libraries and Hibernate 3.0 Advanced Support Libraries in my class path.

    #246635 Reply

    Haris Peco
    Member

    Smoyer,

    Class org.hibernate.criterion.Criterion is from hibernate3.jar – check if you add this file (you have to find this in Hibernate Core 3.0 libraries)

    best

    #246672 Reply

    smoyer
    Member

    org.hibernate.criterion.Criterion is there.

Viewing 15 posts - 1 through 15 (of 19 total)
Reply To: Spring-Hibernate: Class-cast exception when retrieving DAO

You must be logged in to post in the forum log in