Cloud Foundry Blog

Cloud Foundry Java App Errors – Root Cause Analysis

On the night of March 29, 2012, we upgraded our Tomcat from version 6 to version 7 as part of our normal production upgrade schedule.

Early in the morning of March 30th, we discovered that Java apps that were created or re-pushed were receiving an error.

At 9am PT that morning we identified the specific issue causing the error.  The script catalina.sh was modified in Tomcat 7 to start Tomcat using eval exec instead of exec.  We were setting the CATALINA_OPTS environment variable to include values for -Dhttp.nonProxyHosts that contained a pipe character, which was interpreted by eval as Unix pipe. This affected the application start command, leading to a failure to start the application.  This change did not affect our QA environment, as there was no proxy configured (or required), and thus the problem escaped our testing.  Once we understood the issue, our first priority was to minimize the impact on our users.  The best course of action was deemed to be reverting back to the last known good version (Tomcat 6).

The version rollback and validations completed at 1:20pm PT.

This problem impacted about 60 people who were performing pushes or creating apps during the time Tomcat 7 was in place.

We are learning from our mistake.  We will start by adding tests based on this incident, and will continue investigating other mechanisms to prevent similar issues from occurring in the future.

We would like to apologize to all of you who suffered from this problem.

- Ramnivas Laddad
Cloud Foundry Frameworks Engineering

Facebook Twitter Linkedin Digg Delicious Reddit Stumbleupon Email

Cloud Foundry Further Improves Support for Ruby Applications

We have recently made many improvements to Cloud Foundry to increase Ruby developer productivity and expand support for Ruby application frameworks.  Cloud Foundry was built to run multiple languages and frameworks, and we have had support for Ruby from day one.

It is well known that VMware developers are the stewards of the incredibly popular Java Spring framework.  Therefore, Cloud Foundry’s support for running Java applications in a platform as a service environment has always been excellent.  However, many CloudFoundry.com users may not realize that most of Cloud Foundry’s system components are built using the Ruby programming language, and providing great support for Ruby applications is also very important to us.

In the past few months, we have been quietly adding features and improving support for running Ruby, Rails, Sinatra, Rack, and even JRuby applications on CloudFoundry.com.  Jennifer Hickey, a developer on the Cloud Foundry team, recently hosted a webinar on deploying Ruby applications to Cloud Foundry and covered the following topics:

  • Rails 3.1 and 3.2 applications are now well-supported on CloudFoundry.com.  The development team resolved a number of issues that had previously required workarounds.
  • JRuby applications can run on CloudFoundry.com with some simple tweaks.  Look for a blog post soon that will document the steps to deploy a JRuby application to Cloud Foundry.
  • Auto-reconfiguration for Ruby are now supported for Rails and Sinatra applications using Cloud Foundry services.  The auto-reconfiguration capability will automatically locate the initialization for Postgres, MySQL, Redis, Mongo, or RabbitMQ anywhere in your code and dynamically update them to the service(s) bound to your application.  This allows you to simply deploy your Ruby applications to CloudFoundry.com without changing any code or configuration.  We have fully detailed this feature and its technical details in a blog post: Part 1 – Auto-reconfiguration.  We also give to the option of having more control and explicitly configure your application to run on Cloud Foundry. This is documented in another blog post: Part 2 – Run-time Support for Ruby Applications.
  • Rails console, a popular tool for Rails developers to interact with their Rails application, is now available through the VMC command line client.  A blog post, Cloud Foundry Now Supports the Rails Console, was published to explain how to use this feature to connect to Rails applications.  Using the Rails console, you can easily view and modify your data, inspect state, or interact with application methods.  You can even run Rake tasks inside the Rails console to perform administrative tasks on your applications.
  • Rack applications, a modular Ruby web server interface, are now supported.  Cloud Foundry’s VMC will automatically recognize a config.ru Rackup file and use it to run your web application.  The auto-reconfiguration feature is also supported for rack applications.

If you develop Ruby applications, you will want to view Jennifer’s webinar recording and see how fast and easy it is to deploy Ruby applications on CloudFoundry.com.

We strive to provide the best PaaS support for running Ruby applications.  If you have any feedback for us on how to improve Cloud Foundry’s Ruby support, we welcome you to drop us a note at our support site.

-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

How OpenCredo Launched Three New Products in Seven Months with Cloud Foundry

From the beginning, Cloud Foundry has been about simplifying the development, deployment and operation of cloud applications.  In this second post in a series of guest blogs by application developers, we bring the story of OpenCredo and how Cloud Foundry helped to launch three new products for a major insurance company in just seven months instead of what would typically take years.

Guest blog by Russell Miles, CEO of OpenCredo

OpenCredo is a software professional services company that provides technology training and software delivery for clients who are typically facing interesting IT challenges in launching new products and testing new markets. We employ lean and agile methods to focus on building rapid business value. Based in London, OpenCredo’s clients include many blue-chip organizations across Europe and North America.

