The Cloud Foundry Blog

Running Standalone Web Applications on Cloud Foundry

In this final post of the four-part series on deploying standalone apps to Cloud Foundry, we will explore how to build and deploy JVM-based web applications that aren’t packaged as traditional WAR files. This includes applications that are built on top of an NIO Framework like Grizzly or Netty (notable frameworks include Blue Eyes and vert.x) and applications that ship their own container, such as an embedded Jetty server.

Deploying a Spray Application to Cloud Foundry

Spray is a suite of lightweight Scala libraries for building and consuming RESTful web services on top of Akka. Let’s deploy the Spray simple-http-server example that uses spray-can: a low-level, low-overhead, high-performance, fully asynchronous HTTP/1.1 server.

mycomp$: git clone git://github.com/spray/spray.git
mycomp$: cd spray/examples/spray-can/simple-http-server

We will use the sbt-package-dist plugin to package the app and all of its dependencies into a Zip file that we can push to Cloud Foundry. Therefore, we need to add the following files to the simple-http-server directory:

build.sbt:

 
import com.twitter.sbt._ seq(StandardProject.newSettings: _*) packageDistZipName := "simple-http-server.zip" organization := "cc.spray" name := "simple-http-server" version := "0.1.0-SNAPSHOT" scalaVersion := "2.9.1" resolvers ++= Seq( "Typesafe repo" at "http://repo.typesafe.com/typesafe/releases/", "spray repo" at "http://repo.spray.cc/" ) libraryDependencies ++= Seq( "cc.spray" % "spray-server" % "1.0-M1", "cc.spray" % "spray-can" % "1.0-M1", "com.typesafe.akka" % "akka-actor" % "2.0" ) 

project/plugins.sbt:

  
addSbtPlugin("com.twitter" %% "sbt-package-dist" % "1.0.0") resolvers += "twitter-repo" at "http://maven.twttr.com" 

project/build.properties:

 
sbt.version=0.11.2 

Next, we need to modify Main.scala to start the HTTP server on the host and port provided by Cloud Foundry:

 
server ! HttpServer.Bind(Option(System.getenv("VCAP_APP_HOST")).getOrElse("localhost"), Option(System.getenv("VCAP_APP_PORT")).getOrElse("8080").toInt) 

Now we are ready to build and deploy the sample!

