A lot has been said and done about services on the cloud lately and "Platform as a Service" (PaaS) is probably one of the most popular buzz-word that's been around for quite sometime now. However, I sincerely feel that the common man (read as "developer") is yet to get a taste of what it really means. Now, this very paradigm seems to be soon changing, with VMWare Cloud Foundry. Cloud Foundry is the world’s very first open Platform as a Service (PaaS). It is designed to help developers easily create web applications, using multiple programming frameworks including Spring for Java, Ruby on Rails and Sinatra for Ruby; that can run upon public and private cloud environments, with just about no additional learning curve. So, by now if you are dreaming of a possibility to port your existing web-applications to the cloud with minimal efforts, then let me give you the good news - "it's all possible here..."
Well, looks like i've done a lot of sales talks in favour of VMWare Cloud Foundry. Now lets get under the hood and get hands-on with developing an extreamly simple web application that demonstrates the following -
1. Setting up VMWare Cloud Foundry
2. Consuming Cloud Foundry's MySQL service in a JSP, using the standard JDBC way
3. Deploying a web archive and running the JSP on Cloud Foundry
Setting up VMWare Cloud Foundry
Windows Setup
Linux Setup
The document here is the best source of information for setting up the cloud-controller upon various Linux flavours.
Consuming Cloud Foundry's MySQL service
There are plenty of elaborate tutorials available on the web, that illustrate accessing the MySQL service at Cloud foundry using Spring. However, this one is a bit different, because it does not use Spring at all and demonstrates the same functionality with plain and simple Java and standard JDBC API.
The following code snippet demonstrates the approach -
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@page import="java.sql.*,javax.sql.*"%>
<%@page import="org.cloudfoundry.services.*"%>
<%
String query = "Select * FROM users";
%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Cloud Foundry with Simple Java</title>
</head>
<body>
Welcome to the simple web application on cloud-foundry...
<%
Connection connection = null;
try {
// establish connection to MySQL Service
ServiceManager services = ServiceManager.INSTANCE;
connection = (Connection) services.getInstance(CloudFoundryServices.MYSQL);
if (connection != null && !connection.isClosed()) {
out.println("<p>Successfully connected to MySQL service</p>");
// creating a database table and populating some values
Statement s = connection.createStatement();
int count;
s.executeUpdate("DROP TABLE IF EXISTS animal");
s.executeUpdate("CREATE TABLE animal ("
+ "id INT UNSIGNED NOT NULL AUTO_INCREMENT,"
+ "PRIMARY KEY (id),"
+ "name CHAR(40), category CHAR(40))");
out.println("<p>[1] Table successfully created.</p>");
count = s.executeUpdate("INSERT INTO animal (name, category)"
+ " VALUES"
+ "('snake', 'reptile'),"
+ "('frog', 'amphibian'),"
+ "('tuna', 'fish'),"
+ "('racoon', 'mammal')");
out.println("<p>[2] " + count + " rows were inserted.</p>");
count = 0;
ResultSet rs = s.executeQuery("select * from animal");
while (rs.next()) {
count++;
}
out.println("<p>[3] " + count + " rows were fetched.</p>");
s.close();
}
} catch (Exception e) {
out.println(e.getMessage());
} finally {
if (connection != null && !connection.isClosed()) {
connection.close();
}
connection = null;
}
%>
</body>
</html>
In the above code, org.cloudfoundry.services is a custom package which primarily contains a Singleton implementation, namely "ServiceManager"; and an interface to hold the constants, namely "CloudFoundryServices". Following are the sources for the same -
CloudFoundryServices.java
package org.cloudfoundry.services;
public interface CloudFoundryServices {
public static final int MYSQL = 1;
}
ServiceManager.java
package org.cloudfoundry.services;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import argo.jdom.JdomParser;
import argo.jdom.JsonNode;
import argo.jdom.JsonRootNode;
public enum ServiceManager implements CloudFoundryServices {
INSTANCE;
private static final String NULL_STRING = "";
public Object getInstance(int service_type) throws Exception {
if (service_type == MYSQL) {
return getMySQLConnection();
} else {
throw new IllegalArgumentException("Service for id " + service_type + " not found...");
}
}
/*
* This method is responsible for establishing a valid connection to the MySQL service,
* using the credentials available in the environment variable, namely "VCAP_SERVICES".
*
* The content of VCAP_SERVICES environment variable is a JSON string, thus this method
* uses standard interfaces from the Argo JSON parsing API to extract the credentials.
*/
private Object getMySQLConnection() throws SQLException {
String vcap_services = System.getenv("VCAP_SERVICES");
String hostname = NULL_STRING;
String dbname = NULL_STRING;
String user = NULL_STRING;
String password = NULL_STRING;
String port = NULL_STRING;
if (vcap_services != null && vcap_services.length() > 0) {
try {
JsonRootNode root = new JdomParser().parse(vcap_services);
JsonNode mysqlNode = root.getNode("mysql-5.1");
JsonNode credentials = mysqlNode.getNode(0).getNode("credentials");
dbname = credentials.getStringValue("name");
hostname = credentials.getStringValue("hostname");
user = credentials.getStringValue("user");
password = credentials.getStringValue("password");
port = credentials.getNumberValue("port");
String dbUrl = "jdbc:mysql://" + hostname + ":" + port + "/" + dbname;
Class.forName("com.mysql.jdbc.Driver");
Connection connection = DriverManager.getConnection(dbUrl, user, password);
return connection;
} catch (Exception e) {
throw new SQLException(e);
}
}
return null;
}
}
Now all you need to do now is, bundle everything together and get yourself a standard WAR (web archive) file.
Deploying a web archive and running the JSP on Cloud Foundry
Once you have the WAR file in place, browse to the location where the file is placed, using your command-line console; and execute the following cloud-controller commands -
Thats all for now, I hope you liked the post and should you have any issues getting this up and running feel free to reach out to me.
Additional Resources
Well, looks like i've done a lot of sales talks in favour of VMWare Cloud Foundry. Now lets get under the hood and get hands-on with developing an extreamly simple web application that demonstrates the following -
1. Setting up VMWare Cloud Foundry
2. Consuming Cloud Foundry's MySQL service in a JSP, using the standard JDBC way
3. Deploying a web archive and running the JSP on Cloud Foundry
Setting up VMWare Cloud Foundry
Windows Setup
- Apply for a Cloud Foundry account at www.cloudfoundry.com; you will be notified by email when your account is activated
- Install Ruby from www.rubyinstaller.org; The Cloud Foundry cloud-controller command line is built in Ruby so this is required. As the installer runs, make sure to check the boxes to add the ruby directory to your command path
- Start the Windows command line client (Start Menu -> Run -> "cmd")
- To install the cloud-controller tool type : gem install vmc (If you are behind a firewall then : gem install --http-proxy http://proxy.vmware.com:3128 vmc)
- Inform Cloud-Foundry which cloud you want to connect to : vmc target api.cloudfoundry.com
- To login to Cloud Foundry type : vmc login (enter your account credentials when prompted)
Linux Setup
The document here is the best source of information for setting up the cloud-controller upon various Linux flavours.
Consuming Cloud Foundry's MySQL service
There are plenty of elaborate tutorials available on the web, that illustrate accessing the MySQL service at Cloud foundry using Spring. However, this one is a bit different, because it does not use Spring at all and demonstrates the same functionality with plain and simple Java and standard JDBC API.
The following code snippet demonstrates the approach -
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@page import="java.sql.*,javax.sql.*"%>
<%@page import="org.cloudfoundry.services.*"%>
<%
String query = "Select * FROM users";
%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Cloud Foundry with Simple Java</title>
</head>
<body>
Welcome to the simple web application on cloud-foundry...
<%
Connection connection = null;
try {
// establish connection to MySQL Service
ServiceManager services = ServiceManager.INSTANCE;
connection = (Connection) services.getInstance(CloudFoundryServices.MYSQL);
if (connection != null && !connection.isClosed()) {
out.println("<p>Successfully connected to MySQL service</p>");
// creating a database table and populating some values
Statement s = connection.createStatement();
int count;
s.executeUpdate("DROP TABLE IF EXISTS animal");
s.executeUpdate("CREATE TABLE animal ("
+ "id INT UNSIGNED NOT NULL AUTO_INCREMENT,"
+ "PRIMARY KEY (id),"
+ "name CHAR(40), category CHAR(40))");
out.println("<p>[1] Table successfully created.</p>");
count = s.executeUpdate("INSERT INTO animal (name, category)"
+ " VALUES"
+ "('snake', 'reptile'),"
+ "('frog', 'amphibian'),"
+ "('tuna', 'fish'),"
+ "('racoon', 'mammal')");
out.println("<p>[2] " + count + " rows were inserted.</p>");
count = 0;
ResultSet rs = s.executeQuery("select * from animal");
while (rs.next()) {
count++;
}
out.println("<p>[3] " + count + " rows were fetched.</p>");
s.close();
}
} catch (Exception e) {
out.println(e.getMessage());
} finally {
if (connection != null && !connection.isClosed()) {
connection.close();
}
connection = null;
}
%>
</body>
</html>
In the above code, org.cloudfoundry.services is a custom package which primarily contains a Singleton implementation, namely "ServiceManager"; and an interface to hold the constants, namely "CloudFoundryServices". Following are the sources for the same -
CloudFoundryServices.java
package org.cloudfoundry.services;
public interface CloudFoundryServices {
public static final int MYSQL = 1;
}
ServiceManager.java
package org.cloudfoundry.services;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import argo.jdom.JdomParser;
import argo.jdom.JsonNode;
import argo.jdom.JsonRootNode;
public enum ServiceManager implements CloudFoundryServices {
INSTANCE;
private static final String NULL_STRING = "";
public Object getInstance(int service_type) throws Exception {
if (service_type == MYSQL) {
return getMySQLConnection();
} else {
throw new IllegalArgumentException("Service for id " + service_type + " not found...");
}
}
/*
* This method is responsible for establishing a valid connection to the MySQL service,
* using the credentials available in the environment variable, namely "VCAP_SERVICES".
*
* The content of VCAP_SERVICES environment variable is a JSON string, thus this method
* uses standard interfaces from the Argo JSON parsing API to extract the credentials.
*/
private Object getMySQLConnection() throws SQLException {
String vcap_services = System.getenv("VCAP_SERVICES");
String hostname = NULL_STRING;
String dbname = NULL_STRING;
String user = NULL_STRING;
String password = NULL_STRING;
String port = NULL_STRING;
if (vcap_services != null && vcap_services.length() > 0) {
try {
JsonRootNode root = new JdomParser().parse(vcap_services);
JsonNode mysqlNode = root.getNode("mysql-5.1");
JsonNode credentials = mysqlNode.getNode(0).getNode("credentials");
dbname = credentials.getStringValue("name");
hostname = credentials.getStringValue("hostname");
user = credentials.getStringValue("user");
password = credentials.getStringValue("password");
port = credentials.getNumberValue("port");
String dbUrl = "jdbc:mysql://" + hostname + ":" + port + "/" + dbname;
Class.forName("com.mysql.jdbc.Driver");
Connection connection = DriverManager.getConnection(dbUrl, user, password);
return connection;
} catch (Exception e) {
throw new SQLException(e);
}
}
return null;
}
}
Now all you need to do now is, bundle everything together and get yourself a standard WAR (web archive) file.
Deploying a web archive and running the JSP on Cloud Foundry
Once you have the WAR file in place, browse to the location where the file is placed, using your command-line console; and execute the following cloud-controller commands -
- In case you are not yet logged in to the cloud, type : vmc login (and, provide the required credentials when prompted)
- vmc push
- Enter a unique application name when prompted, could be anything like in my case its my name "rahulr"
- Select 'Y' when prompted to bind a service and select the MySQL service from the offered list of services
Thats all for now, I hope you liked the post and should you have any issues getting this up and running feel free to reach out to me.
Additional Resources
Following are some links which I found useful -