The Cloud Foundry Blog

Deploying Tomcat 7 Using the Standalone Framework

Editors Note: This post is now outdated and should only be considered eligible to work with Cloud Foundry v1.

The new standalone framework support greatly increases the number of different types of non-Web applications that can run on Cloud Foundry, including application servers. This tutorial will walk you through the steps to deploy a “hello world” application in a Tomcat 7 container on Cloud Foundry. Currently, Cloud Foundry leverages Tomcat 6 to host Java web applications. While the team is working to support Tomcat 7 as a first-class container, it is very straightforward to use the standalone application support to run Tomcat 7 in the meantime, which is particularly useful for applications that leverage Servlet 3.0. The basic outline involves installing your application into a local Tomcat 7 instance, making minor modifications to the configuration and pushing the entire contents of Tomcat 7 and your application to Cloud Foundry as a standalone application.

Step 1 – Download Apache Tomcat

Download Apache Tomcat 7 to the location where you will use the vmc command line tool. If you do not have vmc, then follow these instructions to install it. I downloaded Apache 7.0.27, which is currently the latest version 7.0 release and the file name is apache-tomcat-7.0.27.zip. All of the commands throughout this tutorial will assume that the present working directory is the Tomcat 7 base directory.

Step 2 – Extract Tomcat and Update Permissions

