This tutorial will demonstrate how to create a Spring Boot CRUD application using AngularJS as front end.

AngularJS is a Javascript based framework for dynamic web apps. It lets you use HTML as your template language and lets you extend its syntax to express your application's components clearly and in a concise way. In this tutorial we will combina an Angular JS Controller with a Spring Boot REST Service.

Let's start from the dependencies needed for this application:

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-web</artifactId>
</dependency>

<dependency>
	<groupId>com.h2database</groupId>
	<artifactId>h2</artifactId>
	<scope>runtime</scope>
</dependency>

As our application will persist data in an H2 Database, we have added both the spring-boot-starter-data-jpa and the h2 dependencies. Then, we have also included the spring-boot-starter-web that allows us using RESTful applications and Spring MVC.

Let's start from the Entity class, named Customer:

package com.example.cruddemo.entities;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.validation.constraints.NotBlank;

@Entity
public class Customer {
    
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private long id;
    @NotBlank(message = "Name is required")
    private String name;

    @NotBlank(message = "Surname is required")
    private String surname;

    public Customer() {}

    public void setId(long id) {
        this.id = id;
    }
    
    public long getId() {
        return id;
    }
    
    public void setName(String name) {
        this.name = name;
    }


    public String getName() {
        return name;
    }
     public String getSurname() {
        return surname;
    }

    public void setSurname(String surname) {
        this.surname = surname;
    }

}

In order to persist data, we will extend the CrudRepository base class, overriding just the findAll method, as we will return a List of Customer objects (instead of an Iterable set):

package com.example.cruddemo.repositories;

import com.example.cruddemo.entities.Customer;

import java.util.List;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface CustomerRepository extends CrudRepository<Customer, Long> {

    @Override
    List<Customer> findAll();
    
}

Then, here is our Controller class, which contains a method for each HTTP method:

package com.example.cruddemo.controllers;

import com.example.cruddemo.entities.Customer;
import com.example.cruddemo.repositories.CustomerRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import java.util.List;

@Controller
@RequestMapping(value = "/customers")
public class CustomerController {
    
    private final CustomerRepository customerRepository;

    @Autowired
    public CustomerController(CustomerRepository customerRepository) {
        this.customerRepository = customerRepository;
    }

    @RequestMapping(method = RequestMethod.GET, produces = {"application/json"})
    public  @ResponseBody
    List<Customer> listCustomers() {
       return customerRepository.findAll();
    }

    @RequestMapping(method = RequestMethod.POST, consumes = {"application/json"})
    public @ResponseBody void addCustomer(@RequestBody Customer customer) {
        customerRepository.save(customer);
    }

    @RequestMapping(method = RequestMethod.PUT, consumes = {"application/json"})
    public @ResponseBody void updateCustomer(@RequestBody Customer customer) {
        customerRepository.save(customer);
    }

    @RequestMapping(method = RequestMethod.DELETE)
    public @ResponseBody void deleteCustomer(@RequestParam("id") Long id) {
        customerRepository.deleteById(id);

    }


}

Please notice the @ResponseBody annotation which tells a controller that the object returned is automatically serialized into JSON and passed back into the HttpResponse object. If not included, Spring MVC would expect to return the view where the navigation continues.

Finally, an Application class is included to boot our Spring Boot CRUD application:

package com.example.cruddemo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication 
public class DemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }
    
}

That's all with the Spring Boot part. Now let's add an index.html page under src/main/webapp. We will check at first the AngularJS part, then the HTML form:

    <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
    <script type="text/javascript">
      var app = angular.module("customerManagement", []);
      angular.module('customerManagement').constant('SERVER_URL','/customers');

      //Controller Part
      app.controller("customerManagementController",  function ($scope, $http, SERVER_URL) {
        //Initialize page with default data which is blank in this example
        $scope.customers = [];
        $scope.form = {
          id: -1,
          name: "",
          surname: ""
        };
        //Now load the data from server
        _refreshPageData();
        //HTTP POST/PUT methods for add/edit customers
        $scope.update = function () {
          var method = "";
          var url = "";
          var data = {};
          if ($scope.form.id == -1) {
            //Id is absent so add customers - POST operation
            method = "POST";
            url = SERVER_URL;
            data.name = $scope.form.name;
            data.surname = $scope.form.surname;
          } else {
            //If Id is present, it's edit operation - PUT operation
            method = "PUT";
            url = SERVER_URL;

            data.id = $scope.form.id;
            data.name = $scope.form.name;
            data.surname = $scope.form.surname;
          }
          $http({
            method: method,
            url: url,
            data: angular.toJson(data),
            headers: {
              'Content-Type': 'application/json'
            }
          }).then(_success, _error);
        };
        //HTTP DELETE- delete customer by id
        $scope.remove = function (customer) {

          $http({
            method: 'DELETE',
            url: SERVER_URL+'?id='+customer.id
          }).then(_success, _error);
        };
        //In case of edit customers, populate form with customer data
        $scope.edit = function (customer) {
          $scope.form.name = customer.name;
          $scope.form.surname = customer.surname;
          $scope.form.id = customer.id;
        };
          /* Private Methods */
        //HTTP GET- get all customers collection
        function _refreshPageData() {
          $http({
            method: 'GET',
            url: SERVER_URL
          }).then(function successCallback(response) {
            $scope.customers = response.data;
          }, function errorCallback(response) {
            console.log(response.statusText);
          });
        }
        function _success(response) {
          _refreshPageData();
          _clearForm()
        }
        function _error(response) {
          alert(response.data.message || response.statusText);
        }
        //Clear the form
        function _clearForm() {
          $scope.form.name = "";
          $scope.form.surname = "";
          $scope.form.id = -1;
        }
      });
    </script>

As you can see from above, we have created a customerManagementController with a set of functions to handle the HTTP GET, POST, PUT and DELETE functions, passing as argument the HTML data in JSON format. Here is the HTML form contained:

  <div class="divTable blueTable">
        <div class="divTableHeading">
            <div  class="divTableHead">Customer Name</div>
            <div  class="divTableHead">Customer Surname</div>
            <div  class="divTableHead">Action</div>
        </div>
        <div class="divTableRow" ng-repeat="customer in customers">
            <div class="divTableCell">{{ customer.name }}</div>
            <div class="divTableCell">{{ customer.surname }}</div>
            <div class="divTableCell"><a ng-click="edit( customer )" class="myButton">Edit</a> <a ng-click="remove( customer )" class="myButton">Remove</a></div>
        </div>
    </div>

You can check the full source code for this example at the bottom of this article.

Here is our project tree:

src
├── main
│   ├── java
│   │   └── com
│   │       └── example
│   │           └── cruddemo
│   │               ├── controllers
│   │               │   └── CustomerController.java
│   │               ├── DemoApplication.java
│   │               ├── entities
│   │               │   └── Customer.java
│   │               └── repositories
│   │                   └── CustomerRepository.java
│   ├── resources
│   │   ├── application.properties
│   └── webapp
│       ├── index.html
│       └── stylesheet.css

Build your Spring Boot CRUD application with:

mvn clean install spring-boot:run

And finally, here is your AngularJS Spring Boot CRUD application in action:

spring boot angularjs CRUD tutorial spring boot angularjs CRUD tutorial

Source code for the AngularJS Spring Boot CRUD application: https://github.com/fmarchioni/masterspringboot/tree/master/crud/spring-crud-angular/angulardemo

FREE WildFly Application Server - JBoss - Quarkus - Drools Tutorials