Een Todo application with servlet and jsp

In this web application we will servlets and jsp's as technology

   todo
     + src
     | + main
     |   + java 
     |   | + com
     |   |   + littleworld
     |   |     + todo
     |   |       + model
     |   |          - Todo.java
     |   |       + servlets
     |   |          - TodoCreateServlet.java
     |   |          - TodoListServlet.java
     |   |          - TodoDeleteServlet.java
     |   |       + services
     |   |          - TodoMockService.java
     |   |          - TodoJDBCService.java
     |   + webapp
     |     - todoForm.jsp
     |     - todoList.jsp
     - pom.xml
     - create.sql

Maven POM

In the POM we define the library dependencies of this project

The dependencies are:

We will use the jetty plugin


<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.littleworld</groupId>
  <artifactId>todo</artifactId>
  <packaging>war</packaging>
  <version>1.0-SNAPSHOT</version>
  <name>todo</name>

  <properties>
    <jdk.version>1.8</jdk.version>
    <jstl.version>1.2</jstl.version>
    <servlet.version>3.1.0</servlet.version>
  </properties>

  <dependencies>
    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>jstl</artifactId>
      <version>${jstl.version}</version>
    </dependency>

    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>javax.servlet-api</artifactId>
      <version>${servlet.version}</version>
      <scope>provided</scope>
    </dependency>

    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>5.1.37</version>
    </dependency>
  </dependencies>

  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.3</version>
        <configuration>
          <source>${jdk.version}</source>
          <target>${jdk.version}</target>
        </configuration>
      </plugin>

      <plugin>
        <groupId>org.eclipse.jetty</groupId>
        <artifactId>jetty-maven-plugin</artifactId>
        <version>9.3.6.v20151106</version>
        <configuration>
          <scanIntervalSeconds>10</scanIntervalSeconds>
          <webApp>
            <contextPath>/todo</contextPath>
          </webApp>
        </configuration>
      </plugin>

      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-eclipse-plugin</artifactId>
        <version>2.9</version>
        <configuration>
          <wtpversion>2.0</wtpversion>
          <wtpContextName>todo</wtpContextName>
        </configuration>
      </plugin>
    </plugins>
  </build>
</project>

Model

This project uses the todo as model

The fields in the model will be used in the views form and list. Apart from the id field.


package com.littleworld.todo.model;

public class Todo {
  int id;
  String task;

  public Todo(int id, String task) {
    this.id = id;
    this.task = task;
  }

  public int getId() {
    return id;
  }
  public void setId(int id)  {
    this.id = id;
  } 
  public String getTask() {
    return task;
  }
  public void setTask(String task)  {
    this.task = task;
  } 
}

The HTML View

HTML List

The list page act as the landing page

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE html>
<html>
<head>
  <title>todo list</title>
</head>
<body>

  <jsp:include page="todoForm.jsp" />
  <hr>
  <table>
    <tr><th>task</th></tr>
 
    <c:forEach items="${todos}" var="todo">
    <tr><td>${todo.task}</td><td><a href="delete?id=${todo.id}">delete</a></tr>
    </c:forEach>  

  </table>
</body>
</html>

The HTML form

<form action="create" method="post">
    <table>
      <tr><td>task:</td><td><input type='text' name='task'></td></tr>
      <tr><td><input type="submit" name="naam" value="OK"></td><td></td></tr>
    </table>
  </form>

Servlets

We will use 3 servlets
package com.littleworld.todo.servlets;

import java.io.IOException;
import java.util.UUID;
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 com.littleworld.todo.model.*;
import com.littleworld.todo.services.*;


@WebServlet("/create")
public class TodoCreateServlet extends HttpServlet {

  protected void doPost(HttpServletRequest request,
      HttpServletResponse response) throws ServletException, IOException {
    String task = request.getParameter("task");

    
    Todo todo = new Todo(0, task);

    TodoMockService.getInstance().create(todo);
    //TodoJDBCService.getInstance().create(todo);
    response.sendRedirect("list");
  }
}

package com.littleworld.todo.servlets;

import java.io.IOException;
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.util.List;

import com.littleworld.todo.model.*;
import com.littleworld.todo.services.*;

@WebServlet("/list")
public class TodoListServlet extends HttpServlet {