In July 2011, we came upon the opportunity to build products for one of the largest independent insurance underwriters in London. The company is introducing new insurance products into specific vertical markets, and trying new distribution techniques as older products are increasingly becoming commoditized and commissions eaten up by intermediaries.

We were confident in our capabilities and choices of technology for the project – Scala, Lift and Cloud Foundry. By industry standards, such products typically take up to 2 years to build, but we set out to deliver 2 products with the goal of being in the market in just 2-3 months and a third product to follow soon after that.

Frequent changes from the client were expected (e.g. compliance needs, policy updates etc.) and going at the pace of a weekly release would simply not have worked for the proposed time frame. Also adding to the unknowns was that the product would be marketed and distributed by one of the world’s largest online retailers – this meant it has to quickly scale to handle unpredictable spikes in traffic.

We had 3-6+ people working in parallel on these products. Scala was chosen for its sophisticated type system needed by the complex data model in the quoting engine and for its ability to work well with both SQL and NOSQL databases. Lift provided a good database integration layer. At first Cloud Foundry was not in our design plans, but a few things changed that:

  • Lift support was announced
  • We were able to code to a cloud deployed on our local machine (Micro Cloud Foundry) and thus reduce surprises when deploying to the staging instance
  • There was no need to deal with several differently configured SQL services. We just took the application and ran it on Cloud Foundry and we were done from persistence layer to the web layer
  • Cloud Foundry lowered the barrier to polyglot programming. When extending product functionality, we are now experimenting with Node.js and Redis in prototypes. Rather than installing and extending a new environment, Cloud Foundry is practical in that it offers everything in one environment. Cloud Foundry brought together multiple technologies so that the right tool for the job could be chosen.
  • Lastly, one of the nicest things about Cloud Foundry was that “it got perfectly out of the way”. Prior to using Cloud Foundry, it had been very difficult getting feedback from the client who is located in a different city. So, OpenCredo had to provision our own server, work with our system administrator to open it to the client, and then regularly deploy the app onto the server. This included provisioning our own databases etc. All of this took up significant cycles of time. By using Cloud Foundry, the effort reduced to zero to get the feedback from the client.
High Level Architecture Diagram

High Level Architecture Diagram

Performance is currently being tested, but the product was architected in anticipation of high volumes of traffic and, while scaling is not automatic, Cloud Foundry can easily be made to scale quickly to offer more instances without any downtime.

Our process was also a key enabler for our rapid development and deployment goals. We have 3 instances of Cloud Foundry running– one for staging where the applications are deployed first, and one production instance for each application. Each instance just differs on scale. Firstly, the product owner provided us with requirements and we implemented and commited the code to Github after testing the code against Micro Cloud Foundry. Jenkins, which is being used for continuous integration, regularly polls for changes in the code. The project is set up to build, and then automatically release from the CI server and then, upon testing success, automatically manage the push to the staging environment. Upon feature validation from the client, a click of a button runs a further script which pushes the binaries to the production environment. This is a streamlined and almost fully automated process in keeping with our company’s lean and agile philosophies of maximizing value and eliminating errors and waste.

High Level Development and Deployment Process

High Level Development and Deployment Process

It turned out that with the streamlined and automated deployment process, and because of the way Scala, Lift and Cloud Foundry work together, the client’s product could be updated in a tenth of the time it normally took going from a few hours to a few minutes per iteration. With this winning combination of technology and process, the client was able to get to market much sooner with their products.

The most recent product launched for the insurer was Web Trader which is their third product in seven months using Scala Lift and Cloud Foundry. This is a new insurance product specifically designed for the SME with a heavy web presence, clearly an appropriate use for a technology such as this with a company such as ours.

I would like to say, “Happy ending”, but really what we have is a happy beginning for three new products with more to come.

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

Facebook Twitter Linkedin Digg Delicious Reddit Stumbleupon Email

Rethink Application Logging with RabbitMQ

Application logging is essential to monitoring applications and diagnosing problems, but in a cloud universe where file systems may be ephemeral and application instances are provisioned dynamically keeping track of your application logs can be a challenge. Fortunately with Cloud Foundry you can get fast, multi-instance, cloud-proof application logging in just a few steps with RabbitMQ

In this blog post I’ll show you how to configure a Spring application so that it logs messages via AMQP. But first, what are the benefits? The primary motivations are that it’s fast and it doesn’t rely on the local file system of your application (which can disappear in a cloud environment). It’s also very easy to set up multiple applications to log to the same message broker, allowing you to aggregate log messages. Finally, you have the power to route and process those messages, for example allowing you to index them for search and store them in a blob store.

So how do you go about logging messages via the broker? If you’re happy to use Spring, you’re already ahead of the game. One of the best kept secrets of the Spring AMQP project is an AMQP Log4j appender that allows you log messages to any AMQP broker. All you have to do is configure it.

