Spring Boot, MVC, Data and MongoDB CRUD Java Web Application

by Didin J. on Sep 11, 2017 Spring Boot, MVC, Data and MongoDB CRUD Java Web Application

A comprehensive step by step Java tutorial on how to create Java and MongoDB CRUD web app using Spring Boot, Spring MVC, and Spring Data

Java tutorial: This is a practical step by step tutorial on how to create Java and MongoDB create, read, update, and delete (CRUD) web app using Spring Boot, Spring MVC, and Spring Data. In this tutorial, we are using Gradle based project for compile, build, and run the Java web app. The project will be generated using Spring Initializr online Java project generator. For the development process, we are use Apache Netbeans IDE to make development easier and faster.

Table of Contents:

We will show you how to create the Java web app that can display the list of product, show, create, edit, update and delete it using Spring MVC. The data GET, POST, PUT, and DELETE from MongoDB using Spring Data. We're using the following tools, framework, and library:

  1. Java Development Kit (JDK) 8
  2. Gradle
  3. Spring Boot
  4. Spring MVC
  5. Spring Data MongoDB
  6. Thymeleaf
  7. Webjars Bootstrap
  8. Spring Initializer
  9. Netbeans or Eclipse
  10. Terminal or cmd

You can watch this tutorial on our YouTube channel. Please like, share, comment, and subscribe to our YouTube channel.


Generate Spring Boot Gradle Java Web App

We assume that you have installed JDK 8, Gradle and IDE (Netbeans or Eclipse). Next, we will create a new Spring Boot Gradle project using Spring Initializer. Spring Initializr provides an extensible API to generate quickstart projects, and to inspect the metadata used to generate projects, for instance, to list the available dependencies and versions. Just go to Spring Initializer web-based Spring project generator then fill the required frameworks and libraries.

Spring Boot, MVC, Data and MongoDB CRUD Java Web Application - Spring Initializr

After filling all fields, click Generate Project. It will automatically download the zipped project. Next, extract the zipped project to your java projects folder. On the project folder root, you will find `build.gradle` file for register dependencies, initially it looks like this.

plugins {
	id 'org.springframework.boot' version '2.2.5.RELEASE'
	id 'io.spring.dependency-management' version '1.0.9.RELEASE'
	id 'java'
}

group = 'com.djamware'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '1.8'

repositories {
	mavenCentral()
}

dependencies {
	implementation 'org.springframework.boot:spring-boot-starter-data-mongodb'
	implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
	implementation 'org.springframework.boot:spring-boot-starter-web'
        compile 'nz.net.ultraq.thymeleaf:thymeleaf-layout-dialect:2.4.1'
        compile 'org.webjars:bootstrap:3.3.7'
	testImplementation('org.springframework.boot:spring-boot-starter-test') {
		exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
	}
}

test {
	useJUnitPlatform()
}

Next, open the terminal then goes to the newly extracted project folder then type this command.

./gradlew build

It will build and install all Gradle dependencies. Open this Gradle project using Netbeans or Eclipse then open and edit `build.gradle` from the root of the project folder. Add this line to dependencies to install additional Twitter Bootstrap front UI/UX.

compile('org.webjars:bootstrap:3.3.7')

On the terminal run again this command.

./gradlew build

To configure Spring Data with MongoDB, simply open and edit `src/resources/application.properties` then add these lines of strings.

spring.data.mongodb.database=springmongodb
spring.data.mongodb.host=localhost
spring.data.mongodb.port=27017


Create Java Model or Entity Class

Part of the MVC concept is Model/Entity/Domain. For that, we will create a new Model or Entity class. The entity is a lightweight Java class whose state is typically persisted to a table or collection in a relational or document database. Using IDE like Netbeans  8.2 right-click on the project name in projects panel then choose New then choose Java Class.

Spring Boot, MVC, Data and MongoDB CRUD Java Web Application - Create Java Class

Give the class name `Product` and the package name `com.springmvc.springmongodbweb.models` then click the finish button.

Spring Boot, MVC, Data and MongoDB CRUD Java Web Application - New Java Class

That will create a new file name `Product.java` and open in Netbeans main panel. Fill with the codes below that contain Java POJO, Spring Data MongoDB annotation that point to a collection, fields with their types, constructor, and getter/setter methods.

package com.springmvc.springmongodbweb.models;

import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;

@Document(collection = "products")
public class Product {
    @Id
    String id;
    String prodName;
    String prodDesc;
    Double prodPrice;
    String prodImage;

    public Product() {
    }

