Using Cloud Foundry Services with Spring: Part 1 – The Basics |
|

Services offered in Cloud Foundry make writing efficient and effective applications possible. Developers can now choose just the right kind of services without worrying about operating those services. For example, a portion of an application can choose Postgres for the parts where transactional access is crucial, MongoDB where interacting with data as a collection of documents makes sense, Redis where key-value is the right abstraction, and RabbitMQ where messaging helps create effective architecture. In this four-part blog series, we will explore how Spring applications can use Cloud Foundry services. While our focus is on Spring, developers using other frameworks, especially JVM-based frameworks (Grails, Lift, and plain Java Web) will find good portion of these blogs relevant.
In this first installment, we will explore how Cloud Foundry exposes service information to applications. In the next blog, I will describe how a typical Spring application can use the auto-reconfiguration mechanism that allows using services without any modifications. In the third blog, Thomas Risberg will explain how to use the “cloud” namespace to have an explicit control over consuming services. In the fourth installment, Scott Andrews will show how to combine the profile support in Spring 3.1 with the “cloud” namespace to create applications that allow explicit control over services, while allowing applications to run locally or in Cloud Foundry without any change. By the end of this blog series, you should have sufficient information to use Cloud Foundry services effectively from Spring applications.
When you bind Cloud Foundry services such as Postgres or Mongo to an application, information about the bound services such as host, port, and credentials are exposed through environment variables with values encoded as JSON. To illustrate this point, we will create a simple web application that shows all the environment variables. We start with a Spring MVC Template project and add the following end point to HomeController (you can see this application on github).
@RequestMapping("/env")
public void env(HttpServletResponse response) throws IOException {
response.setContentType("text/plain");
PrintWriter out = response.getWriter();
out.println("System Environment:");
for (Map.Entry<String, String> envvar : System.getenv().entrySet()) {
out.println(envvar.getKey() + ": " + envvar.getValue());
}
}
Let’s deploy this application. I will use the 'vmc' tool, but using STS with the Cloud Foundry plugin will work, as well. Note that I am using hello-env as the application name and default URL based on it (hello-env.cloudfoundry.com). If you are coding along with this blog, you will want to choose an application name such as the default URL for it is not already taken. Alternatively, you can deploy to Micro Cloud Foundry.
$ vmc push hello-env -n
Creating Application: OK
Uploading Application:
Checking for available resources: OK
Processing resources: OK
Packing application: OK
Uploading (8K): OK
Push Status: OK
Staging Application: OK
Starting Application: OK
At this point if you navigate to http://hello-env.cloudfoundry.com/env, you will see a page full for all environment variables, many with the name starting with VCAP_ exposing all sorts of information about the application. Of our interest is the VCAP_SERVICES variable, which currently shows as
VCAP_SERVICES: {}
We see the variable as empty map (in JSON representation) indicating, rightly so, that no services have been bound. Let's create a Postgres service, name it env-postgresql, and bind it to our application. Note the form of the command: vmc create-service <service-type> <service-name> <applciation-name>.
$ vmc create-service postgresql env-postgresql hello-env
Creating Service: OK
Binding Service: OK
Stopping Application: OK
Staging Application: OK
Starting Application: OK
Now, let's navigate again to http://hello-env.cloudfoundry.com/env and you will see the VCAP_SERVICES environment variable as (formatted here for readability):
{
"postgresql-9.0": [{
"name": "env-postgresql",
"label": "postgresql-9.0",
"plan": "free",
"credentials": {
"name": "de24667f9344b4eeaad6b5a2326d52faa",
"host": "172.30.48.122",
"hostname": "172.30.48.122",
"port": 5432,
"user": "u50ce600bba434bacbc99e034bb415644",
"username": "u50ce600bba434bacbc99e034bb415644",
"password": "pf4dca5bd449d4732841f0c4ae3f299d0"
}
}]
}
This has all the information necessary for the application to connect to it: host, port, and name to create a JDBC URL as well as username and password to connect to it (hostname is deprecated and will be removed in a future version).
Let's bind another service, this time a MongoDB.
$ vmc create-service mongodb env-mongodb hello-env
Now the environment variable will look like:
{
"mongodb-1.8": [{
"name": "env-mongodb",
"label": "mongodb-1.8",
"plan": "free",
"tags": ["mongodb", "mongodb-1.8", "nosql"],
"credentials": {
"hostname": "172.30.48.68",
"host": "172.30.48.68",
"port": 25026,
"username": "b8b312a0-9b43-4104-90f8-52f2ac8bc7c6",
"password": "6a62732d-f820-4690-9bab-d1c85af13323",
"name": "416e990a-6f81-46f9-abaa-1233a11ca5d6",
"db": "db"
}
}],
"postgresql-9.0": [{
"name": "env-postgresql",
"label": "postgresql-9.0",
"plan": "free",
"credentials": {
"name": "de24667f9344b4eeaad6b5a2326d52faa",
"host": "172.30.48.122",
"hostname": "172.30.48.122",
"port": 5432,
"user": "u50ce600bba434bacbc99e034bb415644",
"username": "u50ce600bba434bacbc99e034bb415644",
"password": "pf4dca5bd449d4732841f0c4ae3f299d0"
}
}]
}
Again, the MongoDB portion has all the information needed to create a connection to it.
This is how Cloud Foundry exposes service information to your application so that it can consume the services bound to it. This requires accessing the environment variable, parsing JSON, and creating access objects (such as DataSource for relational database). While not too difficult, this is not something a programmer wants or likes to deal with directly. Therefore, Cloud Foundry provides a few mechanisms to simplify the task of connecting to services, which we will explore later in this series.
In the next installment, I will show you the auto-reconfiguration mechanism that lets typical Spring applications consume services without changing anything in the application. Until then, enjoy!
Similar Posts
- Using Cloud Foundry Services with Spring: Part 4 – Spring Profiles
- Using Postgres on Cloud Foundry
- Micro Cloud Foundry for Spring Developers
- Rapid Cloud Foundry Deployments with Maven
- Using Micro Cloud Foundry from Grails





Shekhar Gulati says:
Added on October 16th, 2011 at 12:49 pmIs there a way that one can use username, password and host properties to connect to the cloud instance using admin clients like mysql admin or mongodb shell ?
I tried it but it does not work.
Ramnivas Laddad (blog author) says:
Added on October 16th, 2011 at 12:57 pmServices are accessible only from within Cloud Foundry. In other words, hosts exposing services aren't available from outside. We are working on a solution that will allow you to connect to those services externally. Stay tuned!
Shekhar Gulati says:
Added on October 19th, 2011 at 2:21 pmThanks for your reply Ramnivas.
Jorge Middleton says:
Added on October 22nd, 2011 at 8:21 amHello, so if we want to put an application in the cloud that use database at the moment we have to use something like hbm2ddl option? There is an other option?
Thanks in advance.
Cédrik LIME says:
Added on November 7th, 2011 at 12:32 pmAnother possibility to look at environment variables is to install MessAdmin in an empty application.
It is even faster than creating the 9-lines Spring VMC class, and gives you a ton of useful technical information about your application.
You don't know it yet, but you'll need MessAdmin in your versatile toolbox!
Jerime Cortes says:
Added on October 29th, 2012 at 4:46 pmOn october 16 2011 the following post was added:
"Services are accessible only from within Cloud Foundry. In other words, hosts exposing services aren't available from outside. We are working on a solution that will allow you to connect to those services externally. Stay tuned!"
Is it possible to connect to an outside database provider now?