Application changes

As an example, I’m going to use the Spring travel application. The same principles apply to any Java, servlet-based web application.

In order to send log messages to a non-standard location, you have to attach the appropriate appender to a logger. Typically, you attach it to the root logger. The easiest way to do this is to add the appender to your Log4j configuration file, be it a properties file or XML. The Spring travel application uses XML configuration, so adding the AMQP appender is a simple case of inserting the appender definition into log4j.xml:

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE log4j:configuration PUBLIC "-//APACHE//DTD LOG4J 1.2//EN" "log4j.dtd">
    <log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
        ...
        <appender name="amqp" class="org.springframework.amqp.rabbit.log4j.AmqpAppender">
            <param name="ExchangeName" value="amq.topic" />
            <param name="ExchangeType" value="topic" />
            <param name="RoutingKeyPattern" value="logs.spring-travel" />
            <param name="ApplicationId" value="spring-travel" />
        </appender>
        ...
    </log4j:configuration>

and then adding the appender to whichever loggers you want. In the case of the root logger:

    <root>
        <priority value="info" />
        <appender-ref ref="console" />
        <appender-ref ref="amqp"/>  <!--   <-- Add this line -->
    </root>

These simple changes will result in the Spring Travel application logging messages to a RabbitMQ broker – as long as it’s running on the default port and with the standard ‘guest’ account. You can configure the connection settings for the broker in log4j.xml if you know the broker host and port information in advance, but Cloud Foundry assigns these values dynamically. Fortunately it is easy to configure your Cloud Foundry application to use those dynamically assigned values.

Since the connection settings for the various Cloud Foundry services are injected into an application at runtime (via an environment variable), we have to programmatically configure Log4j at runtime as well. This is a simple case of adding a ServletContextListener that checks whether the application is running inside Cloud Foundry and if so, updates the connection settings of the “amqp” appender.

The full code is in the application sample, but the basic process involves initializing the logging from log4j.xml, getting the appender by name, closing it (so that any existing AMQP connections are dropped) and then updating the connection settings.

Of course, we need to make sure the listener actually runs! So, drop the listener definition into the applications web descriptor:

    <listener>
        <listener-class>org.springframework.samples.travel.web.Log4jConfigListener</listener-class>
    </listener>

The last piece of the puzzle is to make sure that AmqpAppender is on the application’s classpath, which means you need to add the spring-rabbit library as a dependency:

    <dependency>
        <groupId>org.springframework.amqp</groupId>
        <artifactId>spring-rabbit</artifactId>
        <version>1.0.0.RELEASE</version>
    </dependency>

And because we’re using the CloudEnvironment class to extract the RabbitMQ connection settings from Cloud Foundry, we also need the cloudfoundry-runtime JAR, although that’s already part of the Spring Travel sample project:

    <dependency>
        <groupId>org.cloudfoundry</groupId>
        <artifactId>cloudfoundry-runtime</artifactId>
        <version>0.8.1</version>
    </dependency>

Everything is now in place, so we’re ready to deploy the application to Cloud Foundry. All that’s unique to this deployment is that you have to bind a RabbitMQ service called “rabbitmq-logs” to the application. This is because that’s the name of the service the code in Log4jConfigListener looks for. If you want to try this app yourself, just clone the repository and use the latest vmc to deploy it:

$ git clone https://github.com/pledbrook/spring-travel.git
$ cd spring-travel/server
$ mvn package
$ vmc push --path target
Would you like to deploy from the current directory? [Yn]: 
Application Name: spring-travel
Detected a Java SpringSource Spring Application, is this correct? [Yn]: 
Application Deployed URL [spring-travel.cloudfoundry.com]: koala-travel
Memory reservation (128M, 256M, 512M, 1G, 2G) [512M]:    
How many instances? [1]: 
Bind existing services to 'spring-travel'? [yN]: 
Create services to bind to 'spring-travel'? [yN]: y
1: mongodb
2: mysql
3: postgresql
4: rabbitmq
5: redis
What kind of service?: 2
Specify the name of the service [mysql-6117e]: travel-rdbms
Create another? [yN]: y
1: mongodb
2: mysql
3: postgresql
4: rabbitmq
5: redis
What kind of service?: 4
Specify the name of the service [rabbitmq-abd55]: rabbitmq-logs
Create another? [yN]: 
Would you like to save this configuration? [yN]: y
Manifest written to manifest.yml.
Creating Application: OK
Creating Service [travel-rdbms]: OK
Binding Service [travel-rdbms]: OK
Binding Service [rabbitmq-logs]: OK
Uploading Application:
  Checking for available resources: OK
  Processing resources: OK
  Packing application: OK
  Uploading (41K): OK
Push Status: OK
Staging Application 'spring-travel': OK
Starting Application 'spring-travel': OK

