Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Getting Hold of an Unused Port When Writing a Test

DZone's Guide to

Getting Hold of an Unused Port When Writing a Test

How to use an unused port when writing a test with JAX-RS and Java.

· DevOps Zone ·
Free Resource

Do you need to strengthen the security of the mobile apps you build? Discover more than 50 secure mobile development coding practices to make your apps more secure.

A really quick post today, I was writing a unit test that needed to put up a temporary JAX-RS resource in order to test something very specific with out the need of a large testing framework. Unfortunately the code I was using didn't know about replacing zero with a random allocated port so I had to do something different. The nice tidy code that does this looks like the following:

try(ServerSocket ss = new ServerSocket(0)) {
 freePort = ss.getLocalPort();
}

server = createServerWithPort(freePort);

But of course there is a race condition here as there could be another process on the machine running the exact same code that gets lucky with its time on the CPU — note the API I was using couldn't use the ServerSocket directly so there is a gap where the port is not tied up. So to rule out the one in a million failure chance, which always comes on a Friday at 5pm, we need to wrap this code in a loop.

while(server==null) {
 try(ServerSocket ss = new ServerSocket(0)) {
 freePort = ss.getLocalPort();
 }

 server = createServerWithPort(freePort);
}

This may seem extreme; but if you are running some kind of CI system like Hudson or Jenkins it is not unusual to be running multiple executors on the same machine. You might have two developers running preflights at the same time causing an annoying intermittent failure as described above.

Finally a version using a JDK 8 stream with a helper method to convert the IOException from ServerSocket into a RuntimeException. Some would argue this is less readable; but I find it more explicit.

server = Stream.generate(convertException(() -> {
 try(ServerSocket ss = new ServerSocket(0)) {
 return ss.getLocalPort();
 }
})).map(TestClass::createServerWithPort)
.filter(Objects::nonNull)
.findFirst().get();

Check out tips for blazing the way from agile to DevSecOps with security built into your mobile app toolchain.

Topics:
java ,ci

Published at DZone with permission of

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}