Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Port is already in use when using @SpringBootTest with a separate management port and a mock web environment #38554

Closed
jimshowalter opened this issue Nov 26, 2023 · 35 comments
Labels
type: regression A regression from a previous release
Milestone

Comments

@jimshowalter
Copy link

jimshowalter commented Nov 26, 2023

We didn't change anything in our code or configuration, other than upgrading versions.

We can run the service locally, and can run the tests individually. But when we try to run the tests together, we get the port error.

We were already on Spring 6.1.0 and Spring Boot 3.1.5, so this should have been a small upgrade.

We're using the latest version of JUnit, and are not running the tests in parallel.

The tests fail with the port error whether virtual threads are enabled or disabled.

Is there some new cleanup/finalization we need to add? We looked at the release notes for both Spring and Spring Boot and didn't see anything relevant.

@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged label Nov 26, 2023
@yanivnahoum
Copy link

Seeing the same thing. Not sure if in @jimshowalter 's configuration 8090 is the value of management.server.port, but in my case, when I assign a value to management.server.port, a few @SpringBootTests start failing with "Port xxxx is already in use", where xxxx is the value of management.server.port

@wilkinsona
Copy link
Member

I'm not aware of anything that would have changed the behavior here. Perhaps #38502, but that's little more than a guess at this point.

If you would like us to spend some more time investigating, please spend some time providing a complete yet minimal sample that reproduces the problem. You can share it with us by pushing it to a separate repository on GitHub or by zipping it up and attaching it to this issue.

@wilkinsona wilkinsona added the status: waiting-for-feedback We need additional information before we can continue label Nov 26, 2023
@jimshowalter
Copy link
Author

jimshowalter commented Nov 26, 2023

8090 is the management.server.port we use in tests. If we change management.server.port to some other port, we get the same error.

@spring-projects-issues spring-projects-issues added status: feedback-provided Feedback has been provided and removed status: waiting-for-feedback We need additional information before we can continue labels Nov 26, 2023
@jimshowalter
Copy link
Author

You're asking us to try to cut a huge pile of intellectual property down to a reproducible test case, but we know something in the latest Spring or Spring Boot causes this, and you're way more famliar with that codebase than we are.

This will block many developers from using virtual threads. Can you please fix this problem?

@wilkinsona
Copy link
Member

we know something in the latest Spring or Spring Boot causes this, and you're way more famliar with that codebase than we are

We know that a combination of something in your codebase and something in the latest Spring or Spring Boot causes this. We know nothing about your codebase and you know something about ours. It's very helpful if someone who's familiar with both sides of the problem spends some time creating a minimal reproducer.

Can you please fix this problem?

We were not refusing to fix it, far from it, just looking for some assistance in addressing the problem that you've reported.

I have now managed to reproduce the problem and, as guessed above, #38502 is the cause unfortunately. A (far from ideal) partial workaround is to use @DirtiesContext to prevent caching of test contexts.

@wilkinsona wilkinsona added type: regression A regression from a previous release and removed status: waiting-for-triage An issue we've not yet triaged status: feedback-provided Feedback has been provided labels Nov 26, 2023
@wilkinsona wilkinsona added this to the 3.2.x milestone Nov 26, 2023
@jimshowalter
Copy link
Author

That was fast!

Do you have a sense for when the next release will be published?

@jimshowalter
Copy link
Author

"We know that a combination of something in your codebase and something in the latest Spring or Spring Boot causes this. We know nothing about your codebase and you know something about ours. It's very helpful if someone who's familiar with both sides of the problem spends some time creating a minimal reproducer."

That's a very fair point. Unfortunately, our codebase is massive, and every time we try to reduce it to a reproducible example, we fail.

@jimshowalter
Copy link
Author

We can offer a joint debugging session in Zoom or similar.

@mr-hamburg
Copy link

mr-hamburg commented Nov 27, 2023

Good morning from Hamburg! Our RenovateBot tried to update the version of the artefact "spring-boot-starter-parent" from version 3.1.5 to 3.2.0 on Friday morning, whereupon all build pipelines in all our projects failed. We have not made any changes to the code that would cause this error. Our management port is 8900 and the error message looks like this:
Caused by: org.springframework.boot.web.server.PortInUseException: Port 8900 is already in use
I understand that it is valuable to have a reproducible test, how does this work for you?

