본문 바로가기

삽질

[Spring Boot] A bean with that name has already been defined ~ in defined in @EnableElasticsearchRepositories declared on ElasticsearchRepositoriesRegistrar.EnableElasticsearchRepositoriesConfiguration and overriding is disabled.

이 글을 읽기 전에 https://ksb-dev.tistory.com/313를 읽고 오시는 것을 추천드립니다.

💡 해당 글과 이 글의 내용은 매우 밀접하게 연관되어 있습니다.

 

1. 문제

Spring Boot와 Elasticsearch 연동을 테스트 하던 중 제목과 같은 에러를 만날 수 있었습니다.

패키지 구조는 아래와 같습니다.

es_springboot
    -config
        -AbstractElasticsearchConfiguration.java
        -ElasticSearchConfig.java
    -domain
        -UserDocument.java
    -repository
        -UserSearchRepository.java

 

위 오류와 직접적으로 연관이 있는 클래스는 세 개 입니다.

@Configuration
@EnableElasticsearchRepositories
public class ElasticSearchConfig extends AbstractElasticsearchConfiguration {

    @Override
    public RestHighLevelClient elasticsearchClient() {
        ClientConfiguration clientConfiguration = ClientConfiguration.builder()
                .connectedTo("localhost:9200")
                .build();
        return RestClients.create(clientConfiguration).rest();
    }
}
@SpringBootApplication
public class EsSpringBootApplication {
    public static void main(String[] args) {
        SpringApplication.run(EsSpringBootApplication.class, args);
    }
}
public interface UserSearchRepository extends ElasticsearchRepository<UserDocument, Long> {
}

 

맨 위의 링크에서 알 수 있듯이,

Spring Boot는 자동으로 @EnableJpaRepositories를 사용합니다.

 

@EnableJpaRepositories는 위 그림과 같이 JpaRepositoriesRegistrar를 Import하고, 해당 클래스는 ReposistoryBeanDefinitionRegistrarSupport를 상속 받습니다.

해당 클래스들로 빈이 정의되고, 프로그램을 실행할 때, 빈으로 등록됩니다.

 

@EnableElasticsearchRepositories를 살펴보겠습니다.

@EnableElasticsearchRepositories 역시 ReposistoryBeanDefinitionRegistrarSupport를 상속받고 있습니다.

 

즉, @EnableElasticsearchRepositories를 사용하면 빈으로 등록됩니다.

 

이제 문제가 발생합니다.

 

public interface UserSearchRepository extends ElasticsearchRepository<UserDocument, Long> {
}

 

위 코드는 Spring Boot에 의해 자동으로 빈 등록이 됩니다.

 

@Configuration
@EnableElasticsearchRepositories
public class ElasticSearchConfig extends AbstractElasticsearchConfiguration {
    ...
}

위 코드 역시 @EnableElasticsearchRepositories에 의해 빈으로 등록 됩니다.

 

즉, 빈 등록이 두 번 등록되어 제목과 같이 빈이 이미 정의되어 있다고 뜨는 것입니다.

💡 등록된 빈을 로그로 찍어본 결과 확실하지는 않지만, ElasticsearchRepositoryConfigExtension로 빈 등록이 되는거 같습니다. 정확히 아시는 분은 댓글 달아주시기 바랍니다.

 

2. 해결법

해결 방법은 간단합니다.

자동으로 빈 등록되지 않도록 하면 됩니다.

 

그렇게 되면 한 번만 빈 등록이 되기 때문에 문제를 해결할 수 있습니다.

아래 코드와 같이 스캔할 때, 엘라스틱서치와 관련된 것은 등록하지 않게 하면 됩니다.

@EnableJpaRepositories(excludeFilters = @ComponentScan.Filter(
        type = FilterType.ASSIGNABLE_TYPE,
        classes = UserSearchRepository.class))
@SpringBootApplication
public class EsSpringBootApplication {
    public static void main(String[] args) {
        SpringApplication.run(EsSpringBootApplication.class, args);
    }
}