James Williams
LinkedInMastodonGithub

Dynamic Port Discovery With Ratpack

One of the default settings in Ratpack is that it starts applications on port 5000. It's easy enough to override this but on several occasions I deployed several Ratpack apps in the same container and have one or more fail to deploy because the port was already in use.

A solution to this annoyance is to have Ratpack dynamically select a port instead of defaulting to 5000 as shown in the snippet below:

    def findOpenPort = {
        def port = new ServerSocket(0)
        def portNum = port.getLocalPort()
        port.setReuseAddress(true)
        port.close()
        return portNum
    }

Passing a zero to ServerSocket tells it to dynamically pick an open port. Once the port is opened, we grab the port number, tell Java that we want to immediately reuse the port without a timeout, and close the port.

Listed below is full example file. The first few lines download Ratpack and its dependencies from MavenCentral.

    @Grapes([
        @Grab(group='org.slf4j', module='slf4j-simple', version='1.6.4'),
        @Grab(group='com.augusttechgroup', module='ratpack-core', version='0.5')
    ])
    import java.net.ServerSocket
    import com.bleedingwolf.ratpack.*

    def findOpenPort = {
        def port = new ServerSocket(0)
        def portNum = port.getLocalPort()
        port.setReuseAddress(true)
        port.close()
        return portNum
    }

    def port = findOpenPort()

    def app = Ratpack.app {
        set 'port', port

        get("/") {
            request.toString()
        }
    }
    println "App loaded on port ${port}"
    RatpackServlet.serve(app)