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

Embedded Tomcat container binds port before application is completely started #55

Closed
nebhale opened this issue Sep 20, 2013 · 3 comments

Comments

@nebhale
Copy link
Member

nebhale commented Sep 20, 2013

Currently, when an application is starting up, the embedded Tomcat container binds to its port before the application has finished starting. To see this in action, attempt to start a controller that sleeps in a static block. Something like the following:

Controller
class Example {

    static {
        Thread.sleep(30*1000)
    }

    @RequestMapping("/")
    @ResponseBody
    public String controller(HttpEntity<String> requestEntity) {
        return "Hello World!"
    }
}

When you run spring run app.groovy, you'll see the console stall before the application has stated completely. However, if you attempt to curl http://localhost:8080, curl will also stall because the port is bound and while no response has been returned, a socket connection can be completed. An alternative test is to telnet localhost 8080 and see if a connection can be made.

This is problematic in Cloud Foundry as the HealthManager determines when an application has started by attempted a socket connection to it's provided port. Whether the application is running behind the scenes isn't actually checked, so a false-positive started can be returned.

The intended behavior should be that when the console is stalled as described above, curl should return curl: (7) couldn't connect to host indicating that the port hasn't even been bound to yet. This is typically set in the Tomcat configuration using bindOnInit. I believe that there is a programmatic equivalent to this configuration parameter.

@dsyer
Copy link
Member

dsyer commented Sep 20, 2013

I don't see a way to get a hold of an AbstractEndpoint to call that setter. Going to have to ask a friend...

@dsyer
Copy link
Member

dsyer commented Sep 20, 2013

OK, Mark T showed me how to set the property (connector.setProperty("bindOnInit", "false")), but it doesn't seem to solve the problem - curl hangs connecting to localhost while the Controller above is initializing. Any other ideas?

@dsyer
Copy link
Member

dsyer commented Sep 20, 2013

I think I may have cracked it - we have to explicitly stop the connector after it has started (e.g. in TomcatEmbeddedServletContainer.initialize()), to set the endpoint into the UNBOUND state. Testing...

@dsyer dsyer closed this as completed Sep 20, 2013
dsyer pushed a commit that referenced this issue Sep 20, 2013
The `Tomcat.start()` has to happen to initialize the `ServletContext`
but we can immediately stop the connector and then restart it when
the context is finished refreshing. Seems to make curl fail quickly
if an app is slow to start.
gregturn pushed a commit to gregturn/spring-boot that referenced this issue Sep 20, 2013
The `Tomcat.start()` has to happen to initialize the `ServletContext`
but we can immediately stop the connector and then restart it when
the context is finished refreshing. Seems to make curl fail quickly
if an app is slow to start.
gigfork pushed a commit to boostrack/spring-boot that referenced this issue Apr 21, 2014
The `Tomcat.start()` has to happen to initialize the `ServletContext`
but we can immediately stop the connector and then restart it when
the context is finished refreshing. Seems to make curl fail quickly
if an app is slow to start.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants