Announcement Announcement Module
Collapse
No announcement yet.
[Spring + Hibernate + Jersey] Unable to configure Persistence Layer Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • [Spring + Hibernate + Jersey] Unable to configure Persistence Layer

    Hi all,
    There are a lot of days i'm trying to configure Spring, to use Hibernate, without success.

    I Created a GenericDAO, a concrete DAO, a GenericService and a Concrete Service.

    To make everything up and running, I did the following applicationContext.xml:

    Code:
    <?xml version="1.0" encoding="UTF-8"?>
    <beans ... default-autowire="byName">
    
        <context:component-scan base-package="project" />
        <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
            <property name="driverClassName" value="com.mysql.jdbc.Driver" />
            <property name="url" value="jdbc:mysql://localhost:3306/project" />
            <property name="username" value="user" />
            <property name="password" value="password" />
        </bean>
    
        <bean id="sessionFactory" 
            class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
            <property name="configLocation" value="classpath:META-INF/hibernate.cfg.xml" />
    		<property name="dataSource" ref="dataSource" />
            <property name="packagesToScan" value="project.persistence.entities" />
        </bean>
    
        <bean id="transactionManager" 
            class="org.springframework.orm.hibernate3.HibernateTransactionManager">
            <property name="sessionFactory" ref="sessionFactory"/>
        </bean>
    
        <tx:annotation-driven />
    </beans>
    In hibernate cfg i put this properties:

    Code:
    ...
        <property name="hibernate.archive.autodetection">none</property>
        <property name="hibernate.bytecode.use_reflection_optimizer">false</property>
        <property name="hibernate.connection.autocommit">true</property>
        <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
        <property name="hibernate.connection.release_mode">auto</property>
    
        <property name="hibernate.dialect">org.hibernate.dialect.MySQLInnoDBDialect</property>
        <property name="hibernate.ejb.discard_pc_on_close">false</property>
        <property name="hibernate.query.jpaql_strict_compliance">true</property>
        <property name="hibernate.transaction.factory_class">
            org.hibernate.transaction.JDBCTransactionFactory</property>
        <property name="hibernate.transaction.flush_before_completion">false</property>
        <property name="hibernate.use_identifier_rollback">false</property>
        <property name="hibernate.show_sql">true</property>
        <property name="hibernate.current_session_context_class">thread</property>
    ...
    The class needs my service is UserResource and expects that @Autowired set all needed dependencies:

    Code:
    // ... imports ...
    @Path("/users")
    @Component
    public class UserResource {
        @Autowired
        private UserService userService;
    
        @GET
        @Produces(MediaType.APPLICATION_JSON)
        public List<User> getAll() throws Exception {
            return userService.findAll(User.class);
        }
    
        // other super-complicated methods :D
    }
    At Application Startup I received a wonderful stack-trace that tells me about it cannot autowire my UserService implementation:

    Code:
    [10-06-07 12:03:28] [ERROR] - org.springframework.web.context.ContextLoader(
        initWebApplicationContext:215) - 
        Context initialization failed
    org.springframework.beans.factory.BeanCreationException: 
        Error creating bean with name 'userResource': 
        Autowiring of fields failed; nested exception is org.springframework.beans.factory.BeanCreationException: 
        Could not autowire field: private     
        project.implementations.UserService 
        project.web.rest.controller.UserResource.userService; 
        nested exception is 
        org.springframework.beans.factory.NoSuchBeanDefinitionException: 
        No unique bean of type 
        [it.treis.zero.services.implementations.UserService] 
        is defined: Unsatisfied dependency of type [class it.treis.zero.services.implementations.UserService]: 
        expected at least 1 matching bean
            at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessAfterInstantiation(
        AutowiredAnnotationBeanPostProcessor.java:243)
            at 
    [BLA BLA BLA]
    Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: private 
    project.services.implementations.UserService 
    project.web.rest.controller.UserResource.userService; nested exception 
    is org.springframework.beans.factory.NoSuchBeanDefinitionException: No 
    unique bean of type [it.treis.zero.services.implementations.UserService] is 
    defined: Unsatisfied dependency of type [class 
    project.services.implementations.UserService]: expected at least 1 
    matching bean
            at 
    org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPost
    Processor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:435)
            at 
    org.springframework.beans.factory.annotation.InjectionMetadata.injectFields
    (InjectionMetadata.java:105)
            at 
    org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPost
    Processor.postProcessAfterInstantiation(AutowiredAnnotationBeanPostProcessor.java:240)
            ... 49 more
    Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No 
    unique bean of type [project.services.implementations.UserService] is 
    defined: Unsatisfied dependency of type [class 
    project.services.implementations.UserService]: expected at least 1 
    matching bean
            at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(
    DefaultListableBeanFactory.java:613)
            at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(
    AutowiredAnnotationBeanPostProcessor.java:412)
            ... 51 more
    The service is a concrete class implementing an interface and extending a GenericService:

    UserService
    Code:
    // ... Some imports ...
    @Service
    public class UserService extends GenericService<User, UserId> implements IUserService {
    }
    GenericService
    Code:
    // ... Some imports ...
    @Service
    public class GenericService<T, ID extends Serializable> implements IGenericService<T, ID> {
    
        protected Class<T> persistentClass;
    	
        // ApplicationContext, needed to lookup specificDAO
        @Autowired
        private ApplicationContext applicationContext;
    
        @Transactional
        public List<T> findAll(Class<T> clazz) throws Exception{
            List<T> list = null;
    	try {
                log.info("Listing all "+persistentClass);
                IGenericDAO dao = factoryDAO(clazz);
                list = dao.findAll();
            } catch (Throwable e) {
                log.error("Error during listing all "+persistentClass, e);
                throw new BusinessServiceFailureException(e);
            }
            return list;
        }
    
        // Other super-complicated methods
    
        // Methods used to lookup the right DAO
        @SuppressWarnings("unchecked")
        private IGenericDAO factoryDAO(Object entity) throws Exception{
            return this.factoryDAO(entity.getClass());
        }
    
        @SuppressWarnings("unchecked")
        private IGenericDAO factoryDAO(Class entity) throws Exception{
            try {
                String daoName = StringUtils.uncapitalize(entity.getSimpleName()+"DAO");
                return (IGenericDAO) applicationContext.getBean(daoName);
            } catch (Exception e){
                throw new DAONotFoundException(
                    "No DAO found for object type " + 
                    entity.getClass() + 
                    " in service class " + 
                    this.getClass()
                );
            }
        }
    }
    I think that the error is wired to the transaction Manager! When I add @Transactional on service or <tx:annotation-driven /> on my applicationContext the listener does not start!

    Have you any Idea? I'm really confused!

    Thank's a lot to anyone has an idea or simply read this article!
    I'm loosing faith on IT and really consider to go to the dark side of the force and become a project manager

    Ciao, Davide.

  • #2
    Hi Davide!

    The error:

    Code:
    No unique bean of type 
        [it.treis.zero.services.implementations.UserService] 
        is defined: Unsatisfied dependency of type [class it.treis.zero.services.implementations.UserService]: 
        expected at least 1 matching bean
    indicates that you have more than 1 bean of the type UserService! When using @Autowired there should be only one bean of this type configured in your application context.

    You can try using @Resource (checks for the name of the bean, not the type).

    I'd first check if there are more beans of the same type in your application context.

    Comment


    • #3
      Hi, I used ApplicationContext to get the bean, but read about the message:

      Code:
      7-giu-2010 13.30.38 com.sun.jersey.spi.container.ContainerResponse mapMappableContainerException
      GRAVE: The RuntimeException could not be mapped to a response, re-throwing to the HTTP container
      java.lang.ClassCastException: $Proxy89 cannot be cast to it.treis.zero.services.implementations.UserService
              at it.treis.zero.web.rest.controller.UserResource.getAll(UserResource.java:47)
              at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
              at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
              at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
              at java.lang.reflect.Method.invoke(Method.java:597)
              at com.sun.jersey.server.impl.model.method.dispatch.AbstractResourceMethodDispatchProvider$TypeOutInvoker._dispatch(AbstractResourceMethodDispatchProvider.java:153)
              at com.sun.jersey.server.impl.model.method.dispatch.ResourceJavaMethodDispatcher.dispatch(ResourceJavaMethodDispatcher.java:67)
              at com.sun.jersey.server.impl.uri.rules.HttpMethodRule.accept(HttpMethodRule.java:265)
              at com.sun.jersey.server.impl.uri.rules.ResourceClassRule.accept(ResourceClassRule.java:83)
              at com.sun.jersey.server.impl.uri.rules.RightHandPathRule.accept(RightHandPathRule.java:133)
      The Service is proxed... Any idea?
      I investigate...

      Comment


      • #4
        Spring uses proxy based AOP so casting to a concrete implementation isn't going to work. You will need to cast to an interface (IGenericService in your case) you will need to use a @Qualifier to get the correct instance.

        You also have some issues (which you will run into next) with your hibernate settings.

        Code:
        <property name="hibernate.archive.autodetection">none</property>
            <property name="hibernate.bytecode.use_reflection_optimizer">false</property>
            <property name="hibernate.connection.autocommit">true</property>
            <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
            <property name="hibernate.connection.release_mode">auto</property>
        
            <property name="hibernate.dialect">org.hibernate.dialect.MySQLInnoDBDialect</property>
            <property name="hibernate.ejb.discard_pc_on_close">false</property>
            <property name="hibernate.query.jpaql_strict_compliance">true</property>
            <property name="hibernate.transaction.factory_class">
                org.hibernate.transaction.JDBCTransactionFactory</property>
            <property name="hibernate.transaction.flush_before_completion">false</property>
            <property name="hibernate.use_identifier_rollback">false</property>
            <property name="hibernate.show_sql">true</property>
            <property name="hibernate.current_session_context_class">thread</property>
        
        Blue - useless can be removed
        Red - breaks proper spring integration.

        Comment


        • #5
          Wow!

          It seems to work! Really thank's a lot!!!

          To solve problem I deleted red and blue property declarations on hibernate cfg, but I think the most important correction is to change UserService reference to his interface, IUserService.

          Thank's again, Davide.

          Comment

          Working...
          X