Cloud Development: Creating Services to Run in a Cloud Environment

By Jos Dirksen

Running in the cloud allows you to start quickly, with minimal expenses and lots of flexibility. This article based on chapter 6 of SOA Governance in Action shows how you can create services that can be run in a cloud environment.

Suppose your company defines a policy that it should be possible for their applications to run in the cloud. Before we look at this policy, and show you an example of how you can create a service that can run in the cloud, we’ll look a bit closer at what running in the cloud means.

When we talk about cloud computing, we usually mean that instead of accessing computing resources (for example, CPU and storage) locally we access them remotely. For instance, we can create a set of services, deploy those to a cloud provider, and this provider will make sure enough CPU, IO, and storage is available for our services. The big advantage of this model is that you, as a company, don’t have to make big investments in hardware and datacenters. You can use the resources from your cloud provider and don’t have to worry about adding extra hardware when the number of consumers grows. Besides this, an added advantage is that with most cloud providers you only pay for what you use. So, running in the cloud allows you to start quickly, with minimal expenses and lots of flexibility.

Different types of cloud services

There is a lot of talk about running services in the cloud, but this doesn’t mean you can just select one of the cloud providers, upload your service and it will work. We have to make sure we select a cloud provider that offers the functionality we need. If we look at the cloud providers out there, we can divide these into three distinct categories:

  • Software as a Service (SaaS) — When you use a SaaS environment, you get access to a full application or service hosted somewhere online. You don’t deploy your own applications or services on this cloud but make use of what is offered by the SaaS provider. Google Docs, SalesForce, and Office 365 are all examples of SaaS.
  • Platform as a Service (PaaS) — If we want to deploy our own applications, we might use a PaaS. With a PaaS, you are offered a complete computing platform or software stack that you can use to create your own applications and services. Google Apps, Amazon AWS, Microsoft Azure, and many more, provide this service.
  • Infrastructure as a Service (IaaS) — Finally, we have IaaS. This service provides computing infrastructure such as CPU resources, datastorage and network IO. Often PaaS makes uses of the services provided by IaaS. There are many IaaS providers: cloud.com, Rackspace, Amazon and HP to name but a few.

As we’re looking for a platform to run services on, we’ll focus on PaaS. We aren’t interested in using computing resources or already available software services such as SalesForce. Since we’ll be deploying services, we need to take governance into account. If we want to run a service in the cloud, we have to closely look at the features and functionality provided by a specific provider. Next, we show an overview of what to look for in your cloud provider.

Requirements for the cloud provider

There are many cloud providers available. On the one hand, you’ve got very specialized cloud providers that offer computing resources for CPU-intensive tasks to analyze complex mathematical problems. On the other hand, you’ve got general cloud providers that offer complete software stacks with which to build your applications. This makes choosing the correct cloud provider for your specific requirements rather hard. The following list shows a number of requirements that can help you to determine which cloud provider to use:

  • Functionality — Not all cloud providers offer the same functionality. Some might only offer computing resources, while others offer a complete software stack. When looking at a possible cloud provider, determine the functionality you need. Do you need an online database, email functionality, or maybe a messaging system? Try to find one that covers all these requirements. If you can’t find one, try to find a few that can integrate well with each other.
  • Software stack — Not all services are created using the same technology. You could just as well be developing in Java, .NET, Ruby, Python, Scala, or something else. When choosing a cloud provider, look for one that supports your development stack and, if it offers additional features (for example, key/value based storage), look for one that provides an API in your language.
  • Portability of data — When you run your services in the cloud and use of the storage options provided by the cloud, make sure this provider allows you to easily export your data.
  • Scalability — An important advantage of using a cloud provider is that you don’t have to worry about adding extra resources when your application grows. When looking for a cloud provider, look for one that provides transparent scalability. Should your resource requirements grow, the cloud provider should automatically be able to scale up. If your resource requirements are lower, than the cloud provider should scale down.
  • Data security — When you use a cloud provider, you store your sensitive information in the cloud. This data might even be stored in a different country. When selecting a cloud provider, make sure that the data security options provided by this provider match your and your customers’ requirements.
  • Backup policy — If you use the cloud platform for storage, it’s important to determine the backup policies of the cloud provider. Do they back up the data regularly, are databases replicated, and do you have the control to restore backups yourself?
  • Manageability — The cloud platform should be easy to manage. There should be a management interface with which you can easily see the resource usage of your services and add extra functionality. Besides this, you should also be able to easily view the logging and audit records for your application.
  • Cost — Cost is always an important factor. Look at what you have to pay for the services offered. Is there a minimum price you have to pay each month? Does your average price go down when you use a lot of resources?