    public Product(String prodName, String prodDesc, Double prodPrice, String prodImage) {
        this.prodName = prodName;
        this.prodDesc = prodDesc;
        this.prodPrice = prodPrice;
        this.prodImage = prodImage;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getProdName() {
        return prodName;
    }

    public void setProdName(String prodName) {
        this.prodName = prodName;
    }

    public String getProdDesc() {
        return prodDesc;
    }

    public void setProdDesc(String prodDesc) {
        this.prodDesc = prodDesc;
    }

    public Double getProdPrice() {
        return prodPrice;
    }

    public void setProdPrice(Double prodPrice) {
        this.prodPrice = prodPrice;
    }

    public String getProdImage() {
        return prodImage;
    }

    public void setProdImage(String prodImage) {
        this.prodImage = prodImage;
    }
}

That product class mapping to product collections of MongoDB which has 5 fields. Each field has getter and setter.


Create Java Repository Interface

Now, we need to create an interface for connecting the Product model and controller. On Netbeans right-click project name on projects left panel then choose new then choose Java Interface.

Spring Boot, MVC, Data and MongoDB CRUD Java Web Application - Create Java Interface

Give the name of interface `ProductRepository` and create new package name `com.springmvc.springmongodbweb.repositories` then click Finish.

Spring Boot, MVC, Data and MongoDB CRUD Java Web Application - New Java Interface

It will open the `ProductRepository.java` interface file on the Netbean's main panel after created. Just replace all codes with these codes of ProductRepository that extends the Spring Data CrudRepository that returns Product and String objects. 

package com.springmvc.springmongodbweb.repositories;

import com.springmvc.springmongodbweb.models.Product;
import org.springframework.data.repository.CrudRepository;

public interface ProductRepository extends CrudRepository<Product, String> {
    
    @Override
    public void delete(Product product);
    
}

We only add `findOne` and `delete` method to the interface because the rest method already handled by `CrudRepository` of Spring Data MongoDB.


Create Spring MVC Controller

Now, it's time for `C` terms of MVC that means Controller. To create it on Netbeans just right click on project name from projects left panel then choose new then choose Java Class.

Spring Boot, MVC, Data and MongoDB CRUD Java Web Application - Create New Controller

Give the name of controller class `ProductController` and create a new package name `com.springmvc.springmongodbweb.controllers` then click Finish.

Spring Boot, MVC, Data and MongoDB CRUD Java Web Application - New Java Class for Controller

It will open `ProductController.java` file on the Netbeans main panel after created. Replace all codes with these codes of the implementation of ProductRepository, Spring Framework model, request, response, params, etc.

package com.springmvc.springmongodbweb.controllers;

import com.springmvc.springmongodbweb.models.Product;
import com.springmvc.springmongodbweb.repositories.ProductRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
public class ProductController {

    @Autowired
    ProductRepository productRepository;

    @RequestMapping("/product")
    public String product(Model model) {
        model.addAttribute("products", productRepository.findAll());
        return "product";
    }

    @RequestMapping("/create")
    public String create(Model model) {
        return "create";
    }

    @RequestMapping("/save")
    public String save(@RequestParam String prodName, @RequestParam String prodDesc, @RequestParam Double prodPrice, @RequestParam String prodImage) {
        Product product = new Product();
        product.setProdName(prodName);
        product.setProdDesc(prodDesc);
        product.setProdPrice(prodPrice);
        product.setProdImage(prodImage);
        productRepository.save(product);

        return "redirect:/show/" + product.getId();
    }

    @RequestMapping("/show/{id}")
    public String show(@PathVariable String id, Model model) {
        model.addAttribute("product", productRepository.findById(id).get());
        return "show";
    }

    @RequestMapping("/delete")
    public String delete(@RequestParam String id) {
        Optional<Product> product = productRepository.findById(id);
        productRepository.delete(product.get());

        return "redirect:/product";
    }
    
    @RequestMapping("/edit/{id}")
    public String edit(@PathVariable String id, Model model) {
        model.addAttribute("product", productRepository.findById(id).get());
        return "edit";
    }
    
