It's easier than it may seem to get started with a Cloud Foundry project. This tutorial lays out the entire process of getting a simple Java servlet application working in the CenturyLink Platform. I will walk through the entire process, from sign-up to working code. Note: This article is written with the assumption you are familiar with Java servlet programming, and the MySQL database.
The example is a Java application. IT IS NOT DESIGNED TO FUNCTION ON YOUR LOCAL MACHINE. You can run it, and the pages will come up, but the interaction is intended to function within the AppFog environment. To create similar code for your own use, you will need a few java libraries. The code was built on Java 1.7.
You will need:
- The MySQL jdbc connector, which is available here: https://dev.mysql.com/downloads/connector/j/5.1.html. This needs to be installed in your
JAVA_CLASSPATH
. - The org.json library, which is available here: http://central.maven.org/maven2/org/json/json/20140107/json-20140107.jar. This is the version for Java 1.7. This also needs to be installed in your
JAVA_CLASSPATH
.
Again, you don’t need these for this exercise.
You need to install the Cloud Foundry Command Line tools, which are obtained here: https://github.com/cloudfoundry/cli/releases. Download and install the correct version for your local machine.
The overall process is:
- Create a CenturyLink Cloud account.
- Download the example code.
- Log into AppFog.
- Push the code into AppFog to establish your instance.
- Define a database service instance.
- Set up a database in the service instance so that we have something to connect to.
- Register the database service with your application.
- Access the application to test.
- Review the results.
Are you ready? Let’s start!
Create a CenturyLink Account
If you don't have a CenturyLink Cloud account yet, start a free trial. Enter an email address and phone number. You will be required to enter a credit card, but you will not be charged for your first 30 days’ usage. If you wish to cancel your trial without cost, contact support@ctl.io.
At the end of the sign-up, you will receive an email with your username and a system defined password. Go to Control Panel and login with these credentials. When you do that, you will be given a chance to change your password, and then you should see this page:
Select “Activate AppFog”.
Now the page will update so that the Appfog icon on the left is no longer grayed out:
Select that icon, and you will see the following page:
Click the “add region” button for US East. The radio button will highlight, and the page will look as follows:
Select the “US East” link.
The will bring you to this page:
The cf login
string will have your account information, with your alias (“ATBT” above) and username (“abrunette.test” above”). We’ll use that in a bit. At this point, you have successfully setup your AppFog instance. Good work!
Download The Example Code
The next step is fetching the example code from GitHub. The example application is a simple servlet app that allows you to see your database configuration variables and to test connection to a database. Therefore, it demonstrates the code needed to do so. The example code is hosted at: https://github.com/andrewBrunette/AppFog-JavaMySQLExample. Access this link in your web browser. It will bring up this page:
The appearance of the page may change over time, but the instructions are the same. We will omit the robust GitHub cloning approach and download the repository as a zip file using the “Download Zip” button in the lower right of the page. Unzip this file into an empty directory of your choice.
Log-in to AppFog
AppFog is based on Cloud Foundry, an open source environment used to build Platform as a service environment. You'll need the Cloud Foundry command line tools to control AppFog. As you play with AppFog, keep our knowledge base in mind. However, solutions found searching Cloud Foundry should also be applicable to AppFog.
Open a command/terminal window and change your current directory to the directory where you saved the example code. Enter the login string as you saw in the last page of the control portal similar to what is shown below:
The system will ask for your password and to select a space for the app to run in. The password is the same as your CenturyLink account password. Choose 1 for “dev”. The result should look similar to:
Now, we are going to push the sample application from our local machine into Appfog. This moves the code into AppFog and configures an instance to support the application. The instance is an empty execution environment. It needs to be configured to support our application. This is done by specifying a ‘buildpack’. The buildpack configures the execution environment to support our application -- in this case by provisioning Java and Tomcat. There are buildpacks available for Java, Ruby, Python, Go, Node.js, and other environments. Since it is an open standard you can also build your own, but that is out of scope for this article.
You need to specify a unique name for your example. I will be using “atb-af-example”. This name must be globally unique within AppFog as it is used to form the URL that is used to reach your application.
Make sure you are in the directory that contains the various application directories for the example. You should have a directory dist
in your current directory.
The application is pushed up using the CLI command cf push
. The full command we will use is:
cf push atb-af-example -p dist\AFJavaExample.war -b https://github.com/cloudfoundry/java-buildpack.git
See cf help push
for a detailed explanation of the parameters. We’ll execute the command but not show the terminal window because it spits a lot of messages. The command takes a minute or so to run. At the end, you will see a screen that looks like this:
Note the “urls:” item. This is the URL of the application. You can access this now. Try it to verify your success so far. You should see this page:
Great work! This app is designed to access your environment variables, and check a db connection. Since we haven’t connected a database yet, these variables don’t exist, and we can’t connect yet. So, let’s set that up…
Configuring The Database Service
The next thing we want is a database to run against. We will get database features through CenturyLink's MySQL Database-as-a-Service. We find the name of available services through the AppFog marketplace. This is accessed through a call to the Command Line Interface (CLI), cf marketplace
as shown below:
This shows that there are two services available in the marketplace, ctl_mysql
and orchestrate
, a NoSQL database solution. The next step is to create an instance of the ctl_mysql service, which causes the service to provision a service instance for our use. This is done using the CLI again, using the command:
cf create-service ctl_mysql free <my_instance_name>
where my_instance_name
is a name for our use. ctl_mysql
is the service we are binding to, free
is the billing plan name. In production setups there will be multiple levels of plans with different costs and levels of resources. For now, though, let's keep it cheap! Create the DB instance as shown below:
For the next step we need to know the name of our application. Our application name was given in the cf push
command above, and is atb-af-example
. YOU WILL NEED A UNIQUE NAME. We are going to bind the database service to the application, through the command:
cf bind-service atb-af-example atb_instance
This command will end with a note that you need to re-stage your app to be able to access the environment variables that having the database login information. That command is:
cf restage atb-af-example
Run that command now. This restarts the application, allowing it to pick up the environment variables that contain the DB connection parameters. You should now enter the URL “
Try the “VCAP_SERVICES” Values button. That should give you a page similar to this:
These are the environment variables needed to access the database service. You can use these values to access the database via your usual client, but we’ll access it using Java. The code is in CheckConnection.java, and the interesting bit is:
JSONArray serviceData = parmList.getJSONArray("ctl_mysql");// fetch the credentials for the my_sql service
JSONObject payload = serviceData.getJSONObject(0);
JSONObject credentials = payload.getJSONObject("credentials");
String host = credentials.getString("host");
Integer port = credentials.getInt("port");
String dbUser = credentials.getString("username");
String dbPassword = credentials.getString("password");
String database = credentials.getString("dbname");
String certificate = credentials.getString("certificate");
try {
addCertToKeystore(host, certificate.getBytes());
Class.forName("com.mysql.jdbc.Driver");
String url = new StringBuilder("jdbc:mysql://").append(host).append(":").append(port)
.append("/").append(database).append("?")
.append("user=").append(dbUser)
.append("&password=").append(dbPassword)
.append("&useSSL=true").toString();
Connection conn = DriverManager.getConnection(url);
//
At this point we have a connection; let's do something with it. We'll do something simple:
PreparedStatement preparedStatement = conn.prepareStatement("show status like
Ssl_cipher%'");
ResultSet rs = preparedStatement.executeQuery();
StringBuilder output = new StringBuilder();
output.append("Your connection has succeeded. The ssl status is:");
while (rs.next()) {
output.append(rs.getString(1) + ":" + rs.getString(2) + "</br>")
}
rs.close();
conn.close();
return output.toString();
}
catch (Exception e) {
System.out.println(e.getMessage());
return e.getMessage();
}
If we click the “test connection” button, the result should be similar to what is shown below. If there is a problem, the exception message should display:
Congratulations! You have successfully run your first AppFog example, connecting to CenturyLink's MySQL Database-as-a-Service.
Code Review
The code to access the environment variables is in src\com\centurylinkcloud\ecosystem\VcapVars.java
. The interesting bit is:
String json = new String();
JSONObject jObj = null;
try {
int spacesToIndentEachLevel = 2;
json = new JSONObject(System.getenv("VCAP_SERVICES")).toString(spacesToIndentEachLevel);
}
This simply gets the environment variable VCAP_SERVICES
and formats it as a string for purposes of display. To get the data into a connection call, see CheckConnection.java in the same directory, where the interesting bit is:
private JSONObject getEnvData()throws Exception {
try {
return new JSONObject(System.getenv("VCAP_SERVICES"));
}
catch (Exception e){
throw new Exception("Your VCAP_SERVICES environment variable is not set, indicating no service available");
}
}
private String tryConnection(JSONObject parmList) {
System.setProperty("javax.net.ssl.keyStore", getKeyStorePath());
System.setProperty("javax.net.ssl.keyStorePassword", PASS);
System.setProperty("javax.net.ssl.trustStore", getKeyStorePath());
System.setProperty("javax.net.ssl.trustStorePassword", PASS);
JSONArray serviceData = parmList.getJSONArray("ctl_mysql");// fetch the credentials for the my_sql service
JSONObject payload = serviceData.getJSONObject(0);
JSONObject credentials = payload.getJSONObject("credentials");
String host = credentials.getString("host");
Integer port = credentials.getInt("port");
String dbUser = credentials.getString("username");
String dbPassword = credentials.getString("password");
String database = credentials.getString("dbname");
String certificate = credentials.getString("certificate");
try {
addCertToKeystore(host, certificate.getBytes());
Class.forName("com.mysql.jdbc.Driver");
String url = new StringBuilder("jdbc:mysql://").append(host).append(":").append(port)
.append("/").append(database).append("?")
.append("user=").append(dbUser)
.append("&password=").append(dbPassword)
.append("&useSSL=true").toString();
Connection conn = DriverManager.getConnection(url);
At this point you have a valid connection and can use it as you would normally
conn.close();
return new String ("success");
} catch (Exception e) {
System.out.println(e.getMessage());
return e.getMessage();
}
}
protected void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
JSONObject credentials = null;
try {
credentials = getEnvData();
}
….
String result = tryConnection(credentials);
The processRequest()
method calls getEnvData()
method to get the environment, and then executes the tryConnection()
method to use them.
Using SSL
Since you are accessing your data over the open Internet, it is important to use an encrypted connection. The code included here includes the necessary steps to use the certificate provided, and should need no modification. The useSSL=true
parameter in the connection setup tells MySQL to use SSL. The four methods at the bottom of the file, addCertToKeystore()
, getKeystore()
, getKeyStorePath()
, and persistKeyStore()
are necessary to handle the certificate so that the MySQL connector can access it. You will need to either use these, or manage your own keystore in some other manner. You are free to use this code without attribution.
Stopping and Deprovisioning
AppFog and the database connections are services. You accumulate charges if they stay running. To avoid this, shut them down when done. You shut down your AppFog instance using the CLI command, cf stop <APPNAME>
or in this example as shown below:
You remove the database service by first unbinding it from the app, then deleting it. Unbind it using the CLI command cf unbind <appname> <servicename>
. Then delete it using cf delete-service <servicename>
.
Finally, delete your instance using the cf delete <appname>
command
See below for the complete sequence. This will cause your account to not be further charged for any activity.
Conclusion
Hopefully, this tutorial got you on the right path to getting started on your Cloud Foundry project. The result is increased agility and productivity, more efficient use of resources, and a simplified deployment and management experience. Enjoy!