Extract the tomcat zip file to a local directory. I changed the permissions of the bin/*.sh scripts to have executable permissions.

unzip apache-tomcat-7.0.27.zip
cd apache-tomcat-7.0.27
chmod +x bin/*.sh

Linux and OSX users should be able to test the scripts on their local systems before pushing them to Cloud Foundry’s Ubuntu-based server environment. Unfortunately, Windows users cannot test the bin/startup.sh script changes locally first, but the modifications are really quite simple.

Step 3 – Edit Startup Scripts

bin/startup.sh

Tomcat is typically started with the bin/startup.sh script. In order for Tomcat to use the same shell that invokes startup.sh instead of spawning a new shell, change the execution argument in the last line of startup.sh from “start” to “run“:

exec "$PRGDIR"/"$EXECUTABLE" start "$@"

to:

exec "$PRGDIR"/"$EXECUTABLE" run "$@"

bin/catalina.sh

Instead of using a pre-defined static port, we would like Tomcat 7 to use the port assigned by Cloud Foundry, which will be stored in the VCAP_APP_PORT environment variable when deployed. Place the following bash code near the top of catalina.sh after the initial comments. Just so that we can run this locally as well without modifying the code, this code will assign a static port number of 8080 if the dynamic port is not available as an environment variable.

# USE VCAP PORT IF IT EXISTS, OTHERWISE DEFAULT TO 8080

if [ -z ${VCAP_APP_PORT} ]; then

export VCAP_APP_PORT=8080

fi

export JAVA_OPTS="-Dport.http.nonssl=$VCAP_APP_PORT $JAVA_OPTS"

Step 4 – Edit Tomcat Configuration

conf/server.xml

Set the port attribute of the Server element to -1, which disables the Tomcat shutdown port. Cloud Foundry does not use the shutdown port because it issues a “kill -9 PID” command to stop any standalone app instance. We want to avoid any potential port conflicts with other applications that are running on the same Droplet Execution Agent (DEA), so only using a single http port is the current recommendation for standalone applications running on Cloud Foundry.

Since Cloud Foundry handles the load balancing for you without using the AJP connector, you should disable the AJP connector to ensure we do not get a port conflict by commenting out the section shown below.

<!-- Define an AJP 1.3 Connector on port 8009
<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />
-->

The Connector element should use the port provided in the JAVA_OPTS environment variable, which we have set previously in the catalina.sh script.

At this point, I recommend trying the edits on your local server to see if Tomcat 7 starts up as expected. In order to test whether the VCAP_APP_PORT is being used, I recommend using a command shell to assign a sample port such as 8082.

jbayer$ export VCAP_APP_PORT=8082
jbayer$ bin/startup.sh

The console should not return (it should block while Tomcat is running) and one of the last lines in the console output should be:

INFO: Starting ProtocolHandler ["http-bio-8082"]

If that is the case, you should be able to visit http://localhost:8082 to see if the welcome page is there.

Tomcat 7 Running Locally

Tomcat 7 Running Locally

At this point you may want to back up (zip) the entire Tomcat 7 directory with the customizations you have done thus far so you can reuse it on other applications later.

Step 5 – Install your application

In order to show a Tomcat 7 feature, I used Servlet 3.0 which now has support for Servlet annotations as shown below in the simple Servlet.

package tomcat7;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.*;

@WebServlet("/Servlet3")
public class Servlet3 extends HttpServlet {

    public Servlet3() {
        super();
    }

	protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		response.getWriter().println("Hello from Servlet 3.0!");
	}

}

Cloud Foundry uses the ROOT web application with Tomcat 6, so let’s replicate that same behavior for Tomcat 7.

First delete the existing ROOT application.

jbayer$ rm –r webapps/ROOT

Now take your web application and explode it into the webapps/ROOT location. If you have a .war file then the command looks like this:

jbayer$ unzip –d webapps/ROOT ~/dev/mytomcat7.war

Check your application locally to see if it functions properly.

Tomcat 7 With Servlet 3.0 Running Locally

Step 6 – Push the application to Cloud Foundry

Execute the vmc command from the Tomcat 7 base directory, selecting many of the default selections. Notice that vmc auto-detects that it is a “Standalone Application,” and you simply need to provide the startup script path and map an unique URL. Note that you will get an error if the URL is not unique.

jbayer$ vmc push mytomcat7
Would you like to deploy from the current directory? [Yn]:
Detected a Standalone Application, is this correct? [Yn]:
1: java
2: node
3: node06
4: ruby18
5: ruby19
Select Runtime 1: 1
Selected java
Start Command: bin/startup.sh
Application Deployed URL [None]: mytomcat7.cloudfoundry.com
Memory reservation (128M, 256M, 512M, 1G, 2G) [512M]: 256M
How many instances? [1]:
Bind existing services to 'mytomcat7'? [yN]:
Create services to bind to 'mytomcat7'? [yN]:
Would you like to save this configuration? [yN]: y
Manifest written to manifest.yml.
Creating Application: OK
Uploading Application:
  Checking for available resources: OK
  Processing resources: OK
  Packing application: OK
  Uploading (23K): OK
Push Status: OK
Staging Application 'mytomcat7': OK
Starting Application 'mytomcat7': OK

Tomcat 7 With Servlet 3.0 on CloudFoundry.com

At the end of the push process, you will be offered the option to write the configuration to a manifest file. Here is the resulting manifest.mf file that got written to the Tomcat 7 base directory from our deployment. Note that it contains the startup command, bin/startup.sh. By having this file present in the root directory vmc will read from this file and skip the interactive questions the next time you push this application.

---
applications:
  .:
    url: mytomcat7.cloudfoundry.com
    command: bin/startup.sh
    runtime: java
    framework:
      info:
        exec:
        description: Standalone Application
        mem: 64M
      name: standalone
    name: mytomcat7
    instances: 1
    mem: 256M

Conclusion

Other containers such as Jetty would follow a similar pattern as described above. Most applications should be able to use the existing frameworks Cloud Foundry makes available. Should the need arise to customize or bring your own container, Cloud Foundry standalone application support is a great option.

- James Bayer

The Cloud Foundry Team

Try Cloud Foundry on ClouFoundry.com for free

This entry was posted in Cloud Foundry. Bookmark the permalink.

15 Responses to Deploying Tomcat 7 Using the Standalone Framework

  1. Alex says:

    I tried to deploy a grails application like this. I deleted webapps/ROOT and put a ROOT.war( what I need to deploy) in webapps. After running the server locally, it can generate a new webapps/ROOT for me. It works perfect locally. But when I pushed that to cloud foundry, it displays “404 Not Found nginx” error. Any idea about that?

    • James Bayer says:

      Alex, I recommend first trying to pre-explode the ROOT.war into a ROOT directory before you push the standalone application. Upload it exactly as you have it working locally. I do not recommend leaving it in WAR format when you upload as then that stage needs to be done on the server-side and perhaps Tomcat hasn’t finished exploding your WAR file by the time the router starts routing request there. There may be other possible explanations too. Good luck, James

  2. Rob Mitchell says:

    Very nice write-up! Has anyone tried doing a JBOSS app ?

  3. Pingback: 使用独立框架部署 Tomcat 7 | 博客

  4. Khaled says:

    great, I tried a dummy groovy(gmaven) h2 spring primefaces and it works

  5. Layne says:

    Is there some problems may happen since CF use “kill -9 PID” to kill a standalone app? If the start command initial a sub-process, and it is running. When you kill main process, the resource of sub-process may not release.

  6. Atava Raghava says:

    i want to develop java application in CloudFoundry i.e.. servlet or jsp application can any one guide me deploy java application in CloudFoundry

  7. lukaberdeen says:

    Hi, is there any way I can do it from the STS? How to push Tomcat from ? Thanks

  8. Nayyab says:

    I would like to push an OSGi container to cloud foundry via Eclipse. How can I do that? Thanks.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title="" rel=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>