Sans Pareil Technologies, Inc.

Key To Your Business

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.

group 'mis283'

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>&nbsp;</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));
    }
}