Hey everyone. I'm attempting make my DAO, Service and Controller classes all generic, as our data modal has about 15 entities and most of our transactions simply use the standard find, list, add, update, remove. I've been working on this for some time now and I'm stuck on one particular error. Before I give up I thought I'd post here.
Spring is failing to create the controller beans, because it cannot instantiate the related service beans, and this in turn is due to an IllegalArgumentException: argument type mismatch.
The abstract service class (EntityService) expects an IGenericDao<E, K> instance as a parameter to its constructor, and each service that extends EntityService passes in a specific DAO (e.g., ProjectDao). These specific DAOs extend the abstract class GenericDao, which implements IGenericDao.
I cannot understand why Spring has an issue with this, and especially why, at the same time, Spring seems OK passing a specific implementation of IEntityService into each controller, which to me seems to be the same process.
Is it possible for me to achieve this, and if so, what am I doing wrong?
My architecture looks like this (stripped down as much as possible):
Controllers:
Code:public interface IGenericController<E, K> { HttpEntity<String> post(String entityJson); HttpEntity<String> delete(K key); }Code:public abstract class GenericController<E, K extends Serializable> implements IGenericController<E, K> { protected Gson gson; protected IEntityService<E, K> service; public GenericController(IEntityService<E, K> service, GsonBuilder gsonBuilder) { this.service = service; this.gson = gsonBuilder.create(); } @RequestMapping(method = RequestMethod.POST) public final HttpEntity<String> post(@RequestBody final String entityJson) { E entity = gson.fromJson(entityJson, getEntityType()); service.add(entity); return JsonEntity.create(gson.toJson(entity)); } @RequestMapping(value = "/{id}", method = RequestMethod.DELETE) public final HttpEntity<String> delete(@PathVariable("id") final K id) { service.remove(id); HttpEntity<String> response = new ResponseEntity<String>(HttpStatus.OK); return response; } public abstract Class<E> getEntityType(); }Code:@Controller @RequestMapping("/projects/") public class ProjectController extends GenericController<Project, Integer> { @Autowired public ProjectController(ProjectService service, GsonBuilder gsonBuilder) { super(service, gsonBuilder); } @Override public Class<Project> getEntityType() { return Project.class; } }
Services:
Code:public interface IEntityService<E, K> { void add(E entity); void remove(K key); }Code:@Transactional public abstract class EntityService<E, K extends Serializable> implements IEntityService<E, K> { protected IGenericDao<E, K> dao; public EntityService(IGenericDao<E, K> dao) { this.dao = dao; } public void add(E entity) { dao.add(entity); } public void remove(K key) { dao.remove(key); } }DAOs:Code:@Service public class ProjectService extends EntityService<Project, Integer> { @Autowired public ProjectService(ProjectDao dao) { super(dao); } }
Code:public interface IGenericDao<E, K> { void add(E entity); void remove(K key); }Code:public abstract class GenericDao<E, K extends Serializable> implements IGenericDao<E, K> { @PersistenceContext protected EntityManager em; public void add(E e) { em.persist(e); em.flush(); } public void remove(K k) { E entity = find(k); em.remove(entity); em.flush(); } protected abstract String getListQuery(); protected abstract Class<E> getEntityType(); }Code:@Repository public class ProjectDao extends GenericDao<Project, Integer> { private static final String ALL_PROJECTS = "SELECT p from Project p"; @Override protected String getListQuery() { return ALL_PROJECTS; } @Override protected Class<Project> getEntityType() { return Project.class; } }


Reply With Quote
