'How to close ElasticSearch RestHighLevelClient in spring-data in order to avoid sonar blocking issue Resources should be closed

Sonar complains because RestHighLevelClient is not closed explicitly, but I am using spring-data and client is used by the repository transparenty for me.

I have a configuration class

@Configuration
@EnableElasticsearchRepositories(basePackages = "foo.package.repository")
public class RestClientESConfig extends AbstractElasticsearchConfiguration {

    // elastic search host
    @Value("${spring.elasticsearch.rest.uris}")
    private String elasticsearchHost;

    @Override
    public RestHighLevelClient elasticsearchClient() {
        return RestClients.create(
                ClientConfiguration.builder()
                        .connectedTo(elasticsearchHost)
                        .build())
                .rest();
    }
}

sonar says:

Resources should be closed

Blocker java:S2095

Connections, streams, files, and other classes that implement the Closeable interface or its super-interface, AutoCloseable, needs to be closed after use. Further, that close call must be made in a finally block otherwise an exception could keep the call from being made. Preferably, when class implements AutoCloseable, resource should be created using "try-with-resources" pattern and will be closed automatically.***

What can I do to avoid this sonar blocking issue?



Solution 1:[1]

I'm not a Spring data user but can't you have RestClientESConfig implements Closeable so you can implement the close() method which would then call the client close() method?

Something like this untested code?

@Configuration
@EnableElasticsearchRepositories(basePackages = "foo.package.repository")
public class RestClientESConfig extends AbstractElasticsearchConfiguration implements Closeable {

    // elastic search host
    @Value("${spring.elasticsearch.rest.uris}")
    private String elasticsearchHost;
    private final RestHighLevelClient client;

    public RestClientESConfig() {
      client = RestClients.create(
                ClientConfiguration.builder()
                        .connectedTo(elasticsearchHost)
                        .build())
                .rest();
    }

    @Override
    public RestHighLevelClient elasticsearchClient() {
        return client;
    }

    @Override
    public void close() {
        client.close();
    }
}

Solution 2:[2]

It looks like it is not a spring data problem, but a sonar rule one. Sonar should not check if client is closed manually because spring data does it automatically.

Solution 3:[3]

You may close it in a method annotated by @PreDestroy or @Bean(destroyMethod = "close"). But Sonar is not able to detect this fix, so provide // NOSONAR hint.

@Bean(destroyMethod = "close")
public RestHighLevelClient restHighLevelClient() {
    return new RestHighLevelClient(
            RestClient.builder(new HttpHost(address, port, "http"))); // NOSONAR java:S2095 closed by spring @Bean(destroyMethod = "close")
}

Inspired by https://stackoverflow.com/a/55025393/204950

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 dadoonet
Solution 2 J. Escribano
Solution 3 banterCZ