Cloud Foundry Blog

Cloud Foundry Now Supports Play!

Cloud Foundry now supports Play 2.0 as a first-class framework. Play is a lightweight, stateless, web-friendly framework for Java and Scala. Developers can leverage this event-driven non-blocking IO architecture to build highly scalable applications. Play 1.0 applications were previously deployable to Cloud Foundry as WAR files. Play 2.0, which doesn’t have built-in support for WAR files, can now be deployed to CloudFoundry.com and take advantage of being a fully supported framework that includes auto-reconfiguration, simplified service connections, and automatic database management. Play developers, welcome to Cloud Foundry!

Getting Started with Play 2.0

First, we will need to install or update the Cloud Foundry command line tool, VMC, to the latest version by using the following command:

gem install vmc

We can verify that we have the right version using:

vmc -v

which should show the version to be 0.3.18 or higher.

Now let’s get started with the Java zentasks sample found in the Play 2.0 distribution. We’ll run the “play dist” command which will compile our code, retrieve all the required dependencies and create a self-contained binary that can be uploaded to Cloud Foundry.

dev$: cd play-2.0.1/samples/java/zentasks
zentasks$: play clean dist
[info] Loading project definition from /Users/jencompgeek/development/resources/play-2.0.1/samples/java/zentasks/project
[info] Set current project to zentask (in build file:/Users/jencompgeek/development/resources/play-2.0.1/samples/java/zentasks/)
[success] Total time: 0 s, completed May 15, 2012 2:27:29 PM
[info] Updating {file:/Users/jencompgeek/development/resources/play-2.0.1/samples/java/zentasks/}zentask...
[info] Done updating.
[info] Compiling 10 Scala sources and 9 Java sources to /Users/jencompgeek/development/resources/play-2.0.1/samples/java/zentasks/target/scala-2.9.1/classes...
[warn] Note: Some input files use unchecked or unsafe operations.
[warn] Note: Recompile with -Xlint:unchecked for details.
[info] Packaging /Users/jencompgeek/development/resources/play-2.0.1/samples/java/zentasks/target/scala-2.9.1/zentask_2.9.1-1.0.jar ...
[info] Done packaging.

Your application is ready in /Users/jencompgeek/development/resources/play-2.0.1/samples/java/zentasks/dist/zentask-1.0.zip

Now we can deploy the application to Cloud Foundry with the VMC push command:

zentasks$: vmc push --path=dist/zentask-1.0.zip
Application Name: zentasks
Detected a Play Framework Application, is this correct? [Yn]:
Application Deployed URL [zentasks.cloudfoundry.com]:
Memory reservation (128M, 256M, 512M, 1G, 2G) [256M]:
How many instances? [1]:
Create services to bind to 'zentasks'? [yN]: y
1: mongodb
2: mysql
3: postgresql
4: rabbitmq
5: redis
What kind of service?: 3
Specify the name of the service [postgresql-38199]: tasks-db
Create another? [yN]:
Would you like to save this configuration? [yN]: y
Manifest written to manifest.yml.
Creating Application: OK
Creating Service [tasks-db]: OK
Binding Service [tasks-db]: OK
Uploading Application:
  Checking for available resources: OK
  Processing resources: OK
  Packing application: OK
  Uploading (186K): OK
Push Status: OK
Staging Application 'zentasks': OK
Starting Application 'zentasks': OK

Looks like zentasks deployed successfully. Let’s check the logs:

zentasks$: vmc logs zentasks
====> logs/stdout.log <====

Auto-reconfiguring default
Enabling JPA auto-reconfiguration
Play server process ID is 13269
[warn] play - Plugin [play.db.jpa.JPAPlugin] is disabled
[info] play - database [default] connected at jdbc:postgresql://172.31.244.70:5432/dd2c9bc5b72134998adcfe4dcfa6660f4
[info] play - Application started (Prod)
[info] play - Listening for HTTP on port 59907...

Our Play 2.0 application is up and running on Cloud Foundry in 2 simple steps, no modification required!

Like most Play applications, zentasks contains database evolutions. Cloud Foundry automatically applied these evolutions to the database on application start. But how was the app able to make use of the PostgreSQL service we provisioned and bound to the application during deployment? If we look at the application.conf file, we see that the application is configured to use an in-memory database:

db.default.driver=org.h2.Driver
db.default.url="jdbc:h2:mem:play"

Cloud Foundry actually used a mechanism called auto-reconfiguration to automatically connect the Play application to the relational database service. If a single database configuration is found in the Play configuration (for example, “default” from above) and a single database service instance is bound to the application, Cloud Foundry will automatically override the connection properties in the configuration to point to the PostgreSQL or MySQL service bound to the application.

This is a great way to get simple apps up and running quickly. However, it is quite possible that your application will contain SQL that is specific to the type of database you are using. For example, several of the samples that come with Play make use of sequences in evolution scripts. This, of course, works with the in-memory database and will also work on PostgreSQL, but it will not work on MySQL. In these cases, or if your app needs to bind to multiple services, you may choose to avoid auto-reconfiguration and explicitly specify the service connection properties.

Connecting to Cloud Foundry Services

As always, Cloud Foundry provides all of your service connection information to your application in JSON format through the VCAP_SERVICES environment variable. However, connection information is also available as series of properties you can use in your Play configuration. Here is an example of connecting to a PostgreSQL service named “tasks-db” from within an application.conf file:

db.default.driver=${?cloud.services.tasks-db.connection.driver}
db.default.url=${?cloud.services.tasks-db.connection.url}
db.default.password=${?cloud.services.tasks-db.connection.password}
db.default.user=${?cloud.services.tasks-db.connection.username}

This information is available for all types of services, including NoSQL and messaging services. Also, if there is only a single service of a type (e.g. postgresql), you can refer to that service only by type instead of specifically by name, as exemplified below:

db.default.driver=${?cloud.services.postgresql.connection.driver}
db.default.url=${?cloud.services.postgresql.connection.url}
db.default.password=${?cloud.services.postgresql.connection.password}
db.default.user=${?cloud.services.postgresql.connection.username}