Now that we’ve got a set of requirements we can use to determine a cloud provider, let’s look at how to run one of our examples in the cloud. For our example, we’ll use Amazon AWS. Amazon provides an easy-to-use cloud environment with all the features we require for our architecture. The Amazon AWS environment is also free to use the first year. If you want to use the Amazon cloud, you have to register an account. An account can be created from http://aws.amazon.com/. After you’ve created an account, you would set up the AWS environment we use for testing.

Creating a service that can run in the Amazon cloud

Most of the services offered by our sample organization, OpenGov, focus on allowing residents of a city to communicate with various local city departments. One of the applications offered by OpenGov provides different kinds of information regarding the city, for example, the opening hours of shops, garbage collection times, festival schedules. OpenGov wants to extend this platform so that residents can share information. In their first iteration, they decide that they’ll offer a service where residents can share images and comment on those images. Besides storing the image, OpenGov also wants to provide a simple query function, where based on location a set of images and comments can be retrieved. Since they expect much usage of this service, and it’s one of the policies defined by the OpenGov organization, this service will be created to run in the cloud. Figure 1 shows a high-level overview of this service, which we’ll call ImageCommentService.

Cloud Development: Creating Cloud Services
Figure 1. The components of the ImageCommentService

Figure 1 shows that we provide a REST layer which the users of our service can use to add their images. Through a data layer, this information is stored in a datastore. You’ll see how to map these various components to the components provided by Amazon. We start with the data layer and see how we can implement that layer with Amazon Web Services.

The data layer

With this service, the user can store an image together with some metadata. This means that our data layer needs to be able to store binary data, the image, and a set of metadata information. Listing 1 shows a simple POJO that captures the information that we want to store.

Listing 1. The model for the ImageCommentService

public?class?ImageComment?{????private?InputStream?stream;????private?String?comments;????private?String?location;????private?String?timestamp;????private?Map?userdata;}

Listing 1 shows binary data (the InputStream), a number of Strings, and a map containing an arbitrary amount of custom user information. What options does Amazon offer for us to store this image and its metadata? In Figure 2, you can see the complete set of AWS products offered by Amazon. One of these products should be able to fill our requirements.

Cloud Development: Creating Cloud Services

The interesting services here are the ones in the Database and Storage lists. From these lists, we could use the following products to store data in the cloud:

  • Amazon Simple Storage Service (S3) — With S3, Amazon offers a simple REST interface you can use to store objects in the cloud. These can be objects anywhere from 1 byte to 5 terabytes. Each object can be retrieved using a unique, developer-assigned key.
  • Amazon SimpleDB — With Amazon SimpleDB, you can easily store and query information in a key/value-based manner. All of the stored values are indexed for easy searching.
  • Amazon Relation Database Service (RDS) — Amazon RDS provides a relational database you can use in the cloud. You can choose to use a MySQL or an Oracle-based database.

If we look back at the model from listing 1, you can see that we have two different types of data to store. On the one hand, we’ve got the binary data representing the image and we’ve got a set of key/value pairs. For this example, we’ll store the image in S3, since it’s a blob of unstructured data, and we’ll store the key/values pair in Amazon SimpleDB, where we’ll also store the reference to the object stored in S3. We store this object using the storeImageComment operation of the AmaxonImageCommentRepository. The first part of the storeImageComment method is shown in listing 1 and the second part is shown in listing 3. In Listing 2, we show you the basics of how you can store objects using S3.

Listing 2. Using Amazon S3 to store an object (AmazonImageCommentRepository)

