PROBLEM
Let’s assume we have the following Spring Data JPA repository…
public interface ProjectRepository extends JpaRepository<Project, Long>, ProjectRepositoryCustom { Project findByName(String name); }
… this repository has some custom implementation…
public interface ProjectRepositoryCustom { Project doCustom(String name); }
… this custom implementation depends on the original repository to reuse existing APIs…
public final class ProjectRepositoryImpl implements ProjectRepositoryCustom { private final ProjectRepository projectRepository; @Autowired public ProjectRepositoryImpl(final ProjectRepository projectRepository) { this.projectRepository = projectRepository; } @Override public Project doCustom(final String name) { final Project project = projectRepository.findByName(name); return ... } }
When we run the code, we get the following exception:-
Caused by: org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'projectRepositoryImpl': Requested bean is currently in creation: Is there an unresolvable circular reference? at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.beforeSingletonCreation(DefaultSingletonBeanRegistry.java:347) at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:223) at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:299) at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:194) at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:293)
SOLUTION
To fix the circular reference problem, instead of auto-wiring ProjectRepository
using the constructor, auto-wire using the field or setter method:-
public final class ProjectRepositoryImpl implements ProjectRepositoryCustom { // this field cannot be `final` anymore private ProjectRepository projectRepository; @Autowired public void setProjectRepository(final ProjectRepository projectRepository) { this.projectRepository = projectRepository; } @Override public Project doCustom(final String name) { final Project project = projectRepository.findByName(name); return ... } }