Cloud Foundry Blog

Experimental Clojure Support in Cloud Foundry

We have been working on making it easier to deploy Clojure apps to Cloud Foundry [1]. Clojure is a functional language that runs on the JVM that allows rapid prototyping of applications while offering great support for integration with Java libraries. Many interesting projects–for example, Twitter’s own realtime processing framework Storm–are written in Clojure.

To help to run Clojure apps in Cloud Foundry, we have written a library called claude that you can use to easily access the different services offered by Cloud Foundry, like MongoDB or RabbitMQ.

Now let’s see how you can start deploying your Clojure apps to Cloud Foundry.

Deploying Your Clojure Apps to Cloud Foundry

We assume that you are using leiningen for your Clojure projects.

First you will add the latest version of claude into your project dependencies:

[claude "0.2.1-SNAPSHOT"] Then run lein deps to obtain the project dependencies.

Once you have your project set up then you need to declare your project main function:

:main clojure-demo.server

See this project project.clj file for more details.

Then on your main namespace you need to add a :gen-class like in this example:

(ns clojure-demo.server
  (:gen-class)
  (:require [noir.server :as server]
            [claude.core :as cf]))

If you are creating a web app then another tweak you need to perform is to inform your app of the port in which it has to run. You can obtain the port from the VMC_APP_PORT environment variable. Here’s an example:

(defn -main [& m]
  (let [mode (if (cf/cloudfoundry?) :prod :dev)
        port (Integer. (get (System/getenv) "VMC_APP_PORT" "8080"))]
    (server/start port {:mode mode
                        :ns 'clojure-demo})))

Also, as you can see in that code snippet, we are using the claude.core/cloudfoundry? helper to see if we are running in the cloud. In that case, we can set the web app environment to :prod.

So far we have a basic Clojure project that can be run from a .jar file. Let’s create that jar file and deploy it to Cloud Foundry. We asume that you are already logged into Cloud Foundry using vmc. Run the following commands inside your Clojure project folder:

mkdir cf
lein uberjar
cp target/clojure-demo-0.1.0-SNAPSHOT-standalone.jar cf/
cd cf

There we created a new folder to hold our app .jar file. Now we are ready to deploy it. In this case, I will bind one instance of each service provided by Cloud Foundry. Therefore, you will see a lot of output in the following transcript. Let’s start with vmc push:

vmc push
Would you like to deploy from the current directory? [Yn]: Y
Application Name: clojure-demo
Detected a Standalone Application, is this correct? [Yn]: Y
1: java
2: java7
3: node
4: node06
5: node08
6: ruby18
7: ruby19
Select Runtime


: java7
Selected java7
Start Command: java $JAVA_OPTS -cp clojure-demo-0.1.0-SNAPSHOT-standalone.jar clojure_demo.server

Up to here we told vmc that we are deploying a standalone application, that the runtime is java7 and we provided our startup command. Make sure to change the application name on your own deployment.

Let’s continue our deployment:

Application Deployed URL [None]: ${name}.${target-base}
Memory reservation (128M, 256M, 512M, 1G, 2G) [512M]: 512
How many instances? [1]: 1

If we are deploying a web application, then we need to provide the URL for our app. In our case we let vmc build the URL based on our application name. In this case it will be under http://clojure-demo.cloudfoundry.com. Keep in mind that you only need a URL if you are deploying a web app.

Now let’s create and bind one instance of each service type to our app:

Bind existing services to 'clojure-demo'? [yN]: N
Create services to bind to 'clojure-demo'? [yN]: y
1: blob
2: mongodb
3: mysql
4: postgresql
5: rabbitmq
6: redis
What kind of service?: 1
Specify the name of the service [blob-9dcdc]:
Create another? [yN]: y
1: blob
2: mongodb
3: mysql
4: postgresql
5: rabbitmq
6: redis
What kind of service?: 2
Specify the name of the service [mongodb-cb862]:
Create another? [yN]: y
1: blob
2: mongodb
3: mysql
4: postgresql
5: rabbitmq
6: redis
What kind of service?: 3
Specify the name of the service [mysql-2358b]:
Create another? [yN]: y
1: blob
2: mongodb
3: mysql
4: postgresql
5: rabbitmq
6: redis
What kind of service?: 4
Specify the name of the service [postgresql-de020]:
Create another? [yN]: y
1: blob
2: mongodb
3: mysql
4: postgresql
5: rabbitmq
6: redis
What kind of service?: 5
Specify the name of the service [rabbitmq-3422d]:
Create another? [yN]: y
1: blob
2: mongodb
3: mysql
4: postgresql
5: rabbitmq
6: redis
What kind of service?: 6
Specify the name of the service [redis-29cde]:
Create another? [yN]: N

Note that we did this for our example’s sake. Your app might not need as many services or you might choose to not use any of them. It’s all up to you.

Now we probably want to save this configuration inside a manyfest.yml file so we don’t need to type all that again the next time we deploy our app from scratch.

Would you like to save this configuration? [yN]: y
Manifest written to manifest.yml.

Now vmc will stage your app and it will start it automatically:

Creating Application: OK
Creating Service [mongodb-cb862]: OK
Binding Service [mongodb-cb862]: OK
Creating Service [mysql-2358b]: OK
Binding Service [mysql-2358b]: OK
Creating Service [postgresql-de020]: OK
Binding Service [postgresql-de020]: OK
Creating Service [blob-9dcdc]: OK
Binding Service [blob-9dcdc]: OK
Creating Service [rabbitmq-3422d]: OK
Binding Service [rabbitmq-3422d]: OK
Creating Service [redis-29cde]: OK
Binding Service [redis-29cde]: OK
Uploading Application:
  Checking for available resources: OK
  Processing resources: OK
  Packing application: OK
  Uploading (5M): OK
Push Status: OK
Staging Application 'clojure-demo': OK
Starting Application 'clojure-demo': OK

You can access a demo app here.

While this seems to be a little long, in fact we detailed every single step to get you up and running. To recap this is what we need did:

  • Add the claude dependency to your project.
  • Add a (:gen-class) to your main namespace. This is a Clojure/Java requirement
  • Generate your uberjar.
  • Deploy your app providing a start up command

And that’s it! Now create a free account at Cloud Foundry and let’s see your awesome Clojure apps deployed to Cloud Foundry!

1 *NOTE: At the time of this writing Clojure is unofficially supported at Cloud Foundry. *

Facebook Twitter Linkedin Digg Delicious Reddit Stumbleupon Email

Cloud Foundry Visits India

Cloud Foundry Open Tour developer events are designed to help technologists behind the industry’s leading open Platform as a Service to meet and exchange ideas. Last week, we visited India with a huge success–about 1,100 developers attended a series of Cloud Foundry sessions and a hackathon. Developers learned about the open source Cloud Foundry Platform as a Service and how it supports multiple services, frameworks and IaaS layers.

The Cloud Foundry Open Tour is not only a developer event for professional developers; it also attracts students who ended up building some great apps in the hackathon. There were a few professors from technology schools trying to understand how Cloud Foundry fits into the larger cloud ecosystem. We also saw a healthy media presence and coverage before, during and after the event.

We were really impressed by the dedication the developers showed by arriving at 9:00 a.m. and staying on until 10:00 pm in Bangalore and Pune. The enthusiasm was also evident in the overwhelming number of requests to participate in the morning sessions and evening hackathon, even after the seats had sold out.

The five session speakers, who came from various geographies including the US, Singapore and India, deserve a big thank you. From VMware were Chris Richardson, Josh Long, Raja Rao and Rajdeep Dua. Guest speakers included Hugues Malphettes, Senior Software Architect at Intalio, and industry spokeserson Janakiram MSV.

What We Covered

Morning Sessions
We started the morning sessions with keynote delivered by Niranjan Maka and Chris Richardson. Niranjan covered the VMware product strategy and portfolio, and the concept of the software-defined data center. Chris’s talk focused on the history of Cloud Foundry and various aspects of open source PaaS. This was following by a very well-received Node.js session by Raja Rao. Josh covered the Spring framework and Spring integration with Cloud Foundry.

Chris came back on stage to do his architecture session on decomposing apps for scalability. After lunch, Hugues from Intalio showcased Intalio|Create, which is an innovative way of building business applications. It is built using Cloud Foundry and can be deployed on public as well as private clouds. Rajdeep had a session on the Play Framework and its support in Cloud Foundry. The morning session was wrapped up with Janakiram’s talk on deploying .NET applications on Iron Foundry. Developers responded very favorably to the choice of frameworks available with Cloud Foundry.

We wrapped up the morning session and doing an iPhone 4S raffle for the attendees.

Evening Hackathon
The evening hackathon started with an hour-long boot camp on how to get started with Cloud Foundry using vmc and the Spring Source Tool Suite (STS). This was run in a similar manner in Bangalore and Pune.

Participants pushed over 185 Hello World apps to win t-shirts. This was significant because just a few hours back these same developers were totally new to Cloud Foundry and now they were pushing their applications.

Boot camp was followed by a two-hour hackathon where developers formed teams,  hacked over their ideas and published a total of 19 apps to cloudfoundry.com.

Hackathon Winners

The winner in Bangalore was a group of students from P.E.S. Institute of Technology who built a GRE test helper app. This app sends an SMS to a number for an English word. Then the app talks to a Word Link service and returns English word’s definition.

Winners in Pune built an online exam results portal using Ruby on Rails. Another runner-up built a social sentiment analysis service using Spring MVC, Neo4j and Twitter4J. Another winner built a chat application.

Quotes from Bloggers and Attendees

A developer conference’s pulse can be gauged from what audience has to say or write about it.
Cloudstory.in: “The best thing of the event was the Hackathon that was scheduled in the evening. In both the cities the developers stayed till late evening to deploy live applications on cloudfoundry.com and appfog.com. It was exciting to see hundreds of developers coding away in their favorite language and deploying the application on a platform that they experienced only a few hours ago. That only shows how simple it is to get started on Cloud Foundry.”
One of the developer attendees said: “Just wanted to send a THANK YOU and tell you how much I enjoyed the Cloud Foundry Pune Open Tour 2012. You people did a great job in putting it all together and I especially enjoyed my first ever hackathon. It was indeed great experience.”

Presentation Slides

Slides for the talks can be found at the following links:

The Open Tour Continues

It was a great experience interacting with developers in Pune and Bangalore, helping them learn about Cloud Foundry. Since the Cloud Foundry Open Tour 2012 is a global series of one day developer events, stay tuned for more announcements on new dates and locations.

Rajdeep Dua, the Cloud Foundry Developer Relations Team

Facebook Twitter Linkedin Digg Delicious Reddit Stumbleupon Email

Cloud Foundry Integration for Eclipse Now Supports Standalone Java Applications and Java 7

A new release of Cloud Foundry Integration for Eclipse is available which features the ability to publish standalone Java applications to CloudFoundry.com using either Java 6 or Java 7. Java 7 is also now supported for Grails, Java Web and Spring applications. Standalone applications can only be published to Cloud Foundry instances that support standalone applications such as CloudFoundry.com.

The new integration (version 1.2.0)  allows users to publish standalone Java applications from within Eclipse Indigo JEE or SpringSource Tool Suite (STS) version 2.9.0 or higher.

The previous Cloud Foundry plugin (1.1.0) introduced tunneling support for data services, and further improvements to service tunneling are also available as part of 1.2.0.

Follow the documented instructions to install the Cloud Foundry Integration for Eclipse. If you had previously installed Cloud Foundry plugin 1.0.0 or 1.1.0 in Eclipse or STS, the update will be automatically detected or you can manually check for updates in the IDE. Note that updates for older Cloud Foundry plugins prior to 1.0.0 are not supported. Old versions prior to 1.0.0 must first be uninstalled before installing 1.2.0.

Enabling Standalone Support

Java projects in Eclipse can now be published to CloudFoundry.com by enabling Cloud Foundry standalone support on the Java project, and then dragging and dropping them like any other supported application type (Grails, Spring) into either a Cloud Foundry server instance in the Servers view or into the Applications section in the server editor.

To make your Java project publishable to CloudFoundry.com, simply select it in either the Project or Package Explorer, right-click and choose Configure -> Enable as Cloud Foundry Standalone App.

To remove the configuration, select  Configure -> Disable as Cloud Foundry Standalone App.

A Java standalone application can be published in just a few simple steps:

1. Right-click on the Java project and enable standalone support.

2. Drag and drop the application into either the Servers view or server editor for a CloudFoundry.com server.

3. Complete the Application wizard that opens, much like publishing any other supported application type.

Configuring a Standalone Java Application

Once a standalone Java application is dragged and dropped into either a CloudFoundry.com server instance in the Servers view, or the server’s editor, an Application wizard is opened allowing a user to configure the application details like the application name and runtime type.

Both Java 6 and Java 7 are supported for standalone applications and a user can select either one from the “Runtime” widget shown above.

In many cases, the standalone support will automatically detect a Java type with a main method, and the application can be deployed from the first page of the wizard. If no main method type was detected, or if a user wants to change the automatically resolved type, clicking “Next” will display a page where the Java start command can be set.

Unlike other supported applications like Grails or Spring, URLs are optional for standalone Java applications. However, a start command is required.

A user has the option of specifying the start command in one of two ways:

1. Java: A JVM Java start command with recommended default options set to “$JAVA_OPTS -cp lib/*:.” and a Java type with a main method. The lib folder for the class path option need not exist in the Java project. It is automatically created remotely in the Cloud Foundry server and it is where all jar project dependencies, excluding the JRE dependency, are published.

2. Other: A full user-defined start command, which may include the name of a script file.

For the first option, a user can use the built in Java content assist in the Main Type text widget to select a Java type.

Alternately, the Browse button can be clicked to open a Java type browse dialogue.

If selecting Other, the full start command can be specified, like a script file as seen below.

Once published, the standalone application can be managed from the Cloud Foundry server editor like other application type, including starting, stopping, restarting and update restarting, and removing the application, as well as changing the number of application instances and memory settings. In addition, the published resources can be browsed by clicking on Remote Systems View in the server editor.

Java Application Dependencies

All standalone dependencies, with the exception of the JRE dependency, are automatically resolved and published to a remote “lib” folder relatively to the application folder in the Cloud Foundry server. The lib folder need not exist in the Java application before publishing it.

For example, for a Java Maven project, all Maven dependencies are published to the remote lib directory relative to the application.

The Cloud Foundry standalone support determines what application resources to publish to the cloud server based on the configuration defined in the project’s Java Build Path. Any resources that the application requires, including Java source output or target folders, binaries, and XML and script files, need to be listed in the project’s Java Build Path. The Java Build Path can be accessed by right-clicking on the Java project and selecting Build Path -> Configure Build Path…

In addition, the standalone support automatically skips any test source folders, even when listed in the project’s Java Build Path. Output targets for sources folders containing the pattern “src/test” are skipped.

Java 7 Support for Other Application Types

In addition to supporting Java 7 for standalone applications, Cloud Foundry Integration for Eclipse and STS now supports Java 7 for Grails, Spring, Java Web and Lift for CloudFoundry.com. For other cloud servers, Java 6 is still the default runtime type. Java 7 is only shown if the server supports it.

Cloud Foundry Integration for Eclipse 1.2.0 can be installed or updated from the official update site:

http://dist.springsource.com/release/TOOLS/cloudfoundry/

- The Cloud Foundry Team

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

Facebook Twitter Linkedin Digg Delicious Reddit Stumbleupon Email

How We Built AppFog Using Cloud Foundry

The value proposition of using the cloud is that “things will be easy this way.” Building and operating large scale clouds, however, is rarely easy. As Mark Lucovsky said in his recent interview, “Who said large scale distributed systems are simple?” While solutions like Cloud Foundry make building core cloud technology less daunting, it’s still not easy.

In this guest blog, Lucas Carlson, Founder and CEO of AppFog, illustrates the story of how AppFog was built using Cloud Foundry open PaaS technology and what they learned along the way.

Core Cloud Technology is Hard

Running a simple Cloud Foundry-based service is not very hard. Check out Micro Cloud FoundryTM.

Building one that is suitable for production and enterprise workloads is fairly hard.

Building a Cloud Foundry-based service with one API end-point to run in 6+ different availability zones on 4+ independent infrastructure vendors and that is suitable for production and enterprise workloads, at scale and in general availability? Now that is really hard.

Hitting the Ground Running with Cloud Foundry

As you can imagine, ever since AppFog announced GA, people have been asking how we did it. How did we figure out how to scale up a public cloud offering for Cloud Foundry that delivers one interoperable interface across multiple clouds, multiple availability zones and multiple vendors?

First: The Cloud Foundry codebase is really very good. In choosing to build using Cloud Foundry we eliminated a number of the potential serious challenges and major time sinks likely with this sort of project.

Second: The leverage that we were able to gain from the additional tools, code and services from within the Cloud Foundry ecosystem dramatically accelerated our development.

Third: Having a non-Cloud Foundry-based public PaaS already in GA and already at scale was a massive boost for us. We had the operational experience in-house needed to pull off a great PaaS.

AppFog’s ops experience was invaluable for us. Although PaaS is closely tied to the NoOps movement, NoOps doesn’t mean no ops, it only means no ops for the developer. As anyone who has run Cloud Foundry knows, a lot of ops is necessary and essential to running PaaS.

And most importantly, we had a vibrant community of tens of thousands of developers (the users of PHP Fog) that we could consult to help us define, test, and evolve AppFog through private beta to Public Beta and now to GA.

We Listened and Delivered

It was this community that helped us figure out what AppFog at GA would need to be, how it would need to work, and what our pricing would be. This was what devs asked us for:

  • The ability to easily scale apps across dozens or hundreds of load-balanced instances, even on the free plan
  • Must run apps on the fastest servers available in the infrastructure (yes, we mean, for example, M2.4XL)
  • Must be able to run apps across multiple infrastructures (Rackspace, HP, AWS, Azure–and with no price difference)
  • Must simplify pricing. No more weird packages and bundles and names. Make it simple and affordable and most of all make it fair.
  • True interoperability in the cloud, including single-click, zero-code migrations between cloud vendors, eliminating all traces of vendor lock-in
  • Target of 30-second deployments to AWS, Rackspace, HP, Azure, etc.
  • Support for any and all languages in the Cloud Foundry codebase
  • Support for any and all relational and NoSQL data stores**

This is a daunting list. But it’s what devs wanted.

So let’s get into the nitty gritty… how did we actually do this?

How We Built a PaaS Around Cloud Foundry

This is a complex story. Fortunately, a few months ago, Jeremy Voorhis gave a talk at QCon in London describing how AppFog built a commercial system by using the Cloud Foundry OSS bits alongside our own set of custom extensions and enhancements. This is far and away the best place to start for understanding the Cloud Foundry-to-AppFog evolution. The slides for the talk can be found here and the video here.

We won’t go over everything in Jeremy’s hour-long talk here, but we’d like to cover some of the main points.

First, Jeremy clears up some of the confusion surrounding the signifier “Cloud Foundry.” On one hand, CloudFoundry.com is a hosted PaaS offering from VMware that runs on the vSphere virtualization platform based on the open source project found on CloudFoundry.org. VMware also has open sourced the tooling it uses to manage CloudFoundry.com–Cloud Foundry BOSH–and exposes the exact BOSH releases used live in production on their hosted service.

We do not run on the hosted VMware service but instead we are built from the same open source Cloud Foundry project. This open source distributed system enabling teams to manage and deploy apps and services over their lifecycle in the cloud is the core of the AppFog service.

AppFog is unique within the current Cloud Foundry ecosystem because we have built an infrastructure-agnostic Cloud Foundry service.

The beauty of Cloud Foundry is that it can, in principle, be implemented in conjunction with infrastructure offerings ranging from an OpenStack-based IaaS like Rackspace or HP to AWSJoyentCitrix, and beyond. This inherent multi-cloud portability is why the Cloud Foundry project was so inspiring to us.

For us, the ability to deploy and redeploy across infrastructures within the lifecycle of an application is the key to building a next-generation PaaS. It also, we think, fulfills the underlying mission of PaaS to: (a) sharpen product team focus in development; (b) produce a shorter feedback loop within app lifecycles, and; (c) provide the possibility of near-instant horizontal scalability.

Cloud Foundry’s Role in the Evolution of Cloud Computing

Even for those who are familiar with the space of cloud computing in general, it’s important to review historical context. For us at AppFog, Cloud Foundry has provided some of the crucial building blocks to assembling the first next-generation PaaS. But what do we mean by that?

First, it’s important to get some background. PaaS in its initial forms was enabled by a number of historical breakthroughs such as:

  • The rise of data centers via companies like Rackspace in the 1990s
  • The emergence of server virtualization via VMware in the early ‘00s
  • The introduction of APIs to virtualized resources via AWS in the mid ‘00s
  • The more recent rise of the DevOps paradigm with their associated and derived tools like Puppet and Chef.

But this trajectory really began coming to fruition in just the past two years. Tools like Cloud Foundry and OpenStack have emerged that enable full application lifecycle management. What this means is that the “platform” in “platform as a service” can now encompass all aspects of the application lifecycle outside of development. Jeremy refers to this as “NoOps” in the talk. What it means is emphatically not that no one does Ops work anymore. Instead, it means that responsibility for Ops work is passed on to the platform layer and remains there for most if not all of the app’s lifecycle.

Without a comprehensive tool like Cloud Foundry, we never would have been able to overcome the gap between (a) first-generation PaaS platforms, which we were essentially little more than gateways for (unwieldy) infrastructure management, and (b) next-generation PaaS like AppFog, which provide a far more comprehensive set of user benefits.

AppFog’s Modifications of Cloud Foundry

AppFog began as an effort to bring a great user interface and multi-cloud experience to the hosted Cloud Foundry ecosystem. We saw a number of stumbling blocks standing between the Cloud Foundry codebase and a full-fledged PaaS offering. The current Cloudfoundry.org project has CLI and various IDE integrations, but our vision included the full user experience, including fast sign-up, a web console, pre-built example applications that became what we call Jumpstarts, add-ons, and more.

While some Cloud Foundry users are indeed quite comfortable operating the system from the command line, Eclipse or the Spring Tool Suite (just as many AppFog users do), we also wanted to provide users with an elegant and intuitive console from which they could manage all of their apps. An example of the AppFog console is below:

The creators of the system wanted Cloud Foundry to remain agnostic toward the UX side of things and didn’t want to make its UX implementation overly opinionated. We know that simplicity and intuitiveness are not ends in themselves, and that it’s all too easy to produce an elegant UX on top of a subpar underlying system. But there’s also a lot to be said for seeking to accommodate the needs of as many end users as possible and we believe that we’ve done that. Here are some of the many innovations that we introduced on top of and below Cloud Foundry:
  • Varnish-based caching tier used to achieve significant speed gains
  • Single-click clone from one CF-based infrastructure to another for true workload portability
  • A Cloud Foundry API compatibility layer to auto-route requests to completely autonomous CF instances running in totally different parts of the planet
  • Deep cross-datacenter nagios integration so we know about problems before they affect you

In addition, Cloud Foundry enabled AppFog to create a deeply holistic, self-communicating architecture. It has also enabled us to design AppFog as a system that

assumes that failure happens and provides a set of protocols for handling failure, be it at the infrastructure level or elsewhere.

Carrying Cloud Foundry Forward

Building a full-fledged, commercial grade PaaS that spans multiple clouds, across multiple clouds, connecting it all together with a state of the art end-user experience is an immense undertaking even when starting with the base CloudFoundry.org system. It takes a dedicated team with a great deal of developer empathy, a team willing to step into the customers shoes and think like they think. But we think that the result has been more than worth the effort. We were very fortunate to have a core system like Cloud Foundry available to us. We’ve given back in many ways, including adding initial

PHP runtime support to the project, and continue to give back as we optimize Cloud Foundry to run well in public clouds. We are incredibly excited about AppFog going GA. We are even more excited about the thousands and thousands of developers who have already signed up and deployed thousands and thousands of apps. We believe that the success of AppFog demonstrates not just the power of PaaS, but also the strength of the Cloud Foundry codebase and the power of its open source ecosystem and community. This is a win not just for AppFog, but for everyone invested in the success of Cloud Foundry.

About the Author: Lucas Carlson is an entrepreneur and professional programmer who specializes in the development of web applications at scale. Lucas is the Founder and CEO at the leading cross-cloud PaaS company AppFog. He has authored over a dozen Ruby libraries and contributed to a range of significant Rails products including Rails and RedCloth. Lucas founded, ran and judged the popular Ruby on Rails contest Rails Day and has been a well-received speaker at many major programming conferences. Lucas was the first engineer at MOG and was responsible for development and technical direction for that seminal music streaming service. Lucas lives in Portland, Oregon, and loves statistics and Go.

Facebook Twitter Linkedin Digg Delicious Reddit Stumbleupon Email

Build a Real Time Activity Stream on Cloud Foundry with Node.js, Redis and MongoDB 2.0 – Part III

In Part II of this series, we covered the architecture needed for persisting the Activity Streams to MongoDB and fanning it out in real-time to all the clients using Redis PubSub.

Since then, some exciting new Node.js features for Cloud Foundry were launched. In addition, the MongoDB version on Cloud Foundry has been upgraded to 2.0.

In this blog post we will cover how to:

  • Use Mongoose-Auth to store basic user information, including information from Facebook, Twitter, and Github, and how we made this module with native dependencies work on Cloud Foundry
  • Use Mongo GridFS and ImageMagick to store user uploaded photos and profile pictures
  • Perform powerful stream filtering, thanks to new capabilities exposed in MongoDB 2.0
  • Update the UX of the app to become a real-time stream client using Bootstrap, Backbone.js and Jade.

Offering SSO and Persisting Users

The requirement for this boilerplate Activity Streams App was to allow users to log in with Facebook, Twitter, or Github, and to persist this user data in the database.

I am sure many of you are familiar with how to store user information in a database and perhaps even in MongoDB. What some of you may not have tried is storing third party user information like the one we obtain when users log in with Facebook, Twitter or Github. In a relational database, you would probably store this information across multiple records in multiple tables (e.g., users, services, accounts, or auth). However, with MongoDB you can use embedded documents and store all this information in a single document, thus reducing the complexity of the operation. I found that this was very easy to do using @bnoguchi’s mongoose-auth which decorates the Mongoose User Schema with the third party services fields.

My previous version of the app was using another popular module from Brian called everyauth which handled SSO very well, but it did not persist the user info. It was fairly straightforward to upgrade from everyauth to mongoose-auth.

First, I updated a helper module I created called activity-streams-mongoose to offer a User Schema and made it possible to extend all schemas. Then I loaded mongoose-auth and decorated that schema with the specifics needed. You can see the exact code changes in this diff. The key part in the upgrade was to normalize the user data as it was saved. I did this by leveraging the pre-save callback MongooseJS offers.

Here is a snippet of the code:

var streamLib = require('activity-streams-mongoose')({
  mongoUrl: app.siteConf.mongoUrl,
  redis: app.siteConf.redisOptions,
  defaultActor: defaultAvatar
});

var authentication = new require('./authentication.js')(streamLib, app.siteConf);

// Moved normalization to only be done on pre save
streamLib.types.UserSchema.pre('save', function (next) {
  var user = this;
  var svcUrl = null;
  if (user.fb && user.fb.id) {
    user.displayName = "FB: " + user.fb.name.full;
    asmsDB.ActivityObject.findOne().where('url', facebookHash.url).exec(function(err, doc){
      if (err) throw err;
      user.author = doc._id;
      // Need to fetch the users image...
      https.get({
        'host': 'graph.facebook.com'
        , 'path': '/me/picture?access_token='+ user.fb.accessToken
      }, function(response) {
        user.image = {url: response.headers.location};
        next();
      }).on('error', function(e) {
        next();
      });
    })
  } else  {
    if (user.github && user.github.id) {
      user.displayName = "GitHub: " + user.github.name;
      var avatar = 'http://1.gravatar.com/avatar/'+ user.github.gravatarId + '?s=48'
      user.image = {url: avatar};
      svcUrl = githubHash.url;
    } else if (user.twit && user.twit.id) {
      user.displayName = "Twitter: " + user.twit.name;
      user.image = {url: user.twit.profileImageUrl};
      svcUrl = twitterHash.url;
    }

    if(!user.actor) {
      asmsDB.ActivityObject.findOne().where('url', svcUrl).exec(function(err, doc){
        user.author = doc;
        next();
      });
    } else {
      next();
    }
  }
  });

var asmsDB = new streamLib.DB(streamLib.db, streamLib.types);
streamLib.asmsDB = asmsDB;

MongoDB 2.0 and Cloud Foundry

For those of you not familiar with MongoDB 2.0, one neat feature is that it supports Multi-location Documents. I was also able to add a location property to the core Activity Object in the activity-streams-mongoose module which can be used with the Activities, Activity Objects and User collections to allow performing Geo Queries.

var LocationHash = {
  displayName: {type: String},
  position: {
    latitude: Number,
    longitude: Number
  }
};

var ActivityObjectHash = {
  id: {type: String},
  image: {type: MediaLinkHash, default: null},
  icon: {type: MediaLinkHash, default: null},
  displayName: {type: String},
  summary: {type: String},
  content: {type: String},
  url: {type:String},
  published: {type: Date, default: null},
  objectType: {type: String},
  updated: {type: Date, default: null},
  location: LocationHash,
  fullImage : {type: MediaLinkHash, default: null},
  thumbnail : {type: MediaLinkHash, default: null},
  author : {type: ObjectId, ref: "activityObject"},
  attachments : [{type: ObjectId, ref: 'activityObject'}],
  upstreamDuplicates : [{type: String, default: null}],
  downstreamDuplicates : [{type: String, default: null}]
};

Another interesting geo feature in MongoDB 2.0 is polygonal search. This means that you can search whether a given object is in a specified area by providing the area points. For example, this can be helpful when you want to see if certain objects, like houses, are in a certain zip code.

Working with Node.js Modules with Native Dependencies

Mongoose-Auth requires a module bcrypt which has a native dependency (it gets compiled locally when you do a Node Package Manager (npm) install and the binary placed in the mode_modules directory). If you are working from a Mac or Windows and deploying to the cloud you can run into issues by including your node_modules folder. Luckily, now there is support in Cloud Foundry for excluding the node_modules folder and having Cloud Foundry fetch and build the npm modules server-side.

$ npm shrinkwrap
$ echo "{ignoreNodeModules: true}" > cloudfoundry.json
$ vmc update

For more info you can read this blog post from Maria and/or watch this helpful video from Raja.

My recommendation is that when you start a new Node.js App make sure to add the cloudfoundry.json file with skip node_modules folder set to true so all the native dependencies are built directly on Cloud Foundry. Also don’t forget to run npm shrinkwrap if you change package.json.

User Uploaded Photos with ImageMagick and Mongo GridFS

One of the most engaging objects to show in a web app like this
Activity Stream boilerplate app are photos. Apps like Instagram and Pinterest have taken photo sharing to a whole new level and have completely redesigned the UX of photo feeds. We wanted to help developers build Activity Stream apps with rich photo sharing and thus needed a library to help us manipulate images and a place to store all these images. Since we were already using MongoDB, I decided to leverage Mongo GridFS to store the images.

I had previously worked storing photos in GridFS but it was from Ruby. It was a little bit more challenging to find the right tools in Node.js. I found a lot of npm modules which seemed to handle it for me, but found that they were either unfinished or loaded several additional components which were incompatible. I really wanted to keep it simple so I ended up following the documentation on the official Node.js Mongo DB driver and creating a few routes to handle creating photos and viewing photos.

Here is how I ingested the photos into Mongo GridFS:

var im = require('imagemagick');
var Guid = require('guid');
var siteConf = require('./lib/getConfig');
var lib = new require('./lib/asms-client.js')(app, cf).streamLib;

function ingestPhoto(req, res, next){
  if (req.files.image) {
    im.identify(req.files.image.path, function(err, features){
      if (features && features.width) {
        var guid = Guid.create();
        // Concatenating name to guid guarantees that we always have
        // unique file names
        var fileId = guid + '/' + req.files.image.name;
        // The GridStore class is the equivalent of a File class but has the
        // added benefit of allowing you to store metadata
        var gs = lib.GridStore(lib.realMongoDB, fileId, "w", {
          content_type : req.files.image.type,
          // metadata is optional
          metadata : {
            author: req.session.user._id,
            public : false,
            filename: req.files.image.name,
            path: req.files.image.path,
            width: features.width,
            height: features.height,
            format: features.format,
            size_kb: req.files.image.size / 1024 | 0
          }
        });
         // This command copies the file from the file system(temp dir)
         // to GridFS.
         // GridFS supports any file size by breaking it into chunks
         // behind the scenes
        gs.writeFile(req.files.image.path, function(err, doc){
          if (err) {
            next(err);
          } else {
            if (! req.photosUploaded) {
              req.photosUploaded = {};
            }
            // I have another express route to serve the photos by fileId
            var url = siteConf.uri + "/photos/" + fileId;
            // Add the results of the upload to the chain
            req.photosUploaded['original'] = {url : url, metadata: gs.metadata};
            req.nextSizeIndex = 0;
            next();
          }
        });
      } else {
        if (err) throw err;
        throw(new Error("Cannot get width for photo"));
      }
    });
  } else {
    next(new Error("Could not find the file"));
  }
};

The above snippet shows how I used ImageMagick to get the photo dimensions. ImageMagick is an amazing open source software suite for manipulating images and there is an easy to use ImageMagick node module to expose its functionality.

An open source project backed by years of continual development, ImageMagick supports about 100 image formats and can perform impressive operations such as creating images from scratch; changing colors; stretching, rotating, and overlaying images; and overlaying text on images.

ImageMagick.org

And this snippet shows how to produce a new image of smaller size:

var im = require('imagemagick');
var Guid = require('guid');

function reducePhoto(req, res, next){
    var photoIngested = req.photosUploaded['original'];
    if (photoIngested) {
        var sizeName = sizes[req.nextSizeIndex].name;
        var destPath = photoIngested.metadata.path + '-' + sizeName ;
        var nameParts = photoIngested.metadata.filename.split('.');
        var newName = nameParts[0] + '-' + sizeName + '.' + nameParts[1];
        var width = sizes[req.nextSizeIndex].width;

        im.resize({
          srcPath: photoIngested.metadata.path,
          dstPath: destPath,
          width:   width
        }, function(err, stdout, stderr){
          if (err) {
              next(err);
          } else {
            console.log("The photo was resized to " + width + "px wide");
            var guid = Guid.create();
            var fileId = guid + '/' + newName;
            var ratio = photoIngested.metadata.width / width;
            var height = photoIngested.metadata.height / ratio;
            var gs = asmsClient.streamLib.GridStore(asmsClient.streamLib.realMongoDB, fileId, "w", {
                  content_type : req.files.image.type,
                  metadata : {
                      author: req.session.user._id,
                      public : false,
                      filename: newName,
                      width: width,
                      height: height,
                      path: destPath
                  }
              });
              gs.writeFile(destPath, function(err, doc){
                  if (err) {
                    next(err);
                  } else {
                      var url = siteConf.uri + "/photos/" + fileId;
                      req.photosUploaded[sizeName] = {url : url, metadata: gs.metadata};
                      req.nextSizeIndex = req.nextSizeIndex + 1;
                      next();
                  }
              });
          }
        });
    }
};

The only gotcha on Cloud Foundry was that it did not set for us the environment variable TMP which is used by the formidable module to offer a temp directory where the files are first uploaded. Once I set it using env-add the problem was solved.

bash-3.2$ vmc files asms app/tmp

   36272c476f10ecbf0e3a99481a8d365b         50.6K

All apps on Cloud Foundry have permissions to write files to its own directory or a subdirectory. Set the environment variable TMP to a subdir if you are working with express/formidable to have it handle form uploads.

More Powerful Queries with MongoDB
Part of the beauty of the ActivityStrea.ms format is that it provides a lot of metadata about each activity which can then be searched, aggregated and pivoted to draw interesting conclusions about certain topics and trends.

Examples of these fields are: Hashtags or Topics, Verb, Object Types, Actor Types and Location.

The first step to allowing users to analyze the stream data is providing them with a map of their universe. This means allowing them to see all the possible values for each field. For example, if we are talking about hashtags, then we would show our users that the population has used so far ten hashtags. We would then reveal the distribution in usage across everyone. Then we would provide our users with the ability to drill in by segmenting via actor type or location, for example. This could yield interesting results showing where certain topics are most popular.

var getDistinct = function (req, res, next, term, init){
  var key = 'used.' + term;
  req[key] = init ? init : [];
  var query = {streams: req.session.desiredStream};
  asmsDB.Activity.distinct(term, query, function(err, docs) {
    if (!err && docs) {
      _.each(docs, function(result){
        req[key].push(result);
      });
      next();
    } else {
      next(new Error('Failed to fetch distinct ' + term));
    }
  });
}

//..

function getDistinctVerbs(req, res, next){
  getDistinct(req, res, next, 'verb');
};

function getDistinctActors(req, res, next){
  getDistinct(req, res, next, 'actor');
};

function getDistinctObjects(req, res, next){
  getDistinct(req, res, next, 'object', ['none']);
};

function getDistinctObjectTypes(req, res, next){
  getDistinct(req, res, next, 'object.object.type', ['none']);
};

function getDistinctActorObjectTypes(req, res, next){
  getDistinct(req, res, next, 'actor.object.type', ['none']);
};

//...

app.get('/streams/:streamName', loadUser, getDistinctStreams, getDistinctVerbs, getDistinctObjects, getDistinctActors,
  getDistinctObjectTypes, getDistinctActorObjectTypes, getDistinctVerbs, getMetaData, function(req, res) {

    asmsClient.asmsDB.Activity.getStream(req.params.streamName, 20, function (err, docs) {
    var activities = [];
    if (!err && docs) {
      activities = docs;
    }
    req.streams[req.params.streamName].items = activities;
    var data = {
      currentUser: req.user,
      streams : req.streams,
      desiredStream : req.session.desiredStream,
      actorTypes: req.actorTypes,
      objectTypes : req.objectTypes,
      verbs: req.verbs,
      usedVerbs: req['used.verb'],
      usedObjects: req['used.object'],
      usedObjectTypes: req['used.object.type'],
      usedActorObjectTypes: req['used.actor.object.type'],
      usedActors: req['used.actor']
    };
    if (req.is('json')) {
      res.json(data);

    } else {
       res.render('index', data);
    }
  });

});

A Robust Activity Stream UX

The initial node-express-boilerplate app had some basic jQuery used to show plain text messages and users’ photos. In the new app, we have much richer messages and the ability to post and filter them. For this reason, we decided to use some of the great client-side open source tools available today.

After some consideration, we ended up using these three tools:

  1. Backbone.js: A lightweight client-side MVC framework
  2. Bootstrap: A set of CSS, HTML and Javascript components which help developers produce great looking apps, without needing to start from scratch
  3. Jade: A templating language with the help of ClientJade

Templating, Markup and CSS

If you are a web developer, you probably know that there are many choices in tools to render HTML dynamically. A good number of web developers prefer to use templating engines to render HTML because these help you produce more readable code. Using declarative programming, you can interpolate variables and directives in the HTML. The most popular templating engine for Node.js is Embedded JavaScript (EJS), which resembles ERB in Ruby. This is what the node-express-boilerplate project included. When I started working with Node.js, I found many more choices that were not present in the Ruby world such as: Mustache, Handlebars, Dust and Jade. In fact, LinkedIn wrote an excellent blog post discussing the many alternative choices for templating engines.

I ended up selecting Jade because I already liked HAML, which is very similar to Jade in its terseness. Both templating languages use indentation to understand the hierarchy of elements. Jade is even terser than HAML because it removes the need to put % in front of the HTML tags.

Another cool thing about Jade is that it already had support for server-side and client-side rendering via ClientJade. Here is how I broke out the views allowing easy extension of the object types.

I then compiled the Jade views into js for faster client-side rendering with ClientJade.

clientjade views/*.* > public/js/templates.js

Once this was done, I simply included templates.js in the list of files to be minified and used it like this from Backbone:

var ActivityCreateView = Backbone.View.extend({
    el: '#new_activity',
    initialize: function(){
        _.bindAll(this, 'newAct', 'render', 'changeType', 'includeLocation', 'sendMessage');

        this.trimForServer = App.helper.trimForServer;

        var streamName = this.$el.find('#streamName').val();
        var verb = this.trimForServer(this.$el.find('#verb-show'));
        var objectType = this.trimForServer(this.$el.find('#object-show'));

        this.newAct(streamName, verb, objectType);
        this.render();
    },
    events: {
        "click .type-select" : "changeType",
        "click #includeLocation" : "includeLocation",
        "click #send-message" : "sendMessage"
    },
    newAct : function(streamName, verb, objectType) {
        this.streamName = streamName;
        this.model = new Activity({
            object: {content: '', objectType: objectType, title: '', url: ''},
            verb: verb,
            streams: [streamName]
        });
    },
    render: function(){
      var actData = this.model.toJSON();
      this.$el.find("#specific-activity-input").html(jade.templates[actData.object.objectType]());

      return this; // for chainable calls, like .render().el
    },
    changeType : function(event) {
        console.log(event);
        var itemName = $(event.target).data("type-show");
        if (itemName) {
            $("#" + itemName)[0].innerHTML = event.target.text + "  ";
            var val = this.trimForServer(event.target.text);
            if (itemName == "verb-show") {
                this.model.set('verb', val);
            } else {
                var obj = this.model.get('object');
                obj.objectType = val;
                this.model.set('object', obj);
            }
        }
        this.render();
    },
    includeLocation : function(event) {
        if (navigator.geolocation) {
            navigator.geolocation.getCurrentPosition(App.helper.getLocation);
        } else {
            alert("Geo Location is not supported on your device");
        }
    },
    sendMessage : function() {
        console.log("In send message");

        var obj = this.model.get('object');
        obj.content = $("#msg").val();
        obj.url = $('#url').val();
        obj.title = $('#title').val();
        obj.objectType = this.trimForServer($('#object-show'));
        this.model.set('object', obj);

        var streamName = $('#streamName').val();
        this.model.set('streams', [streamName]);

        var verb = this.trimForServer($('#verb-show'));
        this.model.set('verb', verb);

        if (this.model.isValid()) {
            if (this.model.save()) {
                this.newAct(streamName, verb, obj.objectType);
                this.render();
            }
        }

    }

});

The original node-express-boilerplate app was using 960gs and jQuery. However, this activity streams boilerplate app is a bit more complex so I switched to using Twitter’s Bootstrap as the first step. This provided me a nice way to the nav bar, hero unit, modals, drop downs and so on. Also it was easy enough to go from using one grid system to another. For the moment the app is using the default grid system but it can easily be made to use Bootstrap’s Fluid Layout and Responsive Design enhancements.

Manipulating Data on the Client with Backbone.js

Instead of having a large number of individual jQuery handlers on HTML elements, Backbone.js helps you break your UX apart into components called Views which are more similar to Controllers when thinking of server-side MVC frameworks. These Backbone views can take Backbone models and templates and render them, as well as listen for events on the elements that comprise the view. You can see in the snippet above we have a Backbone view that works with a Backbone model for an Activity.
Backbone Models are pretty simple classes you create by detailing all the properties for the model and validation rules. Here is the code for the Activity Backbone Model which is also used to create the ActivityStreamView:

var Activity = Backbone.Model.extend({
    url : "/activities",
    // From activity-streams-mongoose/lib/activityMongoose.js
    defaults: {
        verb: 'post',
        object: null, //ActivityObject
        actor: null, //ActivityObject
        url: '',
        title: '',
        content: '',
        icon: null, // MediaLinkHash
        target: null, //ActivityObject
        published: Date.now,
        updated: Date.now,
        inReplyTo: null, //Activity
        provider: null, //ActivityObject
        generator: null, //ActivityObject
        streams: ['firehose'],
        likes: {},
        likes_count: 0,
        comments: [],
        comments_count: 0,
        userFriendlyDate: 'No idea when'
    },
    validate: function(attrs) {

    if (! attrs.object) {
        return "Object is missing"
    }
    if (!attrs.object.title) {
      return "Title is missing";
    }
  }
});

You can then easily instantiate passing a javascript bare object. In the example below, I took the output from socket.io when a message comes in, converted it to an object and added it to the Backbone collection associated with the Stream View:

var streamView = new ActivityStreamView();
App.socketIoClient.on('message', function(json) {
  var doc = JSON.parse(json);
    if (doc) {
      streamView.collection.add(new Activity(doc));
    }
});

Working with Backbone.js was very fun but it definitely takes some time to convert all your logic to using Backbone Views and Models. In this example, I only used Backbone.js for a subset of the app. Having Jade as my templating language and Node.js allowed me to share code between server and client. If you have a trivial application, you may not need to use Backbone.js and may be able to keep it simple with express and server side templates. In the case of this Activity Streams application, which syndicates in real time and offers the ability to react to any new item, it made sense to use Backbone.js. It also allowed me to provide the hooks for the next iteration of this app. After all, this is a boilerplate app.

Remember that it is very easy to push updates to your application on Cloud Foundry as you make progress doing:

bash-3.2$ vmc update

Updating application 'asms'...
Uploading Application:
  Checking for available resources: OK
  Processing resources: OK
  Packing application: OK
  Uploading (380K): OK   
Push Status: OK
Stopping Application 'asms': OK
Staging Application 'asms': OK                                                  
Starting Application 'asms': OK

Conclusion

As a contributor to the ActivityStrea.ms specification, I find it necessary (and fun) to get my hands dirty building the apps which use open standards to see where there are limitations and what technologies can make it easier. Working with MongoDB proved to be the right choice, giving me the ability to do complex queries, aggregation and full modeling of my objects which are needed for quickly painting the stream. I am really happy that MongoDB 2.0 is now running on Cloud Foundry because a lot of the Object Document Mappers like Mongoid in Ruby only support 2.x. This is a very exciting time to be a developer, as things are moving very fast and there is ample opportunity to make a difference via open source.

Here is the final architecture of the app at a very high-level:

Activity Streams Boilerplate App Architecture

To try this application, you can visit it here. To get the full code, you can clone or fork it here.

–Monica Wilkinson

Facebook Twitter Linkedin Digg Delicious Reddit Stumbleupon Email

Deploying to AWS Using Cloud Foundry BOSH

Cloud Foundry was designed and built to support distributed applications that can be moved between multiple clouds, including those running on different IaaS infrastructures such as vSphere, vCloud, OpenStack and Amazon Web Services. The key to supporting multiple clouds is BOSH, a cloud deployment and lifecycle management tool that was announced earlier this year.

This blog post will walk you through the steps to start using BOSH on AWS and then show you how to deploy a sample three-tier application. Continue reading

Facebook Twitter Linkedin Digg Delicious Reddit Stumbleupon Email