mycomp$: sbt clean compile package-dist
mycomp$: vmc push simple-http-server --path=dist/simple-http-server/simple-http-server.zip
Detected a Standalone Application, is this correct? [Yn]:
1: java
2: node
3: node06
4: ruby18
5: ruby19
Select Runtime [/java]: 
Selected java 
Start Command: java $JAVA_OPTS -jar simple-http-server_2.9.1-0.1.0-SNAPSHOT.jar 
Application Deployed URL [None]: simple-http-server.${target-base} 
Memory reservation (128M, 256M, 512M, 1G, 2G) [512M]: 
How many instances? [1]: 
Create services to bind to 'simple-http-server'? [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 (248K): OK 
Push Status: OK 
Staging Application 'simple-http-server': OK 
Starting Application 'simple-http-server': OK

So we’ve pushed the simple-http-server Zip file as a standalone app with a Java runtime. We gave the command “java $JAVA_OPTS -jar simple-http-server_2.9.1-0.1.0-SNAPSHOT.jar” to start the server, as sbt-package-dist creates an executable jar file. Notice the use of the JAVA_OPTS environment variable. When we deploy this app, Cloud Foundry will set JAVA_OPTS to a min and max heap size based on the memory reservation we provide. If we are running against Micro Cloud Foundry or a local vcap setup, remote debug options will also be added to JAVA_OPTS if we push or start the app with –debug.

That’s right, you can remote debug your standalone JVM applications with your favorite IDE. Since “simple-http-server” needs a web port, we provided a URL to use. Notice the use of the ${target-base} variable for the domain. This will allow us to reuse the generated manifest against multiple clouds (such as public or Micro Cloud Foundry). Let’s visit the web page and confirm that the app is up and running:

Looks like we are in business with spray! Note that you can access this complete example here.

Deploying an Embedded Jetty Server to Cloud Foundry

Since its launch, Cloud Foundry has allowed you to easily deploy a wide variety of web applications to Tomcat. We take care of configuring and starting the container, you bring the web app! However, sometimes you may want to bundle your own container or web server. Standalone app support allows you to do this. Let’s see an example using

Unfiltered, a toolkit for servicing HTTP requests in Scala. We will start by using giter8 to create a simple project template:

mycomp$: g8 softprops/unfiltered
This template generates an Unfiltered project. By default it depends on "unfiltered-jetty". For AJP support, set unfiltered_module to "unfiltered-jetty-ajp".
version [0.1.0-SNAPSHOT]:
name [My Web Project]:
cf-unfiltered-sample unfiltered_version [0.6.1]:
Applied softprops/unfiltered.g8 in cf-unfiltered-sample
mycomp$: cd cf-unfiltered-sample

We need to introduce the same sbt-package-dist build settings as the previous example. Add the following to the top of build.sbt: [code language=”scala”] import com.twitter.sbt._ seq(StandardProject.newSettings: _*) packageDistZipName := "cf-unfiltered-sample.zip" [/code] And create the plugins.sbt and build.properties files in the project directory as outlined above. Finally, we need to modify Example.scala to start Jetty on the port provided by Cloud Foundry:

 
val http = unfiltered.jetty.Http(Option(System.getenv("VCAP_APP_PORT")).getOrElse("8080").toInt) 

And we need to modify avsl.conf to write the log file to a location relative to the app's working directory:

  [handler_h1] ... path: log ... 

Now we are ready to build and deploy the sample!

mycomp$: sbt clean compile package-dist
mycomp$: vmc push cf-unfiltered-sample --path=dist/cf-unfiltered-sample/cf-unfiltered-sample.zip
Detected a Standalone Application, is this correct? [Yn]:
1: java
2: node
3: node06
4: ruby18
5: ruby19
Select Runtime [/java]

: Selected java Start Command: java $JAVA_OPTS -jar cf-unfiltered-sample_2.9.1-0.1.0-SNAPSHOT.jar Application Deployed URL [None]: cf-unfiltered-sample.${target-base} Memory reservation (128M, 256M, 512M, 1G, 2G) [512M]: How many instances? [1]: Create services to bind to 'cf-unfiltered-sample? [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 (248K): OK Push Status: OK Staging Application 'cf-unfiltered-sample': OK Starting Application 'cf-unfiltered-sample': OK

The answers we gave here are pretty much identical to those given in the first section. We provisioned a Java runtime, provided a start command that includes JAVA_OPTS, and supplied a URL. Looks like the app is up!

You can check out this complete example here.

Conclusion

In this final installment of the four-part series, we introduced new support for standalone applications and showed some examples of common uses. We would love to hear your use cases and suggestions for enhancing this support. Please visit the Forums or JIRA, or submit a pull request. We look forward to seeing your new standalone apps!

- Jennifer Hickey The Cloud Foundry Team
Don’t have a Cloud Foundry account yet?  Sign up for free today

This entry was posted in CloudFoundry and tagged . Bookmark the permalink.

15 Responses to Running Standalone Web Applications on Cloud Foundry

  1. Tomas Lin says:

    Can you specify which version of Java to run? The blog post mentions vert.x but vert.x requires java 7.

    • Jennifer Hickey says:

      Currently Java 6 is the only option available. We are working on adding Java 7 support now, and it should be available soon. At that time, we will post some vert.x samples.

  2. Pingback: Running Workers on Cloud Foundry with Spring | Blog

  3. clive says:

    Hello,
    we started with Spray to end with Unfiltered, that s could generate some confusion..
    Anyway thanks for those tutorial, could not wait to test it.
    Clive

  4. Pingback: Cloud Foundry Improves Support For Background Processing | Blog

  5. Pingback: Running Resque Workers on Cloud Foundry | Blog

  6. Pingback: Running Workers on Cloud Foundry with Spring | Blog

  7. Pingback: Deploying vert.x Applications to Cloud Foundry | Blog

  8. Pingback: Task scheduling support on AppFog with standalone apps - Platform as a Service Magazine

  9. Pingback: New Release of Micro Cloud Foundry | CloudFoundry.com Blog

  10. Hi,

    The DNS support is not yet added with this release, correct? …any anticipated date?

    Thank you,

  11. Ashutosh says:

    Can you also explain how to deploy and configure a JAVA SE JDK based Web Server application using Eclipse plugin?

    I have a Web Server application without any container/framework, a simple socket based server, its basically a reverse proxy that routes(TCP connects) to other application servers on receipt of HTTP requests on port 5050. It does an outgoing TCP connect to servers hosted on 80 & non-80/443 ports.

    Is it possible to deploy this application on to CloudFoundry.com? If yes, how?

  12. aldrin says:

    I do not get a ‘standalone’ option when pushing a new app – only get the following:
    [WARNING] Can’t determine the Application Type.
    Select Application Type: (Rails, Spring, Grails, Roo, JavaWeb, Sinatra or Node)

    How do I specify a standalone mode?

    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>