We recommend keeping these properties in a separate file (for example “cloud.conf”) and then including them only when building a distribution for Cloud Foundry. You can specify an alternative config file to “play dist” by using “-Dconfig.file”.

Opting Out of Auto-Reconfiguration

There may be situations in which you would like to opt out of auto-reconfiguration. For example, you may have an in-memory database that should not be bound to a Cloud Foundry service. If you use the properties referenced above, you will automatically be opted-out. To explicitly opt out, include a file named “cloudfoundry.properties” in your application’s conf directory, and add the entry “autoconfig=false“.

Debugging Your Play Application

If you are using a local Cloud Foundry setup, you can remotely debug your Play applications. Simply use the flag “--debug” when doing a “vmc push” or “vmc start“. You can then run “vmc instances” to get the debug host and port information:

zentasks$: vmc instances
+-------+---------+--------------------+-----------------+------------+
| Index | State   | Start Time         | Debug IP        | Debug Port |
+-------+---------+--------------------+-----------------+------------+
| 0     | RUNNING | 05/15/2012 05:50PM | 192.168.193.193 | 59845      |
+-------+---------+--------------------+-----------------+------------+

Just use the displayed debug IP and port in the remote debugger in your favorite IDE and start debugging!

Conclusion

We look forward to seeing your Play applications on Cloud Foundry. Please feel free to send us feedback or submit a pull request to help us improve our support for the Play Framework. Now get started building those apps!

- Jennifer Hickey
The Cloud Foundry Team

Don’t have a Cloud Foundry account yet?  Sign up for free today

Facebook Twitter Linkedin Digg Delicious Reddit Stumbleupon Email

Cloud Foundry Supports Node.js Modules with NPM

Update: Recent Changes in Node.js Modules Support

We are pleased to announce support for npm (Node Package Manager) which manages Node.js application module dependencies on CloudFoundry.com. The popularity of Node.js can be partially attributed to its strong ecosystem that has created modules for practically any programming task–from database access to payment processing. At present, there are over 10,000 node modules listed on search.nodejs.org. Any cloud that aspires to provide good support for Node.js needs to simplify the task of using node modules. With the addition of npm support, Cloud Foundry now makes it easier for you to manage modules for node applications.

The normal process of creating a Node.js application requires local installation of node modules (typically in the node_modules folder inside the application), essentially making the application self-contained. You can deploy this application locally or push all its contents, including the node modules, to CloudFoundry.com. This works fine as long as the app didn’t need a node module with native dependencies, which must be compiled specifically for the target platform. The npm support described in this blog obviates the need to package module dependencies with the app and makes it possible to use modules with native dependencies.

Requirements and Limitations

In order to use the npm feature, you would need to follow a few simple steps:

  • The application must provide an npm-shrinkwrap.json file. This file can be generated with the npm shrinkwrap command and reflects the whole tree of dependencies with fixed versions. This file is a snapshot of application dependencies in the same way that Gemfile.lock serves Ruby applications. This guarantees that Cloud Foundry will provide the exact same node module versions, which avoids incompatibility issues and follows the same dependencies hierarchy.
  • By default, Cloud Foundry uses node modules if the application includes them. More concretely, if an application has a node_modules folder in its base folder, then Cloud Foundry will simply use the modules in that folder. To overwrite the existing modules in the node_modules folder, you would provide a configuration file, cloudfoundry.json, with the “ignoreNodeModules” option set to true.

If the above conditions are met, Cloud Foundry will install node modules to the application during staging based on the module versions, application runtime version and npm version. If a required node module does not work with the node engine that the application is running on, the module will not be installed. Currently, in order to push the application with the node engine version 0.6.x, it needs to be explicitly specified during application push.

$ vmc push app-name --runtime=node06

If a module installation fails for some reason, Cloud Foundry will use the node module provided by the user. Besides the compatibility requirement outlined above, there may be other possible reasons for installation failures. For example, when a node module of a given version is not found in the npm registry. When an error occurs, information about the installation process along with any npm error messages can be found in the application logs.

$ vmc logs app-name
...
Installing dependencies. Node version 0.6.8
Failed getting the requested package: bcrypt@0.4.5

Note that although npm supports git URLs specified manually after npm-shrinkwrap.json was generated, Cloud Foundry currently does not support git URLs.

Native node modules

Cloud Foundry npm support also allows deployment of Node.js applications with native module dependencies. Many popular node modules such as bcrypt, fibers and nowjs have native code that depends on the platform. So locally installed node modules that were pushed along with the application would raise platform incompatibility errors often manifested as “invalid ELF header” errors during execution.

Now, if an application meets the above requirements for npm support, compiled native dependencies will be provided by Cloud Foundry to the application during an application push.

Example of npm support in action

Let’s see how npm support works. Here we have an application with the main file app.js:

var app = require("express").createServer();
var bcrypt = require("bcrypt");

app.get("/", function(req, res) {
  var salt = bcrypt.genSaltSync(10);
  var hash = bcrypt.hashSync("B4c0/\/", salt);
  if (bcrypt.compareSync("B4c0/\/", hash))
    res.send("World is safe!");
  else
    res.send("World is in trouble!");
});

var port = process.env.VCAP_APP_PORT || 3000;
app.listen(port);

And package.json that specifies our dependencies. In this example we use express, which depends on other node modules and native dependency, bcrypt.

{
  "name" : "node-dependencies-example",
  "version" : "0.1.0",
  "dependencies" : {
    "express" : "2.5.x",
    "bcrypt" : "0.5.x"
  }
}

We first verified that the application is working locally with installed module versions. We can then run the ”npm shrinkwrap” command in the application’s base directory to generate the npm-shrinkwrap.json file:

{
  "name": "node-dependencies-example",
  "version": "0.1.0",
  "dependencies": {
    "express": {
      "version": "2.5.9",
      "dependencies": {
        "connect": {
          "version": "1.8.7",
          "dependencies": {
            "formidable": {
              "version": "1.0.9"
            }
          }
        },
        "mime": {
          "version": "1.2.4"
        },
        "qs": {
          "version": "0.4.2"
        },
        "mkdirp": {
          "version": "0.3.0"
        }
      }
    },
    "bcrypt": {
      "version": "0.5.0"
    }
  }
}

We can now push the application without the node_modules folder, or we can provide a cloudfoundry.json file in the application’s base directory, which sets ignoreNodeModules to true to bypass the existing node modules.

{ "ignoreNodeModules" : true }

If we push our application now, Cloud Foundry will install node modules into the application that were compiled on Cloud Foundry’s platform.

$ vmc push node-dependencies-example --runtime=node06

Note that bcrypt has different APIs for different node engines, so we have to explicitly specify the required runtime.

Finally, if we go to a browser we would see the display, “World is safe!”.

Node dependencies example app screenshot

To summarize, npm support is a long-awaited feature that allows you to use the full variety of node modules available today, greatly enhancing your application.

- Maria Shaldibina

The Cloud Foundry Team

Don’t have a Cloud Foundry account yet?  Sign up for free today

Facebook Twitter Linkedin Digg Delicious Reddit Stumbleupon Email

Building a Real Time Activity Stream on Cloud Foundry with Node.js, Redis and MongoDB – Part I

Cloud Foundry provides developers with several choices of frameworks, application infrastructure services and deployment clouds. This approach to providing a platform as a service enables the fast creation of useful cloud applications that take advantage of polyglot programming and multiple data services. As an example of how this enables us to be more productive, I was able to use Node.js, Redis, and MongoDB to create an Activity Streams application in a short time, despite the fact that I mainly develop Web Applications in Ruby. Based on the developer interest after a demo of this application at NodeSummit 2012 and MongoSF 2012,  I was inspired to do a 3 part blog series that fully details the creation, deployment, and scaling of this application on CloudFoundry.com.

The application is based on an interesting project I came across recently called “node-express-boilerplate” developed by @mape which is a full-featured but simple boilerplate Node.js app. Given my previous experience working on Social Networking software and Open Web Standards, I decided to morph this app into an Activity Streams sample application.

Initial Boilerplate Architecture without MongoDB or Redis PubSub

“Node-express-boilerplate” is a starter application written in Node.js which showcases how users can log into a website using Facebook, Twitter or GitHub, display basic profile info from those sites, and have real-time communication between server and clients. In this first blog post, we are going to review the components of the boilerplate application so that developers can learn how to use them for other applications and  deploy locally as well as on Cloud Foundry.

A tour of the Boilerplate Components

Before we move to the setup, here are some code highlights explaining the various parts of the application.

Express MVC Framework

Working with the Express framework is very easy to do because its creator, @tjholowaychuk, has made it simple yet flexible to use while providing good documentation and screencasts.

You can use any web templating engine. For my project, I switched from using Embedded Javascript (EJS) to jade which is even terser than HTML Abstraction Markup Language (Haml).

// Settings
app.configure(function() {
	app.set('view engine', 'jade');
	app.set('views', __dirname+'/views');
});

Route Middleware

This middleware allows us to chain functions to pre-process the request. In this example I am showing how to invoke loadUser to read the current user, getDistinctStreams to get all the different topics and getMetaData to get the list of verbs and object types.

app.get('/streams/:streamName', loadUser, getDistinctStreams, getMetaData, function(req, res) {

    asmsDB.getActivityStream(req.params.streamName, 20, function (err, docs) {
        var activities = [];
        if (!err && docs) {
            activities = docs;
        }
        req.streams[req.params.streamName].items = activities;
        res.render('index', {
            currentUser: req.user,
            providerFavicon: req.providerFavicon,
            streams : req.streams,
            desiredStream : req.session.desiredStream,
            objectTypes : req.objectTypes,
            verbs: req.verbs
        });
    });

});

Session Management

In the boilerplate application, sessions are stored in Redis, allowing us to scale to more than one instance. Not only does this application properly manage user sessions, it also supports single sign-on with  GitHub, Facebook and Twitter via module everyauth.

Packaging Assets

In real world applications today, users expect immediate feedback and this cannot be done if your client is executing multiple http requests to render the app. This boilerplate sample uses @mape‘s module connect-assetmanager which minifies and bundles CSS and Javascript assets so the responses are very fast. This module is very flexible and allows pre and post manipulation of assets.

Here is an example which packages the js and the css files