  protected void doGet(HttpServletRequest request,
      HttpServletResponse response) throws ServletException, IOException {
  
    List<Todo> todos = TodoMockService.getInstance().findAll();
    //List<Todo> todos = TodoJDBCService.getInstance().findAll();
    request.setAttribute("todos", todos);
    request.getServletContext().getRequestDispatcher("/todoList.jsp").forward(request, response);
  }
}

package com.littleworld.todo.servlets;

import java.io.IOException;
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 com.littleworld.todo.model.*;
import com.littleworld.todo.services.*;


@WebServlet("/delete")
public class TodoDeleteServlet extends HttpServlet {

  protected void doGet(HttpServletRequest request,
      HttpServletResponse response) throws ServletException, IOException {
   
   
    int id = request.getParameter("id") != null ? Integer.parseInt(request.getParameter("id")) : 0;

    TodoMockService.getInstance().delete(id);
    //TodoJDBCService.getInstance().delete(id);
    response.sendRedirect("list");
  }
}

Services

The service layer

TodoService contains 3 methodes supporting the 3 servlets We support two different implementations - TodoService will keep the todos in an ArrayList - In the TodoJDBCService the todos are presisted in a mysql database

package com.littleworld.todo.services;

import java.util.List;
import java.util.ArrayList;
import com.littleworld.todo.model.*;

public class TodoMockService {

    // create singleton
    private static TodoMockService instance = new TodoMockService();

    public static TodoMockService getInstance() {
      return instance;
    }

    private TodoMockService() {}
    
    // generate id with auto increment    
    int uniqueId = 1;

    List<Todo> todos = new ArrayList<Todo>();

    public Todo create(Todo todo ) {
        todo.setId(uniqueId++);
        todos.add(todo);
        return todo;
    }

    public List<Todo> findAll() {
        return todos;
    }
 
    public Todo findById(int id) {
        return todos.get(id);
    }

    public void delete(int id) {
      for (int i = 0; i <  todos.size(); i++) {
        if (todos.get(i).getId() == id) { 
          todos.remove(i);
          break;
        }
      }
    }
}


package com.littleworld.todo.services;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.Statement;
import java.sql.ResultSet;
import java.sql.SQLException;

import java.util.*;

import com.littleworld.todo.model.*;

public class TodoJDBCService {

    // create singleton
    private static TodoJDBCService instance = new TodoJDBCService();

    public static TodoJDBCService getInstance() {
      return instance;
    }

    private TodoJDBCService() {}
  
    Connection getConnection() {
      Connection connection = null;
      try {
        Class.forName("com.mysql.jdbc.Driver");
        connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/todo","root", "");
      } catch (ClassNotFoundException e) {
        e.printStackTrace();
      } catch (SQLException e) {
        e.printStackTrace();
      }
      return connection;
    }

    public Todo create(Todo todo ) {
      String sql = "INSERT INTO TODO " + "(id, task) VALUES (NULL, ?)";
      try {
        Connection connection = getConnection();
        PreparedStatement ps = connection.prepareStatement(sql);
        ps.setString(1, todo.getTask());
        ps.executeUpdate();
        ps.close();
      } catch (SQLException e) { 
        e.printStackTrace();
      }
      return todo;
    }

    public List<Todo> findAll() {
      String sql = "SELECT * FROM TODO";
      List<Todo> todos = new ArrayList<Todo>();
      try {
        Connection connection = getConnection();
        Statement stmt = connection.createStatement();
        ResultSet rs = stmt.executeQuery(sql);
        while (rs.next()) {
           todos.add(new Todo(rs.getInt("id"), rs.getString("task") ));
        }
      } catch (SQLException e) { 
        e.printStackTrace();
      }
      return todos;
    }
 
    public Todo findById(int id) {
        return null;
    }

    public void delete(int id) {
      String sql = "DELETE FROM TODO WHERE ID = ?";
      try {
        Connection connection = getConnection();
        PreparedStatement ps = connection.prepareStatement(sql);
        ps.setInt(1, id);
        ps.executeUpdate();
        ps.close();
      } catch (SQLException e) { 
        e.printStackTrace();
      }
    }
}

the create table script

create table todo (
  id integer primary key auto_increment,
  task varchar(255)
);

Run the application

To run the application. Goto the root directory of the application and type

(Maven should in the enviroment variable PATH; and JAVA_HOME should be set to the jdk installation dir)

mvn jetty:run
http://localhost:8080/todo/list