Een Todo application with spring and jsp

   todo
     + src
     | + main
     |   + java 
     |   | + com
     |   |   + litteworld
     |   |     + todo
     |   |       + model
     |   |          - Todo.java
     |   |       + controllers
     |   |          - TodoController.java
     |   |       + services
     |   |          - TodoMockService.java
     |   + webapp
     |     + WEB-INF
     |       - web.xml 
     |       - spring-context.xml
     |       + views
     |         - todoForm.jsp
     |         - todoList.jsp
     - pom.xml

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>
    <spring.version>4.2.3.RELEASE</spring.version>
    <jstl.version>1.2</jstl.version>
  </properties>

  <dependencies>

    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-webmvc</artifactId>
      <version>${spring.version}</version>
    </dependency>

    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>jstl</artifactId>
      <version>${jstl.version}</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() {}

  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/${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>

Controller

We will use a Spring MVC

/* generated by: ControllerGenerator Mon Apr 18 22:35:30 CEST 2016 */
package com.littleworld.todo.controllers;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.List;

import com.littleworld.todo.model.Todo;
import com.littleworld.todo.services.TodoMockService;

@Controller
public class TodoController {

    @Autowired  private TodoMockService todoService;

    @RequestMapping(value="/todo", method=RequestMethod.GET)
    public String todoForm(Model model) {
        model.addAttribute("todo", new Todo());
        return "todoForm";
    }

    @RequestMapping(value="/create", method=RequestMethod.POST)
    public String todoCreate(Todo todo) {
        todoService.create(todo);
        return "redirect:list";
    }

    @RequestMapping(value="/todo/{index}", method=RequestMethod.GET)
    public String todoFindById(@PathVariable int index, Model model) {
        Todo todo = todoService.findById(index) ;
        model.addAttribute("todo", todo);
        return "todoView";
    }

    @RequestMapping(value="/list", method=RequestMethod.GET)
    public String todoFindAll(Model model) {
        List<Todo> todos = todoService.findAll();
        model.addAttribute("todos", todos);
        return "todoList";
    }

    @RequestMapping(value = "/delete/{id}", method = RequestMethod.GET)
    public String delete(@PathVariable int id) {
      todoService.delete(id);
      return "redirect:/list";
    }
}

Services

The service layer

TodoService contains 3 methodes We support a simple implementation - TodoServiceImpl will keep the todos in an ArrayList

package com.littleworld.todo.services;

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

public class 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;
        }
      }
    }
}

Context

We configure this in a web.xml and a spring-context.xml
<web-app xmlns="http://java.sun.com/xml/ns/javaee" 
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
	http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
	version="3.0">
	<servlet>
		<servlet-name>spring-web</servlet-name>
		<servlet-class>
      org.springframework.web.servlet.DispatcherServlet
    </servlet-class>
		<load-on-startup>1</load-on-startup>
		<init-param>
			<param-name>contextConfigLocation</param-name>
			<param-value>/WEB-INF/spring-context.xml</param-value>
		</init-param>
	</servlet>

	<servlet-mapping>
		<servlet-name>spring-web</servlet-name>
		<url-pattern>/</url-pattern>
	</servlet-mapping>
</web-app>

<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:context="http://www.springframework.org/schema/context"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:mvc="http://www.springframework.org/schema/mvc"
  xsi:schemaLocation="
        http://www.springframework.org/schema/beans     
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/mvc 
        http://www.springframework.org/schema/mvc/spring-mvc.xsd
        http://www.springframework.org/schema/context 
        http://www.springframework.org/schema/context/spring-context.xsd ">
 
  <context:component-scan base-package="com.littleworld.todo"/>
 
  <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
    <property name="prefix" value="/WEB-INF/views/" />
    <property name="suffix" value=".jsp" />
  </bean>
 
  <mvc:resources mapping="/resources/**" location="/resources/" />

  <bean id="todoService" class="com.littleworld.todo.services.TodoMockService" />
   
  <mvc:annotation-driven />
 
</beans>

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