You are here: Home / Past Courses / Spring 2012 - ECPE 293A / Projects / Web App from Scratch Tutorial

Web App from Scratch Tutorial

Overview

In this tutorial you will create a school schedule Web application. This application will allow students to input their courses and create a schedule. This tutorial will introduce you to JSP's, servlets and the Amazon Elastic Beanstalk Environment.

In contrast to the last tutorial, where all the code was pre-written, here you get to build the application from the ground up!

This tutorial is based on the original "Building a School Schedule Web App" tutorial by Lawrence Mandel, with modifications to accomodate the AWS Elastic Beanstalk service and store data in SimpleDB.

Getting Started

This tutorial assumes you have already completed the Elastic Beanstalk tutorial, and thus have already configured Eclipse.

Create a new project:

  • Select File -> New -> Project.
  • Select AWS -> AWS Java Web Project and click Next.
  • Give your project a name: FromScratchWebApp
  • Select your AWS account username (should be saved from last tutorial)
  • Select "Basic Java Web Application" and click Finish

 

Creating Class and Schedule Containers

For your web application to pass class information between the JSP page that displays the schedule and the servlet that registers the classes with the schedule you will need a representation of a class and a representation of a schedule. A class will have a title, day of week, start time and end time. A schedule will be a collection of classes. To implement these two objects you will create two classes: SchoolClass and SchoolSchedule.

Create the .java file to hold SchoolClass:

  • Right click on the FromScratchWebApp/Java Resources/src folder in the Project Explorer pane and select New->Class.
  • Name the class SchoolClass
  • Set the package to a new custom name you devise, such as org.yourname.classschedule. Remember what you chose here!
  • Click Finish. The SchoolClass class will now appear in the Java Resources/src folder and open in the Java editor.

 

Coding: We said earlier that a SchoolClass object will need to hold a title, day, start time and end time. Create private variables for each of these.The title should be of type String and the rest should be of type int.

private String title; 
private int startTime;
private int endTime;
private int day;

 

Coding: This information should be set when an instance of SchoolClass is created, so you will need to create a constructor that will accept the four pieces of information. Create a constructor that takes in the four parameters and sets the class variables.

public SchoolClass(String title, int startTime, int endTime, int day)
{
   this.title = title;
   this.startTime = startTime;
   this.endTime = endTime;
   this.day = day;
}

 

