spring-boot-testjars icon indicating copy to clipboard operation
spring-boot-testjars copied to clipboard

Abstraction for port discovery / server startup

Open dsyer opened this issue 10 months ago • 5 comments

Currently a WebServer is deemed to have started when it has written a port file. Some apps do not run as a WebServerApplicationContext so they never write the file, but they still have a startup lifecycle, and could probably be persuaded to send a message (e.g. by writing to a file). An abstraction for this might be useful. Cf #44.

dsyer avatar Feb 26 '25 11:02 dsyer

Thanks @dsyer! Can you provide a concrete example of what you are wanting to solve?

rwinch avatar Mar 27 '25 21:03 rwinch

There's a sample in the gRPC project ("grpc-client"). The server is not a web server, so I had to abuse the notation a bit, and write a custom ApplicationListener. Testjars doesn't provide a hook to register it, so it had to be in META-INF/spring.factories.

dsyer avatar Mar 28 '25 08:03 dsyer

@dsyer I'm not fond of the idea of Testjars providing an abstraction for the figuring out the port that is available because Testjars is a test dependency which should not be on the classpath for production code and thus the application that Testjars is starting.

I wonder if it makes sense for Spring gRPC to create a class named GrpcWebServer that implements WebServer and publishes a WebServerInitializedEvent. If this happens, you could remove the custom ApplicationListener. This also prevents the need for another abstraction in Testjars (which would be a test dependency) since it relies on the existing Spring Boot abstraction.

What are your thoughts on Spring gRPC publishing WebServerInitializedEvent?

rwinch avatar Nov 10 '25 02:11 rwinch

TBH I'm about as fond of that idea as you are of mine. It would mean taking a dependency on spring-boot-web-server in the Spring gRPC autoconfiguration which is probably going to cause all sorts of issues.

Our solution for now is to take that dependency in the application that testjars is starting, and you can do that without modifying the original application code. So I'm not sure why you couldn't do that with a testjars dependency - maybe it could be a separate module if it isn't really "test" code?

A better solution for both of us would be to generalize the port writer concept in Boot (make it not depend on WebServer).

dsyer avatar Nov 10 '25 08:11 dsyer

Thanks for the fast response @dsyer

We were speaking about this offline and I wanted to document (somewhat thinking out loud) what we discussed so it wasn't lost.

I wonder if a port file is does not address all of the information that Testjars needs. It seems that it might need an "opt in" portion of the environment (including the port of a server) that is written out and then remapped to the application consuming that application.

An example of why this is would be a messaging application that is connecting to a broker like Rabbit. The port is not sufficient because we don't know the URL of the broker. To complicate things further, there may be an application that is a web server and also a messaging application in which case we need both the messaging and web server information.

Instead, we could instruct the application portions of the environment to export (such as the server.port and write that to a properties file. The properties file is then ingested by Testjars and remapped into the consuming application (the one that spun up the dependent application).

We'd need to be careful about credentials. Applications will need to know these (e.g. what is the username/password to connect to Rabbit). However, we do not want to write this to disk. One option would be to inject the credentials into the application via properties. In this way the consuming application would already know the secrets. This would work if we can control the credentials, but in some cases this might not be possible.

Exporting the environment can also help with scenarios where two testjars applications need an Authorization Server spun up. In this case, we don't want to start multiple Authorization Servers but instead connect them all to the same Authorization Server. This can help ensure that a single AuthZ Server is spun up. Related https://github.com/spring-projects-experimental/spring-boot-testjars/issues/40

rwinch avatar Nov 10 '25 17:11 rwinch