@PostConstructpublic?void?init()?{??s3?=?new?AmazonS3Client(new?BasicAWSCredentials(sharedKey,secret));?#1??bucket?=?s3.createBucket(SOAGOV_BUCKET);??#2??...}?public?void?storeImageComment(ImageComment?comment)?{??String?key?=?KEY_PREFIX?+?UUID.randomUUID();??????????#3??s3.putObject(bucket.getName(),?key?,comment.getStream(),?null);?#4??...}

#1 Creates an S3 client
#2 Creates a bucket
#3 Generates a unique key
#4 Stores the data

To store an object, we use the Amazon-provided Java client. This client handles all the low-level REST calls. All we have to do is specify the shared key and the secret to use with the call (#1). If you’ve registered with AWS, you can get this information from your account page. Once you’ve set up a client, the next step is to make sure we’ve got a bucket. A bucket is a container in which we store our objects. The code at #2 will create a new bucket if one with the specified name doesn’t already exist. All we need to store the object is the inputstream, a unique key (#3), and the name of the bucket in which to store the data. If we call s3.putObject with these arguments, the object will be stored in the Amazon S3 cloud.

Now that we’ve stored the image, we also need to store the metadata of the object. Listing 3 shows how you can use Amazon SimpleDB to store this information.

Listing 3. Using Amazon SimpleDB to store the metadata

@PostConstructpublic?void?init()?{?...?sdb?=?new?AmazonSimpleDBClient(?????????????????#1???new?BasicAWSCredentials(sharedKey,secret));???#1?sdb.createDomain(new?CreateDomainRequest(SOAGOV_DOMAIN));??#2}?public?void?storeImageComment(ImageComment?comment)?{??...??List?attributes?=?new??????#3????ArrayList();?????????????#3??attributes.add(new?ReplaceableAttribute(????TIMESTAMP,?Long.toString(System.currentTimeMillis()),?true));??attributes.add(new?ReplaceableAttribute(????COMMENTS,?comment.getComments(),?true));??attributes.add(new?ReplaceableAttribute(????LOCATION,?comment.getLocation(),?true));?????????????Map?otherData?=?comment.getUserdata();?#4??for?(String?userelement?:?otherData.keySet())?{????????#4????attributes.add(new?ReplaceableAttribute(????????????#4??????userelement,?otherData.get(userelement),?true));???#4??}???????????????????????????????????sdb.putAttributes(new?PutAttributesRequest(???#5????SOAGOV_DOMAIN,?key,?attributes));????????????#5}

#1 Creates a client for simpleDB
#2 Creates domain
#3 Attributes to store
#4 Adds userdata
#5 Stores in the database

In listing 3, you can see how we can use the AmazonSimpleDBClient to store the non-binary information from our ImageComment class. We first get a client, just as we did for S3 (#1). This time, we also need to create the location where our information needs to be stored. For simpleDB, this is called a domain, which we create in #2. We can then use this client to store the rest of the data. We do this by creating a list of attributes (#3), which are simple name/value pairs. We also add the user-specified data (#4) to this attribute list and, finally, use the putAttributes method to store the information. One thing to notice is that we use the same key in this operation (#5) as we did for the call to S3 in listing 2. This way, we can easily correlate the information from S3 with the information we stored in simpleDB, since both keys are the same.

We also mentioned that we would like to support searching for ImageComments based on location. We won’t show you the complete code for this, but we’ll just show you how to query simpleDB and retrieve information from S3. Querying simpleDB can be done in a way similar to SQL. For our scenario, we use the following statements for our search function:

String?selectExpression?=?"select?*?from?'"+?SOAGOV_DOMAIN??+"'?where?location?like?'%"?+?location?+?"%'";SelectRequest?selectRequest?=?new?SelectRequest(selectExpression);List?queryResut?=?sdb.select(selectRequest).getItems();

With these couple of statements, we create an SQL-like query, and use the AmazonSimpleDBClient to execute he query. This will return a set of Item objects, where each item contains a name that contains the value of our key, and all the attributes we stored. Because the image we stored in S3 was stored with the same name as the metadata in SimpleDB, we can also use this name to retrieve the image data from S3.

InputStream?data?=?s3.getObject????????????(bucket.getName(),?key).getObjectContent();

With this information, we can create list of ImageComment objects that we return as search results. Note that in this simple cloud example we haven’t defined an internal service layer. The remoting layer directly uses the data layer to store and query data.

The remoting layer

For the REST remoting layer, we can use the same setup as we did for the other REST-based services. We create a Spring bean and use JAX-RS annotations to define which method should be invoked when a specific resource location is requested with a specific HTTP verb. Listing 4 shows the remoting layer for this service.

Listing 4. The REST remoting layer

@[email protected]("/opengov/govdata/")public?class?GovDataCloudService?{[email protected](name="ImageCommentRepository")??private?ImageCommentRepository?repository;[email protected]??public?Response?addImageComment(String?jsonData)?{????ImageComment?imagecomment?=?jsonToToImageComment(jsonData);?#1????repository.storeImageComment(imagecomment);?????????????????#1????return?Response.ok().build();??}[email protected][email protected]("application/cloudservice.imagecomments+json")??public?Response?searchImageComments(@QueryParam("loc")??String?query)???????????????????????throws?IOException?{????JSONObject?responseData?=?new?JSONObject();????????List?comments?=????????????????????????????????#2?????????????repository.findImageCommentsForLocation(query);?????#2????List?foundElements?=?new?ArrayList();????for?(ImageComment?imageComment?:?comments)?{??????foundElements.add(imageCommentToJson(imageComment));???????}????????return?Response.ok().entity(responseData?????????.element("imagecomments",?foundElements).toString(3,1)).build();??}

#1 Converts and stores the JSON request
#2 Finds all ImageComment objects

In this listing, we don’t do anything that is specific to Amazon or for running in the cloud. It’s just a basic JAX-RS-based service that uses the repository (#1) to store incoming data and to find (#2) ImageComments based on a location.

So far, we’ve seen how the data layer and the REST layer are implemented. The final step we need to do is create the Spring application context that glues everything together. Listing 5 shows the Spring configuration file used in this example.

Listing 5. Spring configuration for the Amazon cloud-based service

??????????????????????????????

Listing 5 shows you see a basic JAX-RS configuration. The main difference is that in this instance we don’t specify the full address for our service but just the context “/cloud”. The reason is that we’ll be running this service in the container provided to us by Amazon, so the hostname and port is defined for us by this container.

Packaging, deploying, and testing the service

All we need to do now is to package all of our classes, deploy this service to Amazon, and test to see if the service is working. For this, we’ll use the Amazon Elastic Beanstalk. With this product, we can easily deploy and manage an application on Amazon’s cloud without having to worry about the underlying platforms and products. The standard platform used by the Elastic Beanstalk is a Tomcat-based software stack. To deploy our application, we need to package it as a WAR file and upload it to the Elastic Beanstalk.

We’ve specified the following in the pom.xml: war. If we use Maven to package (execute mvn package) this project, Maven will create a war file for us. If you want to test this WAR locally, you can deploy it to a locally installed Tomcat instance. The behavior should be the same as when you deploy the WAR to the Amazon cloud.

To deploy this WAR, go to the AWS page and login to the AWS Management Console. Open the Elastic Beanstalk tab ,and you’ll be greeted with Figure 3.

Cloud Development: Creating Cloud Services
Figure 3. Elastic Beanstalk welcome screen

From this screen, select the Upload your own application option and click the button. This will bring you to the screen shown in Figure 4.

Cloud Development: Creating Cloud Services
Figure 4. Creating a new application for Elastic Beanstalk deployment

In this form, fill in “soagov-cloud-test” as application name and browse to your cloud/target folder in your workspace where the .war file was created. After you’ve done this once again click “continue”. In the next step, we’re going to configure the environment in which our service will be running. This is shown in Figure 5.

Cloud Development: Creating Cloud Services
Figure 5. Configuring the environment in which to run our service

Check the Launch a new environment checkbox and fill in the hostname you’d like your service to run on. For the container select 32bit Tomcat 6 and click Continue. On the next screen, make sure the instance type is set to t1.micro and click Continue. Check whether you’ve filled in everything correctly in the review screen and click Finish. Now you’ll have to wait a bit while your application gets uploaded en deployed. After a couple of minutes, you’ll get a message stating successful deployment and, after closing that screen, you’ll see the screen shown in Figure 6, which shows the applications you’ve got running in the cloud.

Cloud Development: Creating Cloud Services
Figure 6. Overview of your beanstalk deployed applications

The easiest way to test whether deployment was successful is to click the View running version button. This will bring you to the homepage of your web application which lists the available REST services. This should look something like Figure 7.

Cloud Development: Creating Cloud Services
Figure 7. Welcome screen of our application in the cloud applications

Now that you’ve got your service running in the Amazon cloud, you of course want to test this. In the “test/resources” folder for this chapter you can find a sample json request you can use to test your cloud enabled service.

Summary

We’ve looked at running services in the cloud and shown you an example using Amazon Web Services. The most important points are:

  • Base your choice for a cloud provider on your specific requirements.
  • Try to find a single cloud provider that offers the features you need. If that can’t be found, try to find a couple that integrate well with each other.
  • Deploying and developing for the cloud isn’t that hard. Most practices you’re used to when developing services for a normal environment can be applied for services that run in the cloud.

About the Author

Jos Dirksen is a software architect with extensive experience applying open source tools to integration and governance challenges. He is coauthor of Open-Source ESBs in Action.

Share the Post:
Share on facebook
Share on twitter
Share on linkedin

Related Posts