Don’t forget to change the application URL if you’re deploying to cloudfoundry.com, otherwise you may be told that it’s already in use and the deployment will fail.

Once you have successfully deployed the application and it starts up, those log messages will be flying! Hmmm…but where will they be flying to?

Who ate all the messages?

RabbitMQ will shift those log messages at a tremendous rate and retain them up to a point, but those messages need to be routed somewhere if you want to view them easily or search the logs in a week’s time. We obviously need to pick up those messages and put them into a data store for easy retrieval.

For this blog post, I’m going to create a simple Grails application that consumes the messages and stores them in a MongoDB instance. I could use a relational database, but ACID and referential integrity aren’t important in this scenario.

There are two parts to this application: a message consumer that stores the log messages in the database and a UI for viewing the messages. For the first part, I just declare dependencies on the RabbitMQ and MongoDB plugins (removing the Hibernate plugin) and create a handler service that consumes the messages and stores them into MongoDB:

    package org.example

    import org.springframework.amqp.core.Message

    class MessageStoreService {
        static transactional = false

        static rabbitSubscribe = [
                name: "amq.topic",
                routingKey: "logs.#",
                messageConverterBean: ""]

        void handleMessage(Message msg) {
            def props = msg.messageProperties
            def logMessage = new LogMessage(
                    message: new String(msg.body, props.contentEncoding ?: "UTF-8"),
                    appName: props.receivedRoutingKey - "logs.",
                    category: props.headers.categoryName,
                    level: props.headers.level).save(flush: true)
        }
    }

The handleMessage() method is invoked each time a message is received from the amq.topic exchange whose routing key matches “logs.#”. It just extracts the relevant information from the AMQP message and stores that in a LogMessage instance, which maps to a MongoDB record:

    package org.example

    class LogMessage {
        String appName
        String message
        String category
        String level

        static constraints = {
            category nullable: true
            level nullable: true
        }
    }

Note that the application name is pulled from the routing key of the message. Finally, the application has a scaffolded controller for LogMessage so that users can view the log messages:

    package org.example

    class LogMessageController {
        static scaffold = true
    }

The above are the only extra classes you need on top of a fresh Grails application. You will also need to add some RabbitMQ configuration to grails-app/conf/Config.groovy:

    rabbitmq {
        connectionfactory {
            username = 'guest'
            password = 'guest'
            hostname = 'localhost'
            consumers = 5
        }

        queues = {
            exchange name: "amq.topic", type: topic, durable: true, autoDelete: false
        }
    }

The key entry is the declaration of the ‘amq.topic’ exchange.

The full source is of this application is available on GitHub and can be deployed directly to any Cloud Foundry account. All you need to do is create and bind a MongoDB service to the application and bind “rabbitmq-logs” (or whatever RabbitMQ service you’re using for logging). You will also need to download and install Grails 2 to try this application.

$ git clone https://github.com/pledbrook/cf-log-app.git
$ cd cf-log-app
$ grails compile
$ grails
grails> cf-create-service rabbitmq rabbitmq-logs
Service 'rabbitmq-logs' provisioned.
grails> cf-create-service mongodb mongo-logs
Service 'mongo-logs' provisioned.
grails> prod cf-push --appname=cf-log-apps --services=rabbitmq-logs,mongo-logs
Building war file
| Done creating WAR target/cf-temp-1332242548101.war
> 
Application Deployed URL: 'cf-log-apps.cloudfoundry.com'? 

Creating application cf-log-apps at cf-log-apps.cloudfoundry.com with 512MB and services [rabbitmq-logs, mongo-logs]:
2012-03-20 11:22:40,498 [main] WARN  client.RestTemplate  - GET request for "http://api.cloudfoundry.com/apps/cf-log-apps" resulted in 404 (Not Found); invoking error handler
 OK
Uploading Application:
  Checking for available resources:
 OK
  Processing resources:
 OK
  Packing application:
 OK
  Uploading (6K):
 OK

Trying to start Application: 'cf-log-apps'......
Application 'cf-log-apps' started at http://cf-log-apps.cloudfoundry.com

As before, don’t forget to change the application name if you follow the above instructions. You can also see the application live on cloudfoundry.com with some log messages from the grailstwitter sample application.

Power logging

This is of course a very basic application but it does demonstrate how easy it is to aggregrate the logs from multiple applications into a single location. It would also be fairly easy to add a separate application that archives logs to a blob service, all the while ensuring low latency inside the applications that are performing the logging. This is the power of logging via a message broker.

Why stop at Java? In a polyglot environment, logging via AMQP will allow you to aggregate logs from all sorts of frameworks, such as Node.js and Ruby on Rails. As long as the consumer can handle any differences between message formats, you’re good to go.

- Peter Ledbrook
Cloud Foundry Developer Relations

