Results 1 to 3 of 3

Thread: GenericDAO and GenericService .. dependency problem

  1. #1
    Join Date
    Oct 2010
    Posts
    2

    Default GenericDAO and GenericService .. dependency problem

    Hi,
    I am trying to implement Generic DAO and Generic Service but with no luck (knowledge?). Maybe this is all wrong, I don't know... (or just partially wrong )
    there is too much things to take into account and I am new in spring fw (spring mvc in this case)
    Here's a basic example:

    Repository package:

    IGENERICDAO:

    Code:
    public interface IGenericDAO<T> {
    	T save(T obj); 
    }
    GENERICDAO

    Code:
    public abstract class GenericDAO<T> implements IGenericDAO<T> {
    	
    	protected SessionFactory sessionFactory; 
    	private Class<T> type;
    	
    	@Autowired
    	public void setSessionFactory(SessionFactory sessionFactory) {  
    		this.sessionFactory = sessionFactory;  
    	}
    
    	public Class<T> getType(){
    		return this.type;
    	}
    	public void setType(Class<T> type){
    		this.type = type;
    	}
    	
    	@SuppressWarnings("unchecked")
    	public GenericDAO() {  
    		this.type = (Class<T>)
    				((ParameterizedType)getClass().getGenericSuperclass()).getActualTypeArguments()[0];  
    	}	
    	
    	@Override
    	public T save(T obj) {
    		this.sessionFactory.getCurrentSession().saveOrUpdate(obj);
    		return obj;
    	}
    }
    CATEGORYDAO

    Code:
    @Repository
    public class CategoryDAO extends GenericDAO<Category>{
    	
    	//stupid example ... never mind..just to see if it can be done
    	public int hello(){
    		System.out.println("HELLO!!");
    		Session session = this.sessionFactory.getCurrentSession();
    		Query query = session.createQuery("from Category cat where cat.id=? ");
    		query.setParameter(0, 101);
    		List<Category> results = query.list();		
    		int result = results.get(0).getId();
    		return result;
    	}
    }
    Service package - layer:

    IGENERICSERVICE

    Code:
    public interface IGenericService<T> {
    	T insert(T obj);
    }
    GENERICSERVICE

    Code:
    public class GenericService<T,D extends GenericDAO<T>> implements IGenericService<T>{
    
    	protected D dao;
    	@Autowired
    	public void setDao(D dao){
    		this.dao = dao;
    	}
    
    	@Override
    	public T insert(T obj) {
    		// TODO Auto-generated method stub
    		return null;
    	}
    }
    CATEGORYSERVICE

    Code:
    @Service
    public class CategoryService extends GenericService<Category, CategoryDAO>{
    	
    	@Transactional
    	public int hello(){
    		return dao.hello();
    	}
    }
    CONTROLLER

    Code:
    @Controller
    @RequestMapping("/homecontroller/*")
    public class HomeController {
    
    	private CategoryService categoryService;
    	@Autowired
    	public void setCategoryService(CategoryService categoryService){
    		this.categoryService = categoryService;
    	}	
    	
    	@RequestMapping(value="hello")
    	public void hello(){
    		try{
    			int intValue = categoryService.hello();
    			System.out.println(intValue);
    		}catch(Exception e){
    			e.printStackTrace();
    		}
    	}	
    }
    DISPATCHER-SERVLET:

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="
    http://www.springframework.org/schema/beans http://www.springframework.org/schem...-beans-3.0.xsd
    http://www.springframework.org/schema/context http://www.springframework.org/schem...ontext-3.0.xsd
    http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">


    <context:component-scan base-package="com.temptemp.patients" use-default-filters="true" />

    <mvc:annotation-driven/>

    <bean id="viewResolver" class="org.springframework.web.servlet.view.UrlBas edViewResolver">
    <property name="viewClass" value="org.springframework.web.servlet.view.JstlVi ew" />
    <property name="prefix" value="/WEB-INF/jsp/" />
    <property name="suffix" value=".jsp" />
    </bean>

    <!-- Configures Hibernate - Database Config -->
    <import resource="db-config.xml" />

    </beans>
    DB-CONFIG

    Code:
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
    	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    	xmlns:tx="http://www.springframework.org/schema/tx"
    	xmlns:aop="http://www.springframework.org/schema/aop"
    	xsi:schemaLocation="
    		http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
    		http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
    		http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
    
    	<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
            <property name="driverClassName"><value>com.mysql.jdbc.Driver</value></property>
            <property name="url"><value>jdbc:mysql://localhost:3306/temptemp</value></property>
            <property name="username"><value>something</value></property>
            <property name="password"><value>something</value></property>
        </bean>
        
        <!-- Hibernate SessionFactory -->
       <bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
           <property name="dataSource"><ref local="dataSource"/></property>
           
           <property name="packagesToScan">
           	<list>
           		<value>com.temptemp.patients.domain</value>
           	</list>
           </property>
           
           <property name="hibernateProperties">
           	<props>
               <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
               <prop key="hibernate.show_sql">true</prop>
           	</props>
           </property>
       </bean>
    	
    	<!-- Transaction manager for a single Hibernate SessionFactory (alternative to JTA) -->
    	<tx:annotation-driven/>
        <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
            <property name="sessionFactory"><ref local="sessionFactory"/></property>
        </bean>
        
    
    </beans>
    and I get the following message - error:

    Code:
    org.springframework.beans.factory.BeanCreationException: Could not autowire method: public void com.temptemp.patients.web.controllers.HomeController.setCategoryService(com.temptemp.patients.service.CategoryService); nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No matching bean of type [com.temptemp.patients.service.CategoryService] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {}
    If I use next code then it works

    CATEGORYSERVICE

    Code:
    @Service
    public class CategoryService{
    	private CategoryDAO dao;
    	@Autowired
    	public void setDao(CategoryDAO dao){
    		this.dao = dao;
    	}
    	
    	@Transactional
    	public int hello(){
    		return dao.hello();
    	}
               
               .............
    
    }
    but than I have to implement all crud methods in every class I make in service layer.
    I want to put CRUD methods in my Generic classes (in DAO and service) and to extend those classes:



    Is it possible to achieve this kind of implementation (1st one not this second one that works) (of course with modifications) or am I completely on the wrong track?


    Also I am trying to do this with less xml code as possible...

  2. #2
    Join Date
    Sep 2009
    Location
    Vilnius, Lithuania
    Posts
    118

    Default

    My guess is that <tx:annotation-driven/> does not proxy target class (in this case, CategoryService) if that class implements at least one interface. Which means that the resulting bean (with AOP transaction management applied) is of type GenericService, not CategoryService. That's why application context cannot find it. You could try to fix it by moving all public methods of CategoryService into an ICategoryService interface, and autowiring your controllers to the interface, not the implementation.

    My other concern is the whole idea of "generic service". Why would you do something like that? First, you can avoid most of XML configuration by using autowiring and component scanning. Second, if all your service does is delegate to respository, why not invoke the repository directly?

  3. #3
    Join Date
    Oct 2010
    Posts
    2

    Default

    @Osvaldas Grigas BIG THANKS..

    My guess is that <tx:annotation-driven/> does not proxy target class (in this case, CategoryService) if that class implements at least one interface. Which means that the resulting bean (with AOP transaction management applied) is of type GenericService, not CategoryService. That's why application context cannot find it. You could try to fix it by moving all public methods of CategoryService into an ICategoryService interface, and autowiring your controllers to the interface, not the implementation.
    Thats exectly what I have done in a first place.. I worked with interfaces .. and it worked... but when I wonted to use some methods that I didn't have in GenericService there was a problem .. because I didn't have at all interface for my categoryservice class..
    i tried to skip that part ...

    My other concern is the whole idea of "generic service". Why would you do something like that? First, you can avoid most of XML configuration by using autowiring and component scanning. Second, if all your service does is delegate to repository, why not invoke the repository directly?
    This is just a basic example.. application will have business logic not just delegation to repository .. I needed this just to see how to make basic skeleton for my application and to see what is possible and what not .. I'm still learning...

    Regarding that here is new solution ..i hope I did it right (it works):

    ICATEGORYSERVICE

    Code:
    public interface ICategoryService extends IGenericService<Category>{
    	
    	int hello();
    }
    CATEGORYSERVICE

    Code:
    @Service
    public class CategoryService extends GenericService<Category,CategoryDAO> implements ICategoryService {
    	
    	@Transactional
    	public int hello(){
    		return dao.hello();
    	}
    }
    CONTROLLER:

    Code:
    	..............
    	private ICategoryService categoryService;
    	
    	@Autowired
    	public void setCategoryService(ICategoryService categoryService){
    		this.categoryService = categoryService;
    	}
    	................
    Last edited by trix; Oct 8th, 2010 at 07:06 AM.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •