I have been trying to test EventStore with the TestContainers library, using the Java client.
Unfortunately, regardless of all my efforts to tell the Java client to use the port provided by TestContainer for each test, it always sends its messages towards server port 2113.
The version of the Java library I have used is “com.eventstore” % “db-client-java” %“5.3.1” (sbt format, as I am actually using Scala, and not plain Java).
I have tried to load the Java client project into an IDE to investigate the problem further, but I was not able to easily build it, as it lacks a POM file, and the gradle script was failing to load.
At the moment I am investigating using the raw grpc
calls directly from scala
, even though I am struggling to understand how to properly invoke the “Streams.Append” method.
What does your connection string looks like ?
esdb://Some.Host:2113/
you can change the port ^
Thanks Yves for the pointer.
What I am reporting is that, even if I do change the port in the connection string, the Java client still connects to port 2113.
It feels very weird, but after having struggled for a couple of days with the issue, I have collect enough evidence that seems to prove the point pretty strongly.
I am not completely ruling out that I have done some stupid things, but the evidence looked pretty strong to me.
Could it be that you are incorrectly exposing the ports in your Docker Compose file and how you’re configuring the TestContainers environment?
Your Docker Compose file, exposing the ports, might look like this:
version: "3.9"
services:
eventstore:
image: eventstore/eventstore:latest
environment:
- EVENTSTORE_CLUSTER_SIZE=1
- EVENTSTORE_RUN_PROJECTIONS=All
- EVENTSTORE_START_STANDARD_PROJECTIONS=true
- EVENTSTORE_HTTP_PORT=2115
- EVENTSTORE_INSECURE=true
- EVENTSTORE_ENABLE_ATOM_PUB_OVER_HTTP=true
ports:
- "3133:2115"
Then, your TestContainers configuration could look like this:
new DockerComposeContainer(new File("src/test/resources/compose-test.yaml"))
.withExposedService("eventstore", 2115)
.withStartupTimeout(Duration.ofSeconds(30));
And your connection string should look like this:
EventStoreDBClientSettings settings = EventStoreDBConnectionString.parseOrThrow("esdb://localhost:3133?tls" +
"=false");
EventStoreDBClient client = EventStoreDBClient.create(settings);
Try it out and let us know if it worked.
I don’t think this was the issue, as I was able to correctly connect to the EventStore on the “weird” port via an external GRPC client.
I will try to trim down the project to a replicable example and share it when done.
Hello,
here (Microsoft OneDrive) you can find a trivial Java project (built using Maven) that uses TestContainers to spin an EventStoreDB instance and run three tests:
- the new instance is not listening on port 2113
- a generic GRPC client is able to read the server version
- the official JavaClient can NOT get the server version, as it fails with “The connection is closed” exception.
ATTENTION: the last test will not fail if an instance of EventSourceDB is listening on port 2113.
If the code to configure the Official Java Client (src/test/java/it/avanscoperta/eventstore/connectionportissue/ConnectionPortIssueTest.java#60) is not screwed for some reasons I can not see, my point should be proved.
Thanks for sending the sample.
T̶h̶e̶ ̶̶e̶s̶d̶b̶+̶d̶i̶s̶c̶o̶v̶e̶r̶:̶/̶/̶
̶ ̶i̶n̶ ̶y̶o̶u̶r̶ ̶c̶o̶n̶n̶e̶c̶t̶i̶o̶n̶ ̶s̶t̶r̶i̶n̶g̶ ̶w̶a̶s̶ ̶c̶a̶u̶s̶i̶n̶g̶ ̶t̶h̶e̶ ̶i̶s̶s̶u̶e̶.̶ ̶I̶t̶’̶s̶ ̶u̶s̶e̶d̶ ̶f̶o̶r̶ ̶d̶i̶s̶c̶o̶v̶e̶r̶i̶n̶g̶ ̶n̶o̶d̶e̶s̶ ̶i̶n̶ ̶a̶ ̶c̶l̶u̶s̶t̶e̶r̶,̶ ̶b̶u̶t̶ ̶s̶i̶n̶c̶e̶ ̶y̶o̶u̶’̶r̶e̶ ̶j̶u̶s̶t̶ ̶c̶o̶n̶n̶e̶c̶t̶i̶n̶g̶ ̶t̶o̶ ̶a̶ ̶s̶i̶n̶g̶l̶e̶ ̶i̶n̶s̶t̶a̶n̶c̶e̶,̶ ̶y̶o̶u̶ ̶d̶o̶n̶’̶t̶ ̶n̶e̶e̶d̶ ̶i̶t̶.̶
A random port is allocated when using testcontainers and in order to make it work you should use the env variable EVENTSTORE_ADVERTISE_NODE_PORT_TO_CLIENT_AS
provided by EventStoreDB.
or you alternatively, you could remove +discover from your connection string.
See solution below
Thanks William,
sticking with the esdb
only protocol worked; thanks.
Now I need to review the documentation to understand what is actually happening when using the esdb+discover
protocol, though.
Thanks,
Giulio Cesare
Looking through the documentation, the main reference to the connection string
I found is this:
And this references the “above connection string generator”, but no detailed documentation on how this string is composed is referenced.
The generator itself though does not seem to work properly for some configuration options:
In the example above, the suggested connection string is obviously wrong (hostname is still [not provided]
, and the port still 2113
), but it does not provide any hint at the fact that the protocol handler should be changed.
When changing some of the parameters in the configurator form, the JavaScript console was logging messages like x.el is undefined
.
Not sure what is happening there, but at least I now understand the original seed of the problem I was having.
I̶n̶ ̶a̶ ̶s̶i̶n̶g̶l̶e̶-̶n̶o̶d̶e̶ ̶c̶o̶n̶f̶i̶g̶u̶r̶a̶t̶i̶o̶n̶,̶ ̶t̶h̶e̶r̶e̶ ̶i̶s̶ ̶n̶o̶ ̶n̶e̶e̶d̶ ̶f̶o̶r̶ ̶n̶o̶d̶e̶ ̶d̶i̶s̶c̶o̶v̶e̶r̶y̶ ̶b̶e̶c̶a̶u̶s̶e̶ ̶t̶h̶e̶r̶e̶ ̶a̶r̶e̶ ̶n̶o̶ ̶a̶d̶d̶i̶t̶i̶o̶n̶a̶l̶ ̶n̶o̶d̶e̶s̶ ̶t̶o̶ ̶d̶i̶s̶c̶o̶v̶e̶r̶.̶ ̶Y̶o̶u̶ ̶c̶o̶u̶l̶d̶ ̶l̶e̶a̶v̶e̶ ̶+̶d̶i̶s̶c̶o̶v̶e̶r̶ ̶i̶n̶ ̶y̶o̶u̶r̶ ̶c̶o̶n̶n̶e̶c̶t̶i̶o̶n̶ ̶s̶t̶r̶i̶n̶g̶ ̶b̶u̶t̶ ̶y̶o̶u̶ ̶w̶i̶l̶l̶ ̶h̶a̶v̶e̶ ̶t̶o̶ ̶s̶e̶t̶ ̶̶E̶V̶E̶N̶T̶S̶T̶O̶R̶E̶_̶D̶I̶S̶C̶O̶V̶E̶R̶_̶V̶I̶A̶_̶D̶N̶S̶ ̶
̶ ̶t̶o̶ ̶̶f̶a̶l̶s̶e̶
̶ ̶i̶n̶ ̶y̶o̶u̶r̶ ̶s̶e̶r̶v̶e̶r̶ ̶c̶o̶n̶f̶i̶g̶u̶r̶a̶t̶i̶o̶n̶.̶
This is incorrect.
1 Like
Setting the EVENTSTORE_DISCOVER_VIA_DNS
option to false
did not fixed the connection issue, when using the esdb+discover
protocol handler in my test project.
Sorry, scratch my last comment. What I said was incorrect. Your observation about the connection details form not being updated when the values are changed has been noted and will be fixed.
1 Like
Thanks William for the update.
I found this interesting option (EVENTSTORE_GOSSIP_ON_SINGLE_NODE
) that looked like a viable option to retain the esdb+discover
protocol handler, even if running just a single instance: Highly-available cluster | EventStoreDB Documentation
to prevent changing the connection style, you might want to connect to your single-node instance using the gossip protocol as well. To do so, you’d need to enable gossip for that instance as it is disabled by default.
I tried setting this setting to true
, but my simple test case still fails.
Actually, you will need to use EVENTSTORE_ADVERTISE_NODE_PORT_TO_CLIENT_AS
to advertise the external port and not the internal port. see Networking | EventStoreDB Documentation
Where this value should be equal to the mapped port of the container
Thanks William,
but the suggestion to use EVENTSTORE_ADVERTISE_NODE_PORT_TO_CLIENT_AS
is not effective in my setup, as this value should be provided when starting up the pod instance, but the actual port assigned by TestContainers to the pod will be available only after having boot the pod. Classical catch-22 situation.
I will stick with the esdb
protocol; thanks.
but the actual port assigned by TestContainers to the pod will be available only after having boot the pod
You can actually. there is a method available for that called addFixedExposedPort but you will have to change your class a little bit.
Hope this helps.
1 Like