Coding (via automation!): You now need to create a way to access the object's information. Eclipse can automatically code get() and set() functions for private variables in your class.

  • Right click in the editor and select Source -> Generate Getters and Setters... (Note: ensure you click within the class' curly braces.)
  • Click the "Select Getters" button on the right. The four getter methods are now selected.
  • Click OK, and verify that the new code has appeared in the source file.

 

Create the .java file to hold SchoolSchedule:

  • You will now create the SchoolSchedule class which will act as a container for all of the classes.
  • Right click on the package org.yourname.classschedule and select New->Class.
  • Notice that the package field is automatically populated.
  • Name the class SchoolSchedule
  • Click Finish.

 

Coding: Add a private list of classes to the SchoolSchedule class.

private List<SchoolClass> classes = new ArrayList<SchoolClass>();

The List and ArrayList classes are underlined and flagged as errors as they have not yet been imported.

  • Right click in the editor and select Source->Organize Imports.
  • Select java.util.List
  • Click Finish. The necessary import statements will be added to the class.

 

Coding (via automation!): Create the get() method for the classes list

  • Right click in the editor within the class
  • Select Source->Generate Getters and Setters..
  • Click Select Getters on the right
  • Click OK.

 

Coding: Create a method to add new classes to the list. Create a method named addClass that takes a parameter of SchoolClass and adds it to the list.

public void addClass(SchoolClass schoolClass)
{
   classes.add(schoolClass);
}

Save your .java files

 

Adding Classes To The Schedule

You will now create a Java Server Page (JSP) that will allow students to add a class to their schedule. JSPs provide a way to access information stored in Java objects and perform Java operations within an HTML page. Your JSP will contain a form where students can submit their information. In the following section you will create an action to process the form submission.

Create the JSP file:

  • Right click on the WebContent folder in the Project Explorer pane
  • Select New->File
  • Name the file Schedule.jsp
  • Click Finish. The Schedule.jsp file opens in the JSP source page editor.

 

Coding: Design the JSP page

You now need to create the form to submit courses. The structure of a JSP page is very similar to that of an HTML page. A JSP page can simply use more tags and offer more functionality. In this step you will really just be creating an HTML page with a form. Create an HTML page with a form that has a text box for submitting a title, check boxes for the days of the week, and a drop-down menu for both the start time and end time of the class. The form will also need a submit button. You should ignore the action attribute on the FORM element for now. We will look at this in the next section when you create your submit action.

<HTML>
<HEAD>
<TITLE>Student Schedule</TITLE>
</HEAD>

<BODY>
<FORM action="" method="post">
Course Name: <INPUT type="text" name="title" size="35"><BR>
Course Time:
Sun<INPUT type="checkbox" name="day" value="sun">
Mon<INPUT type="checkbox" name="day" value="mon">
Tue<INPUT type="checkbox" name="day" value="tue">
Wed<INPUT type="checkbox" name="day" value="wed">
Thu<INPUT type="checkbox" name="day" value="thu">
Fri<INPUT type="checkbox" name="day" value="fri">
Sat<INPUT type="checkbox" name="day" value="sat">
<SELECT name="starttime">
<OPTION value="8">8:00am</OPTION>
<OPTION value="9">9:00am</OPTION>
<OPTION value="10">10:00am</OPTION>
<OPTION value="11">11:00am</OPTION>
<OPTION value="12">12:00pm</OPTION>
<OPTION value="13">1:00pm</OPTION>
<OPTION value="14">2:00pm</OPTION>
<OPTION value="15">3:00pm</OPTION>
<OPTION value="16">4:00pm</OPTION>
<OPTION value="17">5:00pm</OPTION>
<OPTION value="18">6:00pm</OPTION>
<OPTION value="19">7:00pm</OPTION>
<OPTION value="20">8:00pm</OPTION>
<OPTION value="21">9:00pm</OPTION>
</SELECT>
to
<SELECT name="endtime">
<OPTION value="9">9:00am</OPTION>
<OPTION value="10">10:00am</OPTION>
<OPTION value="11">11:00am</OPTION>
<OPTION value="12">12:00pm</OPTION>
<OPTION value="13">1:00pm</OPTION>
<OPTION value="14">2:00pm</OPTION>
<OPTION value="15">3:00pm</OPTION>
<OPTION value="16">4:00pm</OPTION>
<OPTION value="17">5:00pm</OPTION>
<OPTION value="18">6:00pm</OPTION>
<OPTION value="19">7:00pm</OPTION>
<OPTION value="20">8:00pm</OPTION>
<OPTION value="21">9:00pm</OPTION>
<OPTION value="22">10:00pm</OPTION>
</SELECT>
<BR>
<BR>
<INPUT type="submit" name="Submit" value="Add Course">
</FORM>

</BODY>
</HTML>

 

Testing - Phase 1

It is now time to test that this page displays properly on the server (even though submitting the form won't do anything yet...)  This is the same process you used in the previous tutorial.

 

First, create the new AWS Elastic Beanstalk Environment:

  • In Eclipse, find the Orange AWS logo button AWS Logo on the top toolbar. Select the drop-down arrow next to the button, and choose "New AWS Elastic Beanstalk Environment".  Select the AWS option for Tomcat 6 (not 7).
  • Leave the server host name as "localhost"  (this isn't relevant)
  • Leave the server name as "AWS Elastic Beanstalk for Tomcat 6 at localhost" (this isn't relevant)
  • Click Next
  • Select a region for your Elastic Beanstalk application. (Currently, US-East is the only available region!)
  • Select create a new application
    • An Application is a logical collection of AWS Elastic Beanstalk components, including environments and versions. In AWS Elastic Beanstalk an application is conceptually similar to a folder.
    • Name:  Enter something like YOURNAME-Scheduler
    • Description:  Enter something like YOURNAME Scheduler App
  • Configure a new environment for your application
    • Environment Name: YOURNAME-Scheduler-1
    • Environment Description: YOURNAME Scheduler Environment #1
  • Click Next
  • Check "Deploy with Keypair" (so that you can SSH to your server using this keypair later)
    • Scroll and select your username on the list (recall that you previously create a keypair in the first tutorial)
    • Click the "gearbox" icon, and then navigate and find the .pem keypair file you previously downloaded in the first tutorial.
    • When properly selected, the red X next to your keypair name should turn into a green checkbox
  • Check "Assign CNAME to new server", and enter a CNAME for your site:  YOURNAME-scheduler
    • This will translate into a URL of http://YOURNAME-scheduler.elasticbeanstalk.com
  • Leave the Health check URL blank - not implemented here!
  • Email address for notifications: <use your email address>
  • Turn off incremental deployments (At least, I had problems with them...)
  • Click Finish

 

Second, run your application:

  • Right-click on your project name in the Explorer window (FromScratchWebApp)
  • Choose Run As->Run On Server.
  • Select "Choose an existing server".
  • Choose your Elastic Beanstalk config just created. The environment name you selected should appear here.
  • Click Finish
  • Enter a version label to identify this specific .war program from any other .war files you might later upload as part of this same program: v1
  • Wait. Give Eclipse a few minutes to upload the file and for Amazon to launch an EC2 instance.
  • While waiting, you can check your email, and follow the link to enable notifications from Amazon for this specific environment.

 

When finished, Elipse should show a preview window of your web app.

Checkpoint 1 - Show me the Schedule.jsp page, running on EC2, as accessed by a web browser outside of Eclipse.


The Submit Action

When the form in Schedule.jsp is submitted, an action needs to be performed on the data. In this section you will create a servlet that processes the input from the form, creates the necessary SchoolClass objects and adds them to the SchoolSchedule.

A servlet is a Java class that executes on the server. In order to have the class information from previous submits stay available, the SchoolSchedule will be added to a session object. (If you do not do this, the schedule will only be able to show the information from the last form submission.)

Create the servlet:

  • Right click on the package org.YOURNAME.classschedule and select New->Class.
  • Servlet name: ScheduleServlet.
  • Superclass: javax.servlet.http.HttpServlet
  • Select Add next to Interfaces
  • Add javax.servlet.Servlet
  • Click Finish. The new ScheduleServlet will appear in the src folder and open in the Java editor.

 

Coding: Add a new method to handle POSTs (i.e. when the web form is submitted)

  • Right click in the editor (which has the servlet open)
  • Source -> Override/Implement Methods...
  • Select the doPost(HttpServletRequest, HttpServletResponse) method
  • Click OK. The doPost method will now show in your ScheduleServlet class.
  • Remove this auto-generated stub block - you don't need it:
    // TODO Auto-generated method stub
    super.doPost(req, resp);

 

The doPost method is where you will take the input from the form and perform your actions. The doPost method is used because you specified that your form would submit data using the POST method. You could also have used the GET method in which case your servlet would need to implement doGet() instead of doPost().

Coding: Inside the doPost method, first read in the information submitted by the form. This information can be obtained through the request object's getParameter method. the getParameterValues method is used for the days as there may be more than one day selected.

String title = req.getParameter("title");
int starttime = Integer.parseInt(req.getParameter("starttime"));
int endtime = Integer.parseInt(req.getParameter("endtime"));
String[] days = req.getParameterValues("day");

 

Coding: The next step is to obtain the existing SchoolSchedule, if there is one, or to create a new one if one hasn't been created yet.

SchoolSchedule schedule = (SchoolSchedule)req.getSession(true).getAttribute("schoolschedule");
if(schedule == null)
{
   schedule = new SchoolSchedule();
}

 

Coding: Now you can create new SchoolClass objects. As there may be many days for the school class you are adding, you will iterate over all of the days and create a new SchoolClass object for each day that was selected. Creating SchoolClass objects in this way will make displaying them via Schedule.jsp easier. After a SchoolClass object is created you will add it to the schedule.

if(days != null)
{
for(int i = 0; i < days.length; i++)
{
String dayString = days[i];
int day;
if(dayString.equalsIgnoreCase("SUN")) day = 0;
else if(dayString.equalsIgnoreCase("MON")) day = 1;
else if(dayString.equalsIgnoreCase("TUE")) day = 2;
else if(dayString.equalsIgnoreCase("WED")) day = 3;
else if(dayString.equalsIgnoreCase("THU")) day = 4;
else if(dayString.equalsIgnoreCase("FRI")) day = 5;
else day = 6;

SchoolClass clazz = new SchoolClass(title, starttime, endtime, day);
schedule.addClass(clazz);
}
}

 

Coding: You need to set the schedule in the session so Schedule.jsp will have access to it and forward control back to Schedule.jsp.

req.getSession().setAttribute("schoolschedule", schedule);
getServletContext().getRequestDispatcher("/Schedule.jsp").forward(req, resp);

Save the class.

 

Configure Servlet: You have now created your servlet but your Web application does not yet know about it. In order for your Web application to know about the servlet you will have to define it in the Deployment Descriptor.

  • Double click on the Deployment Descriptor under the FromScratchWebApp project
  • You should see web.xml open. (If not, find the XML tab to view the source)
  • Copy the following lines under the display element
<servlet>
<servlet-name>ScheduleServlet</servlet-name>
<servlet-class>org.YOURNAME.classschedule.ScheduleServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ScheduleServlet</servlet-name>
<url-pattern>/ScheduleServlet-web</url-pattern>
</servlet-mapping>

 

Now that you have defined where your servlet action is located, you can specify the location in your Schedule JSP.

  • Open the Schedule.jsp file
  • Specify the action location of your form (i.e. modify the existing FORM action that is there)
<FORM action="/ScheduleServlet-web" method="post">

 

Displaying The Schedule

Your servlet has now been defined with your Web application and is ready to be used. You can now return to Schedule.jsp and work on displaying the Schedule. In this section you will use some of the custom tag libraries that are available for working with JSPs.

In order to use the standard tag libraries, you will first have to download and install them into your project.

  • Open your Web browser to http://tomcat.apache.org/taglibs/standard/
  • Follow the "Download" link next to Standard 1.1
  • Select "Binaries"
  • Download the file jakarta-taglibs-standard-1.1.2.tar.gz (or .zip, for windows)
  • Uncompress the download file someplace.
  • Copy the following files out of the extracted download archive: jstl.jar and standard.jar
  • Place these two files into the WebContent/WEB-INF/lib folder of your current project
  • Go back to Eclipse, select your project, right click on it and select Refresh. The libraries are automatically added to your Java classpath, and you should see them in Project Explorer.

 

Open Schedule.jsp in the JSP source page editor.

Coding: In order to use the tag libraries you have just downloaded you will have to declare them in your JSP. At the top of the Schedule.jsp file (above the HTML element) add in the following line:

<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>

 

Coding: Next, we will dynamically create a table that will hold our schedule. The table will list the days of the week and the time from 8:00am until 9:00pm. For each time slot we will check to see if there is a class and if there is we will display the title of the class.

First create the header of the table as follows.

<TABLE border="1" cellspacing="0">
<TBODY>
<TR>
<TH align="center" valign="middle" width="80"></TH>
<TH align="center" valign="middle" width="100">Sunday</TH>
<TH align="center" valign="middle">Monday</TH>
<TH align="center" valign="middle">Tuesday</TH>
<TH align="center" valign="middle">Wednesday</TH>
<TH align="center" valign="middle">Thursday</TH>
<TH align="center" valign="middle">Friday</TH>
<TH align="center" valign="middle">Saturday</TH>
</TR>

Now you will create the content of the table. In order to create the content you will iterate through the times of the day and the days of the week. As your schedule will display from 8:00am to 9:00pm you will iterate from 8 to 21 for the time. For the days of the week you will iterate from 0 to 6. There is some simple logic for displaying the time in a nice way. As you can see below, the tags that are prefixed with 'c' are from the custom tag library you imported earlier. These tags allow for the iteration and conditional logic you are using. In the third forEach loop you can see where the information is retrieved from the school schedule object your servlet creates and where the individual information is retrieved from each SchoolClass object.

<c:forEach begin="8" end="21" step="1" var="time">
<TR>
<TD align="center" valign="middle" width="80">
<c:choose>
<c:when test="${time == 12}">
<c:out value="${time}" />:00pm
</c:when>
<c:when test="${time > 12}">
<c:out value="${time - 12}" />:00pm
</c:when>
<c:otherwise>
<c:out value="${time}" />:00am
</c:otherwise>
</c:choose></TD>
<c:forEach begin="0" end="6" step="1" var="day">
<TD align="center" valign="middle" width="100">
<c:forEach items="${schoolschedule.classes}" var="clazz">
<c:if test="${clazz.startTime <= time
&& clazz.endTime > time
&& clazz.day == day}">
<c:out value="${clazz.title}" />
</c:if>
</c:forEach>
</TD>
</c:forEach>
</TR>
</c:forEach>
</TBODY>
</TABLE>

Save the Schedule.jsp file.

 

Important Note! When you access .endTime, .startTime, .day, and .title in the JSP code above, you are NOT directly accessing the endTime, startTime, day, and title member variables.  Instead, you are accessing the "getter" methods defined in SchoolClass, specifically getEndTime(), getStartTime(), getDay(), and getTitle().  Don't forget to add these methods for any custom classes you define in your own application!

 

Testing - Phase 2

Your school schedule application is now complete. Now it is time to take it for a spin.

Note: You do not need to create a new Environment. The environment from phase 1 is is still available (and running, and costing $$). Instead, you can use Eclipse to upload a new application version to the existing environment, and automatically start serving the new application.

Run your application:

  • Right-click on your project name in the Explorer window (FromScratchWebApp)
  • Choose Run As->Run On Server.
  • Select "Choose an existing server".
  • Choose your Elastic Beanstalk config previously created. The environment name you selected should appear here.
  • Click Finish
  • Enter a version label to identify this specific .war program from any other .war files you might later upload as part of this same program: v2
  • Wait. Give Eclipse a few minutes to upload the file and for Amazon to launch an EC2 instance.
  • While waiting, you can check your email, and follow the link to enable notifications from Amazon for this specific environment.

 

When finished, Elipse should show a preview window of your web app. Notice that the calendar is initially empty. Add a class to the calendar and click Add Course. The course is now added to the calendar. For example, try adding "COMP 51 - Intro to CS" on Mon, Wed and Fri from 10:00am until 11:00am to your schedule.

 

Checkpoint 2 - Show me the working application, accessed outside of Eclipse!

 

SimpleDB - Background Reading

Amazon SimpleDB is a non-relational data store that manages multiple geographically distributed replicas of your data automatically to enable high availability and data durability.

For an overview on Amazon SimpleDB, read the main product page, starting at "Detailed Description" halfway down the page.

Items to note:

  • Data model
  • Operations: Create/Delete Domains, Put/Delete/Select Data, etc...
  • Consistency model - when are new data items actually available? (Hint: Not instantly!)
  • Data size limits - Each attribute value can only be up to 1024 bytes in size. (Larger data should be stored in S3, with the path/filename placed in SimpleDB)

 

References:

 

SimpleDB - Creating Domain

This interface is based on an Amazon-provided file (SimpleDBSample.java) with examples for creating, listing, and destroying domains, and putting/deleting/selecting data within a domain. I obtained that example code from Eclipse by creating a new "AWS Java Project" (not a "AWS Java Web Project").   Note that the Amazon example is for a stand-alone Java program. In this tutorial, we'll use similar code to manipulate SimpleDB as part of our web application.

First, create a new class that can manage a SimpleDB domain.

  • Right click on the FromScratchWebApp/Java Resources/src folder in the Project Explorer pane and select New->Class.
  • Name the class DBManage
  • Set the package to a new custom name you devise, such as org.yourname.simpledb. Remember what you chose here!
  • Click Finish. The DBManage class will now appear in the Java Resources/src folder and open in the Java editor.

 

The purpose of this class is to centralize all aspects of database communication, and to separate the back-end database communication from the front-end display and presentation to the user. Eventually, this class will contain the following features:

  • Constructor - Initialize the database client object
  • createDomain() - Create a new domain (or, if the domain already exists, do nothing)
  • storeClass() - Store a specific class name/day/time entry in the domain
  • loadSchedule() - Create a new SchoolSchedule class fully populated with all classes stored in the database
  • handleExceptions() - Error checking and output

 

Coding: Let's first implement the constructor and createDomain() method, and then trigger that method with another Servlet.  Copy the following code into the DBManage class, replacing YOURNAME where appropriate:

 String myDomain = "YOURNAME-Schedule";
PrintWriter out;
AmazonSimpleDB sdb;

// Constructor
public DBManage(PrintWriter out) throws IOException
{
// Location to write output to
this.out = out;
// SimpleDB management client (based on login stored in AwsCredentials.properties file)
sdb = new AmazonSimpleDBClient(new PropertiesCredentials(
this.getClass().getClassLoader().getResourceAsStream("AwsCredentials.properties")));
}

// Create Domain (i.e. a "table" to store data)
public void createDomain()
{
out.println
("<!DOCTYPE html>\n" +
"<html>\n" +
"<head><title>DBManage:createDomain()</title></head>\n" +
"<body>\n" +
"<h1>Result of page:</h1>\n" +
"<pre>\n");

out.println("===========================================");
out.println("Creating SimpleDB domain");
out.println("===========================================\n");

try {
// Create a domain
out.println("Creating domain called " + myDomain + ".\n");
sdb.createDomain(new CreateDomainRequest(myDomain));

// List domains
out.println("Listing all domains in your account:\n");
for (String domainName : sdb.listDomains().getDomainNames()) {
out.println(" " + domainName);
}
out.println();

} catch (AmazonServiceException ase) {
handleExceptions(ase);
} catch (AmazonClientException ace) {
handleExceptions(ace);
}

out.println("<pre>\n" +
"</body></html>");
}

// Handle exceptions produced by SimpleDB operations
// Two types: ServiceExceptions and ClientExceptions
private void handleExceptions(AmazonServiceException ase)
{
out.println("<pre>");
out.println("Caught an AmazonServiceException, which means your request made it "
+ "to Amazon SimpleDB, but was rejected with an error response for some reason.");
out.println("Error Message: " + ase.getMessage());
out.println("HTTP Status Code: " + ase.getStatusCode());
out.println("AWS Error Code: " + ase.getErrorCode());
out.println("Error Type: " + ase.getErrorType());
out.println("Request ID: " + ase.getRequestId());
out.println("</pre>");
}

private void handleExceptions(AmazonClientException ace)
{
out.println("<pre>");
out.println("Caught an AmazonClientException, which means the client encountered "
+ "a serious internal problem while trying to communicate with SimpleDB, "
+ "such as not being able to access the network.");
out.println("Error Message: " + ace.getMessage());
out.println("</pre>");
}

Yikes! Look at all those errors highlighted in red.  After pasting, right-click and choose Source->Organize Imports to ensure that all the correct libraries are imported at top.

The createDomain() method creates a new domain, and then, for good measure, prints out all active domains on our class account.  Note how the database functions are surrounded by a try/catch block. You should never assume that SimpleDB requests always succeed!

 

Coding: Now, create a simple Servlet that will call this new createDomain() method. This servlet should be run once (by an administrator) when installing your application. After all, we don't need to create a new domain every time a page is loaded:

  • Right click on the package org.YOURNAME.simpledb and select New->Class.
  • Servlet name: DBCreateServlet.
  • Superclass: javax.servlet.http.HttpServlet
  • Select Add next to Interfaces
  • Add javax.servlet.Servlet
  • Click Finish. The new DBCreateServlet will appear in the src folder and open in the Java editor.

 

Coding: Add a new method to handle GETs (i.e. when the web page is requested by the browser)

  • Right click in the editor (which has the servlet open) Source -> Override/Implement Methods...
  • Select the doGet(HttpServletRequest, HttpServletResponse) method
  • Click OK. The doGet() method will now show in your ScheduleServlet class.
  • Remove this auto-generated stub block - you don't need it:
    // TODO Auto-generated method stub
    super.doGet(req, resp);

 

The doGet() method is where you will perform your actions that should occur when the page is loaded.

Coding: Place the following code inside the doGet() method. It tells the web browser that the object being loaded (i.e. this page) contains HTML, not binary images or anything else. Then, it captures the output stream and passes it to the DBManage class for use in the constructor.  (Otherwise, the DBManage class couldn't output anything!).  FInally, it calls the createDomain() method.

 resp.setContentType("text/html");
PrintWriter out = resp.getWriter();

DBManage myDB = new DBManage(out);
myDB.createDomain();

After entering this code, choose "Organize Imports" again to ensure that this line appears at the top of your file:  import java.io.PrintWriter;

To allow your servlet to run when a specific URL is loaded (http://CNAME.elasticbeanstalk.com/DBCreateServlet-web), add the following code to the web.xml file:

<servlet>
<servlet-name>DBCreateServlet</servlet-name>
<servlet-class>org.YOURNAME.simpledb.DBCreateServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>DBCreateServlet</servlet-name>
<url-pattern>/DBCreateServlet-web</url-pattern>
</servlet-mapping>

 

Run your application using the existing environment.

 

Checkpoint 3 - Show me the working database creation webpage, accessed outside of Eclipse!

 

Result of page:

===========================================
Creating SimpleDB domain
===========================================

Creating domain called Shafer-Schedule.

Listing all domains in your account:

Shafer-Schedule

 

SimpleDB - Saving Data

Now, let's augment the management class so we can save records to SimpleDB, rather than relying on web sessions (i.e. cookies).

Coding: Add the following method to DBManage to add one record to SimpleDB with a random (UUID) item name, since no reasonable unique name is available from the data.

// Store a class entry into a Domain previously created
public void storeClass(String title, int starttime, int endtime, int day)
{
try {
// Put data into a domain
ArrayList<ReplaceableAttribute> newAttributes = new ArrayList<ReplaceableAttribute>();
newAttributes.add(new ReplaceableAttribute("Title", title, false));
newAttributes.add(new ReplaceableAttribute("Starttime", Integer.toString(starttime), false));
newAttributes.add(new ReplaceableAttribute("Endtime", Integer.toString(endtime), false));
newAttributes.add(new ReplaceableAttribute("Day", Integer.toString(day), false));
PutAttributesRequest newRequest = new PutAttributesRequest();
newRequest.setDomainName(myDomain);
newRequest.setItemName(UUID.randomUUID().toString()); // Random item name
newRequest.setAttributes(newAttributes);

sdb.putAttributes(newRequest); 
} catch (AmazonServiceException ase) {
handleExceptions(ase);
} catch (AmazonClientException ace) {
handleExceptions(ace);
}
}

After pasting, right-click and choose Source->Organize Imports to ensure that all the correct libraries are imported at top.

 

Coding: Now, modify ScheduleServlet to call this class, instead of storing the data in the session.

Comment out this line:

req.getSession().setAttribute("schoolschedule", schedule);

Replace these two lines inside the for-loop...

SchoolClass clazz = new SchoolClass(title, starttime, endtime, day);
schedule.addClass(clazz);

... with code that calls our database manager instead:

PrintWriter out = resp.getWriter();
DBManage myDB = new DBManage(out);
myDB.storeClass(title, starttime, endtime, day);
// TODO: A more elegant (and faster) storeClass solution
// would be passed an array of multiple classes, and then
// use Amazon's BatchPutAttributes() API to store multiple
// items at once in SimpleDB. (More efficient that way)

After pasting, right-click and choose Source->Organize Imports to ensure that all the correct libraries are imported at top.

 

Run your application using the existing environment.

Checkpoint 4 - Load your Schedule.jsp page, submit some test data, and show me the data saved in your SimpleDB domain.
(Use the Eclipse SimpleDB browser in the AWS Management Perspective)
You should not see data in the resulting schedule anymore - we commented out the old session functionality.

 

SimpleDB - Loading Data

Finally, let's augment the management class so we can retrieve records from SimpleDB.

Coding: Add the following method to DBManage to read all records from the domain and produce a single SchoolSchedule container.

// Populate a new SchoolSchedule with data previously saved into a domain
public SchoolSchedule loadSchedule()
{
SchoolSchedule newSchedule = new SchoolSchedule();

String title="";
int startTime=0;
int endTime=0;
int day=0;

try {
// Select data from a domain
// Notice the use of backticks around the domain name in our select expression.
//String selectExpression = "select * from `" + myDomain + "` where Category = 'Clothes'";
String selectExpression = "select * from `" + myDomain + "`";
SelectRequest selectRequest = new SelectRequest(selectExpression);
for (Item item : sdb.select(selectRequest).getItems()) {
// For item name, use: item.getName());
//out.println("Name=" + item.getName() + ",Attribute=" + attribute.getName() + ",Value=" + attribute.getValue());

// Got a single item from SimpleDB
for (Attribute attribute : item.getAttributes()) {
if(attribute.getName().equals("Title"))
title = attribute.getValue();
else if(attribute.getName().equals("Starttime"))
startTime = Integer.valueOf(attribute.getValue());
else if(attribute.getName().equals("Endtime"))
endTime = Integer.valueOf(attribute.getValue());
else if(attribute.getName().equals("Day"))
day = Integer.valueOf(attribute.getValue());
}

out.println("<pre>");
out.println("Loading SchoolClass from SimpleDB: "
+ "title=" + title
+ ",startTime=" + startTime
+ ",endTime=" + endTime
+ ",day=" + day);
out.println("</pre>");
newSchedule.addClass(new SchoolClass(title, startTime, endTime, day));
}
} catch (AmazonServiceException ase) {
handleExceptions(ase);
} catch (AmazonClientException ace) {
handleExceptions(ace);
}
return newSchedule;
}

After pasting, right-click and choose Source->Organize Imports to ensure that all the correct libraries are imported at top.

 

Coding: Modify Schedule.jsp to call this new database code before the page is displayed. First, include some libraries at top:

<%@ page import="com.jeffshafer.classschedule.SchoolSchedule" %>
<%@ page import="com.jeffshafer.simpledb.DBManage" %>
<%@ page import="java.io.PrintWriter" %>

Second, place this block right after the <BODY> tag (or at some other convenient spot):

<%
// Populate the schedule from SimpleDB
SchoolSchedule mySchedule = new SchoolSchedule();
PrintWriter outputPrinter = new PrintWriter(out);
DBManage myDB = new DBManage(outputPrinter);
mySchedule = myDB.loadSchedule();

// Hack: Save the schedule to session, so that existing tutorial code
// (see below) can load it back out and display it
request.getSession().setAttribute("schoolschedule", mySchedule);
%>

 

Run your application using the existing environment.

Checkpoint 5 - Show me the following process:
(1) Clearing domain via Eclipse
(2) Creating domain via administrative web page
(3) Adding a new record via Schedule.jsp, and
(4) Viewing the new record via Schedule.jsp.

 

Cleanup

Shut down the EC2 instance(s) used in your environment:

  • Log onto the Amazon web control panel
  • Choose Elastic Beanstalk tab
  • Find your application in the dropdown box (See why we tagged it with your name?)
  • Select Actions->"Terminate this Environment" to stop your running instance(s) of your app

You could also accomplish this same tasks from Eclipse!   Click the Amazon logo and choose "Open AWS Management Perspective", and then browse the entries under "AWS Explorer". There is a LOT here!

 

Delete the Elastic Beanstalk Application and saved versions:

  • Log onto the Amazon web control planel
  • Choose Elastic Beanstalk tab
  • Find your application in the dropdown box
  • Select Versions tab
  • Check all checkboxes next to the version(s) listed, click "Delete Versions"
  • Choose "Delete version from Amazon S3 as well" and click "Yes, Delete"
  • Go back to the Overview sub-tab, and choose "Delete Application"

 

Delete the SimpleDB Domain

  • In Eclipse, switch to the AWS Management Perspective
  • Locate SimpleDB in the list of services at left, and expand the list
  • Right-click on your domain (YOURNAME-Schedule) and choose Delete Domain

 

Delete the Elastic Beanstalk Environment in Eclipse

  • Note: I didn't have to do this with each new application version. But, if I shut down the instances for the night, in the morning I need to clear out this setting in Eclipse in order to publish new applications.
  • In Eclipse, go to Preferences->Server->Run-Time Environments
  • Select the "Tomcat 6 in Elastic Beanstalk" entry
  • Click remove

 

Complete Code Examples

For a quick start, try creating a new empty "AWS Java Web Project" and then copying in the desired source code.   Note that all the examples are from the "com.jeffshafer" package, not "org.yourname".

First version - Saving data only to web session

 

Second version - Saving data to SimpleDB