@SpringBootTest
@ActiveProfiles("test")
class ApplicationTests {

  @Autowired
  private ApplicationContext applicationContext;

  @Test
  void contextLoads() {
    assertThat(applicationContext).isNotNull();
  }

}

Running this test individually works, there is no error. However, if I run all tests of the project, I get this error. It seems to me that the test framework does not work cleanly enough when cleaning up previous test artefacts, so that residues are left behind which can lead to the management port still being in use.

I am very interested in finding a solution and would like to plead for this ticket to be categorised as high as possible so that the process is processed with the greatest urgency.

@wilkinsona
Copy link
Member

I understand that it is valuable to have a reproducible test, how does this work for you?

I doesn't help, I'm afraid.

Running this test individually works, there is no error. However, if I run all tests of the project, I get this error.

You've only provided us with this one test so we have no insight into what other tests are needed to trigger the problem.

I am very interested in finding a solution and would like to plead for this ticket to be categorised as high as possible so that the process is processed with the greatest urgency.

Exerting this kind of pressure doesn't really help anyone. A fix that's made without pressure is much more likely to be successful than one that's done under pressure and in a rush.

If Spring Boot 3.2.0 doesn't work for you, Spring Boot 3.1.x is still available and fully supported.

@wilkinsona
Copy link
Member

There may still be a problem

Thanks for trying that, @jimshowalter. Can you please run your tests with a breakpoint in ChildManagementContextInitializer.createManagementContext() and share the stack trace of when that method is called.

@wilkinsona wilkinsona changed the title Upgrading to Spring 6.1.1 and Spring Boot 3.2.0 causes integration tests to fail with "Port 8090 is already in use" Port is already in use when using @SpringBootTest with a separate management port and a mock web environment Nov 27, 2023
@mr-hamburg
Copy link

You've only provided us with this one test so we have no insight into what other tests are needed to trigger the problem.

This is absolutely correct and at the same time I will not post any further tests on the internet that reveal internal company specifics, thank you for your understanding. This one test, executed separately, works fine, but it fails in the project as a whole.

Exerting this kind of pressure doesn't really help anyone. A fix that's made without pressure is much more likely to be successful than one that's done under pressure and in a rush.

At this point I apologise. I didn't mean to exert any pressure, but rather to show my willingness to help. I'm sorry that I expressed myself incorrectly. Of course you are right, a quick solution can never be the right one. If there's anything I can do that doesn't violate my company rules that will help, please let me know.

If Spring Boot 3.2.0 doesn't work for you, Spring Boot 3.1.x is still available and fully supported.

That's good, because we don't always have to adapt the latest version straight away. We will get by with it and are in no rush. Thank you for your work!

@soer84
Copy link

soer84 commented Nov 27, 2023

i took the liberty and created a reproducer for a case we're currently facing. The tests in the attached zip file work with spring boot 3.1.5 but fail on 3.2.0. - It might be a different root cause but the result seems to be same - a blocked Port.

In my example I just add a new http connector with a fixed port. When running each test on its own they work. But if they're executed in a row i.e. by a mvn verify the second tests fails on initialization stating that the configured connector failed to start.

Maven doesn't print the reason too clearly unfortunately but a little closer investigation inside a IDE reveals the java.net.BindException: Address already in use: bind exception.

SpringTestReproducer.zip

In this example also the "@DirtiesContext" doesn't help. It seems to me as if the Spring / ApplicationContext is cleaned up and the server is rebooted but the old instance of the server hasn't shut down yet or isn't shutting down at all.

@wilkinsona
Copy link
Member

Thanks, @soer84. That appears to be an unrelated problem as you are not used Actuator. Please open a new issue so that your problem can be investigated separately.

@yanivnahoum
Copy link

yanivnahoum commented Nov 27, 2023

@wilkinsona Here we go: https://github.com/yanivnahoum/spring-boot-examples/tree/port-in-use
Please clone and check out the branch above (port-in-use).
Run ./mvnw test to see the error.
To reproduce it, I did 2 things:

  1. Specified a value for management.server.port
  2. Added 2 @SpringBootTests, one of which adds a property to the context (in order to force Spring not to re-use the existing one).