var assetManager = require('connect-assetmanager');
var assetHandler = require('connect-assetmanager-handlers');
...
var assetsSettings = {
	'js': {
		'route': /\/static\/js\/[a-z0-9]+\/.*\.js/
		, 'path': './public/js/'
		, 'dataType': 'javascript'
		, 'files': [
			'http://code.jquery.com/jquery-latest.js'
			, siteConf.uri+'/socket.io/socket.io.js' // special case since the socket.io module serves its own js
			, 'jquery.client.js'
		]
		, 'debug': true
		, 'postManipulate': {
			'^': [
				assetHandler.uglifyJsOptimize
				, function insertSocketIoPort(file, path, index, isLast, callback) {
					callback(file.replace(/.#socketIoPort#./, siteConf.port));
				}
			]
		}
	}
	, 'css': {
		'route': /\/static\/css\/[a-z0-9]+\/.*\.css/
		, 'path': './public/css/'
		, 'dataType': 'css'
		, 'files': [
			'reset.css'
			, 'client.css'
		]
		, 'debug': true
		, 'postManipulate': {
			'^': [
				assetHandler.fixVendorPrefixes
				, assetHandler.fixGradients
				, assetHandler.replaceImageRefToBase64(__dirname+'/public')
				, assetHandler.yuiCssOptimize
			]
		}
	}
};

var assetsMiddleware = assetManager(assetsSettings);

Client-Server Real Time Communication

Socket.io is used to send messages back and forth between the user-agent and the server. This saves us from having to do entire page refreshes to show new content.

In the example below you can see how we subscribe to different events and change the page content accordingly.

var socketIoClient = io.connect(null, {
		'port': '#socketIoPort#'
		, 'rememberTransport': true
		, 'transports': ['xhr-polling']
	});
	socketIoClient.on('connect', function () {
		$$('#connected').addClass('on').find('strong').text('Online');
	});

	var image = $.trim($('#image').val());
	var service = $.trim($('#service').val());

    var $ul = $('#main_stream');

	socketIoClient.on('message', function(json) {
		var doc = JSON.parse(json);
        if (doc) {
            var $li = $(jade.templates["activity"]({activities: [doc]}));
            $ul.prepend($li);
        }
		if ($ul.children.count > 20) {
            $ul.children.last.remove();
        }
	});

Here are the steps we performed to run this application as-is on Cloud Foundry

Setup

  • Get a CloudFoundry.com account if you don’t have one yet.
  • Install vmc command line tool to deploy to Cloud Foundry.
  • Get Node.js running locally on your machine.
    • Install version 0.6.8 or later. NPM is the package manager which will be included.
  • Get Redis running locally.
  • Create Apps on Facebook, Twitter and GitHub for prod and local environments and note the keys.

Configure

Clone @mape‘s repo or fork it and clone your fork and install the dependencies

$ git clone git://github.com/mape/node-express-boilerplate.git
$ cd node-express-boilerplate

Edit package.json to include module cloudfoundry

{
  "name" : "node-express-boilerplate",
  "description" : "A boilerplate used to quickly get projects going.",
  "version" : "0.0.2",
  "author" : "Mathias Pettersson ",
  "engines" : ["node"],
  "repository" : { "type":"git", "url":"http://github.com/mape/node-express-boilerplate" },
  "dependencies" : {
    "cloudfoundry": ">=0.1.0",
    "connect" : ">=1.6.0",
    "connect-assetmanager" : ">=0.0.21",
    "connect-assetmanager-handlers" : ">=0.0.17",
    "ejs" : ">=0.4.3",
    "express" : ">=2.4.3",
    "socket.io" : ">=0.7.8",
    "connect-redis" : ">=1.0.7",
    "connect-notifo" : ">=0.0.1",
    "airbrake" : ">=0.2.0",
    "everyauth" : ">=0.2.18"
  }
}

Install the dependencies locally.

$ npm install

Copy to siteConfig.js

$ cp siteConfig.sample.js siteConfig.js

Edit siteConfig.js to use environment variables and the cloudfoundry module. Changes are detailed here.

Update server.js to use the new siteConfig.js settings as seen here.

Set environment variables for all services. Example in bash:

$ export twitter_consumer_key=2SXwj3HcMHsdsdsL4uuUBdjShw
$ export twitter_consumer_secret=UFamzEOAEhLUwewewDwwEoCI72hN0fl8
$ export facebook_app_id=5925695687264066
$ export facebook_app_secret=cce6f5edefa89f4686e5e036e3ea
$ export airbrake_api_key=63340934f6b376a001eacfc660d06205
$ export github_client_id='92df9d93813ab234e1'
$ export github_client_secret='fa64d10d3a02eee08d00cda3c2965caea2a4ce22'

Run locally

$ node server.js

Run on CloudFoundry.com

Install vmc if you have not already done so

$ sudo gem install vmc --pre

Specify you want Redis “redis-asms” bound to your app when you deploy:

$ vmc push --runtime=node06 --nostart

  Would you like to deploy from the current directory? [Yn]:
  Application Name: node-express-start
  Detected a Node.js Application, is this correct? [Yn]:
  Application Deployed URL [node-express-start.cloudfoundry.com]:
  Memory reservation (128M, 256M, 512M, 1G, 2G) [64M]: 128M
  How many instances? [1]:
  Bind existing services to 'node-express-start'? [yN]:
  Create services to bind to 'node-express-start'? [yN]: Y
    1: mongodb
    2: mysql
    3: postgresql
    4: rabbitmq
    5: redis
  What kind of service?: 5
  Specify the name of the service [redis-9bea7]: redis-asms
  Create another? [yN]: N
  Would you like to save this configuration? [yN]: Y
  Manifest written to manifest.yml.
  Creating Application: OK
  Creating Service [redis-asms]: OK
  Binding Service [redis-asms]: OK
  Uploading Application:
  Checking for available resources: OK
  Processing resources: OK
  Packing application: OK
  Uploading (305K): OK
Push Status: OK

Note that here I responded Yes to saving the configuration which will create a file called manifest.yml. A manifest.yml helps you quickly push and update apps. You can read more about it here.

Now you can run this command to add the keys from the services.

$ export APP_NAME=your_app_name
$ vmc env-add $APP_NAME airbrake_api_key=your_key
$ vmc env-add $APP_NAME github_client_id=github_id
$ vmc env-add $APP_NAME github_client_secret=github_secret
$ vmc env-add $APP_NAME facebook_app_id=fb_id
$ vmc env-add $APP_NAME facebook_app_secret=fb_secret
$ vmc env-add $APP_NAME NODE_ENV=production
$ vmc env-add $APP_NAME twitter_consumer_key=twitter_key
$ vmc env-add $APP_NAME twitter_consumer_secret=twitter_secret

To finish, run:

  vmc start

And that’s it! You are up and running with the boilerplate app as seen here. Please note that the app may not work to spec on IE, but works on Firefox, Safari and Chrome.

Observations so far

node-express-boilerplate is a great starting point on which to build an activity stream engine given that it addresses:

  • Robust real-time messaging between browser and server. Socket.io adapts to the protocols supported by the server and client
  • Performance via Asset Bundling and Minification
  • Provides SSO Support to major Social Networks
  • Handles scalable session management via Redis
  • Built on a great MVC framework

Also, it was good to see that @mape had abstracted the infrastructure details via the creation of a siteConfig.js. We enhanced this even further by using environment variables.

As you saw on the walkthrough all this was possible thanks to the open source community and using a robust platform as a service like CloudFoundry which had everything I needed. I was able to use @igo‘s “cloudfoundry” module to assist in parsing environment details in my app and thus made siteConfig.js even more straightforward.

In the next blog post, I will cover how to start the modification of this app into an Activity Stream engine. The tutorial will include how to create a Node.js module like activity-streams-mongoose and how to manage the persistance of the Activity Streams data on MongoDB as well as real time syndication across multiple app instances with Redis PubSub.

Signup for Cloud Foundry today, and start building your own cool app!

-Monica Wilkinson, Cloud Foundry Team

Facebook Twitter Linkedin Digg Delicious Reddit Stumbleupon Email

Refactoring the VCAP Repo

In my previous post, I talked briefly about the vcap repo refactoring effort. This week, I want to walk you through the process in a little more detail.

If you look closely at the vcap repo, you can see that it’s a collection of major system components (dea, cloud controller, health manager, etc.). This structure is not a scalable structure for the long haul on a number of fronts.

For instance, when building releases we often find ourselves wanting different components at different stages of completion. Within the cf-release repo, we currently have a single sub-module pointer to vcap (src/core). Given the component diversity under vcap, we often find ourselves wanting to be able to manage one launch schedule for each component (e.g., manage the dea and health manager release cycles differently). The singe sub-module pointer approach was too constraining.

Moving forward, we are pulling the major components out of the vcap repo, and into their own repo. In the cf-release repo, under src, we add a new sub-module pointer to point to the new component, adding it to the release. With this structure in place, each major component can publish its own release stream of blessed changes.

The other major change that’s part of this effort is the formalization of shared vcap-common repo and how components formally link to this component.

Walking thru in in more detail in the context of the dea component: The dea repo is the long term location of the dea component’s code and test cases. This component previously lived in the vcap repo as a sub-directory.

The cf-release repo contains a sub-module pointer called “dea”, which links to the new dea repo. See: https://github.com/cloudfoundry/cf-release/tree/master/src and note the sub-module pointers for core, dea, etc. Over time, as we complete the repo refactoring work, we will have additional sub-module pointers (for health manager, cloud controller, etc.).

This repo also contains the package definitions for the various components. In the case of the dea, the packaging in cf-release now refers to the new dea repo, and not the dea sub-directory in the old vcap repo.

And finally, with this round of changes, vcap components formally link to vcap-common as a gem and using a git url in their Gemfile. For example, see the below gem reference to vcap_common from the dea’s Gemfile.

gem 'vcap_common', '~> 1.0.8', :git => 'git://github.com/cloudfoundry/vcap-common.git', :ref => '9673dced'

The repo refactoring work is moving along and if you have some cycles to help, engage with Jesse on vcap-dev@cloudfoundry.org. The dea specific change has been a work in progress over the last few weeks. The final piece is to launch on cloudfoundry.com. That step is in flight as we speak.

Facebook Twitter Linkedin Digg Delicious Reddit Stumbleupon Email

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:

import com.twitter.sbt._

seq(StandardProject.newSettings: _*)

packageDistZipName := "cf-unfiltered-sample.zip"

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

Facebook Twitter Linkedin Digg Delicious Reddit Stumbleupon Email

Running Workers on Cloud Foundry with Spring

In the two previous posts in this series, we discussed using Cloud Foundry’s new support for standalone apps to deploy worker processes. We looked at an example using Resque for Ruby apps. In this third installment, we explore using Spring to create workers in Java apps.

Let’s walk through an example.

Deploying the Cloud Foundry Twitter Search Sample

Cloud Foundry Twitter Search includes two applications: a standalone Java application that periodically polls Twitter for tweets containing the word “cloud” and a Node.js web application that displays the results. The applications communicate via a shared RabbitMQ service. The worker publishes tweet information to a RabbitMQ exchange, and the web application consumes the tweets and pushes them to the browser using SockJS.

Let’s clone the sample app from Github:

mycomp:dev$ git clone https://github.com/cloudfoundry-samples/twitter-rabbit-socks-sample
mycomp:dev$ cd twitter-rabbit-socks-sample/twitter2rabbit

The worker app is written with Spring Integration. In fact, all of the worker’s logic is contained in a single Spring context file.

mycomp:twitter2rabbit$ more src/main/resources/org/springsource/samples/twitter/context.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:int="http://www.springframework.org/schema/integration"
    xmlns:int-twitter="http://www.springframework.org/schema/integration/twitter"
    xmlns:int-amqp="http://www.springframework.org/schema/integration/amqp"
    xmlns:rabbit="http://www.springframework.org/schema/rabbit"
    xmlns:cloud="http://schema.cloudfoundry.org/spring"
    xsi:schemaLocation="http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration-2.1.xsd
		http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/integration/twitter http://www.springframework.org/schema/integration/twitter/spring-integration-twitter-2.1.xsd
		http://www.springframework.org/schema/integration/amqp http://www.springframework.org/schema/integration/amqp/spring-integration-amqp-2.1.xsd
		http://www.springframework.org/schema/rabbit http://www.springframework.org/schema/rabbit/spring-rabbit-1.0.xsd
		http://schema.cloudfoundry.org/spring http://schema.cloudfoundry.org/spring/cloudfoundry-spring-0.8.xsd">

    <int-twitter:search-inbound-channel-adapter id="twitter" query="cloud">
        <int:poller fixed-rate="5000" max-messages-per-poll="10"/>
    </int-twitter:search-inbound-channel-adapter>

	<int:transformer input-channel="twitter" expression="payload.fromUser + ': ' + payload.text"  output-channel="rabbit"/>

	<int-amqp:outbound-channel-adapter id="rabbit" exchange-name="tweets"/>

	<rabbit:fanout-exchange name="tweets" durable="false"/>

	<rabbit:admin connection-factory="rabbitConnectionFactory"/>

	<rabbit:template id="amqpTemplate" connection-factory="rabbitConnectionFactory"/>

	<beans profile="default">
		<rabbit:connection-factory id="rabbitConnectionFactory"/>
	</beans>

	<beans profile="cloud">
		<cloud:rabbit-connection-factory id="rabbitConnectionFactory"/>
	</beans>

</beans>

Using Spring Integration, we’ve set up an Inbound Twitter Channel Adapter to query Twitter for the word “cloud” every five seconds. The user and text from each tweet is published to an AMQP exchange named “tweets.”  The connection to Rabbit is controlled by the choice of “default” or “cloud” profile. The cloud profile uses the cloud namespace provided by the cloudfoundry-runtime library to create a connection to a single Rabbit service bound to the app. The only code in this project is a single class that activates the cloud profile and bootstraps the ApplicationContext.

In order to run this example on Cloud Foundry, we’ll need to package up all of the dependencies. Enter the Maven Application Assembler Plugin.

<build>
	<plugins>
		<plugin>
			<groupId>org.codehaus.mojo</groupId>
			<artifactId>appassembler-maven-plugin</artifactId>
			<version>1.1.1</version>
			<executions>
				<execution>
					<phase>package</phase>
					<goals>
						<goal>assemble</goal>
					</goals>
					<configuration>
						<assembledirectory>target</assembledirectory>
						<programs>
							<program>
								<mainClass>org.springsource.samples.twitter.Demo</mainClass>
							</program>
						</programs>
					</configuration>
				</execution>
			</executions>
		</plugin>
	</plugins>
</build>

The generated start script, target/appassembler/bin/demo, uses the JAVA_OPTS environment variable to pass options to Java. When this app is deployed, 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 a local cloud, 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 Java applications with your favorite IDE.

Now we’ll do a “mvn package” and we’re ready to deploy to Cloud Foundry from our new distribution directory:

mycomp:twitter2rabbit$ vmc push twitter2rabbit --path=target/appassembler
Detected a Standalone Application, is this correct? [Yn]:
1: java
2: node
3: node06
4: ruby18
5: ruby19
Select Runtime :
Selected java
Start Command: bin/demo
Application Deployed URL [None]:
Memory reservation (128M, 256M, 512M, 1G, 2G) [512M]:
How many instances? [1]:
Create services to bind to 'twitter2rabbit'? [yN]: y
1: mongodb
2: mysql
3: postgresql
4: rabbitmq
5: redis
What kind of service?: 4
Specify the name of the service [rabbitmq-f7939]: twitter-rabbit
Create another? [yN]:
Would you like to save this configuration? [yN]: y
Creating Application: OK
Creating Service [twitter-rabbit]: OK
Binding Service [twitter-rabbit]: OK
Uploading Application:
 Checking for available resources: OK
 Processing resources: OK
 Packing application: OK
 Uploading (32K): OK
Push Status: OK
Staging Application 'twitter2rabbit': OK
Starting Application 'twitter2rabbit': OK

VMC has detected that twitter2rabbit is a standalone application, and we selected the Java runtime. We specify the command “bin/demo” to start the server using the generated script. We saved the manifest file for future deployments. The app should now be running and publishing tweets to an exchange on the twitter-rabbit service.

Now let’s deploy the front-end Node.js web application to display these tweets.

mycomp:twitter2rabbit$ cd ../rabbit2socks
mycomp:rabbit2socks$ npm install
mycomp:rabbit2socks$ vmc push mytwittersearch --runtime=node06
Detected a Node.js Application, is this correct? [Yn]:
Application Deployed URL [mytwittersearch.cloudfoundry.com]:
Memory reservation (128M, 256M, 512M, 1G, 2G) [64M]:
How many instances? [1]:
Bind existing services to 'mytwittersearch'? [yN]: y
1: twitter-rabbit
Which one?: 1
Create services to bind to 'mytwittersearch'? [yN]:
Would you like to save this configuration? [yN]: y
Creating Application: OK
Binding Service [twitter-rabbit]: OK
Uploading Application:
  Checking for available resources: OK
  Processing resources: OK
  Packing application: OK
  Uploading (18K): OK
Push Status: OK
Staging Application 'mytwittersearch': OK
Starting Application 'mytwittersearch': OK

The application is pushed and bound to the same twitter-rabbit service as the Java worker, twitter2rabbit. The app will consume tweets from this Rabbit service and push them to the browser using SockJS. Let’s launch the website and watch as tweets start popping up! Here’s a screenshot of the Twitter traffic when I ran my app.

And there you have it! The web page is dynamically updated with results from the Spring Integration-powered worker app. Clone the sample application and try it yourself. The readme also contains instructions on building and deploying with Gradle (using the Gradle Application Plugin to create a distribution) instead of Maven.

There are many other ways to use Spring to create worker apps, including using the Spring Task Scheduler abstraction or Spring Batch. For more examples of Spring workers on Cloud Foundry, check out Josh Long’s post on the SpringSource blog.

In the next and final post of the series, we will look at another category of standalone apps: self-executing web applications. With standalone application support, the possibilities are endless.

- Jennifer Hickey
The Cloud Foundry Team

Don’t have a Cloud Foundry account yet?  Sign up for free today

Facebook Twitter Linkedin Digg Delicious Reddit Stumbleupon Email

Running Resque Workers on Cloud Foundry

We introduced Cloud Foundry’s new “standalone” applications feature in the first post in this four-part series. In this second installment, we will look at the most common use of a standalone application–the worker process. Workers can be used for all kinds of asynchronous background jobs, such as updating search indexes, emailing all users with a password reset approaching, performing a database backup to persistent storage, or uploading new customer data from external storage. In this post, we will walk through an example of deploying workers to Cloud Foundry using Resque.

Resque Workers on Cloud Foundry

Let’s start by cloning the Resque Demo Example.

mycomp:dev$ git clone git://github.com/defunkt/resque.git
mycomp:dev$ cd resque/examples/demo
Let’s add a Gemfile to the example to ensure that Cloud Foundry can find all required gems.

source "http://rubygems.org"
gem 'sinatra'
gem 'resque'
gem 'rake'
gem 'json'

We’ll run “bundle install” and “bundle package” to package the gems in vendor/cache, and we’re ready to deploy.  The resque server is a Rack app, so we’ll deploy it to Cloud Foundry as such.

mycomp:demo$ vmc push resque-server
Would you like to deploy from the current directory? [Yn]:
Detected a Rack Application, is this correct? [Yn]:
Application Deployed URL [resque-server.cloudfoundry.com]: 
Memory reservation (128M, 256M, 512M, 1G, 2G) [128M]:
How many instances? [1]:
Create services to bind to 'resque-server'? [yN]: y
1: mongodb
2: mysql
3: postgresql
4: rabbitmq
5: redis
What kind of service?: 5
Specify the name of the service [redis-2a462]: redis-work-queue
Create another? [yN]:
Would you like to save this configuration? [yN]: y
Manifest written to manifest.yml.
Creating Application: OK
Creating Service [redis-work-queue]: OK
Binding Service [redis-work-queue]: OK
Uploading Application:
Checking for available resources: OK
Processing resources: OK
Packing application: OK
Uploading (21K): OK
Push Status: OK
Staging Application 'resque-server': OK
Starting Application 'resque-server': OK
Let’s have a look at the resque-server app and add some jobs to the queue:
Now that we have some jobs, it’s time to deploy some workers!  First, we need to rename the generated manifest.yml for the Rack app, so it won’t automatically be used in the push.  We can use it again later by doing a “vmc push –manifest server-manifest.yml”.  Now, let’s push the app again as a standalone worker app.
mycomp:demo$ mv manifest.yml server-manifest.yml
mycomp:demo$ vmc push resque-worker
Would you like to deploy from the current directory? [Yn]:
Detected a Rack Application, is this correct? [Yn]: n
1: Rails
2: Spring
3: Grails
4: Lift
5: JavaWeb
6: Standalone
7: Sinatra
8: Node
9: Rack
Select Application Type: 6
Selected Standalone Application
1: java
2: node
3: node06
4: ruby18
5: ruby19
Select Runtime [ruby18]:
Selected ruby18
Start Command: bundle exec rake VERBOSE=true QUEUE=default resque:work
Application Deployed URL [None]:
Memory reservation (128M, 256M, 512M, 1G, 2G) [128M]:
How many instances? [1]:
Bind existing services to 'resque-worker'? [yN]: y
1: redis-work-queue
Which one?: 1
Bind another? [yN]:
Create services to bind to 'resque-worker'? [yN]:
Would you like to save this configuration? [yN]: y
Manifest written to manifest.yml.
Creating Application: OK
Binding Service [redis-work-queue]: OK
Uploading Application:
Checking for available resources: OK
Processing resources: OK
Packing application: OK
Uploading (0K): OK
Push Status: OK
Staging Application 'resque-worker': OK
Starting Application 'resque-worker': OK

So we’ve pushed resque-worker as a standalone app with a Ruby runtime. We gave the command “bundle exec rake VERBOSE=true QUEUE=default resque:work” to start the worker. It is recommended to use bundle exec to ensure that all required gems are available. Since resque-worker does not have a web front-end, we selected “None” for URL.

Lastly, we bound the app to the same Redis service used by resque-server. If you’ve perused the resque demo example, you may have noticed that it is setup to connect to a local Redis service. However, we didn’t change the code before we pushed it. How will the app connect to the provisioned Redis service? Since we used the Ruby runtime provided by Cloud Foundry, the app will benefit from the new Ruby auto-reconfiguration support. Cloud Foundry will automatically replace the local Redis connection with a connection to the Redis service we bound to the application!

Let’s check the logs and see if the worker completed that job:
mycomp:demo$ vmc logs resque-worker
====> /logs/stdout.log <====

Loading Redis auto-reconfiguration.
*** Starting worker ubuntu:10245:default
Auto-reconfiguring Redis.
*** got: (Job{default} | Demo::Job | [{}])
Processed a job!
*** done: (Job{default} | Demo::Job | [{}])
*** got: (Job{default} | Demo::Job | [{}])
Processed a job!
*** done: (Job{default} | Demo::Job | [{}])
And we can verify that the worker has registered through the web interface:
We can even scale the workers up.
mycomp:demo$ vmc instances resque-worker +2
Scaling Application instances up to 3: OK
And now the web interface shows three workers:


And there you have it! We can now deploy Resque workers as standalone apps on Cloud Foundry. Clone the Cloud Foundry resque-sample and try it out for yourself!

Conclusion

Cloud Foundry now provides improved Resque support through standalone applications, as well as support for other Ruby worker libraries or apps. If you can package all the bits and provide a start command, you can run it on Cloud Foundry! In the next installment in this series, we will explore another example of workers in action using Spring integration. Stay tuned!

- Jennifer Hickey
The Cloud Foundry Team

Don’t have a Cloud Foundry account yet?  Sign up for free today

Facebook Twitter Linkedin Digg Delicious Reddit Stumbleupon Email

Cloud Foundry Improves Support For Background Processing

Cloud Foundry has significantly enhanced support for worker applications that perform background processing by allowing applications to run on CloudFoundry.com without the application container. Cloud Foundry applications are no longer limited to Web applications that respond to HTTP requests. Instead, they can be run as executable or “standalone” applications. A standalone application is one that does not require a provided framework or container.

Many developers create distributed applications that have workers to perform specific functions and communicate via a data or messaging system, such as those developed with Spring Batch, Spring Integration, Resque, or Delayed Job. Now Cloud Foundry supports running these worker components by allowing you to push a directory or single file without choosing a pre-defined framework. Simply provide the command required to run your script or executable, chose a runtime, and you’re done. Besides background processing functions, the standalone application support enables these other types of applications as well:

  1. Container-less non-Servlet applications, such as those developed with Netty or Grizzly
  2. Web apps that run with their own bundled containers, such as Jetty

In this blog series, we will walk through several example deployments of standalone apps. We will start with a simple Hello World to illustrate the deployment steps. In future posts, we will show examples of worker apps, distributed apps, and bring-your-own-container and container-less Web apps. While the apps may vary in use case and implementation, the deployment procedure remains the same.

All of these apps are meant to be long-running, as with any other app on Cloud Foundry (meaning they can be scaled, will be monitored for health, restarted if crashed, etc.). We do not yet have support for short-lived background tasks or scheduled tasks. However, we encourage you to keep watching this space!

Getting Started with Standalone Apps on Cloud Foundry

First, install or update your Cloud Foundry command line tool (‘VMC’) to the latest version using the following command:

gem install vmc

You can verify that you got the right version using:

vmc -v

which should show the version to be 0.3.17 or higher.

Let’s start by deploying a simple Hello World Ruby application.

mycomp:$ cd simple-ruby-app
mycomp:$ ls
hello-world.rb
mycomp:$ more hello-world.rb
loop {
  puts 'Hello world'
  sleep 5
}

Since we need a long-running application, this script will print “Hello World” every 5 seconds until stopped. Let’s push this to Cloud Foundry using vmc:

mycomp:$ vmc push helloworld
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 [ruby18]:
Selected ruby18
Start Command: ruby hello-world.rb
Application Deployed URL [None]:
Memory reservation (128M, 256M, 512M, 1G, 2G) [128M]:
How many instances? [1]:
Create services to bind to 'helloworld'? [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
Packing application: OK
Uploading (1K): OK
Push Status: OK
Staging Application 'helloworld': OK
Starting Application 'helloworld': OK

So, what just happened?
1. vmc detected that the app was a “Standalone Application” (due to the fact that no other Framework support was detected).
2. We were asked to provide a runtime. Since the app needs Ruby to run, we chose the “ruby18″ runtime (which vmc detected as default).
3. We provided a command to use for starting the application. Since we’ve chosen a Ruby 1.8 runtime, we don’t need to provide the fully qualified path to Ruby. Cloud Foundry will automatically add Ruby 1.8 to the application’s path.
4. We chose “None” for the application URL. This will run the application without a Web port or URL. There are times when we will want a URL and Web port for a standalone application, as we’ll see in a later blog post.
5. vmc pushed the entire contents of the working directory to Cloud Foundry. Since we only had hello-world.rb in the directory, we could have also executed “vmc push –path ./hello-world.rb”. The –path option comes in handy when working with distribution zip files, as we’ll see in an upcoming post.

Let’s have a look at the application’s logs:

mycomp:$  vmc logs helloworld
====> /logs/stdout.log <====

Hello world
Hello world

As you can see, helloworld can be managed just like any other Cloud Foundry application:

mycomp:$  vmc instances helloworld +2
Scaling Application instances up to 3: OK
mycomp:$ vmc instances helloworld

+-------+---------+--------------------+
| Index | State   | Start Time         |
+-------+---------+--------------------+
| 0     | RUNNING | 04/20/2012 04:47PM |
| 1     | RUNNING | 04/20/2012 04:48PM |
| 2     | RUNNING | 04/20/2012 04:48PM |
+-------+---------+--------------------+

Let’s look at the logs again for two of the instances:

mycomp:$  vmc logs helloworld --instance 0
====> /logs/stdout.log <====
Hello world
Hello world
mycomp:$  vmc logs helloworld --instance 1
====> /logs/stdout.log <====
Hello world
Hello world

Standalone app deployment manifest

Let’s take a look at the manifest file we generated with that vmc push:

mycomp:$ more manifest.yml
---
applications:
.:
name: helloworld
framework:
  name: standalone
  info:
     description: Standalone Application
     mem: 128M
runtime: ruby18
command: ruby hello-world.rb
url:
mem: 128M
instances: 1

Seems pretty straightforward. The app is deployed against a “standalone” framework, with a command and ruby18 runtime. To save time, we’ll be sure to save this manifest file for future deployments.

Tips and Tricks

You should now be able to deploy any long-running app that you can package, using any of Cloud Foundry’s provided runtimes. However, there are some tips and tricks to getting the best experience from Cloud Foundry:

1. Use the VCAP_APP_PORT environment variable if your application requires a web port.
2. Connect your application to Cloud Foundry services using provided libraries (see below) or the VCAP_SERVICES environment variable (value is in JSON).

JVM Applications

1. Package your application using a build plugin that creates a distribution zip file or directory.
Maven AppassemblerGradle Application Plugin, and SBT package-dist are good plugins for creating a distribution, and we’ll show examples of all of these in future posts. It is best not to package your entire application in a single jar file, as you will not be able to take advantage of Cloud Foundry’s incremental upload capability.
2. Always include $JAVA_OPTS in your Java start commands.
When you select your application’s memory reservation through VMC, Cloud Foundry will set the JAVA_OPTS environment variable with corresponding min and max heap sizes, therefore you should include $JAVA_OPTS in your Java start commands (for example, “java $JAVA_OPTS -jar main.jar”). The start scripts generated by Maven Appassembler and Gradle Application Plugin already include JAVA_OPTS. Using JAVA_OPTS will also allow you to start your app in debug mode on local clouds, using “vmc start –debug.”
3. Use the cloudfoundry-runtime library to connect your application to Cloud Foundry services.

Ruby Applications

1. Always include a Gemfile.lock to ensure that all application dependencies are resolved by Cloud Foundry.
2. While not required, we recommend running “bundle package” before deploying your application. This will improve your application start time, as Cloud Foundry will not need to check its cache or download gems from rubygems.org.
3. Standalone Ruby applications can take advantage of Ruby Auto-Reconfiguration.  To make your own connections to Cloud Foundry services, use the cf-runtime gem.

Conclusion

In this post, we used a simple example to get up and running quickly with standalone apps on Cloud Foundry. In the next installments of this four part series, we will have an in-depth look at deploying more complex standalone apps.

- Jennifer Hickey

The Cloud Foundry Team

Don’t have a Cloud Foundry account yet?  Sign up for free today

Facebook Twitter Linkedin Digg Delicious Reddit Stumbleupon Email