Valentin
Valentin

Reputation: 11

Connection refused : Testcontainer and Spring >3.1.x + Elastic 8

I have been running circle for quite some times and I suppose that I missed something in the documentation. I wanted to upgrade our integration test using testcontainer and spring 3.1 update (esp the service connection). It works for the DB I am using but for elastic I had to do an extra step and move from 7.x to 8.1.x. Elastic 8.x. However I run into a nice connection refused loop.

I know that Elastic 8 brings default security enabled (https://github.com/spring-projects/spring-boot/issues/35926) however I disabled those. There is also a default password setup by the container (https://github.com/testcontainers/testcontainers-java/blob/main/modules/elasticsearch/src/main/java/org/testcontainers/elasticsearch/ElasticsearchContainer.java#L138).

Note that I do declare uri, username and password in application-test.yml, however they are not picked up because of this @ServiceConnection it seems. Or more so, they seem to be picked up but the container itself isn't bound to this address. spring.elasticsearch.username: user spring.elasticsearch.password: changeme spring.elasticsearch.uris: http://localhost:9200

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@Testcontainers
@ActiveProfiles("test")
@Slf4j
public class FooControllerIT {
@Container
@ServiceConnection
static MongoDBContainer mongoDBContainer = new      MongoDBContainer(DockerImageName.parse("mongo").withTag("xxx"));
@Container
@ServiceConnection
static ElasticsearchContainer elasticsearchContainer = new ElasticsearchContainer(DockerImageName.parse("docker.elastic.co/elasticsearch/elasticsearch")
        .withTag("8.x"))
        .withEnv("xpack.security.enabled", "false")
        .withEnv("xpack.security.transport.ssl.enabled","false")
        .withEnv("xpack.security.http.ssl.enabled","false");

@Autowired
private SomeController someController;


@BeforeEach
void setUp() {
    mongoDBContainer.start();
    elasticsearchContainer.start();//fails at startup or whenever trying to access one of its properties. <----
    Awaitility.await().atMost(Duration.ofMinutes(2)).until(() ->
            elasticsearchContainer.isRunning()); //<---- does not reach there so connection issue is not because the container is not yet opened 
   log.info("blabla"+elasticsearchContainer.isRunning()+","+elasticsearchContainer.isHostAccessible());
}

I suppose what is happening is that it tries to read the properties and picks up port 9200 while the container is initialized on another port.

Previously I could do something like that

public static class ElasticConfigInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {
    @Override
    public void initialize(ConfigurableApplicationContext applicationContext) {
        elasticsearchContainer.start();
        await().atMost(120, TimeUnit.SECONDS).until(elasticsearchContainer::isRunning);
        String hostAddress = "http://" + elasticsearchContainer.getHttpHostAddress();
        TestPropertyValues.of(
                        "spring.elasticsearch.uris=" + hostAddress)
                .applyTo(applicationContext);
        log.info("finished Elastic config"+ elasticsearchContainer.getBoundPortNumbers()+","+elasticsearchContainer.getLogs());
    }

Is this still needed? I thought the new annotation @ServiceConnection was there to pickup the default values ?

Stacktrace :

Caused by: java.net.ConnectException: Connection refused: no further information
    at java.base/sun.nio.ch.Net.pollConnect(Native Method)
    at java.base/sun.nio.ch.Net.pollConnectNow(Net.java:672)
    at java.base/sun.nio.ch.SocketChannelImpl.finishConnect(SocketChannelImpl.java:946)
    at org.apache.http.impl.nio.reactor.DefaultConnectingIOReactor.processEvent(DefaultConnectingIOReactor.java:174)
    at org.apache.http.impl.nio.reactor.DefaultConnectingIOReactor.processEvents(DefaultConnectingIOReactor.java:148)
    at org.apache.http.impl.nio.reactor.AbstractMultiworkerIOReactor.execute(AbstractMultiworkerIOReactor.java:351)
    at org.apache.http.impl.nio.conn.PoolingNHttpClientConnectionManager.execute(PoolingNHttpClientConnectionManager.java:221)
    at org.apache.http.impl.nio.client.CloseableHttpAsyncClientBase$1.run(CloseableHttpAsyncClientBase.java:64)
    at java.base/java.lang.Thread.run(Thread.java:833)

What I am expecting is simply to get this @ServiceConnection working without having to override the default set up in my configuration. Is that possible? Am I missing something ?

Thanks in advance..

Upvotes: 1

Views: 585

Answers (0)

Related Questions