How to debug the Cloud Foundry Java Buildpack

java-logoA buildpack is a collection of scripts executed during the staging process of your application. To debug a buildpack one executes the scripts in a encapsulated environment like a virtual machine (VM) or a Docker container. We will use the VM approach to debug the staging process using the Cloud Foundry Java buildpack. The steps described below should also be reproducible using another virtualization approach.

For more information on how to use the Cloud Foundry Java Buildpack please refer to their documentation.

Prepare a Virtual Machine

There are many applications allowing you to manage VMs on your development machine. We will use Vagrant and VirtualBox to fire up a VM running Ubuntu 10.04 Lucid64. This article is tested using kernel version 2.6.32-38-server.

For more detailed steps on how to setup a virtual machine please refer to your tool’s documentation.

Dependency Installation

After firing up the VM we have to install some prerequisites before continuing with the debugging process.

Update apt archives

$> apt-get update

Install git, curl & unzip

$> sudo apt-get install git-core curl unzip

Install RVM

$> gpg --keyserver hkp://keys.gnupg.net --recv-keys D39DC0E3

$> curl -sSL https://get.rvm.io | bash -s stable

$> source /home/vagrant/.rvm/scripts/rvm

Install Ruby

The java buildpack relies on ruby to execute the needed steps of the staging process. So make sure to install ruby. As the stemcells contain ruby 1.9.3 let’s install it using:

$> rvm install 1.9.3

Prepare the Java buildpack sources

The buildpack expects a certain structure from its execution environment. Let’s create the required directories as follows:

$> mkdir -p ~/debug-javabuildpack/apps/{app,logs,tmp}

$> mkdir -p ~/debug-javabuildpack/java-buildpack

$> git clone https://github.com/cloudfoundry/java-buildpack.git ~/debug-javabuildpack/java-buildpack

Prepare your application

Next, we have to transfer our application package and decompress our application into the designated app directory:

$> cd ~

$> unzip application.zip -d ~/debug-javabuildpack/apps/app

or

$> unzip application.war -d ~/debug-javabuildpack/apps/app

If you need a simple example application for testing purposes take a look at this one.

Environment Preparation

Service credentials for a service binding are handed over to applications via the VCAP_SERVICES environment variable and the application configuration is stored in VCAP_APPLICATION. In addition we will need to set the PORT variable to define the port our server should use.

If your application depends on external services (databases, message queues, etc. ) please configure the environment variables as described in the Cloud Foundry documentation so the values are pointing to locally accessible service instances.
For now we will just use an empty environment configuration:

$> export VCAP_APPLICATION="{}"

$> export VCAP_SERVICES="{}"

$> export PORT=8080

Debugging the application detection script

The first step of a buildpack staging process is the execution of its detect script. Let’s start the script manually and have a look at the output. We will set the JBP_LOG_LEVEL to DEBUG to ensure a proper script output.

$> cd ~/debug-javabuildpack/apps

$> JBP_LOG_LEVEL=DEBUG ../java-buildpack/bin/detect app/

This command will output the results of the detection process. You can have a closer look at it to ensure the script makes the correct decisions for your application.

Debugging the compile script

Now we can execute the compile script in debug mode to have a look at the scripts execution:

$> cd ~/debug-javabuildpack/apps

$> JBP_LOG_LEVEL=DEBUG ../java-buildpack/bin/compile app/ tmp/

This command will download and install a Java runtime and an application container for hosting the application. You can always have a look at the debug output by looking at the buildpack’s log file:

$> less ~/debug-javabuildpack/apps/app/.java-buildpack.log

Start the server

As a final step, let’s set the correct PATH environment according to our freshly installed Java version and JAVA_HOME environment variable:

$> export PATH=~/debug-javabuildpack/apps/app/.java_buildpack/openjdk_jre/bin:$PATH

$> export JAVA_HOME=~/debug-javabuildpack/apps/app/.java-buildpack/open_jdk_jre

$> export JAVA_OPTS="-Dhttp.port=$PORT"

Start Tomcat:

$> cd ~/debug-javabuildpack/apps

$> app/.java-buildpack/tomcat/bin/startup.sh

Just tail the tomcat logs to gather information on the tomcat process:

$> tail -f -n 300 ~/debug-javabuildpack/apps/app/.java-buildpack/tomcat/logs/catalina.out

Now we have a local copy of the application execution environment running within a Cloud Foundry container. This gives us full access and control to find and resolve problems during the staging and startup process moving forward.

Once everything is working as expected we can access our application like this:

$> curl https://127.0.0.1:8080

As the buildpack adjusts the installation to the application during the detection and compile process, make sure to have a look at the buildpack’s documentation.

Happy debugging :)

Leave a Reply

Your email address will not be published.