Amazon Web Services and Platform as a Service: Building Apps with Maven and Eclipse

Written by: Hannah Inman
7 min read

In this blog, I'm going to show you how to use Maven and Eclipse to build web applications that use Amazon Web Services to run on the CloudBees platform. If all this is second nature to you, please skip this blog and look at the next blog in the series (Amazon Web Services and Platform as a Service: IAM and the Token Vending Machine). I'll use a simple JSP web app to illustrate; the JSP app and the versions of the Token Vending Machine example that I'll be building are available on GitHub . I'll assume that you have a recent version of Eclipse with the AWS Toolkit for Eclipse installed.

Create a new Eclipse workspace and then go to New -> AWS Java Web Project to create a new project using the AWS Eclipse plugin. Select the Basic Java Web Application option and select an AWS account to use: if you haven't configured an AWS account using the Eclipse AWS Toolkit preferences tab, click on the Configure AWS account s link and enter the Access Key ID and Secret Access Key that you can find on your AWS Access Credentials dashboard.

That will create a new Java web application with a JSP home page (index.jsp ) that accesses a number of AWS services, plus a Java properties files (AwsCredentials.properties ) containing your AWS access credentials, which you'll find in the project's /src folder. The important point here is that any files in the /src folder are by default added to the Java classpath for the application, as you can see by right-clicking on the project and selecting Java Build Path -> Configure Build Path :

Then index.jsp (or any Java code) can access the file using the classloader's getResourceAsStream() method, as you can see in this code snippet:

AWSCredentials credentials = new PropertiesCredentials(

getClass().getClassLoader().getResourceAsStream("AwsCredentials.properties"));

From here, you can use Configure -> Convert to Maven Project to generate a skeleton pom.xml and Maven project structure, although I prefer to use the standard Eclipse Maven plugin to create projects in the first place. In that case, the only real difference is that the AwsCredentials.properties file should go in the project's /src/main/resources folder: when you run mvn:install, you'll see the properties file in the target folder under /WEB-INF/classes, which means that it will be on the application classpath and can be streamed in by application classloaders in the same way. The web app's resources (JSP, stylesheets etc.) go in the src/main/webapp folder as usual.

Loading the AWS access credentials using a properties file is fine for testing, but in general a better approach is to pass the Access Key and Secret to the application using system properties, since you don't want to have sensitive information stored on the local file system or kept in your source code repository. When running the application locally (using the CloudBees Eclipse Toolkit), you can define a Maven Build Run Configuration with Run As -> Run Configurations... and then use the JRE tab to add VM arguments with the -D syntax. When deploying applications to the cloud, we would like the PaaS to map these properties into our application regardless of which physical environment it is running on at any given time: the way to do this is to use the CloudBees SDK's config:* commands. There's a detailed article by Michael Neale on the CloudBees developer resources site on how to use the SDK to set configuration parameters for applications on the CloudBees platform, which I'll try to summarize here.

Setting the configuration parameters is straightforward: just download and install the CloudBees SDK and then use the config-plugin to set config params for your application like this (in this example, my domain/appname is mqprichard/aws-cb-webapp):

bees config:set -a aws-cb-webapp AWS_ACCESS_KEY_ID=
bees config:set -a aws-cb-webapp AWS_SECRET_KEY=

You can verify the configuration with the config:list command:
bees config:list -a aws-cb-webapp

To read these system properties within your application, you can either simply use System.getProperty() or you can define them as context-param elements in a cloudbees-web.xml deployment descriptor using the ${config_param} syntax to have the context-param-value injected by the CloudBees runtime stack. It's much easier just to use System.getProperty(), but there are situations where you might prefer to use the context-param approach, so here's an example of how to configure the cloudbees-web.xml:

< cloudbees-web-app xmlns = "http://cloudbees.com/xml/webapp/1">

< appid > mqprichard/aws-cb-webappappid >

< context-param>

