When pushing large Java based applications (this includes anything running on the JVM like Grails & Java Play), it is possible for the application take minutes to start. When running locally this does not cause an issue as your local application container will simply wait as long as it takes for your application to start. However, when pushing to CloudFoundry, this is not the case and the system restricts the time that the application has to start and begin listening for requests.
If you have a large or slow starting application, you may experience an issue similar to the following when you run cf push.
Checking status of app '<app-name>'................
0 of 1 instances running (1 starting)
...
0 of 1 instances running (1 starting)
0 of 1 instances running (1 down)
0 of 1 instances running (1 starting)
0 of 1 instances running (1 starting)
Push unsuccessful.
In this case, it is possible that your application is taking too long to start. There are two workaround for this issue.
- Adjust your application to start faster.
- Fork the Java Build Pack and adjust the packaged Tomcat configuration so that it begins listening for connections prior to deploying your application.
The default configuration of the Tomcat container that is setup by the Java build pack instructs the container to first deploy your application and then begin listening for incoming requests. If we reverse this process, the container will begin listening for connections immediately and CloudFoundry will think that the application has started. At this point, your application will have as much time as it needs to finish starting. This comes with the risk that an application's users may see failed requests during this period of time. Because CloudFoundry thinks the instance has started, it will begin routing user requests to the application. Until the application has actually finished starting requests that come to the application are going to fail.
If you are comfortable with this limitation and would like to make the change, the first thing you'll need to do is fork and clone the Java Build pack. After that, you'll need to remove the bindOnInit=false attribute from the <Connector /> tag in server.xml.
Ex: <Connector port='${http.port}' />
Then commit your changes and push them back to your fork of the build pack. Finally, push your application to CloudFoundry and specify the --buildpack option to indicate that CloudFoundry should use your custom version of the Java Build pack. For instructions on using a custom build pack, see this link.