I have a very simple Spring application with cloud config client and oauth resources. It's turning out to be quite a challenge to run the unit tests without requiring the config server to be up.
None of the solutions out there for disabling cloud config client work for the latest version of spring. I have even tried to use empty or bogus config.import urls, but neither disable it. I really dont want to spin up the config server just for running unit tests and it doesnt feel like the correct way either.
What is the recommended way to setup tests for a config client application?
Looking for pointers, ideas.
Thankyou!
Making the configuration optional in test seems to do the job, though you still see an attempt being made to download the config.
spring.config.import: "optional:configserver:http://localhost:8888"
OR you can use
spring.cloud.config.enabled: false
However, client will always attempt to download the configuration, even though it appears to treat it as optional and moves on. I think this is really confusing for new users - one thinks the client is still enabled. What happens when the configserver is up and you expect the client to not download the config, but it still does. I guess the only way to find out is to test.
The weird part is that the following combination fails to load the context.
spring.config.import: "optional:configserver:http://localhost:8888"
spring.cloud.config.enabled: false
Either the import is set to optional or the config is disabled, but not both at the same time.
And, this is only for the tests. Creating another profile application-standalone.yml with same settings as test, fails.
Related
We recently added MongoCk to our Spring 5 app (using the Spring runner), but are having some issues during our deploys. Our final step in the deploy process is a health check where the deployment server checks a health page every 5s for 5 minutes. Once it gets the correct response the deployment is considered successful and it finishes.
The issue is that MongoCk seems to only start the migration around 30s after the application context loads, resulting in the health check passing and the migration possibly failing after the service was "successfully" launched.
Using a standalone runner might solve this, but we really like the availability of other beans during the changelogs. So is there a way to enforce the changelogs to be processed as part of loading the application context? Or where is this delay coming from, and how can we reduce it?
You don't provide much information, but you are saying that Mongock starts 30 secs after the application context is loaded. That could be happening for two reasons:
The most likely possibility is that you are using runner-type ApplicationRunner(by default). This means that Spring decides when to run it after the entire context is loaded. From what you are saying runner-type InitializingBean is a better fit for you .
Please try this:
mongock:
runner-type: InitializingBean
You have multiple instances fighting for the lock. There is nothing we can do about it, this process is optimised(Although we are improving even more). However, as said, I believe the issue is related with the runner-type
Question:
Is there an option within spring or its embedded servlet container to open ports when spring is ready to handle traffic?
Situation:
In the current setup i use a spring boot application running in google cloud run.
Circumstances:
Cloud run does not support liveness/readyness probes, it considers an open port as "application ready".
Cloud run sends request to the container although spring is not ready to handle requests.
Spring start its servlet container, open its ports while still spinning up its beans.
Problem:
Traffic to an unready application will result in a lot of http 429 status codes.
This affects:
new deployments
scaling capabilities of cloud run
My desire:
Configure spring/servlet container to delay opening ports when application is actually ready
Delaying opening ports to the time the application is ready would ease much pain without interfering too much with the existing code base.
Any alternatives not causing too much pain?
Things i found and considered not viable
Using native-image is not an option as it is considered experimental and consumes more RAM at compile time than our deployment pipeline agents allow to allocate (max 8GB vs needed 13GB)
another answer i found: readiness check for google cloud run - how?
which i don't see how it could satisfy my needs, since spring-boot startup time is still slow. That's why my initial idea was to delay opening ports
I did not have time to test the following, but one thing i stumbled upon is
a blogpost about using multiple processes within a container. Though it is against the recommendation of containers principles, it seems viable for the time until cloud run supports probes of any type.
As you are well aware of the fact that “Cloud Run currently does not have a readiness/liveness check to avoid sending requests to unready applications” I would say there is not much that can be done on Cloud Run’s side except :
Try and optimise the Spring boot app as per the docs.
Make a heavier entrypoint in Cloud Run service that takes care of
more setup tasks. This stackoverflow thread mentions how “A
’heavier’ entrypoint will help post-deploy responsiveness, at the
cost of slower cold-starts” ( this is the most relevant solution
from a Cloud Run perspective and outlines the issue correctly)
Run multiple processes in a container in Cloud Run as you
mentioned.
This question seems more directed at Spring Boot specifically and I found an article with a similar requirement.
However, if you absolutely need the app ready to serve when requests come in, we have another alternative to Cloud Run, Google Kubernetes Engine (GKE) which makes use of readiness/liveness probes.
At work, we have decided we would like to use the java TestContainers package, and it has fallen to me to learn and implement this package. It is important to note that security is a top priority at work, so we are behind a proxy and run our own registry to contain our docker images.
This is what I've got so far.
var dockerImage = DockerImageName.parse("<secure-registry>/mongo:latest")
.asCompatibleSubstituteFor("mongo");
MongoDBContainer mongoDBContainer = new MongoDBContainer(dockerImage)
.withImagePullPolicy(PullPolicy.defaultPolicy())
.withExposedPorts(27019);
mongoDBContainer.start();
Not alot, but that's because I can't progress any further. Any time I attempt to run this code, it gets as far as .start() before throwing the following error
com.github.dockerjava.api.exception.InternalServerErrorException: Status 500: {"message":"Get https://registry-1.docker.io/v2/: dial tcp: lookup registry-1.docker.io on 192.168.65.1:53: no such host"}
The issue is obviously that our proxy is blocking the default registry. I could probably fiddle with proxy settings on my machine so the registry can be resolved, but that is not a company wide solution. This app will be developed and run on many different machines and environments, and reconfiguring all of them would be more effort than it's worth. Furthermore, it shouldn't be communicating with the default registry at all. We have our own registry for a reason. The only real solution I see here is to remove this call entirely but so far, the documentation for both DockerImageName and the containers have been of no help.
If anyone has attempted this, or has another solution, it would be very helpful.
I have since realised my mistake. This page in the documentation reveals the problem. When running, the TestContainers library creates additional containers mainly for management of said containers. Unless a location is specified, it will attempt to pull these from the default registry. The preferred registry can be specified using the instructions in the link above.
As yuppie-flu also mentioned in their comment, this link may provide a nice, global way to set registries.
We have a Spring Boot app that at one point runs a Thread that calls a rest API and does something. When I run it on my machine it works well. Then if I run the same code on another machine it throws the error
SocketTimeoutException: Read timed out issue
So I thought there was some problem with server timeout. So on the other machine I've tried setting server.connection-timeout:-1 in the application.yml. since I've pulled the code from github, all the settings were identical. Then, after changing this on the other machine, it worked well there too.
So I am curious about the difference could be, maybe some settings on the machine itself? Where can I look?
What is difference between publish and restart in jboss/tomcat? I am really confused about when one should use restart or publish?
Every time I make any change config in my Java(Spring) application(on localhost) I had to do a compile and then perform a restart of server so that it picks up the changes.
Is there any easier way to get the changes picked up?
You could use JRebel if you want to avoid redeploys. It fully supports Spring and you'll see changes immediately reflected in the deployed application. It's a commercial plugin but it saves you a lot of time.