Facebook Twitter Linkedin Digg Delicious Reddit Stumbleupon Email

Using Cloud Foundry Services with Ruby: Part 2 – Run-time Support for Ruby Applications

The services offered in Cloud Foundry are necessary for writing any serious application. Our aim is to make it easy to configure and consume these services. In addition to the auto-reconfiguration described in the Using Cloud Foundry Services with Ruby: Part 1 – Auto-reconfiguration blog post we also have support for manual service property lookup as well as library calls to obtain a pre-configured connection object.

Library call to obtain client object

For each supported service type there are corresponding library calls to obtain a pre-configured client object. This makes it easy to use in your code since you don’t have to lookup connection properties, instead you can rely on the library to do the work for you.

Here are some examples for the supported service types:

  • Relational database (PostgreSQL)
    require 'cfruntime/postgres'
    client = CFRuntime::PGClient.create_from_svc('postgres-test')
    ...
    
  • Relational database (MySQL)
    require 'cfruntime/mysql'
    client = CFRuntime::Mysql2Client.create_from_svc('mysql-test')
    ...
    
  • Document database (MongoDB)
    require 'cfruntime/mongodb'
    connection = CFRuntime::MongoClient.create_from_svc('mongo-test')
    db = connection.db
    ...
    
  • Key-Value store (Redis)
    require 'cfruntime/redis'
    client = CFRuntime::RedisClient.create_from_svc('redis-test')
    ...
    
  • Messaging (RabbitMQ)
    • AMQP Client
      require 'cfruntime/amqp'
      client = CFRuntime::AMQPClient.create_from_svc('rabbit-test')
      ...
      
    • Carrot
      require 'cfruntime/carrot'
      client = CFRuntime::CarrotClient.create_from_svc('rabbit-test')
      ...
      

These library calls all use the “create_from_svc” method where you need to specify the name of the service you are connecting to. If you only have a single service of a specific type bound to the app, then you can omit the service name and use the “create” method instead.

You can also provide connection parameters that can be used for local testing. This can be done using a rescue clause since the cloud connection method throws an exception if a cloud service can’t be located. The following is an example of using the “create” method to connect to a single MongoDB service bound to the app with an added rescue clause to provide a localhost db connection for running locally.

require 'cfruntime/mongodb'
...
db = (CFRuntime::MongoClient.create.db rescue Mongo::Connection.new("localhost", 27017).db("db"))
...

The following table shows the available methods and parameters for each service type:

Service Type Returns Method Signatures Comment
PostgreSQL PGConn instance CFRuntime::PGClient.create([options]) options parameter is an optional hash of connection settings to be passed to the PostgreSQL client
CFRuntime::PGClient.create_from_svc (service_name, [options]) service_name is the name of a service bound to the app, options parameter is an optional hash of connection settings to be passed to the PostgreSQL client
MySQL Mysql2 Client instance CFRuntime::Mysql2Client.create([options]) options parameter is an optional hash of connection settings to be passed to the MySQL client
CFRuntime::Mysql2Client.create_from_svc (service_name, [options]) service_name is the name of a service bound to the app, options parameter is an optional hash of connection settings to be passed to the MySQL client
MongoDB Mongo Connection proxy* CFRuntime::MongoClient.create([options]) options parameter is an optional hash of connection settings to be passed to the Mongo client
CFRuntime::MongoClient.create_from_svc (service_name, [options]) service_name is the name of a service bound to the app, options parameter is an optional hash of connection settings to be passed to the Mongo client
Redis Redis instance CFRuntime::RedisClient.create([options]) options parameter is an optional hash of connection settings to be passed to the Redis client
CFRuntime::RedisClient.create_from_svc (service_name, [options]) service_name is the name of a service bound to the app, options parameter is an optional hash of connection settings to be passed to the Redis client
RabbitMQ AMQP Client instance CFRuntime::AMQPClient.create([options]) options parameter is an optional hash of connection settings to be passed to the AMQP client
CFRuntime::AMQPClient.create_from_svc (service_name, [options]) service_name is the name of a service bound to the app, options parameter is an optional hash of connection settings to be passed to the AMQP client
RabbitMQ Carrot instance CFRuntime::CarrotClient.create([options]) options parameter is an optional hash of connection settings to be passed to the Carrot client
CFRuntime::CarrotClient.create_from_svc (service_name, [options]) service_name is the name of a service bound to the app, options parameter is an optional hash of connection settings to be passed to the Carrot client

* The proxy returned for the MongoDB Connection has a no-argument ‘db’ method to get access to the DB object for the database created for the CloudFoundry service.

Service configuration properties lookup

For applications where you want more control, we provide a service configuration properties look-up library. To use this, you can programmatically check whether you are running in a cloud environment, and then use the library to look up a service specific properties needed for manual connection configuration.

What services are supported and what properties are exposed for these services?