Let me know if this helps!

@jimshowalter
Copy link
Author

jimshowalter commented Nov 27, 2023

@wilkinsona, wilkinsona@9503e45 fixes the problem originally reported in this issue!

@jimshowalter
Copy link
Author

How long does it take to publish a new Spring Boot bug-fix version?

@yanivnahoum
Copy link

@jimshowalter what do you mean copy it in? This class is coming from org.springframework.boot:spring-boot-actuator-autoconfigure:3.2.0 . How can I patch it?

@jimshowalter
Copy link
Author

jimshowalter commented Nov 27, 2023

Create a package in your local with the same name as the package in the actuator code, copy the fixed source file into it. It's called class shadowing. Your local classes load ahead of dependencies, so you basically substitute the .class file at load time for what would have been on your classpath from the actuator jar. Decent article: https://medium.com/@akhaku/java-class-shadowing-and-shading-9439b0eacb13. (Doesn't work for JRE classes.)

@yanivnahoum
Copy link

I was afraid you'd say that :-)
Anyway, I'll leave it to the master @wilkinsona to check it, since I won't be upgrading until a fix is out anyway. Thanks!

@jimshowalter
Copy link
Author

I meant try it in your repo where you reproduced the problem.

@benno-sc
Copy link

I tried the fix originally by @wilkinsona, linked by @jimshowalter and can confirm that it fixed the issue in my project.

@jimshowalter
Copy link
Author

Excellent!

@wilkinsona
Copy link
Member

How long does it take to publish a new Spring Boot bug-fix version?

Our release plans are, as ever, available on the milestone page. Spring Boot 3.2.1 is scheduled for December 21.

@jimshowalter
Copy link
Author

3.2.1 doesn't mention the fix for this issue, which is why I asked.

@larsgrefer
Copy link
Contributor

I've stumbled upon the same issue. Our tests were working fine in 3.2.0-RC2 but are broken with 3.2.0
This minimal project can be used to reproduce the problem: https://github.com/larsgrefer/actuator-test-demo

@pcornelissen
Copy link

As workaround you can try to set the actuator port to the same port as the regular port. This "fixed" the problem for me.

@juliojgd
Copy link
Contributor

juliojgd commented Dec 8, 2023

As workaround you can try to set the actuator port to the same port as the regular port. This "fixed" the problem for me.

This does not work as workaround, because changing requisites can'be called "workaround" IMHO

@pcornelissen
Copy link

pcornelissen commented Dec 8, 2023

Well in my running service I prefer the actuator on a dedicated port, in my tests it usually doesn't matter, so I change an aspect, that is of no difference to my tests, while solving a real problem withi the tests.
So if your tests don't break when actuator is not on a dedicated port, feel free to set both to the same value for tests to have green tests again. If it is a problem for your tests, then you might want to stay on 3.1.x until 3.2.1 is out.

@ivan-vlasenko
Copy link

ivan-vlasenko commented Dec 12, 2023

One thing that you could try to do, that actually worked for me, it's to override a management port in certain @SpringBootTest via properties to random one "management.server.port=0". In that case you could avoid unwanted changes in your production code.

@priyanka2277
Copy link

I am using springboot framework .Once i had used port 8080 and save the data in the database ,next time i am running the program the port already used error comes how to use only one port permanently without changing the port multiple times

@pcornelissen
Copy link

I think you are talking about a different problem. This issue concerns a service that has a lot of tests and during these tests the service code under test ran into the port in use when all tests were ran.
If you want to start the service itself and the port is taken, just check what runs on that port. Assumably you have another service or an older version of this service running on port 8080. The ports are not blocked forever, just because you once starten something that listens on a port.
Depending on your operating system, you have different ways to figure out what blocks a port.

For Windows, there are tools you can download for that.
For Mac you can for example use brew and instakk "killport" which kills the application that blocks a port doing "killport 8080" frees up that port.
On linux you could "netstat -tulpen|grep 8080" this would return the processes that listen on port 8080 and one of the first coliums is the PID and you can kill that pid or do a "ps aux|grep ..." to find out about the process

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: regression A regression from a previous release
Projects
None yet
Development

No branches or pull requests