Java SE 8: Creating a Web App with Bootstrap and Tomcat Embedded for Oracle Application Container Cloud Service


Options



Before You Begin

Purpose

This tutorial shows you to create and deploy a simple standalone web application using Servlets, Java Server Pages (JSP), Bootstrap and Tomcat embedded so that you can deploy it to Oracle Application Container Cloud Service.

Time to Complete

60 minutes

Background

A web application is a software program that runs on a web server. Usually a web application is packaged in a WAR file and deployed in a server container like Tomcat, JBOSS, or GlassFish. However, embedded servers provide an interesting alternative. Instead of deploying your app in a server, the server is embedded in your application. The result is a standalone application packaged in a JAR file that can be executed from a command line.

A web application is usually divided in two parts: front-end and back-end. The back end (server side), of the application defines how the site works and is responsible for things like calculations, business logic, database interactions, and performance. The front-end is the part of the application that  web users interact with. It's usually a mixture of HTML, CSS, and JavaScript, all controlled by the browser.

Most modern web projects use some kind of standard framework to make web development faster, easier, and more standards compliant. Currently, Bootstrap is the most popular and widely used framework for creating web applications.

Bootstrap is a front-end framework that contains a collection of tools designed to allow developers to quickly create web applications. It includes design templates based on HTML and CSS for common user interface components like  forms, typography, buttons, navigations, tables,  tabs, dropdowns, alerts, modals, accordion, carousel and many other optional JavaScript extensions.

Bootstrap is simple to use and it's compatible with modern browsers such as Mozilla Firefox, Google Chrome, Safari, Internet Explorer, and Opera.

Scenario

In this tutorial you build a simple Java web application of employees that implements the CRUD (Create, Read, Update, and Delete) operations. The application uses Bootstrap to add User Interface styles, Tomcat as embedded server and Maven to compile and package the dependencies needed to run a standalone web application.

Context

This tutorial covers developing and packaging your application. To learn how to deploy your application see: Deploying an Application to Oracle Application Container Cloud Service.

What Do You Need?

Creating a Maven Project

In this section, you create a basic Maven project from an archetype.

The first time that you execute any Maven command, Maven downloads all the plugins and related dependencies to fulfill the command. From a clean installation of Maven, this can take quite a while based on the internet connection. If you create another project, Maven won't need to download anything new and can execute the command much faster.

  1. Open a command-line window (or terminal in Linux).

  2. Go to the directory where you want to store the project.

  3. Execute the Maven command to generate the project:

    mvn archetype:generate -DarchetypeArtifactId=maven-archetype-webapp -DarchetypeGroupId=org.apache.maven.archetypes -DinteractiveMode=false -DgroupId=com.example.employees -DartifactId=employees-app -DarchetypeVersion=1.0

Ignore any warnings that you see during project creation. They won't affect the correct execution of the command.

This command creates a standard Maven structure. When execution completes, you should see the new employees-app project directory in your current location.

You can change the groupId and artifactId of this command for your particular project.

You can open the project in NetBeans (File -> Open project) or in Eclipse (File -> Import -> Maven-> Existing Maven Project) but you must configure Maven in the IDE. Make sure that the IDE supports java 8. Version 7.4 (or later) of NetBeans includes support for JDK 8.

Configuring the pom.xml File

In this section, you configure the dependencies required to run Tomcat in an embedded mode and the plugins to compile and package the project in a single uber JAR.

Java web applications require a web container, such as Tomcat, to run on. Installing and configuring a web container on each development machine can be time-consuming. Furthermore, other developers must manage the dependencies manually if they want to run the web application.

Maven has a Tomcat plugin that allows you to run an embedded Tomcat instance without installing a local Tomcat server.