All services have the following properties provided in a hash:

  • :label
  • :version
  • :name
  • :username
  • :password
  • :host
  • :port

Each supported service also provides the following properties:

  • Relational database (PostgreSQL, MySQL)
    • :database – the name of the database
  • Document database (MongoDB)
    • :db – the name of the database
  • Key-Value store (Redis)
    • no additional properties
  • Messaging (RabbitMQ)
    • :url – the connection URL

Here is a brief MongoDB example:

require 'cfruntime/properties'

if CFRuntime::CloudApp.running_in_cloud?
  @service_props = CFRuntime::CloudApp.service_props('myservice')
else
  @service_props = {}
  @service_props[:host] = 'localhost'
  @service_props[:port] = 27017
  @service_props[:db] = 'testdb'
end
db = Mongo::Connection.new(@service_props[:host], @service_props[:port]).db(@service_props[:db])
if CFRuntime::CloudApp.running_in_cloud?
  db.authenticate(@service_props[:username], @service_props[:password])
end

Conclusion

In the previous blog post, you learned about Ruby auto-reconfiguration, and in this post we have covered manual configuration. We are pleased to offer these two new approaches to make it even easier to connect to Cloud Foundry services from your Ruby applications. Please feel free to send us any feedback via the Cloud Foundry Support Forums.

- Thomas Risberg
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

Using Cloud Foundry Services with Ruby: Part 1 – Auto-reconfiguration

Right from the launch, Cloud Foundry supported auto-reconfiguration of Spring and Rails apps that use a relational database service.  This allowed deploying such an app without changing a single line of code.  Recently, we extended this support for Spring apps to cover all services (Redis, Mongo, and Rabbit).  We are now extending this support for all services for Rails and making this available for Sinatra apps as well.  In this blog, we will explore how auto-reconfiguration works with Rails and Sinatra applications.

Auto-reconfiguration in action

To demonstrate auto-reconfiguration, we will grab an application from github and deploy it to Cloud Foundry without modification.  Let’s use lamernews, a Sinatra app that uses Redis.

mycomp:lamernews$ vmc push lamernews 
Would you like to deploy from the current directory? [Yn]: 
Application Deployed URL ["lamernews.cloudfoundry.com"]: 
Detected a Sinatra Application, is this correct? [Yn]: 
Memory Reservation ("64M", "128M", "256M", "512M", "1G") ["128M"]: 
Creating Application: OK 
Would you like to bind any services to 'lamernews'? [yN]: y 
The following system services are available 
1: mongodb 
2: mysql 
3: neo4j 
4: postgresql 
5: redis 
Please select one you wish to provision: 5 
Specify the name of the service ["redis-52216"]: 
Creating Service: OK 
Binding Service [redis-52216]: OK 
Uploading Application: 
Checking for available resources: OK 
Processing resources: OK 
Packing application: OK 
Uploading (1K): OK 
Push Status: OK 
Staging Application: OK 
Starting Application: OK 

Looks like the app deployed successfully.   Lamernews uses Redis to store comments, so let’s comment on a post and verify it stores successfully.

Now I press “Send comment”, and it looks like my comment was applied. Let’s take a look at the lamernews code that initializes the Redis connection:

 
RedisHost = "127.0.0.1" 
RedisPort = 10000 
$r = Redis.new(:host => RedisHost, :port => RedisPort) if !$r 

As you can see, the code is attempting to connect to Redis on localhost, however it worked just fine when we deployed to Cloud Foundry.  How is this possible?  Cloud Foundry will automatically detect initialization of several popular clients anywhere in your code and swap out your connection parameters for those of a service bound to your application. Read on to find out more about how this works!

Auto-reconfiguration for Sinatra

Your application consists of business logic and interaction with services such as database and messaging.  In a Sinatra application, you may initialize these services in Sinatra::Base#configure(). However, this is certainly not a requirement.  You are free to initialize your services wherever you want, perhaps lazily in response to a request. Additionally, there are several different client libraries you can use for connection to data and messaging services (ActiveRecord, DataMapper, Mongo Ruby Driver, MongoMapper, etc). For example, consider the following code that creates a Redis client:

 
require 'redis' 
module Demo 
class App < Sinatra::Base 
configure do 
  redis = Redis.new(:host => '127.0.0.1', :port => '6379') 
end 
... 
end 
end 

We can make one easy observation: The Redis host and port point to a server on localhost.  When you push this application to Cloud Foundry and bind a Redis service, the URL for that service is not going to be 127.0.0.1:6379!  So without an additional mechanism, such application will fail on startup.  This is where the auto-reconfiguration mechanism comes into play.  The auto-reconfiguration mechanism leverages Ruby metaprogramming to intercept the Redis initialization and replace the connection parameters with those of the Redis service bound to the application.  The result is that the user application works in local deployment and in Cloud Foundry without any change. When your Sinatra application is staged during the deployment process, Cloud Foundry will make two modifications:

  1. It will add an additional cf-autoconfig gem to your Bundle
  2. It will wrap the execution of your main Sinatra file (e.g. app.rb) in an auto_stage.rb file that ensures that all dynamic class modification is done prior to application execution.

