После миграции Spring Data ES: IllegalArgumentException: NamedWriteable уже зарегистрирован для [...], не может зарегистрироваться [...] - PullRequest
0 голосов
/ 22 октября 2019

У меня есть приложение Spring (это часть кластера Spring Discovery в качестве клиента обнаружения). Мы решили перенести это приложение из Spring Dataasticsearch 2.1.1.RELEASE (ссылка на Dockerise 2.4.3-alpineasticsearch) в SDE 3.0.14.RELEASE (которое можно связать, если я прав, с DockeriseES 5.5.0-альпийский). Моя проблема в том, что это приложение никогда не достигнет начала.

ПРИМЕЧАНИЕ. До миграции все работало идеально.

Сначала я подумал, что это проблема с зависимостями maven, поэтому я попытался найти дублирующиеся зависимости, но у меня не было результата. Я также попытался использовать собственный TransportClient (со стиранием свойств приложения для предотвращения автоконфигурации Spring), как описано в документации Elasticsearch (но, очевидно, Spring должен быть в состоянии сделать это сам).

Вот основной класс (с некоторыми, возможно, полезными, весенними аннотациями):

@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
@EnableConfigurationProperties
@Configuration
@EnableElasticsearchRepositories(basePackages = {"com.sap.testreportservice"}, repositoryBaseClass = ApplicationRepositoryImpl.class)
public class TestreportServiceApplication {

    public static void main(String[] args) {
        SpringApplication.run(TestreportServiceApplication.class, args);
    }
}

Вот его maven зависимости:


<dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-stream-rabbit</artifactId>
        <version>1.2.0.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger2</artifactId>
            <version>2.6.1</version>
        </dependency>
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger-ui</artifactId>
            <version>2.6.1</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-netflix-hystrix-stream</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-zuul</artifactId>
            <version>1.4.7.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.data</groupId>
            <artifactId>spring-data-elasticsearch</artifactId>
            <version>3.0.14.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.elasticsearch</groupId>
            <artifactId>elasticsearch</artifactId>
            <version>5.5.0</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
        <dependency>
            <groupId>org.json</groupId>
            <artifactId>json</artifactId>
            <version>20190722</version>
            <scope>compile</scope>
        </dependency>
    </dependencies>

Вот некоторые свойства приложения:

spring:
  data:
    elasticsearch:
      cluster-name: ${ES_CLUSTER_NAME:insights}
      cluster-nodes: ${ES_CLUSTER_NODES:localhost:9300}

Вот мой пользовательский транспортный клиент:

@Configuration
public class ElasticsearchConfig {

    @Bean
    Client client() {
        Settings settings = Settings.builder()
                .put("cluster.name", "insights")
                .build();
        TransportClient client = new PreBuiltTransportClient(settings);
        try {
            client.addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("localhost"), 9300));
        } catch (UnknownHostException e) {
            e.printStackTrace();
        }
        return client;
    }
}

Вот некоторая выдержка из журнала (попросите у меня полную трассировку стека)


Caused by: java.lang.IllegalArgumentException: NamedWriteable [org.elasticsearch.index.query.QueryBuilder][parent_id] is already registered for [org.elasticsearch.search.SearchModule$$Lambda$942/734191650], cannot register [org.elasticsearch.join.ParentJoinPlugin$$Lambda$952/956934228]
    at org.elasticsearch.common.io.stream.NamedWriteableRegistry.<init>(NamedWriteableRegistry.java:91) ~[elasticsearch-5.5.0.jar:5.5.0]
    at org.elasticsearch.client.transport.TransportClient.buildTemplate(TransportClient.java:148) ~[elasticsearch-5.5.0.jar:5.5.0]
    at org.elasticsearch.client.transport.TransportClient.<init>(TransportClient.java:254) ~[elasticsearch-5.5.0.jar:5.5.0]
    at org.springframework.data.elasticsearch.client.TransportClientFactoryBean$SpringDataTransportClient.<init>(TransportClientFactoryBean.java:234) ~[spring-data-elasticsearch-3.0.14.RELEASE.jar:3.0.14.RELEASE]
    at org.springframework.data.elasticsearch.client.TransportClientFactoryBean.buildClient(TransportClientFactoryBean.java:103) ~[spring-data-elasticsearch-3.0.14.RELEASE.jar:3.0.14.RELEASE]
    at org.springframework.data.elasticsearch.client.TransportClientFactoryBean.afterPropertiesSet(TransportClientFactoryBean.java:98) ~[spring-data-elasticsearch-3.0.14.RELEASE.jar:3.0.14.RELEASE]
    at org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchAutoConfiguration.elasticsearchClient(ElasticsearchAutoConfiguration.java:59) ~[spring-boot-autoconfigure-2.1.7.RELEASE.jar:2.1.7.RELEASE]
    at org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchAutoConfiguration$$EnhancerBySpringCGLIB$$151bff6d.CGLIB$elasticsearchClient$0(<generated>) ~[spring-boot-autoconfigure-2.1.7.RELEASE.jar:2.1.7.RELEASE]
    at org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchAutoConfiguration$$EnhancerBySpringCGLIB$$151bff6d$$FastClassBySpringCGLIB$$575694c9.invoke(<generated>) ~[spring-boot-autoconfigure-2.1.7.RELEASE.jar:2.1.7.RELEASE]
    at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:244) ~[spring-core-5.1.9.RELEASE.jar:5.1.9.RELEASE]
    at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:363) ~[spring-context-5.1.9.RELEASE.jar:5.1.9.RELEASE]
    at org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchAutoConfiguration$$EnhancerBySpringCGLIB$$151bff6d.elasticsearchClient(<generated>) ~[spring-boot-autoconfigure-2.1.7.RELEASE.jar:2.1.7.RELEASE]
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_181]
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_181]
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_181]
    at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_181]
    at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:154) ~[spring-beans-5.1.9.RELEASE.jar:5.1.9.RELEASE]
    ... 145 common frames omitted


1 Ответ

0 голосов
/ 22 октября 2019

Это довольно старые версии, которые вы обновляете.

Глядя на трассировку стека, вы видите, что Spring Boot все еще автоматически создает TransportClient, если вы хотите предоставить свой компонент, вы должны изменить свойкод для:

@Bean
TransportClient elasticsearchClient() {
    Settings settings = Settings.builder()
            .put("cluster.name", "insights")
            .build();
    TransportClient client = new PreBuiltTransportClient(settings);
    try {
        client.addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("localhost"), 9300));
    } catch (UnknownHostException e) {
        e.printStackTrace();
    }
    return client;
}

Автоконфигурация Spring Boot имеет аннотацию @ConditionalOnMissingBean на заводском методе, которая проверяет TransportClient, а не Client. При этом вы предоставите TransportClient, но Spring Boot сделает остальную часть автоконфигурации.

Чтобы отключить автоконфигурацию для Elasticsearch, вы можете использовать @SpringBootApplication(exclude={ElasticsearchAutoConfiguration.class}).

Есть ли у вас плагин эластичный поискконфигурация где-то в вашем конфиге? Поскольку ошибка, которую вы видите, происходит из-за того, что Клиент, который пытается создать автоконфигурация, хочет зарегистрировать ParentJoinPlugin (это жестко задано в TransportClientFactoryBean этой версии, и уже зарегистрирована конфликтующая запись.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...