Adding Maven Dependencies

  1. Open the pom.xml located in the project root directory.

  2. Add the <properties> tags with the tomcat version property before the <dependencies> tags.

    <properties>
        <tomcat.version>7.0.57</tomcat.version>
    </properties> 
  3. Add the following dependencies in the <dependencies> tags:

    <dependencies>
        <dependency>
            <groupId>org.apache.tomcat.embed</groupId>
            <artifactId>tomcat-embed-core</artifactId>
            <version>${tomcat.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.tomcat.embed</groupId>
            <artifactId>tomcat-embed-logging-juli</artifactId>
            <version>${tomcat.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.tomcat.embed</groupId>
            <artifactId>tomcat-embed-jasper</artifactId>
            <version>${tomcat.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.tomcat</groupId>
            <artifactId>tomcat-jasper</artifactId>
            <version>${tomcat.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.tomcat</groupId>
            <artifactId>tomcat-jasper-el</artifactId>
            <version>${tomcat.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.tomcat</groupId>
            <artifactId>tomcat-jsp-api</artifactId>
            <version>${tomcat.version}</version>
        </dependency>
        <dependency>
            <groupId>jstl</groupId>
            <artifactId>jstl</artifactId>
            <version>1.2</version>
        </dependency>
    </dependencies>
    

JSTL (JSP Standard Tag Library) is a JSP-based standard tag library that offers a collection of tags to control the flow in the JSP page, date/number formatting and internationalization facilities, and several utility EL functions.

Adding Build Plugins

In this section, you add code to configure the following plugins:

  • The Maven Compiler Plugin (maven-compiler-plugin) is used to compile the sources of the project.
  • The Maven Assembly Plugin (maven-assembly-plugin) allows users to aggregate the project output along with its dependencies, modules, site documentation, and other files into a single distributable archive.

Build plugins are executed during the build. You configure the plugins in the <build> element of the POM.

  1. To add the <build> element containing the <plugins> section, copy and paste the following code into the pom.xml file:

    <build>
      <finalName>employees-app</finalName>
      <resources>
          <resource>
              <directory>src/main/webapp</directory>
              <targetPath>META-INF/resources</targetPath>
          </resource>
      </resources>
      <plugins>
          <plugin>
              <groupId>org.apache.maven.plugins</groupId>
              <artifactId>maven-compiler-plugin</artifactId>
              <version>2.3.2</version>
              <inherited>true</inherited>
              <configuration>
                  <source>1.8</source>
                  <target>1.8</target>
              </configuration>          
          </plugin>      
          <plugin>
              <groupId>org.apache.maven.plugins</groupId>
              <artifactId>maven-assembly-plugin</artifactId>
              <configuration>
                  <descriptorRefs>
                      <descriptorRef>jar-with-dependencies</descriptorRef>
                  </descriptorRefs>
                  <finalName>${project.build.finalName}-${project.version}</finalName>
                  <archive>
                      <manifest>
                          <mainClass>com.example.employees.Main</mainClass>
                      </manifest>
                  </archive>
              </configuration>
              <executions>
                  <execution>
                      <phase>package</phase>
                      <goals>
                          <goal>single</goal>
                      </goals>
                  </execution>
              </executions>
          </plugin>     
      </plugins>
    </build>            

Usually Maven ignores all but .java files in src/main/java when tasks such as compile and package are executed. The <resource> tag is used to include the jsp, css, js and fonts files in the JAR like resources.

Creating an Employee Class Model

To model the Employee representation, create a plain old Java class with fields, constructors, and accessors for the fields.

  1. Create the package java.com.example.employees in the main directory.
  2. Create the Employee.java class by copying and pasting the following code into the package:
  3. /* Copyright © 2015 Oracle and/or its affiliates. All rights reserved. */
    package com.example.employees;
    
    import java.util.concurrent.atomic.AtomicLong;
    
    public class Employee {
    
        private long id;
        private String name;
        private String lastName;
        private String birthDate;
        private String role;
        private String department;
        private String email;
        private static final AtomicLong counter = new AtomicLong(100);
    
        public Employee(String name, String lastName, String birthDate, String role, String department, String email, long id) {
            this.name = name;
            this.lastName = lastName;
            this.birthDate = birthDate;
            this.role = role;
            this.department = department;
            this.email = email;     
            this.id = id;
        }
        
        public Employee(String name, String lastName, String birthDate, String role, String department, String email) {
            this.name = name;
            this.lastName = lastName;
            this.birthDate = birthDate;
            this.role = role;
            this.department = department;
            this.email = email;     
            this.id = counter.incrementAndGet();
        }
    
        public long getId() {
            return id;
        }
    
        public void setId(long id) {
            this.id = id;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public String getLastName() {
            return lastName;
        }
    
        public void setLastName(String lastName) {
            this.lastName = lastName;
        }
    
        public String getBirthDate() {
            return birthDate;
        }
    
        public void setBirthDate(String birthDate) {
            this.birthDate = birthDate;
        }
    
        public String getRole() {
            return role;
        }
    
        public void setRole(String role) {
            this.role = role;
        }
    
        public String getDepartment() {
            return department;
        }
    
        public void setDepartment(String department) {
            this.department = department;
        }
    
        public String getEmail() {
            return email;
        }
    
        public void setEmail(String email) {
            this.email = email;
        }
    
        @Override
        public String toString() {
            return "Employee{" + "id=" + id + ", name=" + name + 
                    ", lastName=" + lastName + ", birthDate=" + birthDate + 
                    ", role=" + role + ", department=" + department + 
                    ", email=" + email + '}';
        }    
    }
    
  4. Create the EmployeeList class in the same package by copying and pasting the following code:

    /* Copyright © 2015 Oracle and/or its affiliates. All rights reserved. */
    package com.example.employees;
    
    import java.util.ArrayList;
    import java.util.List;
    
    
    public class EmployeeList {
        private static final List<Employee> employeeList = new ArrayList();
        
        private EmployeeList(){
        }
        
        static{
            employeeList.add(new Employee("John","Smith","12-12-1980","Manager","Sales","john.smith@abc.com"));
            employeeList.add(new Employee("Laura","Adams","02-11-1979","Manager","IT","laura.adams@abc.com"));
            employeeList.add(new Employee("Peter","Williams","22-10-1966","Coordinator","HR","peter.williams@abc.com"));
            employeeList.add(new Employee("Joana","Sanders","11-11-1976","Manager","Marketing","joana.sanders@abc.com"));
            employeeList.add(new Employee("John","Drake","18-08-1988","Coordinator","Finance","john.drake@abc.com"));
            employeeList.add(new Employee("Samuel","Williams","22-03-1985","Coordinator","Finance","samuel.williams@abc.com"));
        }
        
        public static List <Employee> getInstance(){
            return employeeList;
        }
    }
    

    Because this is a simple example, this tutorial doesn't use a database to store Employee objects. Instead, you use an ArrayList, and store the Employee objects in memory.

    This class contains two constructors. The first constructor receives all the fields including the id. The second constructor creates a new ID for the employee. You use this to create a new employee.

    The preceding code added six employees to the list so that you have some data to retrieve for testing purposes.

Building a Search Page

In this section, you create a user interface to search for employees that match name or last name.

  1. Create the EmployeeService.java class in the com.example.employees package by copying and pasting the following code:

    /* Copyright © 2015 Oracle and/or its affiliates. All rights reserved. */
    package com.example.employees;
    
    import java.util.Comparator;
    import java.util.List;
    import java.util.Optional;
    import java.util.function.Predicate;
    import java.util.stream.Collectors;
    
    
    public class EmployeeService {
    
        List<Employee> employeeList = EmployeeList.getInstance();
    
        public List<Employee> getAllEmployees() {       
            return employeeList;
        }
    
        public List<Employee> searchEmployeesByName(String name) {
            Comparator<Employee> groupByComparator = Comparator.comparing(Employee::getName)
                                                        .thenComparing(Employee::getLastName);
            List<Employee> result = employeeList
                    .stream()
                    .filter(e -> e.getName().equalsIgnoreCase(name) || e.getLastName().equalsIgnoreCase(name))
                    .sorted(groupByComparator)
                    .collect(Collectors.toList());
            return result;
        }
    
        public Employee getEmployee(long id) throws Exception {
            Optional<Employee> match
                    = employeeList.stream()
                    .filter(e -> e.getId() == id)
                    .findFirst();
            if (match.isPresent()) {
                return match.get();
            } else {
                throw new Exception("The Employee id " + id + " not found");
            }
        }   
    }

    This class contains an instance of EmployeeList and three methods to retrieve the employees using Lambda expressions.

  2. Create the EmployeeServlet.java class in the java.com.example.employees package:

    @WebServlet(
            name = "EmployeeServlet",
            urlPatterns = {"/employee"}
    )
    public class EmployeeServlet extends HttpServlet {
        EmployeeService employeeService = new EmployeeService();

    The @WebServlet annotation is used to declare a servlet instead of using XML in the web deployment descriptor (web.xml) . The annotation is processed by the container at deployment time.

  3. Override the doGetmethod:

    @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            String action = req.getParameter("searchAction");
            if (action!=null){
                switch (action) {           
                case "searchById":
                    searchEmployeeById(req, resp);
                    break;           
                case "searchByName":
                    searchEmployeeByName(req, resp);
                    break;
                }
            }else{
                List<Employee> result = employeeService.getAllEmployees();
                forwardListEmployees(req, resp, result);
            }
        } 

    The doGet method is used to process the HTTP GET request. In this it's implemented to process three kinds of searches: by Id, by Name, and by default the complete list of employees.

    The searchAction parameter is used to determine what kind of search it will be executed.

  4. Create the searchEmployeeById, searchEmployeeByName, and forwardListEmployees methods:

      private void searchEmployeeById(HttpServletRequest req, HttpServletResponse resp)
                throws ServletException, IOException {
            long idEmployee = Integer.valueOf(req.getParameter("idEmployee"));
            Employee employee = null;
            try {
                employee = employeeService.getEmployee(idEmployee);
            } catch (Exception ex) {
                Logger.getLogger(EmployeeServlet.class.getName()).log(Level.SEVERE, null, ex);
            }
            req.setAttribute("employee", employee);
            req.setAttribute("action", "edit");
            String nextJSP = "/jsp/new-employee.jsp";
            RequestDispatcher dispatcher = getServletContext().getRequestDispatcher(nextJSP);
            dispatcher.forward(req, resp);
        }
        
        private void searchEmployeeByName(HttpServletRequest req, HttpServletResponse resp)
                throws ServletException, IOException {
            String employeeName = req.getParameter("employeeName");
            List<Employee> result = employeeService.searchEmployeesByName(employeeName);        
            forwardListEmployees(req, resp, result);
        }
    
        private void forwardListEmployees(HttpServletRequest req, HttpServletResponse resp, List employeeList)
                throws ServletException, IOException {
            String nextJSP = "/jsp/list-employees.jsp";
            RequestDispatcher dispatcher = getServletContext().getRequestDispatcher(nextJSP);
            req.setAttribute("employeeList", employeeList);
            dispatcher.forward(req, resp);
        }    

    The forwardListEmployees method is a helper method to dispatch the employee list to list-employees.jsp. It's in a separate method because the code is reused in other operations.

Creating the User Interface

In this section, you build a user interface to search employees by name or last name and show the results that match in a table. You use Bootstrap to add some styles like the light-blue button and shaded rows you see in the following figure.

UI Employee Search
Description of this image

There are two ways to start using Bootstrap on your website:

  • Download Bootstrap from getbootstrap.com.
  • Include Bootstrap from a Content Delivery Network (CDN).

In this tutorial you download the precompiled and minified versions of Bootstrap CSS, JavaScript and fonts from getbootstrap.com and add them to your project.

  1. Copy the directories js, fonts, and css from the Bootstrap zip to the webapp folder.

    Project structure
    Description of this image
  2. Delete the non-minified versions of the CSS and JS files.

    Delete non-minified versions
    Description of this image

    The minified files are compressed versions of the CSS and JavaScript so they download faster.

  3. Create the list-employees.jsp file in a new folder named jsp under the webapp folder.

  4. Add the bootstrap.min.js and bootstrap.min.css files to the jsp folder:

    <link rel="stylesheet" href="../css/bootstrap.min.css">   		
    <script src="../js/bootstrap.min.js"></script>     
  5. Add taglib for JSTL support:

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

    list-employees.jsp - Fragment

    <div class="container"> 
      <h2>Employees</h2>
      <!--Search Form -->
      <form action="/employee" method="get" id="seachEmployeeForm" role="form" >
        <input type="hidden" id="searchAction" name="searchAction" value="searchByName"/>
        <div class="form-group col-xs-5">
            <input type="text" name="employeeName" id="employeeName" class="form-control" required="true" 
                     placeholder="Type the Name or Last Name of the employee"/>                    
        </div>
        <button type="submit" class="btn btn-info">
            <span class="glyphicon glyphicon-search"></span> Search
        </button>
        <br></br>
        <br></br>
      </form>
    </div> 

    Individual form controls (input, textarea and select) automatically receive some global styling with Bootstrap.

    Bootstrap requires a containing element to wrap site contents. The container class is used for a responsive fixed-width container.

    The required attribute introduced in HTML5 specifies that the user must enter a value before submitting the form.  Bootstrap validates the required fields before submitting the form and shows a predefined message if a field is missing. You can override this behavior by coding your specific rules and messages using jQuery.

    The placeholder is another attribute introduced in HTML5 that describes the expected value of the input field.

    The class .btn provides the default look of a gray button with rounded corners. The btn-info class gives the button the light-blue color that's typically used for informational alert messages.

    Bootstrap includes 200 glyphs from the Glyphicons Halflings set. Glyphicons Halflings aren't usually available for free, although some basic icons are available for Bootstrap free of cost. For example, the btn-info class provides the magnifying glass icon.

  7. Add the table to display the result of the search. Make sure the new form is enclosed in <div class="container"> tags.

    list-employees.jsp - Fragment

    <form action="/employee" method="post" id="employeeForm" role="form" >    
      <c:choose>
          <c:when test="${not empty employeeList}">
              <table  class="table table-striped">
                  <thead>
                      <tr>
                          <td>#</td>
                          <td>Name</td>
                          <td>Last name</td>
                          <td>Birth date</td>
                          <td>Role</td>
                          <td>Department</td>
                          <td>E-mail</td>
                      </tr>
                  </thead>
                  <c:forEach var="employee" items="${employeeList}">
                      <c:set var="classSuccess" value=""/>
                      <c:if test ="${idEmployee == employee.id}">                       	
                          <c:set var="classSuccess" value="info"/>
                      </c:if>
                      <tr class="${classSuccess}">
                          <td>${employee.id}</td>
                          <td>${employee.name}</td>
                          <td>${employee.lastName}</td>
                          <td>${employee.birthDate}</td>
                          <td>${employee.role}</td>
                          <td>${employee.department}</td>
                          <td>${employee.email}</td>                        
                      </tr>
                  </c:forEach>               
              </table>  
          </c:when>                    
          <c:otherwise>
          <br>  </br>           
              <div class="alert alert-info">
                  No people found matching your search criteria
              </div>
          </c:otherwise>
      </c:choose>                        
    </form>

    employeeList is the attribute that contains the employee search results. This fragment of code iterates the employeeList to display the employee information. If no results match the search, then an alert message is displayed.

    The .table-striped class adds the zebra-striping style to any table row.

    Bootstrap has four contextual classes (.alert-success, .alert-info, .alert-warning, .alert-danger) that provide a way to style messages to the user.

    <div class="alert alert-success">Success! Well done it's submitted.</div>
    <div class="alert alert-info">Info! take this info.</div>
    <div class="alert alert-warning">Warning ! Don't submit this.</div>
    <div class="alert alert-danger">Error ! Change a few things.</div>
  8. Review the code. Your code should look like the following:

    <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
    <html>
        <head>
           <link rel="stylesheet" href="../css/bootstrap.min.css"/>         
           <script src="../js/bootstrap.min.js"></script>       
        </head>
    
        <body>          
            <div class="container">
                <h2>Employees</h2>
                <!--Search Form -->
                <form action="/employee" method="get" id="seachEmployeeForm" role="form">
                    <input type="hidden" id="searchAction" name="searchAction" value="searchByName">
                    <div class="form-group col-xs-5">
                        <input type="text" name="employeeName" id="employeeName" class="form-control" required="true" placeholder="Type the Name or Last Name of the employee"/>                    
                    </div>
                    <button type="submit" class="btn btn-info">
                        <span class="glyphicon glyphicon-search"></span> Search
                    </button>
                    <br></br>
                    <br></br>
                </form>
                
                <!--Employees List-->
                <form action="/employee" method="post" id="employeeForm" role="form" >              
                   
                    <c:choose>
                        <c:when test="${not empty employeeList}">
                            <table  class="table table-striped">
                                <thead>
                                    <tr>
                                        <td>#</td>
                                        <td>Name</td>
                                        <td>Last name</td>
                                        <td>Birth date</td>
                                        <td>Role</td>
                                        <td>Department</td>
                                        <td>E-mail</td>                                 
                                    </tr>
                                </thead>
                                <c:forEach var="employee" items="${employeeList}">
                                    <c:set var="classSucess" value=""/>
                                    <c:if test ="${idEmployee == employee.id}">                        	
                                        <c:set var="classSucess" value="info"/>
                                    </c:if>
                                    <tr class="${classSucess}">
                                        <td>${employee.id}</td>
                                        <td>${employee.name}</td>
                                        <td>${employee.lastName}</td>
                                        <td>${employee.birthDate}</td>
                                        <td>${employee.role}</td>
                                        <td>${employee.department}</td>
                                        <td>${employee.email}</td>   
                                       
                                    </tr>
                                </c:forEach>               
                            </table>  
                        </c:when>                    
                        <c:otherwise>
                            <br>           
                            <div class="alert alert-info">
                                No people found matching your search criteria
                            </div>
                        </c:otherwise>
                    </c:choose>                        
                </form>           
            </div>
        </body>
    </html>
    
    
  9. Modify the index.jsp file to forward the content to the servlet:

    <jsp:forward page="/employee" /> 

Creating a Launcher Class

In this section, you create a class with a main method that creates an instance of the Tomcat server. This method is executed when you run the JAR file.

Create the Main class in the com.example.employees package:

/* Copyright © 2015 Oracle and/or its affiliates. All rights reserved. */
package com.example.employees;

import java.util.Optional;
import org.apache.catalina.startup.Tomcat;

public class Main {
    
    public static final Optional<String> port = Optional.ofNullable(System.getenv("PORT"));
    
    public static void main(String[] args) throws Exception {
        String contextPath = "/";
        String appBase = ".";
        Tomcat tomcat = new Tomcat();     
        tomcat.setPort(Integer.valueOf(port.orElse("8080") ));
        tomcat.getHost().setAppBase(appBase);
        tomcat.addWebapp(contextPath, appBase);
        tomcat.start();
        tomcat.getServer().await();
    }
}

With the org.apache.catalina.startup.Tomcat class, you can configure the port using the setPort method, and the context path using the addWebapp method.

Running the Web Application

This section shows, how to compile and run the web application using Maven commands.

Compiling and Running the Web Application

  1. Open a command-line window or terminal
  2. Go to the root directory of the project (employees-app), wherepom.xml resides.
  3. Compile the project: mvn clean compile.
  4. Package the application: mvn package.
  5. Look in the target directory. You should see a file with the following or a similar name: employees-app-1.0-SNAPSHOT-jar-with-dependencies.jar
  6. Change to the target directory.
  7. Execute the JAR: java -jar employees-app-1.0-SNAPSHOT-jar-with-dependencies.jar.

    Running employee app
    Description of this image

    The output indicates that employees-app is running on http://localhost:8080

Testing the Web Application

  1. Open the Firefox or Chrome web browser.

  2. Enter the following URL into the browser address window: http://localhost:8080

    Testing search operation
    Description of this image
  3. Enter a Name or Last Name (for example, Williams) and click Search.

    Testing search operation
    Description of this image.
  4. Search an employee name that doesn't exist in the preload list (for example, Ivan ).

    Testing search operation
    Description of this

    This is how the Bootstrap's class  alert-info looks for alert messages.

Adding Editing Operations

In this section, three new operations: Create, Remove, and Edit an employee.

Editing the Service

Open the EmployeeService.javaclass and add the new three operations:

EmployeeService.java - Fragment

public long addEmployee(Employee employee) {
        employeeList.add(employee);
        return employee.getId();
    }

    public boolean updateEmployee(Employee customer) {
        int matchIdx = 0;
        Optional<Employee> match = employeeList.stream()
                .filter(c -> c.getId() == customer.getId())
                .findFirst();
        if (match.isPresent()) {
            matchIdx = employeeList.indexOf(match.get());
            employeeList.set(matchIdx, customer);
            return true;
        } else {
            return false;
        }
    }

    public boolean deleteEmployee(long id) {
        Predicate<Employee> employee = e -> e.getId() == id;
        if (employeeList.removeIf(employee)) {
            return true;
        } else {
            return false;
        }
    }

Editing the Servlet

  1. Open the EmployeeServlet.javaclass and override the doPost method:

    EmployeeServlet.java - Fragment

    protected void doPost(HttpServletRequest req, HttpServletResponse resp)
                throws ServletException, IOException {       
            String action = req.getParameter("action");
            switch (action) {
                case "add":
                    addEmployeeAction(req, resp);
                    break;
                case "edit":
                    editEmployeeAction(req, resp);
                    break;            
                case "remove":
                    removeEmployeeByName(req, resp);
                    break;            
            }
    
        } 
  2. Add the addEmployeeAction,editEmployeeAction, and removeEmployeeByName methods:

    private void addEmployeeAction(HttpServletRequest req, HttpServletResponse resp)
                throws ServletException, IOException {
            String name = req.getParameter("name");
            String lastName = req.getParameter("lastName");
            String birthday = req.getParameter("birthDate");
            String role = req.getParameter("role");
            String department = req.getParameter("department");
            String email = req.getParameter("email");
            Employee employee = new Employee(name, lastName, birthday, role, department, email);
            long idEmployee = employeeService.addEmployee(employee);
            List<Employee> employeeList = employeeService.getAllEmployees();
            req.setAttribute("idEmployee", idEmployee);
            String message = "The new employee has been successfully created.";
            req.setAttribute("message", message);
            forwardListEmployees(req, resp, employeeList);
        }
    
        private void editEmployeeAction(HttpServletRequest req, HttpServletResponse resp)
                throws ServletException, IOException {
            String name = req.getParameter("name");
            String lastName = req.getParameter("lastName");
            String birthday = req.getParameter("birthDate");
            String role = req.getParameter("role");
            String department = req.getParameter("department");
            String email = req.getParameter("email");
            long idEmployee = Integer.valueOf(req.getParameter("idEmployee"));
            Employee employee = new Employee(name, lastName, birthday, role, department, email, idEmployee);
            employee.setId(idEmployee);
            boolean success = employeeService.updateEmployee(employee);
            String message = null;
            if (success) {
                message = "The employee has been successfully updated.";
            }
            List<Employee> employeeList = employeeService.getAllEmployees();
            req.setAttribute("idEmployee", idEmployee);
            req.setAttribute("message", message);
            forwardListEmployees(req, resp, employeeList);
        }  
    
        private void removeEmployeeByName(HttpServletRequest req, HttpServletResponse resp)
                throws ServletException, IOException {
            long idEmployee = Integer.valueOf(req.getParameter("idEmployee"));
            boolean confirm = employeeService.deleteEmployee(idEmployee);
            if (confirm){
                String message = "The employee has been successfully removed.";
                req.setAttribute("message", message);
            }
            List<Employee> employeeList = employeeService.getAllEmployees();
            forwardListEmployees(req, resp, employeeList);
        }

Editing the View

  1. Open the list-employee.jsp file.
  2. Add two hidden input elemments in the employeeFormform:

    <input type="hidden" id="idEmployee" name="idEmployee">
    <input type="hidden" id="action" name="action">

    These inputs are used to pass the values of idEmployee and type of action to the servlet and execute the corresponding action.

  3. Add a div above the employeeForm form to display an alert message:

    <c:if test="${not empty message}">                
        <div class="alert alert-success">
            ${message}
        </div>
    </c:if> 
  4. Add a link to the first column (#):

    <td>
      <a href="/employee?idEmployee=${employee.id}&searchAction=searchById">${employee.id}</a>
    </td> 

    Use this link to display the values for a particular employee on an edit page.

  5. Add a new column next to the E-mail column for the remove button:

    <td>
      <a href="#" id="remove" 
         onclick="document.getElementById('idEmployee').value='${employee.id}';
                  document.getElementById('action').value='remove';
                  document.getElementById('employeeForm').submit();"> 
          <span class="glyphicon glyphicon-trash"/>
      </a>
    </td> 

    The glyphicon-trash provides a trash can icon.

  6. Add a new form below the employeeForm form with a button for creating a new employee. Make sure that the new form is enclosed in <div class="container"> tags.

    <form action ="jsp/new-employee.jsp">            
        <br></br>
        <button type="submit" class="btn btn-primary  btn-md">New employee</button> 
    </form>
  7. Review the code. Your code should look like the following:

     <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
    <html>
        <head>
            <link rel="stylesheet" href="../css/bootstrap.min.css">   		
            <script src="../js/bootstrap.min.js"></script>       
        </head>
    
        <body>          
            <div class="container">
                <h2>Employees</h2>
                <!--Search Form -->
                <form action="/employee" method="get" id="seachEmployeeForm" role="form">
                    <input type="hidden" id="searchAction" name="searchAction" value="searchByName">
                    <div class="form-group col-xs-5">
                        <input type="text" name="employeeName" id="employeeName" class="form-control" required="true" placeholder="Type the Name or Last Name of the employee"/>                    
                    </div>
                    <button type="submit" class="btn btn-info">
                        <span class="glyphicon glyphicon-search"></span> Search
                    </button>
                    <br></br>
                    <br></br>
                </form>
    
                <!--Employees List-->
                <c:if test="${not empty message}">                
                    <div class="alert alert-success">
                        ${message}
                    </div>
                </c:if> 
                <form action="/employee" method="post" id="employeeForm" role="form" >              
                    <input type="hidden" id="idEmployee" name="idEmployee">
                    <input type="hidden" id="action" name="action">
                    <c:choose>
                        <c:when test="${not empty employeeList}">
                            <table  class="table table-striped">
                                <thead>
                                    <tr>
                                        <td>#</td>
                                        <td>Name</td>
                                        <td>Last name</td>
                                        <td>Birth date</td>
                                        <td>Role</td>
                                        <td>Department</td>
                                        <td>E-mail</td>
                                        <td></td>
                                    </tr>
                                </thead>
                                <c:forEach var="employee" items="${employeeList}">
                                    <c:set var="classSucess" value=""/>
                                    <c:if test ="${idEmployee == employee.id}">                        	
                                        <c:set var="classSucess" value="info"/>
                                    </c:if>
                                    <tr class="${classSucess}">
                                        <td>
                                            <a href="/employee?idEmployee=${employee.id}&searchAction=searchById">${employee.id}</a>
                                        </td>                                    
                                        <td>${employee.name}</td>
                                        <td>${employee.lastName}</td>
                                        <td>${employee.birthDate}</td>
                                        <td>${employee.role}</td>
                                        <td>${employee.department}</td>
                                        <td>${employee.email}</td>   
                                        <td><a href="#" id="remove" 
                                               onclick="document.getElementById('action').value = 'remove';document.getElementById('idEmployee').value = '${employee.id}';
                                                        
                                                        document.getElementById('employeeForm').submit();"> 
                                                <span class="glyphicon glyphicon-trash"/>
                                            </a>
                                                       
                                        </td>
                                    </tr>
                                </c:forEach>               
                            </table>  
                        </c:when>                    
                        <c:otherwise>
                            <br>           
                            <div class="alert alert-info">
                                No people found matching your search criteria
                            </div>
                        </c:otherwise>
                    </c:choose>                        
                </form>
                <form action ="jsp/new-employee.jsp">            
                    <br></br>
                    <button type="submit" class="btn btn-primary  btn-md">New employee</button> 
                </form>
            </div>
        </body>
    </html>
  8. Create the new-employee.jsp file in the jsp directory:

    <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
    <html>
        <head>
           <link rel="stylesheet" href="../css/bootstrap.min.css"/>   		
           <script src="../js/bootstrap.min.js"></script>   
        </head>
        <body>
            <div class="container">
                <form action="/employee" method="post"  role="form" data-toggle="validator" >
                    <c:if test ="${empty action}">                        	
                        <c:set var="action" value="add"/>
                    </c:if>
                    <input type="hidden" id="action" name="action" value="${action}"/>
                    <input type="hidden" id="idEmployee" name="idEmployee" value="${employee.id}"/>
                    <h2>Employee</h2>
                    <div class="form-group col-xs-4">
                        <label for="name" class="control-label col-xs-4">Name:</label>
                        <input type="text" name="name" id="name" class="form-control" value="${employee.name}" 
                            required="true"/>                                   
    
                        <label for="lastName" class="control-label col-xs-4">Last name:</label>                   
                        <input type="text" name="lastName" id="lastName" class="form-control" value="${employee.lastName}" 
                            required="true"/> 
    
                        <label for="birthdate" class="control-label col-xs-4">Birth date</label>                 
                        <input type="text"  pattern="^\d{2}-\d{2}-\d{4}$" name="birthDate" id="birthdate" class="form-control" 
                            value="${employee.birthDate}" maxlength="10" placeholder="dd-MM-yyyy" required="true"/>
    
                        <label for="role" class="control-label col-xs-4">Role:</label>                    
                        <input type="text" name="role" id="role" class="form-control" value="${employee.role}" 
                            required="true"/> 
    
                        <label for="department" class="control-label col-xs-4">Department:</label>
                        <input type="text" name="department" id="department" class="form-control" 
                            value="${employee.department}" required="true"/>
    
                        <label for="department" class="control-label col-xs-4">E-mail:</label>                   
                        <input type="text" name="email" id="email" class="form-control" value="${employee.email}" 
                            placeholder="smith@aol.com" required="true"/>
    
                        <br></br>
                        <button type="submit" class="btn btn-primary  btn-md">Accept</button> 
                    </div>                                                      
                </form>
            </div>
        </body>
    </html>

    This jsp contains a form to add a new employee or edit an existing one. All fields are marked as required.

    The data-toggle="validator" attribute automatically enables form validation for the form element.

    The pattern attribute introduced in HTML5 specifies a JavaScript regular expression for the field’s value to be checked against. This form is used in the birthdate field to validate the format (dd-MM-yyyy).

Testing the New Operations: Create, Edit, and Remove

Running the Web Application

  1. Stop the application (if it'd running).
  2. Reexecute the steps in Compiling and Running the Web Application.
  3. Enter the following URL into the browser address window: http://localhost:8080

    Testing search operation
    Description of this image

Testing the New Employee Feature

  1. Click New employee

    Testing new employee
    Description of this image
  2. Fill in all the fields.

    Note: Try submitting the form leaving one inputbox empty, and see what happens.

    Testing new employee
    Description of this image
  3. Click Accept.

    Testing new employee
    Description of this image

Testing the Remove Feature

  1. Click the trash can icon to delete the employee (for example the 102 employee).

    Testing remove employee
    Description of this image

Testing the Edit Feature

  1. Click the ID number.

    Testing edit employee
    Description of this image
  2. Edit some fields.

    Testing edit employee
    Description of this image
  3. Click Accept.

    Testing edit employee
    Description of this image

    As you can see, Bootstrap is a powerful front-end framework. This tutorial provides the basics to get you started and show you how easy it is to use.

Developing an Application for Cloud Deployment

To properly package, deploy, and execute your application in Oracle Application Container Cloud Service you must understand the concepts in this section.

Container Considerations

Oracle Application Container Cloud Service applications are run in Docker containers. Docker is an open-source software container project. Think of a container as very lightweight virtual machine. Your application runs in its own isolated execution space that has its own memory, file system, and network access. Access to these operating system resources without the cost of having to implement an entire virtual operating system.

When you deploy your application to Oracle Application Container Cloud Service, a container is dynamically generated for your application. The implication of this is that all the typical configuration information, like host name and port number, are also dynamically generated. Therefore, any application that runs in this environment must be read key configuration information from the environment before the application starts.

Additionally, containers for your application can be dynamically allocated to scale up or down as is required by the application load. This dynamic scaling feature is made possible by the load balancers provided by Oracle Application Container Cloud Service. The balancer routes traffic to the application instances thus "balancing" the load.

Given the setup of the service, this has implications for your applications.

Application Considerations for Running in a Container

For an application to run properly on Oracle Application Container Cloud Service, there are a few requirements that must be met.

  • The applications must be stateless: Because the service can run multiple instances of the same application, applications can't share state. For example, items added to a shopping cart application on one instance would not be available to other instances of the application. Because application load is balanced between instances, there is no guarantee that the next request will be handled by the same instance as the last request. Thus trying to store application state could result in possible data loss. Therefore, state information should be stored outside your application in a database. Modern databases are designed to handle connections from multiple concurrent clients.
  • The applications must communicate through a network port: The only way to communicate to a running application is through its assigned network port.
  • Application must configurable at runtime: Applications must be able to start and execute based on values set by the container. Values are passed to an application through environment variables.
  • All dependencies must be included with the application: If your application requires a library to execute, that library must be included with the application when it is deployed. This can be accomplished two ways.
    1. Create an Uber JAR (Java SE only): When you create your application, you include all dependent librariesin the JAR file with the application.
    2. Archived Libaries: Include dependent libraries in the application archive you create. For Java, you can separate the JAR files by using the CLASSPATH command-line option in the application launch command.

For more information, See the Developer Guide.

Configuring Your Application to Run in the Cloud

For you application run on Oracle Application Container Cloud Service, you must let the container assign the host name and port number for your application.The container sets these values using environment variables. Your application must read the HOSTNAME and PORT environment variables, then start your application using those values.

In Java 8, the new Optional class makes it fairly easy to read these values, check for null, and then return the values from the environment variables or use  default values. What follows is a new version of the Main class that checks for the PORT and HOSTNAME environment variables at runtime. If the values are set, then they are used to launch the server. If the values aren't set, default values are used instead. This allows your application to run stand alone locally or in the cloud using Oracle Application Container Cloud Service.

Main.java

package com.example.rest;

import java.util.Optional;

public class Main{    
  
    public static final String BASE_URI;
    public static final String protocol;
    public static final String path;
    public static final Optional<String> host;
    public static final Optional<String> port;
    
    static{
      protocol = "http://";
      host = Optional.ofNullable(System.getenv("HOSTNAME"));
      port = Optional.ofNullable(System.getenv("PORT"));
      path = "myapp";
      BASE_URI = protocol + host.orElse("localhost") + ":" + port.orElse("8080") + "/" + path + "/";
    }
    
    public static void main(String[] args) throws IOException {
        // Start your app here ...
    }
}

A couple of key points.

  • At the top of the class notice two Optional<String> variables are declared. The port and host fields will store the result of your environment variable lookup.
  • In the static initialization block, the System.getenv method is used to get the environment variable. Notice that the Optional.ofNullable method is called. This method will return either the value stored in the environment variable or an empty Optional if no value is returned.
  • The BASE_URI field now uses the Optional variables to create the URI. The orElse method sets a default value if the Optional is empty.

With these improvements, you can set the host name or port using environment variables. The additional code is clear and concise.

Download Suggested Solution

If you want to see the complete set of project files, download the source files and Maven project from the following link:

Creating a Cloud-Ready Package Using manifest.json File

The final step for packaging your application, is to combine your application archive with the manifest.json file.

The manifest.json File

The manifest.json file provides metadata about your Java application. This information includes the version of Java and the command used to execute the application. It may also include notes about your application along with release information.

{
    "runtime": {
        "majorVersion": "7"
    },
    "command": "sh target\/bin\/start",
    "release": {
        "build": "150520.1154",
        "commit": "d8c2596364d9584050461",
        "version": "15.1.0"
    },
    "notes": "notes related to release"
}

JSON Fields Defined

  • runtime:
    • majorVersion: The version of the runtime e.g. for Java it would be 7 or 8.
  • command:The command to execute after deploying the application.
  • release
    • build: A user-specified text value identifying this build.
    • commit: A user-specified text value related to this commit.
    • version: The version text string maintained by user.

Here is the manifest.json file used in the sample application.

{
    "runtime":{
        "majorVersion": "8"
    },
    "command": "java -jar employees-app-1.0-SNAPSHOT-jar-with-dependencies.jar",
    "release": {
        "build": "20150813Build",
        "commit": "commitString",
        "version": "20150813Version"
    },
    "notes": "Web application for testing"
}

Note: From the simplicity of the command used to launch the application, you can see that this is an uber JAR deployment. This application uses Java 8. If your application needs any special command-line switches to run, this is where you would specify here.

Creating the Final Archive

As a final step, you create an archive containing the application archive and manifest.json files. Both files are stored at the root level of the archive file.

For example, create an archive using zip.

zip employees-sample-app.zip manifest.json employees-app-1.0-SNAPSHOT-jar-with-dependencies.jar

Here is an example using tar.

tar cvfz employees-sample-app.tgz manifest.json employees-app-1.0-SNAPSHOT-jar-with-dependencies.jar

When you have created the final archive, your application is ready for deployment.

Packaging an Application Archive Without an Uber JAR File

As an alternative to using an uber JAR, an application can be started by specifying libraries on the java command line or by using a bash shell script. Oracle Application Container Cloud Service uses a Linux container for the execution of applications, so most of the rules that apply to running a command in Linux will apply.

Assumptions

The two examples that follow are based on the following assumptions:

  • The home directory for the application is /u01/app.
  • The application execution code is stored in a JAR named app.jar.
  • All required Java libraries are stored in the lib directory. The lib directory is included in the final archive as a subdirectory from the archive root directory.
  • The lib directory contains the following JAR libraries: web.jar, rest.jar, media.jar.

Executing the Application with Java and Classpath

Given the preceding assumptions, and assuming the lib directory is included as described, the following command could be used to launch the application:

java -cp '/u01/app/lib/*' -jar app.jar

When, the application is deployed, the libraries in the lib directory are copied under the application's home directory. The above command executes the java command and loads all of the libraries in the /u01/app/lib directory. This should provide the JVM with all the necessary classes to run the application.

Executing the Application with a Shell Script

As an alternative you could execute your application using a shell script. The command line for execution would be something like this:

bash -l ./applicationScript.sh

The CLASSPATH environment variable can also be used to set the path. In this example, the script could contain the follow two lines.

export CLASSPATH=/u01/app/lib/web.jar;/u01/app/lib/rest.jar;/u01/app/lib/media.jar;
java -jar app.jar

Cloud Deployment Summary

To properly package your application, you must go through the following steps:

  1. Create an application that is configurable at runtime.
  2. Package your application as an uber jar or as separate library jars.
  3. Create an application archive that contains your application and a manifest.json in a single file. The manifest.json file must be stored in the root directory of your archive.
  4. Deploy your application to Oracle Application Container Cloud Service.

Note: The manifest.json file is optional, as the information contained in the file can also be configured through the user interface.

Deploying Your Applicaiton to Oracle Application Container

Now that you have created an application and packaged it for deployment to Oracle Application Container Cloud Service, you are ready to deploy it. The steps for deploying your application are described in a separate tutorial: Deploying an Application to Oracle Application Container Cloud Service.

Want to Learn More?

Credits

  • Curriculum Developer: Luz Elena Peralta Ayala
  • QA: Veerabhadra Rao Putrevu