Reputation: 63
I am writing a Spring MVC web app. There are three main domain entities: User, Project, Task. Also there are some common operations performed on those so I try to write generic interfaces and abstract classes to aggregate the common logic.
There is GenericRepository interface representing repository behavior:
package org.example.btracker.repository;
import java.io.Serializable;
import java.util.List;
public interface GenericRepository<E, K extends Serializable> {
K save(E entity);
List<E> findSeveralById(K id);
E findOneById(K id);
K update(E changedEntity);
void delete(K id);
}
There is AbstractGenericRepository where the shared logic is implemented:
package org.example.btracker.repository;
import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
@SuppressWarnings("unchecked")
public abstract class AbstractGenericRepository<E, K extends Serializable> implements GenericRepository<E, K> {
@Autowired
private SessionFactory sessionFactory;
protected Session session;
protected Class<E> type;
public AbstractGenericRepository() {
Type t = getClass().getGenericSuperclass();
ParameterizedType pt = (ParameterizedType) t;
type = (Class<E>) pt.getActualTypeArguments()[0];
session = getSession();
}
//method implementation omitted for brevity
//implemented all but findSeveralById method which is specific for each entity
private Session getSession() {
return sessionFactory.getCurrentSession();
}
}
There are three interfaces for each entity. Here is the code for Project entity:
package org.example.btracker.repository;
import org.example.btracker.domain.Project;
public interface ProjectRepository extends GenericRepository<Project, Integer> {
}
There are concrete implementations of the above mentioned interfaces for each entity. Here is the code for Project entity with a specific implementation of findSeveralById method:
package org.example.btracker.repository;
import java.util.List;
import org.example.btracker.domain.Project;
public class ProjectRepositoryImpl extends AbstractGenericRepository<Project, Integer> implements ProjectRepository {
@Override
public List<Project> findSeveralById(Integer id) {
//TODO write an implementation
return null;
}
}
There is a GenericService interface representing common Service behavior:
package org.example.btracker.service;
import java.io.Serializable;
import java.util.List;
public interface GenericService<E, K extends Serializable> {
K create(E entity);
List<E> getAll(K id);
E getOne(K id);
K update(E changedEntity);
void delete(K id);
}
There is also an abstract service where the shared logic is implemented:
package org.example.btracker.service;
import java.io.Serializable;
import java.util.List;
import org.example.btracker.repository.GenericRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
@Transactional
public abstract class AbstractGenericService<E, K extends Serializable, R extends GenericRepository<E, K>> implements GenericService<E, K> {
@Autowired
protected R repository;
//method implementation omitted for brevity
}
There are three interfaces for each entity. Here is the code for Project entity with a specific join method signature:
package org.example.btracker.service;
import org.example.btracker.dto.ProjectDto;
public interface ProjectService extends GenericService<ProjectDto, Integer> {
Integer join(Integer id);
}
There are three concrete implementations of above mentioned interfaces. Here is the code for Project entity with the implementation of the join method:
package org.example.btracker.service;
import org.example.btracker.dto.ProjectDto;
import org.example.btracker.repository.ProjectRepository;
import org.example.btracker.repository.ProjectRepositoryImpl;
import org.springframework.stereotype.Service;
@Service
public class ProjectServiceImpl extends AbstractGenericService<ProjectDto, Integer, ProjectRepository> implements ProjectService {
@Override
public Integer join(Integer id) {
// TODO write an implementation
return null;
}
}
Here in the ProjectServiceImpl class I get the error:
Bound mismatch: The type ProjectRepository is not a valid substitute for the bounded parameter <R extends GenericRepository<E,K>> of the type AbstractGenericService<E,K,R>
I can't understand what is wrong. Please advise! Thank you in advance.
Upvotes: 0
Views: 597
Reputation: 2112
You defined:
public class ProjectServiceImpl extends AbstractGenericService<ProjectDto, Integer, ProjectRepository>
public abstract class AbstractGenericService<E, K extends Serializable, R extends GenericRepository<E, K>>
Here your R extends GenericRepository<E,K>
is ProjectRepository
:
public interface ProjectRepository extends GenericRepository<Project, Integer>
so your E
type is Project
and your K
type is Integer
BUT
in your ProjectServiceImpl
your E
type is ProjectDto
, not Project
.
Upvotes: 2