    @RequestMapping("/update")
    public String update(@RequestParam String id, @RequestParam String prodName, @RequestParam String prodDesc, @RequestParam Double prodPrice, @RequestParam String prodImage) {
        Optional<Product> product = productRepository.findById(id);
        product.get().setProdName(prodName);
        product.get().setProdDesc(prodDesc);
        product.get().setProdPrice(prodPrice);
        product.get().setProdImage(prodImage);
        productRepository.save(product.get());

        return "redirect:/show/" + product.get().getId();
    }
}

On that controller class, we put all CRUD function that interacts between view and model.


Create Spring MVC Views

Now, it's the time of `V` for the View of MVC pattern. Since we are using the Thymeleaf library for view template, so we can create the same layout for all HTML pages. Thymeleaf is a Java XML/XHTML/HTML5 template engine that can work both in web (servlet-based) and non-web environments. It is better suited for serving XHTML/HTML5 at the view layer of MVC-based web applications, but it can process any XML file even in offline environments.

Before start creating the templates for the views, we need to add or install Thymeleaf Dialect that required by the latest Thymeleaf version. Back to build.gradle then add this dependency.

compile 'nz.net.ultraq.thymeleaf:thymeleaf-layout-dialect:2.4.1'

To create the layout, first, create a `default.html` file on the `Resources/templates` folder then add or replace it with these lines of codes.

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:th="http://www.thymeleaf.org"
      xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout">
    <head>
        <meta charset="UTF-8"/>
        <title>Default title for my pages</title>
        <link rel="stylesheet" href="/webjars/bootstrap/3.3.7/css/bootstrap.min.css"/>
        <link rel="stylesheet" href="/webjars/bootstrap/3.3.7/css/bootstrap-theme.min.css"/>
        <link rel="stylesheet" href="/css/style.css" />
    </head>
    <body>
        <nav class="navbar navbar-inverse navbar-fixed-top">
            <div class="container">
                <div class="navbar-header">
                    <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
                        <span class="sr-only">Toggle navigation</span>
                        <span class="icon-bar"></span>
                        <span class="icon-bar"></span>
                        <span class="icon-bar"></span>
                    </button>
                    <a class="navbar-brand" href="/">Product List</a>
                </div>
                <div id="navbar" class="collapse navbar-collapse">
                    <ul class="nav navbar-nav">
                        <li class="active"><a href="/">Home</a></li>
                    </ul>
                </div><!--/.nav-collapse -->
            </div>
        </nav>

        <div class="container">
            <div class="starter-template" layout:fragment="content"></div>
        </div><!-- /.container -->