< param-name > awsAccessKeyparam-name >

< param-value > ${AWS_ACCESS_KEY_ID}param-value >

context-param>

< context-param>

< param-name > awsSecretKeyparam-name >

< param-value > ${AWS_SECRET_KEY}param-value >

context-param>

cloudbees-web-app>

Then you replace PropertiesCredentials withBasicAWSCredentials using either System.getProperty() orgetServletContext().getInitParameter() to retrieve the Access and Secret Keys as shown:

  1. AWSCredentials credentials = new BasicAWSCredentials (

  2. System.getProperty("AWS_ACCESS_KEY_ID" ),

  3. System.getProperty("AWS_SECRET_KEY" ));

  4. AWSCredentials credentials = new BasicAWSCredentials (

  5. getServletContext().getInitParameter("awsAccessKey" ),

  6. getServletContext().getInitParameter("awsSecretKey" ));

Finally, you will need to restart the application instance to pick up the new config parameters using the CloudBees SDK's app:instance:restart command - which you can find with app:instance:list :

bees app:instance:list -a mqprichard/aws-cb-webapp
Instance ID : mqprichard/6199c075-ce93e48c
deployed : 2012-12-06 18:00:11.0
host : ec2-50-19-7-16.compute-1.amazonaws.com
port : 8432

bees app:instance:restart mqprichard/6199c075-ce93e48c

Are you sure you want to restart this instance [mqprichard/6199c075-ce93e48c]: (y/n) y
instance [mqprichard/6199c075-ce93e48c]: restarted

Once you've loaded the AWS access credentials, you can call AWS services directly using the relevant APIs. Here's a brief example that shows how to display the queue URLs associated with a particular account from a JSP, but the APIs all follow the same pattern:

private AmazonSQS sqs;

sqs = new AmazonSQSClient(credentials);

<% for (String queueUrl : sqs.listQueues().getQueueUrls() ) { %>

< li > <%= queueUrl %> li >

<% } %> __

Here's the project pom.xml file: I've added a dependency on aws-java-sdk from com.amazonaws, as well as the bees-maven-plugin from com.cloudbees to support the CloudBees PaaS, so that I can run the app locally using mvn bees:run (you can define an Eclipse Run Configuration for this).

< project xmlns = "http://maven.apache.org/POM/4.0.0" xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation = "http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">

< modelVersion> 4.0.0 modelVersion>

< groupId > com.cloudbees.awsgroupId >

< artifactId> cb-aws-webapp artifactId>

< packaging> war packaging>

< version > 0.0.1-SNAPSHOTversion >

< name > cb-aws-webapp Maven Webappname >

< url > http://maven.apache.orgurl >

__

< dependencies>

< dependency>

< groupId> junit groupId>

< artifactId> junit artifactId>

< version> 3.8.1 version>

< scope > testscope >

dependency>

< dependency>

< groupId > com.amazonawsgroupId >

< artifactId> aws-java-sdk artifactId>

< version> 1.3.26 version>

dependency>

dependencies>

< pluginRepositories>

< pluginRepository>

< id > bees-plugins-snapshotsid >

< url > http://repository-cloudbees.forge.cloudbees.com/public-snapshot/url >

< releases>

< enabled> false enabled>

releases>

< snapshots>

< enabled> true enabled>

snapshots>

pluginRepository>

pluginRepositories>

__

< build>

< finalName> cb-aws-webapp finalName>

< plugins>

< plugin >

< groupId > com.cloudbeesgroupId >

< artifactId > bees-maven-pluginartifactId >

< version > 1.0-SNAPSHOTversion >

plugin >

plugins>

build>

project>

Now try running the app. Here's what it should look like: it's bit boring, as I haven't added any AWS services to my account yet, but we'll do that in the next blog in this series.

Mark Prichard, Senior Director of Product Management

CloudBees

Stay up to date

We'll never share your email address and you can opt out at any time, we promise.