I wish to understand Generic Repository pattern. I have a generic service interface which is implemented by abstract service which is extended by all service implementations. I want to make sure that all CRUD operations and search by criteria/specifications happens in the abstract service.
All my repositories are interfaces extending JpaRepository and JpaSpecificationExecutor. However, I am not able to perform a findAll(specification, pageable) using the autowired repository in the abstract service.
What changes should I make to the structure so that I can leverage the methods of JpaSpecificationExecutor?
Service Interface:
public interface GenericFoo<T, S> {
public List<T> search(S criteria, Pageable pageable) {
}
Abstract service:
public abstract class Foo<T, S> implements GenericFoo<T, S> {
@Autowired
private JpaRepository<T, Long> repository;
public List<T> search(S criteria, Pageable pageable) {
//throws compilation error
repository.findAll(getSpecification(criteria), pageable);
}
protected abstract Specification<T> getSpecification(S criteria);
}
ServiceImpl:
@Component
@Transactional
public class BarServiceImpl extends Foo<Bar, BarSearchCriteria> implements GenericFoo {
protected Specification<Bar> getSpecification(BarSearchCriteria criteria) {
//implementation to be filled for each service
return null;
}
}
Repository:
public interface BarRepository extends JpaRepository<Bar, Long>, JpaSpecificationExecutor<Bar> {
}
EDIT: I tried the following as well, although the compilation error goes away, but still the application fails to start up due to Autowiring exceptions.
SimpleJpaRepository:
public interface SimpleRepository<T> extends JpaRepository<T, Long>, JpaSpecificationExecutor<T> {
}
BaseService:
public abstract class BaseService<T, S> implements GenericService<T, S> {
@Autowired
private SimpleJpaRepository<T, Long> simpleJpaRepository;
public List<T> search(S criteria, Pageable pageable) {
repository.findAll(getSpecification(criteria), pageable);
}
protected abstract Specification<T> getSpecification(S criteria);
}
Repository:
public interface BarRepository extends SimpleJpaRepository<Bar, Long> {
}
Stacktrace:
Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: private org.springframework.data.jpa.repository.support.SimpleJpaRepository com.foopackage.barpackage.services.BaseService.simpleJpaRepository; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [org.springframework.data.jpa.repository.support.SimpleJpaRepository] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:573) ~[spring-beans-4.2.8.RELEASE.jar:4.2.8.RELEASE]
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:88) ~[spring-beans-4.2.8.RELEASE.jar:4.2.8.RELEASE]
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:331) ~[spring-beans-4.2.8.RELEASE.jar:4.2.8.RELEASE]
... 22 common frames omitted
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [org.springframework.data.jpa.repository.support.SimpleJpaRepository] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoSuchBeanDefinitionException(DefaultListableBeanFactory.java:1380) ~[spring-beans-4.2.8.RELEASE.jar:4.2.8.RELEASE]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1126) ~[spring-beans-4.2.8.RELEASE.jar:4.2.8.RELEASE]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1021) ~[spring-beans-4.2.8.RELEASE.jar:4.2.8.RELEASE]
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:545) ~[spring-beans-4.2.8.RELEASE.jar:4.2.8.RELEASE]
... 24 common frames omitted