Experimental Clojure Support in Cloud Foundry

September 25, 2012 Alvaro Videla

featured-cf-genericWe 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. *

About the Author

Biography

Previous
Eric Fischer's Work Blurs the Line Between Data Science, Cartography, and Art
Eric Fischer's Work Blurs the Line Between Data Science, Cartography, and Art

During a talk earlier this year at the Big Data for the Public Good seminar series, Stamen's Eric Rodenbeck...

Next
Passbook for iOS 6
Passbook for iOS 6

Passbook is an exciting new feature coming to iOS 6 which has endless possibilities. Creating a basic pass ...

×

Subscribe to our Newsletter

!
Thank you!
Error - something went wrong!