        <script src="/webjars/jquery/1.11.1/jquery.min.js"></script>
        <script src="/webjars/bootstrap/3.3.7/js/bootstrap.min.js"></script>
    </body>
</html>

All CSS and Javascript files put on that file and called once for all pages that use `default.html` as layout holder. Also, we call Bootstrap and JQuery on that file. Next, we create a view for the Product list with the name `product.html` then replace all codes to that file with this.

<!DOCTYPE HTML>
<html lang="en"
      xmlns="http://www.w3.org/1999/xhtml"
      xmlns:th="http://www.thymeleaf.org"
      xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
      layout:decorate="default">
    <head>
        <title>Product List</title>
    </head>
    <body>
        <div layout:fragment="content" class="row">
            <div class="col-xs-8 col-md-8">
                <h3>
                    <a href="/create" class="btn btn-primary"><span class="glyphicon glyphicon-plus-sign"></span> Product</a>
                </h3>
                <h2>Product List</h2>
                <div class="table-responsive">
                    <table class="table" id="product-table">
                        <thead>
                            <tr>
                                <th>Product Name</th>
                                <th>Product Desc</th>
                                <th>Product Price</th>
                            </tr>
                        </thead>
                        <tbody>
                            <tr th:each="product : ${products}">
                                <td><a th:text="${product.prodName}" th:href="@{'/show/' + ${product.id}}"></a></td>
                                <td th:text="${product.prodDesc}"></td>
                                <td th:text="${product.prodPrice}"></td>
                            </tr>
                        </tbody>
                    </table>
                </div>
            </div>
        </div>
    </body>
</html>

Next, create a view for creating a product form with the name `create.html` on `Resources/templates` folder then replace all codes with this.

<!DOCTYPE HTML>
<html lang="en"
      xmlns:th="http://www.thymeleaf.org"
      xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
      layout:decorator="default">
    <head>
        <title>Create Product</title>
    </head>
    <body>
        <div layout:fragment="content" class="row">
            <div class="col-xs-8 col-md-8">
                <h3>
                    <a href="/product" class="btn btn-lg btn-primary"><span class="glyphicon glyphicon-list"></span> Product</a>
                </h3>
                <h2>Create Product</h2>
                <form action="/save">
                    <div class="form-group">
                        <label for="email">Product Name:</label>
                        <input type="text" class="form-control" name="prodName" />
                    </div>
                    <div class="form-group">
                        <label for="email">Product Description</label>
                        <textarea class="form-control" name="prodDesc" cols="60" rows="3"></textarea>
                    </div>
                    <div class="form-group">
                        <label for="email">Product Price</label>
                        <input type="number" class="form-control" name="prodPrice" />
                    </div>
                    <div class="form-group">
                        <label for="email">Product Image URL:</label>
                        <input type="url" class="form-control" name="prodImage" />
                    </div>
                    <button type="submit" class="btn btn-success">Save</button>
                </form>
            </div>
        </div>
    </body>
</html>

Next, create a view for show product detail with the name `show.html` on `Resources/templates` folder then replace all codes with this.

<!DOCTYPE HTML>
<html lang="en"
      xmlns="http://www.w3.org/1999/xhtml"
      xmlns:th="http://www.thymeleaf.org"
      xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
      layout:decorate="default">
    <head>
        <title>Show Product</title>
    </head>
    <body>
        <div layout:fragment="content" class="row">
            <div class="col-xs-8 col-md-8">
                <h3>
                    <a href="/product" class="btn btn-primary"><span class="glyphicon glyphicon-list"></span> Product</a>
                </h3>
                <h2 th:text="${product.prodName}"></h2>
                <h2><img th:src="${product.prodImage}" width="200" /></h2>
                <dl class="list">
                    <dt>Product Description</dt>
                    <dd th:text="${product.prodDesc}"></dd>
                    <dt>Product Description</dt>
                    <dd th:text="${product.prodPrice}"></dd>
                </dl>
                <form action="/delete">
                    <input type="hidden" name="id" th:value="${product.id}" />
                    <h2><input type="submit" class="btn btn-danger" value="Delete" onclick="return confirm('Are you sure?');" />
                        <a th:href="@{'/edit/' + ${product.id}}" class="btn btn-warning">Edit</a></h2>
                </form>
            </div>
        </div>
    </body>
</html>

Next, create a view for edit product with the name `edit.html` on `Resources/templates` folder then replace all codes with this.

<!DOCTYPE HTML>
<html lang="en"
      xmlns="http://www.w3.org/1999/xhtml"
      xmlns:th="http://www.thymeleaf.org"
      xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
      layout:decorate="default">
    <head>
        <title>Edit Product</title>
    </head>
    <body>
        <div layout:fragment="content" class="row">
            <div class="col-xs-8 col-md-8">
                <h3>
                    <a href="/product" class="btn btn-lg btn-primary"><span class="glyphicon glyphicon-list"></span> Product</a>
                </h3>
                <h2>Edit Product</h2>
                <form action="/update">
                    <div class="form-group">
                        <label for="email">Product Name:</label>
                        <input type="text" class="form-control" name="prodName" th:value="${product.prodName}" />
                    </div>
                    <div class="form-group">
                        <label for="email">Product Description</label>
                        <textarea class="form-control" name="prodDesc" cols="60" rows="3" th:text="${product.prodDesc}"></textarea>
                    </div>
                    <div class="form-group">
                        <label for="email">Product Price</label>
                        <input type="number" class="form-control" name="prodPrice" th:value="${product.prodPrice}" />
                    </div>
                    <div class="form-group">
                        <label for="email">Product Image URL:</label>
                        <input type="url" class="form-control" name="prodImage" th:value="${product.prodImage}" />
                    </div>
                    <input type="hidden" name="id" th:value="${product.id}" />
                    <button type="submit" class="btn btn-success">Save</button>
                </form>
            </div>
        </div>
    </body>
</html>

Finally, open and edit static HTML file `Resources/static/index.html` then replace all codes with this.

<!DOCTYPE HTML>
<html>
    <head>
        <title>Spring MongoDB Java CRUD Web Application</title>
    </head>
    <body>
        <h2>Spring MongoDB Java CRUD Web Application</h2>
        <p><a href="/product">Product List</a></p>
    </body>
</html>

This `index.html` is the first page that shows up on the browser after Web Application run.


Run The Spring Boot MongoDB Java Web App

Using Spring Boot, already define the main class for running the application. Just open the terminal or cmd then type this command to run the web application. Before that, make sure you have run the MongoDB server.

./gradlew bootRun

Then open the browser and go to this address `http://localhost:8080` and you will get the home page like this.

Spring Boot, MVC, Data and MongoDB CRUD Java Web Application - Spring Boot MVC Front Page

Just click on the `product list` link then you will get the page for do some CRUD operation.

Spring Boot, MVC, Data and MongoDB CRUD Java Web Application - Product List

That it's for now. We are creating this tutorial especially for Java Web newbie, for the master of java we need any suggestion and critics in the comments below. You can find the full and working source code on our GitHub.

That just the basic. If you need more deep learning about Java and Spring Framework you can take the following cheap course:

Thanks!