Auto-reconfiguration for Rails

Cloud Foundry already provides auto-reconfiguration of your database in Rails by modifying the production settings in your config/database.yml during staging.  We have now added auto-reconfiguration of Mongo, Redis, and Rabbit clients as well. For example, you may have the following in config/initializers/redis.rb:

 
$redis = Redis.new(:host => '127.0.0.1', :port => 6379, :password => 'mypass') 

Once again, we can see that the Redis host and port point to a server on localhost.  Cloud Foundry will automatically replace these localhost connection parameters with those of the Redis service bound to your application. While it’s fairly common to put these types of connections in a Rails Initializer File, auto-reconfiguration should work just as well if you create the connection somewhere else within your application. When your Rails application is staged during the deployment process, Cloud Foundry will make two modifications:

  1. It will add an additional cf-autoconfig gem to your Bundle
  2. It will add an Initializer file to config/initializers that ensures that all dynamic class modification is done prior to loading other Initializers (and thus before your application executes).

Supported Clients

The following table shows the supported clients for auto-reconfiguration.

Client Minimal Supported Version
redis-rb 2.0
Mongo Ruby Driver 1.2.0
amqp 0.8
carrot 1.0
mysql2 (Sinatra only) 0.2.7
pg PostgreSQL client (Sinatra only) 0.11.0

In some cases, you don’t need to be using these clients directly. For example, the popular object mapper for Mongo, 

mongo_mapper, uses the Mongo Ruby Driver.  Therefore, if your application uses mongo_mapper, Cloud Foundry can auto-reconfigure it to connect to your Mongo service. Note that the mysql and postgresql gems are listed as Sinatra only.  This is because we auto-reconfigure relational database connections in Rails without metaprogramming, by modifying your production database settings in your database.yml file.

Under the Hood

As mentioned, we leverage Ruby metaprogramming to intercept a common set of method calls that create connections.  We then replace the connection parameters with those of the service bound to your application.  We do this with some well-known metaprogramming patterns: Open Class or Class Extension and Around Alias.  These are described thoroughly in the excellent book Metaprogramming Ruby. Here is an example from our Redis auto-reconfiguration support:

 
require 'cfruntime/properties' 
module AutoReconfiguration 
module Redis 
def self.included( base ) 
  base.send( :alias_method, :original_initialize, :initialize) 
  base.send( :alias_method, :initialize, :initialize_with_cf ) 
end 
def initialize_with_cf(options = {}) 
  service_props = CFRuntime::CloudApp.service_props('redis') 
  cfoptions = options 
  cfoptions[:host] = service_props[:host] 
  cfoptions[:port] = service_props[:port] 
  cfoptions[:password] = service_props[:password] 
  original_initialize cfoptions 
end 
end 
end 
require 'redis' 
class Redis 
  include AutoReconfiguration::Redis
end 

The code starts by opening the Redis class and adding the methods defined in our AutoReconfiguration::Redis module.  The first method, self.included, sets up an Around Alias that directs all of your calls to Redis.new to the new initialize_with_cf method.  This method utilizes our cf-runtime gem library look up the Redis service connection properties and then calls the original Redis initialize method with the changed parameters. We use a similar approach for each supported client.  Feel free to browse the code in our github repo for more details.  Let us know if there are other clients or hook points we should support (feel free to submit a pull request!).

Limitations

Auto-reconfiguration of services work only if there is exactly one service of a given service type.  For example, you may bind only one relational database service (MySQL or Postgres) to an application. If an application doesn’t follow these limitations, auto-reconfiguration will not take place.  In those cases, you can still take advantage of the cf-runtime gem described in the next blog post to manually configure service access. The auto-reconfiguration mechanism expects typical Ruby applications.  If your application configuration is complex, it may not work.  In those cases, you can opt out of auto-reconfiguration as we will describe next.

Opting out of auto-reconfiguration

There may be situations where you will like to opt out of auto-reconfiguration.  Cloud Foundry offers a few ways to opt out of the auto-reconfiguration mechanism.

  1. Create a file in your Sinatra or Rails application called “config/cloudfoundry.yml”. Add the entry “autoconfig: false”.
  2. Include the ‘cf-runtime’ gem in you Gemfile. Cloud Foundry uses this mechanism to opt out, since applications either want to have the auto-reconfiguration behavior or simply take control over service creation completely. We do not see the value in auto-reconfiguring some services and manually configuring others. If you are using cf-runtime and not using Bundler, you can still opt-out of auto-reconfiguration by creating the cloudfoundry.yml file as described above.

Conclusion

