Lab 3 - HTML, CSS and JavaScript
In this lab exercise we will develop a simple application that uses HTML, CSS and Javascript. We will create a simple HTML page that displays a form for creating a Person record. We will use a Servlet to handle the form POST, and use an internal JSP page to display the results of creating a Person.
Gradle
Modify the gradle build file and add dependencies for gretty, servlet API, JSTL, JavaMail and httpunit.
apply plugin: 'java' apply plugin: 'war' apply from: 'https://raw.github.com/akhikhl/gretty/master/pluginScripts/gretty.plugin' sourceCompatibility = 1.8 repositories { mavenCentral() } gretty { integrationTestTask = 'test' } dependencies { compile 'javax.servlet:javax.servlet-api:3.1.0' compile 'javax.mail:mail:1.5.0-b01' compile 'javax.servlet:jstl:1.2' testCompile group: 'junit', name: 'junit', version: '4.12’ testCompile 'org.httpunit:httpunit:1.7.2' }
HTML
Create a file named index.html under src/main/webapp. This file will be the default page for our application, and will present the user a simple form to be used to create Person records.
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Lab 3 - HTML & CSS</title> <link rel="stylesheet" type="text/css" href="styles.css"/> <script type="text/javascript"> function isEnoughLength(str,length) { if ((str == null) || isNaN(length)) return false; else if (str.length < length) return false; return true; } function hasMixedCase(passwd) { if (passwd.match(/([a-z].*[A-Z])|([A-Z].*[a-z])/)) return true; else return false; } function hasNumeral(passwd) { if(passwd.match(/[0-9]/)) return true; else return false; } function hasSpecialChars(passwd) { if(passwd.match(/.[!,@,#,$,%,^,&,*,?,_,~]/)) return true; else return false; } function checkPasswordStrength(pwd) { if (isEnoughLength(pwd,8) && hasMixedCase(pwd) && hasNumeral(pwd) && hasSpecialChars(pwd)) return true; else return false; } function submitForm(form) { var status = checkPasswordStrength(form.password.value); var element = document.getElementById("warning"); if (!status) { window.console && console.log("Password fails strength check"); element.style.display = "inline"; form.password.focus(); } else { element.style.display = "none"; } return status; } </script> </head> <body> <section> <h1>Create a Person</h1> <form id="createPerson" method="post" action="person/create" onsubmit="return submitForm(this);"> <label>First Name:</label> <input type="text" name="firstName" maxlength="50" required="required"/> <br/> <label>Middle Name:</label> <input type="text" name="middleName" maxlength="50"/> <br/> <label>Last Name:</label> <input type="text" name="lastName" maxlength="50" required="required"/> <br/> <br/> <label>E-mail:</label> <input type="email" name="email" required="required"/> <br/> <label>Username:</label> <input type="text" name="username" required="required"/> <br/> <label>Password:</label> <input type="password" name="password" required="required"/> <q id="warning" style="display: none;">Weak password. Password should contain numbers, special characters, upper and lower case letters.</q> <br/> <label> </label><input type="submit" name="submit" value="Create"/> </form> </section> <footer> Demo application that illustrates HTML/CSS/JavaScript </footer> </body> </html>
CSS
Create a file named styles.css under src/main/webapp. This is the style file that we will use for our application.
body { font-family: 'DejaVu Sans', Arial, Helvetica, sans-serif; margin-left: 5em; margin-right: 5em; } label { float: left; font-weight: bold; width: 10em; } input[type="text"], input[type="password"], input[type="email"] { width: 20em; margin-left: 0.5em; margin-bottom: 0.5em; } input[type="submit"] { margin-left: 0.5em; margin-bottom: 0.5em; } .bold { font-weight: bold; } #warning { font-size: 80%; color: tan; }
Model
We will create a simple Java class that represents a Person. We will put it under a mis283.model package.
package mis283.model; import java.io.Serializable; import java.util.UUID; import static java.lang.String.format; public class Person implements Serializable { private static final long serialVersionUID = 7465010877201730658L; private final UUID id = UUID.randomUUID(); private String firstName; private String middleName; private String lastName; private String email; private String username; private transient String password; public String getName() { return notEmpty(middleName) ? format("%s %s %s", firstName, middleName, lastName) : format("%s %s", firstName, lastName); } public UUID getId() { return id; } public String getFirstName() { return firstName; } public void setFirstName(String firstName) { this.firstName = firstName; } public String getMiddleName() { return middleName; } public void setMiddleName(String middleName) { this.middleName = middleName; } public String getLastName() { return lastName; } public void setLastName(String lastName) { this.lastName = lastName; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public static boolean notEmpty(final String value) { return ((value != null) && !value.isEmpty()); } }
Controller
We will create a servlet class mis283.controller.PersonHandler. The servlet will handle the form POST requests from the HTML page.
package mis283.controller; import mis283.model.Person; import javax.mail.internet.AddressException; import javax.mail.internet.InternetAddress; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import static java.lang.String.format; import static mis283.model.Person.notEmpty; @WebServlet(urlPatterns = "/person/create") public class PersonHandler extends HttpServlet { @Override protected void doPost(final HttpServletRequest req, final HttpServletResponse resp) throws ServletException, IOException { final Person person = createBean(req); if (!validate(person)) { resp.sendRedirect(format(“%s/index.html”, req.getContextPath())); return; } req.setAttribute("person", person); getServletContext().getRequestDispatcher("/private/personView.jsp").forward(req, resp); } private boolean validate(final Person person) { boolean value = notEmpty(person.getFirstName()) && notEmpty(person.getLastName()) && notEmpty(person.getEmail()) && notEmpty(person.getUsername()) && notEmpty(person.getPassword()); try { new InternetAddress(person.getEmail()); return value; } catch (final AddressException ignored) { return false; } } private Person createBean(final HttpServletRequest request) { final Person person = new Person(); person.setFirstName(request.getParameter("firstName")); person.setMiddleName(request.getParameter("middleName")); person.setLastName(request.getParameter("lastName")); person.setEmail(request.getParameter("email")); person.setUsername(request.getParameter("username")); person.setPassword(request.getParameter("password")); return person; } }
View
We will create a hidden JSP file as src/mainwebapp/private/personView.jsp which will display the information that was submitted from the HTML form.
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <html> <head> <title>Person - ${person.name}</title> <link rel="stylesheet" type="text/css" href="../styles.css"/> </head> <body> <section> <h1>Newly created Person</h1> <label>Person ID:</label><q id="id">${person.id}</q><br/> <label>First Name:</label><q id="firstName">${person.firstName}</q><br/> <c:if test=“${!empty person.middleName}"> <label>Middle Name:</label><q id="middleName">${person.middleName}</q><br/> </c:if> <label>Last Name:</label><q id="lastName">${person.lastName}</q><br/> <label>E-mail:</label><q id="email">${person.email}</q><br/> <label>Username:</label><q id="username">${person.username}</q><br/> </section> <footer> Demo application that illustrates HTML/CSS/JavaScript </footer> </body> </html>
Test
We will add a HttpUnit test suite for our application. We will test the application through the HTML page, as well as by directly submitting information to the servlet.
package mis283; import com.meterware.httpunit.GetMethodWebRequest; import com.meterware.httpunit.HTMLElement; import com.meterware.httpunit.PostMethodWebRequest; import com.meterware.httpunit.WebConversation; import com.meterware.httpunit.WebForm; import com.meterware.httpunit.WebRequest; import com.meterware.httpunit.WebResponse; import org.junit.Test; import static mis283.model.Person.notEmpty; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; public class PersonCreateTest { private static final String firstName = "Unit"; private static final String middleName = "User"; private static final String lastName = "Test"; private static final String email = "unittest@test.com"; private static final String username = "unittest"; @Test public void index() throws Exception { final WebConversation wc = new WebConversation(); final WebRequest request = new GetMethodWebRequest( "http://localhost:8080/lab3/index.html" ); final WebResponse response = wc.getResponse( request ); final WebForm form = response.getFormWithID("createPerson"); form.setParameter("firstName", firstName); form.setParameter("lastName", lastName); form.setParameter("email", email); form.setParameter("username", username); form.setParameter("password", "!Q2e#E4r"); final WebResponse page = form.submit(); checkId(page); check(firstName, "firstName", page); check(lastName, "lastName", page); check(email, "email", page); check(username, "username", page); } @Test public void weakPassword() throws Exception { final WebConversation wc = new WebConversation(); final WebRequest request = new GetMethodWebRequest( "http://localhost:8080/lab3/" ); final WebResponse response = wc.getResponse( request ); WebForm form = response.getFormWithID("createPerson"); form.setParameter("firstName", firstName); form.setParameter("lastName", lastName); form.setParameter("email", email); form.setParameter("username", username); form.setParameter("password", “blah”); final WebResponse page = form.submit(); form = page.getFormWithID("createPerson"); check(firstName, "firstName", form); check(lastName, "lastName", form); check(email, "email", form); check(username, "username", form); } @Test public void servlet() throws Exception { final WebConversation wc = new WebConversation(); final WebRequest request = new PostMethodWebRequest( "http://localhost:8080/lab3/person/create" ); request.setParameter("firstName", firstName); request.setParameter("middleName", middleName); request.setParameter("lastName", lastName); request.setParameter("email", email); request.setParameter("username", username); request.setParameter("password", "!Q2e#E4r"); final WebResponse response = wc.getResponse( request ); checkId(response); check(firstName, "firstName", response); check(middleName, "middleName", response); check(lastName, "lastName", response); check(email, "email", response); check(username, "username", response); } private void checkId(final WebResponse response) throws Exception { final HTMLElement element = response.getElementWithID("id"); assertTrue(notEmpty(element.getText())); } private void check(final String value, final String id, final WebResponse response) throws Exception { final HTMLElement element = response.getElementWithID(id); assertEquals(value, element.getText()); } private void check(final String value, final String id, final WebForm form) throws Exception { assertEquals(value, form.getParameterValue(id)); } }