📘 Premium Read: Access my best content on Medium member-only articles — deep dives into Java, Spring Boot, Microservices, backend architecture, interview preparation, career advice, and industry-standard best practices.
🎓 Top 15 Udemy Courses (80-90% Discount): My Udemy Courses - Ramesh Fadatare — All my Udemy courses are real-time and project oriented courses.
▶️ Subscribe to My YouTube Channel (176K+ subscribers): Java Guides on YouTube
▶️ For AI, ChatGPT, Web, Tech, and Generative AI, subscribe to another channel: Ramesh Fadatare on YouTube
In this part 2, we create Todo management features such as add todo, update todo, list todo and delete todo.
Table of Contents
- Model Layer - Todo.java
- DAO Layer - TodoDao.java and TodoDaoImpl.java
- Controller Layer - TodoController.java
- View Layer - todo-form.jsp and todo-list.jsp
- Creating an error page
Model Layer - Todo.java
package net.javaguides.todoapp.model;
import java.time.LocalDate;
/**
* Todo.java
* This is a model class represents a Todo entity
* @author Ramesh Fadatare
*
*/
public class Todo {
private Long id;
private String title;
private String username;
private String description;
private LocalDate targetDate;
private boolean status;
protected Todo() {
}
public Todo(long id, String title, String username, String description, LocalDate targetDate, boolean isDone) {
super();
this.id = id;
this.title = title;
this.username = username;
this.description = description;
this.targetDate = targetDate;
this.status = isDone;
}
public Todo(String title, String username, String description, LocalDate targetDate, boolean isDone) {
super();
this.title = title;
this.username = username;
this.description = description;
this.targetDate = targetDate;
this.status = isDone;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public LocalDate getTargetDate() {
return targetDate;
}
public void setTargetDate(LocalDate targetDate) {
this.targetDate = targetDate;
}
public boolean getStatus() {
return status;
}
public void setStatus(boolean status) {
this.status = status;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + (int)(id ^ (id >>> 32));
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Todo other = (Todo) obj;
if (id != other.id)
return false;
return true;
}
}
DAO Layer - TodoDao.java and TodoDaoImpl.java
TodoDao.java
package net.javaguides.todoapp.dao;
import java.sql.SQLException;
import java.util.List;
import net.javaguides.todoapp.model.Todo;
public interface TodoDao {
void insertTodo(Todo todo) throws SQLException;
Todo selectTodo(long todoId);
List<Todo> selectAllTodos();
boolean deleteTodo(int id) throws SQLException;
boolean updateTodo(Todo todo) throws SQLException;
}
TodoDaoImpl.java
package net.javaguides.todoapp.dao;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;
import net.javaguides.todoapp.model.Todo;
import net.javaguides.todoapp.utils.JDBCUtils;
/**
* This DAO class provides CRUD database operations for the table todos in the
* database.
*
* @author Ramesh Fadatare
*
*/
public class TodoDaoImpl implements TodoDao {
private static final String INSERT_TODOS_SQL = "INSERT INTO todos" +
" (title, username, description, target_date, is_done) VALUES " + " (?, ?, ?, ?, ?);";
private static final String SELECT_TODO_BY_ID = "select id,title,username,description,target_date,is_done from todos where id =?";
private static final String SELECT_ALL_TODOS = "select * from todos";
private static final String DELETE_TODO_BY_ID = "delete from todos where id = ?;";
private static final String UPDATE_TODO = "update todos set title = ?, username= ?, description =?, target_date =?, is_done = ? where id = ?;";
public TodoDaoImpl() {}
@Override
public void insertTodo(Todo todo) throws SQLException {
System.out.println(INSERT_TODOS_SQL);
// try-with-resource statement will auto close the connection.
try (Connection connection = JDBCUtils.getConnection(); PreparedStatement preparedStatement = connection.prepareStatement(INSERT_TODOS_SQL)) {
preparedStatement.setString(1, todo.getTitle());
preparedStatement.setString(2, todo.getUsername());
preparedStatement.setString(3, todo.getDescription());
preparedStatement.setDate(4, JDBCUtils.getSQLDate(todo.getTargetDate()));
preparedStatement.setBoolean(5, todo.getStatus());
System.out.println(preparedStatement);
preparedStatement.executeUpdate();
} catch (SQLException exception) {
JDBCUtils.printSQLException(exception);
}
}
@Override
public Todo selectTodo(long todoId) {
Todo todo = null;
// Step 1: Establishing a Connection
try (Connection connection = JDBCUtils.getConnection();
// Step 2:Create a statement using connection object
PreparedStatement preparedStatement = connection.prepareStatement(SELECT_TODO_BY_ID);) {
preparedStatement.setLong(1, todoId);
System.out.println(preparedStatement);
// Step 3: Execute the query or update query
ResultSet rs = preparedStatement.executeQuery();
// Step 4: Process the ResultSet object.
while (rs.next()) {
long id = rs.getLong("id");
String title = rs.getString("title");
String username = rs.getString("username");
String description = rs.getString("description");
LocalDate targetDate = rs.getDate("target_date").toLocalDate();
boolean isDone = rs.getBoolean("is_done");
todo = new Todo(id, title, username, description, targetDate, isDone);
}
} catch (SQLException exception) {
JDBCUtils.printSQLException(exception);
}
return todo;
}
@Override
public List < Todo > selectAllTodos() {
// using try-with-resources to avoid closing resources (boiler plate code)
List < Todo > todos = new ArrayList < > ();
// Step 1: Establishing a Connection
try (Connection connection = JDBCUtils.getConnection();
// Step 2:Create a statement using connection object
PreparedStatement preparedStatement = connection.prepareStatement(SELECT_ALL_TODOS);) {
System.out.println(preparedStatement);
// Step 3: Execute the query or update query
ResultSet rs = preparedStatement.executeQuery();
// Step 4: Process the ResultSet object.
while (rs.next()) {
long id = rs.getLong("id");
String title = rs.getString("title");
String username = rs.getString("username");
String description = rs.getString("description");
LocalDate targetDate = rs.getDate("target_date").toLocalDate();
boolean isDone = rs.getBoolean("is_done");
todos.add(new Todo(id, title, username, description, targetDate, isDone));
}
} catch (SQLException exception) {
JDBCUtils.printSQLException(exception);
}
return todos;
}
@Override
public boolean deleteTodo(int id) throws SQLException {
boolean rowDeleted;
try (Connection connection = JDBCUtils.getConnection(); PreparedStatement statement = connection.prepareStatement(DELETE_TODO_BY_ID);) {
statement.setInt(1, id);
rowDeleted = statement.executeUpdate() > 0;
}
return rowDeleted;
}
@Override
public boolean updateTodo(Todo todo) throws SQLException {
boolean rowUpdated;
try (Connection connection = JDBCUtils.getConnection(); PreparedStatement statement = connection.prepareStatement(UPDATE_TODO);) {
statement.setString(1, todo.getTitle());
statement.setString(2, todo.getUsername());
statement.setString(3, todo.getDescription());
statement.setDate(4, JDBCUtils.getSQLDate(todo.getTargetDate()));
statement.setBoolean(5, todo.getStatus());
statement.setLong(6, todo.getId());
rowUpdated = statement.executeUpdate() > 0;
}
return rowUpdated;
}
}
Controller Layer - TodoController
package net.javaguides.todoapp.web;
import java.io.IOException;
import java.sql.SQLException;
import java.time.LocalDate;
import java.util.List;
import javax.servlet.RequestDispatcher;
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 net.javaguides.todoapp.dao.TodoDao;
import net.javaguides.todoapp.dao.TodoDaoImpl;
import net.javaguides.todoapp.model.Todo;
/**
* ControllerServlet.java This servlet acts as a page controller for the
* application, handling all requests from the todo.
*
* @email Ramesh Fadatare
*/
@WebServlet("/")
public class TodoController extends HttpServlet {
private static final long serialVersionUID = 1 L;
private TodoDao todoDAO;
public void init() {
todoDAO = new TodoDaoImpl();
}
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String action = request.getServletPath();
try {
switch (action) {
case "/new":
showNewForm(request, response);
break;
case "/insert":
insertTodo(request, response);
break;
case "/delete":
deleteTodo(request, response);
break;
case "/edit":
showEditForm(request, response);
break;
case "/update":
updateTodo(request, response);
break;
case "/list":
listTodo(request, response);
break;
default:
RequestDispatcher dispatcher = request.getRequestDispatcher("login/login.jsp");
dispatcher.forward(request, response);
break;
}
} catch (SQLException ex) {
throw new ServletException(ex);
}
}
private void listTodo(HttpServletRequest request, HttpServletResponse response)
throws SQLException, IOException, ServletException {
List < Todo > listTodo = todoDAO.selectAllTodos();
request.setAttribute("listTodo", listTodo);
RequestDispatcher dispatcher = request.getRequestDispatcher("todo/todo-list.jsp");
dispatcher.forward(request, response);
}
private void showNewForm(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
RequestDispatcher dispatcher = request.getRequestDispatcher("todo/todo-form.jsp");
dispatcher.forward(request, response);
}
private void showEditForm(HttpServletRequest request, HttpServletResponse response)
throws SQLException, ServletException, IOException {
int id = Integer.parseInt(request.getParameter("id"));
Todo existingTodo = todoDAO.selectTodo(id);
RequestDispatcher dispatcher = request.getRequestDispatcher("todo/todo-form.jsp");
request.setAttribute("todo", existingTodo);
dispatcher.forward(request, response);
}
private void insertTodo(HttpServletRequest request, HttpServletResponse response) throws SQLException, IOException {
String title = request.getParameter("title");
String username = request.getParameter("username");
String description = request.getParameter("description");
/*DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-mm-dd");
LocalDate targetDate = LocalDate.parse(request.getParameter("targetDate"),df);*/
boolean isDone = Boolean.valueOf(request.getParameter("isDone"));
Todo newTodo = new Todo(title, username, description, LocalDate.now(), isDone);
todoDAO.insertTodo(newTodo);
response.sendRedirect("list");
}
private void updateTodo(HttpServletRequest request, HttpServletResponse response) throws SQLException, IOException {
int id = Integer.parseInt(request.getParameter("id"));
String title = request.getParameter("title");
String username = request.getParameter("username");
String description = request.getParameter("description");
//DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-mm-dd");
LocalDate targetDate = LocalDate.parse(request.getParameter("targetDate"));
boolean isDone = Boolean.valueOf(request.getParameter("isDone"));
Todo updateTodo = new Todo(id, title, username, description, targetDate, isDone);
todoDAO.updateTodo(updateTodo);
response.sendRedirect("list");
}
private void deleteTodo(HttpServletRequest request, HttpServletResponse response) throws SQLException, IOException {
int id = Integer.parseInt(request.getParameter("id"));
todoDAO.deleteTodo(id);
response.sendRedirect("list");
}
}
View Layer - todo-form.jsp and todo-list.jsp
todo-form.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<html>
<head>
<title>User Management Application</title>
<link rel="stylesheet"
href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css"
integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T"
crossorigin="anonymous">
</head>
</head>
<body>
<header>
<nav class="navbar navbar-expand-md navbar-dark"
style="background-color: tomato">
<div>
<a href="https://www.javaguides.net" class="navbar-brand"> Todo
App</a>
</div>
<ul class="navbar-nav">
<li><a href="<%=request.getContextPath()%>/list"
class="nav-link">Todos</a></li>
</ul>
<ul class="navbar-nav navbar-collapse justify-content-end">
<li><a href="<%=request.getContextPath()%>/logout"
class="nav-link">Logout</a></li>
</ul>
</nav>
</header>
<div class="container col-md-5">
<div class="card">
<div class="card-body">
<c:if test="${todo != null}">
<form action="update" method="post">
</c:if>
<c:if test="${todo == null}">
<form action="insert" method="post">
</c:if>
<caption>
<h2>
<c:if test="${todo != null}">
Edit Todo
</c:if>
<c:if test="${todo == null}">
Add New Todo
</c:if>
</h2>
</caption>
<c:if test="${todo != null}">
<input type="hidden" name="id" value="<c:out value='${todo.id}' />" />
</c:if>
<fieldset class="form-group">
<label>Todo Title</label> <input type="text"
value="<c:out value='${todo.title}' />" class="form-control"
name="title" required="required" minlength="5">
</fieldset>
<fieldset class="form-group">
<label>Todo Decription</label> <input type="text"
value="<c:out value='${todo.description}' />" class="form-control"
name="description" minlength="5">
</fieldset>
<fieldset class="form-group">
<label>Todo Status</label> <select class="form-control"
name="isDone">
<option value="false">In Progress</option>
<option value="true">Complete</option>
</select>
</fieldset>
<fieldset class="form-group">
<label>Todo Target Date</label> <input type="date"
value="<c:out value='${todo.targetDate}' />" class="form-control"
name="targetDate" required="required">
</fieldset>
<button type="submit" class="btn btn-success">Save</button>
</form>
</div>
</div>
</div>
<jsp:include page="../common/footer.jsp"></jsp:include>
</body>
</html>
todo-list.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<html>
<head>
<title>User Management Application</title>
<link rel="stylesheet"
href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css"
integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T"
crossorigin="anonymous">
</head>
</head>
<body>
<header>
<nav class="navbar navbar-expand-md navbar-dark"
style="background-color: tomato">
<div>
<a href="https://www.javaguides.net" class="navbar-brand"> Todo
App</a>
</div>
<ul class="navbar-nav">
<li><a href="<%=request.getContextPath()%>/list"
class="nav-link">Todos</a></li>
</ul>
<ul class="navbar-nav navbar-collapse justify-content-end">
<li><a href="<%=request.getContextPath()%>/logout"
class="nav-link">Logout</a></li>
</ul>
</nav>
</header>
<div class="row">
<!-- <div class="alert alert-success" *ngIf='message'>{{message}}</div> -->
<div class="container">
<h3 class="text-center">List of Todos</h3>
<hr>
<div class="container text-left">
<a href="<%=request.getContextPath()%>/new"
class="btn btn-success">Add Todo</a>
</div>
<br>
<table class="table table-bordered">
<thead>
<tr>
<th>Title</th>
<th>Target Date</th>
<th>Todo Status</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<!-- for (Todo todo: todos) { -->
<c:forEach var="todo" items="${listTodo}">
<tr>
<td><c:out value="${todo.title}" /></td>
<td><c:out value="${todo.targetDate}" /></td>
<td><c:out value="${todo.status}" /></td>
<td><a href="edit?id=<c:out value='${todo.id}' />">Edit</a>
<a
href="delete?id=<c:out value='${todo.id}' />">Delete</a></td>
<!-- <td><button (click)="updateTodo(todo.id)" class="btn btn-success">Update</button>
<button (click)="deleteTodo(todo.id)" class="btn btn-warning">Delete</button></td> -->
</tr>
</c:forEach>
<!-- } -->
</tbody>
</table>
</div>
</div>
<jsp:include page="../common/footer.jsp"></jsp:include>
</body>
</html>
Creating Error JSP page
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8" isErrorPage="true" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Error</title>
</head>
<body>
<center>
<h1>Error</h1>
<h2><%=exception.getMessage() %><br/> </h2>
</center>
</body>
</html>
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
id="WebApp_ID" version="3.1">
<display-name>Todo Management Web Application</display-name>
<error-page>
<exception-type>java.lang.Exception</exception-type>
<location>/Error.jsp</location>
</error-page>
</web-app>
👍
ReplyDelete