title: Spring MVC: Generic DAO and Service classes
body: <p>I am writting web in Spring MVC. I wrote all DAOs using Generic DAO. Now I would like to rewrite my Service classes. How can I write "Generic Service"?</p>
  
  <p>There are my DAOs:</p>
  
  <pre><code>/* ################################# DAO ################################ */
  package net.example.com.dao;
  
  import java.util.List;
  
  public interface GenericDao&lt;T&gt; {       
          public T findById(int id);     
          public List&lt;T&gt; findAll();      
          public void update(T entity);  
          public void save(T entity);    
          public void delete(T entity);
  }
  
  /* ------------------------------------------------------ */
  
  package net.example.com.dao;
  
  import java.io.Serializable;
  import java.util.List;
  
  import org.hibernate.Session;
  import org.hibernate.SessionFactory;
  import org.springframework.beans.factory.annotation.Autowired;
  import org.springframework.context.annotation.Scope;
  
  @Scope("prototype")
  public abstract class GenericHibernateDaoImpl&lt;T extends Serializable&gt; implements GenericDao&lt;T&gt; {
  
          private Class&lt;T&gt; clazz;
  
          @Autowired
          private SessionFactory sessionFactory;
  
          public final void setClazz(Class&lt;T&gt; clazzToSet) {
                  this.clazz = clazzToSet;               
          }
  
          @SuppressWarnings("unchecked")
          public T findById(int id) {
                  return (T) getCurrentSession().get(clazz, id);
          }
  
          @SuppressWarnings("unchecked")
          public List&lt;T&gt; findAll() {
                  return getCurrentSession().createQuery("FROM " + clazz.getName()).list();              
          }
  
          public void update(T entity) {
                  getCurrentSession().update(entity);            
          }
  
          public void save(T entity) {
                  getCurrentSession().save(entity);              
          }
  
          public void delete(T entity) {
                  getCurrentSession().delete(entity);            
          }
  
          protected final Session getCurrentSession(){
                  return sessionFactory.getCurrentSession();
          }
  }
  
  /* ------------------------------------------------------ */
  
  package net.example.com.dao;
  
  import net.example.com.entity.Country;
  
  public interface CountryDao extends GenericDao&lt;Country&gt; {
  
      public Country findByName(String name);    
      public Country findByCode(String code);
  
  }
  
  /* ------------------------------------------------------ */
  
  package net.example.com.dao;
  
  import org.springframework.stereotype.Repository;
  
  import net.example.com.entity.Country;
  
  @Repository
  public class CountryDaoImpl extends GenericHibernateDaoImpl&lt;Country&gt; implements CountryDao {
  
          @Override
          public Country findByName(String name) {
                  return (Country) getCurrentSession()
                                  .createQuery("FROM Country WHERE name = :name")
                                  .setString("name", name).uniqueResult();
          }
  
          @Override
          public Country findByCode(String code) {
                  return (Country) getCurrentSession()
                                  .createQuery("FROM Country WHERE code = :code")
                                  .setString("code", code).uniqueResult();
          }
  
  }
  
  /* ################################# DAO ################################ */
  </code></pre>
  
  <p>and Services:</p>
  
  <pre><code>/* ################################# SERVICE ################################ */
  
  package net.example.com.service;
  
  import java.util.List;
  
  public interface GenericManager&lt;T&gt; { // GenericManager&lt;T&gt; is the same as GenericDao&lt;T&gt;
  
          public T findById(int id);     
          public List&lt;T&gt; findAll();      
          public void update(T entity);  
          public void save(T entity);    
          public void delete(T entity);
  }
  
  /* ------------------------------------------------------ */
  
  package net.example.com.service;
  
  import java.util.List;
  
  import org.springframework.beans.factory.annotation.Autowired;
  import org.springframework.stereotype.Service;
  
  import net.example.com.dao.GenericDao;
  
  @Service
  public abstract class GenericManagerImpl&lt;T&gt; implements GenericManager&lt;T&gt; {
  
          @Autowired
          protected GenericDao&lt;T&gt; dao;
  
          @Override
          public T findById(int id) {
                  return dao.findById(id);
          }
  
          @Override
          public List&lt;T&gt; findAll() {
                  return dao.findAll();
          }
  
          @Override
          public void update(T entity) {
                  dao.update(entity);
          }
  
          @Override
          public void save(T entity) {
                  dao.save(entity);
          }
  
          @Override
          public void delete(T entity) {
                  dao.delete(entity);    
          }
  }
  /* ------------------------------------------------------ */
  
  package net.example.com.dao;
  
  import net.example.com.entity.Country;
  
  public interface CountryManager extends GenericDao&lt;Country&gt; { // CountryManager is the same as CountryDao
  
      public Country findByName(String name);    
      public Country findByCode(String code);
  }
  
  /* ------------------------------------------------------ */
  
  package net.example.com.service;
  
  import java.util.List;
  
  import javax.transaction.Transactional;
  
  import org.springframework.beans.factory.annotation.Autowired;
  import org.springframework.stereotype.Service;
  
  import net.example.com.dao.CountryDao;
  import net.example.com.entity.Country;
  
  @Service
  @Transactional
  public class CountryManagerImpl extends GenericManagerImpl&lt;Country&gt; implements CountryManager {
  
          @Override
          public List&lt;Country&gt; findAll() {
                  return dao.findAll();
          }
  
          public Country findById(int id) {
                  return dao.findById(id);
          }
  
          @Override
          public Country findByName(String name) {
                  return dao.findByName(name); // compiler (and Eclipse) do not see findByName !!!!!!!!!
          }
  
          @Override
          public Country findByCode(String code) {
                  return dao.findByCode(code); // compiler (and Eclipse) do not see findByCode !!!!!!!!!
          }
  
          @Override
          public void save(Country country) {
                  dao.save(country);
          }
  
          @Override
          public void delete(Country country) {
                  dao.delete(country);
          }
  
          @Override
          public void update(Country country) {
                  dao.update(country);
          }
  
  }
  
  /* ------------------------------------------------------ */
  
  /* ################################# SERVICE ################################ */
  </code></pre>
  
  <p>Compiler (and Eclipse) do not see <code>findByName</code> and <code>findByCode</code> methods. I understand why. But how can I rewrite it?</p>