Auto-reconfiguration in Cloud Foundry is a wonderful way to get started deploying your Rails and Sinatra apps quickly.  As your application matures or makes use of multiple services, you may need finer control of your service connections.  In the next blog in this series, Thomas Risberg will explain how to use the new cf-runtime gem for simplified connections to Cloud Foundry services.

– 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

FeedHenry Brings Mobile App Development to Cloud Foundry

Mobile application developers can now build and deploy applications on Cloud Foundry using the FeedHenry developer platform. This guest post provides another example from the ecosystem of ISVs hosting their applications on Cloud Foundry.

Guest blog post by Mícheál Ó Foghlú.

Available today at mobilecf.feedhenry.com, Cloud Foundry developers can build mobile apps using HTML5, JavaScript and CSS fully integrated and instantly staged to their CloudFoundry.com account. To get started, simply download the FeedHenry Command Line tool, using your existing CloudFoundry.com credentials. New subscribers to CloudFoundry.com can join using the promotion code “feedhenry“.

In the following blog we will demonstrate how to use the FeedHenry Command Line tool to clone a sample/template app, (from GitHub), stage the server-side code to CloudFoundry.com (Node.js and Redis), and build a HTML5 & JS app for an Android device. See http://mobilecf.feedhenry.com for detailed instructions. Also check out the FeedHenry App Studio to preview the app that you create here.

Installing node.js

The FeedHenry CLI tool, fhc, uses node.js on your local machine. To setup node.js use the node installer located at http://nodejs.org/#download

Installing or Updating the FeedHenry CLI Tool (fhc)

Use the Node Package Manager (npm) to install or update the FeedHenry CLI tool (fhc).

$ sudo npm install –g fh-fhc

(the optional prefix “sudo” gives permission to install system-wide in a Unix style environment).

To test fhc is installed correctly and see the version you have installed, use:

$ fhc -v

fhc has some built-in documentation; use fhc help for general help, or fhc help [command] for help on a specific command.

Logging in using your CloudFoundry.com credentials

To get started with the CLI tool you need to login to the FeedHenry platform using your CloudFoundry.com credentials.  This will automatically create a FeedHenry account at mobilecf.feedhenry.com.

$ fhc target https://mobilecf.feedhenry.com/
$ fhc login

In the next 3 simple steps, we will illustrate how to create a HTML5/JS app with an instant backend in cloudfoundry.com.

Forking a template app in github (code)

To edit/modify the template app, login to github, and fork the app to your personal account.

https://github.com/feedhenry/App-Anatomy

Get the read-only git identifier for your cloned app.

git://github.com/YOUR-ID/App-Anatomy.git

Now create an app in the FeedHenry platform linked to your fork of the template app in github.

$ fhc apps create App-Anatomy git://github.com/YOUR-ID/App-Anatomy.git

If using a secured repository, please check out the documentation docs.feedhenry.com for generating and uploading public/private keys.

Staging the backend to Cloud Foundry

Staging to Cloud Foundry requires the use of the unique app identifier that can be acquired by listing the active FeedHenry apps.

$ fhc apps

The staging can be done to the debug environment or the live environment.  The former hosts the server-side for “debug” apps, and the latter for “release” apps.  Separating these allows developers to exercise functionality separately in testing before deploying to production.

$ fhc stage APP-ID --devel

or

$ fhc stage APP-ID --live

To ensure that the app has indeed staged correctly use the Cloud Foundry CLI tool (vmc).

$ vmc target api.cloudfoundry.com
$ vmc login
$ vmc apps
$ vmc logs APP-ID

We have just staged the cloud code from our forked app.  Each app contains three directories: client, cloud, and shared.  The client directory is for the client-side HTML5/JS app, the cloud directory is for the server-side Node.js code (this is what has been staged).  The shared directory is in both. Check out the documentation for more information on using the shared directory.

Building the Android client

To generate an Android debug build of the app:

$ fhc build app=APP-ID config=debug destination=android version=2.2 download=true

The appropriate files are gathered, bundled and dispatched to the FeedHenry build farm. The resulting binary file, for Android, an .apk file, is returned and can then be downloaded to your desktop. You can preview the app using the FeedHenry studio at mobilecf.feedhenry.com.

Load the app onto the phone by using email or Dropbox

That’s it – you have built and staged an app in 3 easy steps.

Note: Editing the code in the git repository can make changes to the server-side and the client-side functionality.  Those changes can be uploaded to FeedHenry via a git pull request. The updated server-side code can be re-staged, and the updated client-side code can be used to build a new version of the app. To find out more about this template app, App-Anatomy, see FH App-Anatomy in the References.

To get started go to http://mobilecf.feedhenry.com

Additional information

Join us for a Cloud Foundry mobile meetup, March 25th, San Francisco.

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

Facebook Twitter Linkedin Digg Delicious Reddit Stumbleupon Email