Spring Boot + Angular 6 example | Spring Data JPA + REST + MySQL CRUD example


In this tutorial, we show you Angular 6 Http Client & Spring Boot Server example that uses Spring JPA to do CRUD with MySQL and Angular 6 as a front-end technology to make request and receive response.

Related Posts:
How to use Spring JPA MySQL | Spring Boot

Update for Angular 8:
Spring Boot 2.1 + Angular 8 + MySQL example | Angular HTTP Client + RestAPIs + Spring JPA CRUD + MySQL tutorial

You may like this series:
Angular Spring Boot JWT Authentication example | Angular 6 + Spring Security + MySQL Full Stack

I. Technologies

– Java 1.8
– Maven 3.3.9
– Spring Tool Suite – Version 3.8.4.RELEASE
– Spring Boot: 2.0.3.RELEASE
– Angular 6
– RxJS 6

II. Overview



1. Spring Boot Server


2. Angular 6 Client


III. Practice

1. Project Structure

1.1 Spring Boot Server


Customer class corresponds to entity and table customer.
CustomerRepository is an interface extends CrudRepository, will be autowired in CustomerController for implementing repository methods and custom finder methods.
CustomerController is a REST Controller which has request mapping methods for RESTful requests such as: getAllCustomers, postCustomer, deleteCustomer, deleteAllCustomers, findByAge, updateCustomer.
– Configuration for Spring Datasource and Spring JPA properties in application.properties
Dependencies for Spring Boot and MySQL in pom.xml

1.2 Angular 6 Client


In this example, we focus on:
– 4 components: customers-list, customer-details, create-customer, search-customer.
– 3 modules: FormsModule, HttpClientModule, AppRoutingModule.
customer.ts: class Customer (id, firstName, lastName)
customer.service.ts: Service for Http Client methods

2. How to do

2.1 Spring Boot Server

2.1.1 Dependency


2.1.2 Customer – Data Model


package com.javasampleapproach.springrest.mysql.model;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;

@Table(name = "customer")
public class Customer {

	@GeneratedValue(strategy = GenerationType.AUTO)
	private long id;

	@Column(name = "name")
	private String name;

	@Column(name = "age")
	private int age;

	@Column(name = "active")
	private boolean active;

	public Customer() {

	public Customer(String name, int age) {
		this.name = name;
		this.age = age;
		this.active = false;

	public long getId() {
		return id;

	public void setName(String name) {
		this.name = name;

	public String getName() {
		return this.name;

	public void setAge(int age) {
		this.age = age;

	public int getAge() {
		return this.age;

	public boolean isActive() {
		return active;

	public void setActive(boolean active) {
		this.active = active;

	public String toString() {
		return "Customer [id=" + id + ", name=" + name + ", age=" + age + ", active=" + active + "]";
2.1.3 JPA Repository


package com.javasampleapproach.springrest.mysql.repo;

import java.util.List;

import org.springframework.data.repository.CrudRepository;

import com.javasampleapproach.springrest.mysql.model.Customer;

public interface CustomerRepository extends CrudRepository {
	List findByAge(int age);
2.1.4 REST Controller


package com.javasampleapproach.springrest.mysql.controller;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.javasampleapproach.springrest.mysql.model.Customer;
import com.javasampleapproach.springrest.mysql.repo.CustomerRepository;

@CrossOrigin(origins = "http://localhost:4200")
public class CustomerController {

	CustomerRepository repository;

	public List getAllCustomers() {
		System.out.println("Get all Customers...");

		List customers = new ArrayList<>();

		return customers;

	@PostMapping(value = "/customers/create")
	public Customer postCustomer(@RequestBody Customer customer) {

		Customer _customer = repository.save(new Customer(customer.getName(), customer.getAge()));
		return _customer;

	public ResponseEntity deleteCustomer(@PathVariable("id") long id) {
		System.out.println("Delete Customer with ID = " + id + "...");


		return new ResponseEntity<>("Customer has been deleted!", HttpStatus.OK);

	public ResponseEntity deleteAllCustomers() {
		System.out.println("Delete All Customers...");


		return new ResponseEntity<>("All customers have been deleted!", HttpStatus.OK);

	@GetMapping(value = "customers/age/{age}")
	public List findByAge(@PathVariable int age) {

		List customers = repository.findByAge(age);
		return customers;

	public ResponseEntity updateCustomer(@PathVariable("id") long id, @RequestBody Customer customer) {
		System.out.println("Update Customer with ID = " + id + "...");

		Optional customerData = repository.findById(id);

		if (customerData.isPresent()) {
			Customer _customer = customerData.get();
			return new ResponseEntity<>(repository.save(_customer), HttpStatus.OK);
		} else {
			return new ResponseEntity<>(HttpStatus.NOT_FOUND);
2.1.5 Configuration for Spring Datasource & JPA properties



2.2 Angular 6 Client

2.2.0 Create Service & Components

Run commands below:
ng g s customer
ng g c create-customer
ng g c customer-details
ng g c customers-list
ng g c search-customers
On each Component selector, delete app- prefix, then change tslint.json rules"component-selector" to false.

2.2.1 Model


export class Customer {
    id: number;
    name: string;
    age: number;
    active: boolean;
2.2.2 CustomerService


import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';

  providedIn: 'root'
export class CustomerService {

  private baseUrl = 'http://localhost:8080/api/customers';

  constructor(private http: HttpClient) { }

  getCustomer(id: number): Observable<Object> {
    return this.http.get(`${this.baseUrl}/${id}`);

  createCustomer(customer: Object): Observable<Object> {
    return this.http.post(`${this.baseUrl}` + `/create`, customer);

  updateCustomer(id: number, value: any): Observable<Object> {
    return this.http.put(`${this.baseUrl}/${id}`, value);

  deleteCustomer(id: number): Observable<any> {
    return this.http.delete(`${this.baseUrl}/${id}`, { responseType: 'text' });

  getCustomersList(): Observable<any> {
    return this.http.get(`${this.baseUrl}`);

  getCustomersByAge(age: number): Observable<any> {
    return this.http.get(`${this.baseUrl}/age/${age}`);

  deleteAll(): Observable<any> {
    return this.http.delete(`${this.baseUrl}` + `/delete`, { responseType: 'text' });
2.2.3 Components

– CustomerDetailsComponent:

import { Component, OnInit, Input } from '@angular/core';
import { CustomerService } from '../customer.service';
import { Customer } from '../customer';

import { CustomersListComponent } from '../customers-list/customers-list.component';

  selector: 'customer-details',
  templateUrl: './customer-details.component.html',
  styleUrls: ['./customer-details.component.css']
export class CustomerDetailsComponent implements OnInit {

  @Input() customer: Customer;

  constructor(private customerService: CustomerService, private listComponent: CustomersListComponent) { }

  ngOnInit() {

  updateActive(isActive: boolean) {
      { name: this.customer.name, age: this.customer.age, active: isActive })
        data => {
          this.customer = data as Customer;
        error => console.log(error));

  deleteCustomer() {
        data => {
        error => console.log(error));


<div *ngIf="customer">
    <label>Name: </label> {{customer.name}}
    <label>Age: </label> {{customer.age}}
    <label>Active: </label> {{customer.active}}

  <span class="button is-small btn-primary" *ngIf='customer.active' (click)='updateActive(false)'>Inactive</span>

  <span class="button is-small btn-primary" *ngIf='!customer.active' (click)='updateActive(true)'>Active</span>

  <span class="button is-small btn-danger" (click)='deleteCustomer()'>Delete</span>


– CustomersListComponent:

import { Component, OnInit } from '@angular/core';
import { Observable } from 'rxjs';

import { CustomerService } from '../customer.service';
import { Customer } from '../customer';

  selector: 'customers-list',
  templateUrl: './customers-list.component.html',
  styleUrls: ['./customers-list.component.css']
export class CustomersListComponent implements OnInit {

  customers: Observable;

  constructor(private customerService: CustomerService) { }

  ngOnInit() {

  deleteCustomers() {
        data => {
        error => console.log('ERROR: ' + error));

  reloadData() {
    this.customers = this.customerService.getCustomersList();



<div *ngFor="let customer of customers | async" style="width: 300px;">
  <customer-details [customer]='customer'></customer-details>

  <button type="button" class="button btn-danger" (click)='deleteCustomers()'>Delete All</button>

– CreateCustomerComponent:

import { Component, OnInit } from '@angular/core';

import { Customer } from '../customer';
import { CustomerService } from '../customer.service';

  selector: 'create-customer',
  templateUrl: './create-customer.component.html',
  styleUrls: ['./create-customer.component.css']
export class CreateCustomerComponent implements OnInit {

  customer: Customer = new Customer();
  submitted = false;

  constructor(private customerService: CustomerService) { }

  ngOnInit() {

  newCustomer(): void {
    this.submitted = false;
    this.customer = new Customer();

  save() {
      .subscribe(data => console.log(data), error => console.log(error));
    this.customer = new Customer();

  onSubmit() {
    this.submitted = true;


<h2>Create Customer</h2>
<div [hidden]="submitted" style="width: 300px;">
  <form (ngSubmit)="onSubmit()">
    <div class="form-group">
      <label for="name">Name</label>
      <input type="text" class="form-control" id="name" required [(ngModel)]="customer.name" name="name">

    <div class="form-group">
      <label for="age">Age</label>
      <input type="text" class="form-control" id="age" required [(ngModel)]="customer.age" name="age">

    <button type="submit" class="btn btn-success">Submit</button>

<div [hidden]="!submitted">
  <h3>You submitted successfully!</h3>
  <button class="btn btn-success" (click)="newCustomer()">Add</button>

– SearchCustomersComponent:

import { Component, OnInit } from '@angular/core';
import { Customer } from '../customer';
import { CustomerService } from '../customer.service';

  selector: 'search-customers',
  templateUrl: './search-customers.component.html',
  styleUrls: ['./search-customers.component.css']
export class SearchCustomersComponent implements OnInit {

  age: number;
  customers: Customer[];

  constructor(private dataService: CustomerService) { }

  ngOnInit() {
    this.age = 0;

  private searchCustomers() {
      .subscribe(customers => this.customers = customers);

  onSubmit() {


<h2>Find By Age</h2>
<div style="width: 300px;">
  <form (ngSubmit)="onSubmit()">
    <div class="form-group">
      <label for="lastname">Age</label>
      <input type="text" class="form-control" id="age" required [(ngModel)]="age" name="age">

    <div class="btn-group">
      <button type="submit" class="btn btn-success">Submit</button>
  <li *ngFor="let customer of customers">
    <h3>{{customer.id}} - {{customer.name}} {{customer.age}}</h3>
2.2.4 AppRoutingModule


import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { CustomersListComponent } from './customers-list/customers-list.component';
import { CreateCustomerComponent } from './create-customer/create-customer.component';
import { SearchCustomersComponent } from './search-customers/search-customers.component';

const routes: Routes = [
    { path: '', redirectTo: 'customer', pathMatch: 'full' },
    { path: 'customer', component: CustomersListComponent },
    { path: 'add', component: CreateCustomerComponent },
    { path: 'findbyage', component: SearchCustomersComponent },

    imports: [RouterModule.forRoot(routes)],
    exports: [RouterModule]

export class AppRoutingModule { }

And AppComponent HTML for routing:

<div style="padding: 20px;">
  <h1 style="color: blue">{{title}}</h1>
    <a routerLink="customer" class="btn btn-primary active" role="button" routerLinkActive="active">Customers</a>
    <a routerLink="add" class="btn btn-primary active" role="button" routerLinkActive="active">Add</a>
    <a routerLink="findbyage" class="btn btn-primary active" role="button" routerLinkActive="active">Search</a>
2.2.5 AppModule


import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';

import { AppComponent } from './app.component';
import { CreateCustomerComponent } from './create-customer/create-customer.component';
import { CustomerDetailsComponent } from './customer-details/customer-details.component';
import { CustomersListComponent } from './customers-list/customers-list.component';
import { SearchCustomersComponent } from './search-customers/search-customers.component';
import { AppRoutingModule } from './app-routing.module';
import { HttpClientModule } from '@angular/common/http';

  declarations: [
  imports: [
  providers: [],
  bootstrap: [AppComponent]
export class AppModule { }

3. Run & Check Result

Build and Run Spring Boot project with commandlines: mvn clean install and mvn spring-boot:run.
– Run the Angular App with command: ng serve.

– Open browser for url http://localhost:4200/:
Add Customer:


Show Customers:


Click on Active button to update Customer status:


Search Customers by Age:


Delete a Customer:


Delete All Customers:


IV. Source Code


24 thoughts on “Spring Boot + Angular 6 example | Spring Data JPA + REST + MySQL CRUD example”

  1. Respected Sir,
    I am new to SPRING BOOT.
    I have download SpringRestMySql-Server above project and unzip,import in STS.
    When I run this app I got the following error.

    Field repository in com.javasampleapproach.springrest.mysql.controller.CustomerController required a bean named ‘entityManagerFactory’ that could not be found.


    Consider defining a bean named ‘entityManagerFactory’ in your configuration.

    Could you please give solution for run above project.

    Thanks & Regards

    1. Here is how I started the application (there can be efficient ways and this is not an official instruction):
      > Created repository : .\ng6SpringBoot
      > Extracted source code files with following Folder Structure ::
      >> .\ng6SpringBoot
      |-> Angular6SpringBoot-Client
      |-> SpringRestMySQL

      ## Frontend
      >>> cd Angular6SpringBoot-Client
      >>> npm install
      >>> ng serve -o
      ^ This step will run the frontend at http://localhost:4200

      ## Backend
      > Open IntelliJ
      >> Import project
      >> Navigate to ./ng6SpringBoot/SpringRestMySQL
      >> Select Maven Project (if not already selected), click Next.
      >> Select the option for “searching Maven Repository recursively” (or something similar)
      >> Click Next > Next > Next.. > Finish

      ## Database
      Install Mysql client and workbench.
      Configure the server with the properties found in application.properties file.

      >> spring.datasource.url=jdbc:mysql://localhost:3306/testdb?useSSL=false
      >> spring.datasource.username=root
      >> spring.datasource.password= 12345
      >> spring.jpa.generate-ddl=true

      DbName: testdb
      Tablename: customer
      id: number;
      name: string;
      age: number;
      active: boolean;

      run the db server
      run the maven application by right clicking SpringRestMySqlApplication.java file and click Run.

      # The projects runs as expected.

      1. Great tutorial. But this answer should be part of the article to help newbies like me. The order should be reverse: database, backend server, frontend Angular app

  2. throwing error

    ng serve
    throw err;

    Error: Cannot find module ‘ng-factory’ from ‘D:\Projects\SpringBootExample\Angular6SpringBoot-Client’
    at Function.module.exports [as sync] (C:\Users\AppData\Roaming\npm\node_modules\ng-cli\node_modules\resolve\lib\sync.js:43:15)
    at module.exports (C:\Users\AppData\Roaming\npm\node_modules\ng-cli\node_modules\resolve-require\lib\index.js:10:24)
    at Command. (C:\Users\AppData\Roaming\npm\node_modules\ng-cli\lib\index.js:49:5)
    at Command.listener (C:\Users\AppData\Roaming\npm\node_modules\ng-cli\node_modules\commander\index.js:315:8)
    at Command.emit (events.js:182:13)
    at Command.parseArgs (C:\Users\AppData\Roaming\npm\node_modules\ng-cli\node_modules\commander\index.js:654:12)
    at Command.parse (C:\Users\AppData\Roaming\npm\node_modules\ng-cli\node_modules\commander\index.js:474:21)
    at Object. (C:\Users\AppData\Roaming\npm\node_modules\ng-cli\lib\index.js:55:9)
    at Module._compile (internal/modules/cjs/loader.js:678:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:689:10)
    PS D:\Projects\SpringBootExample\Angular6SpringBoot-Client>

  3. I have a question.
    I started an application as same as you, but when I browser for url http://localhost:4200/ I see the frontend, but when I click inspect there is no customer.service.ts in sources or any other .ts file.

    May you help me?

    When I try to run SpringRestMySqlApplication.java I get an Error: Could not find or load main class com.javasampleapproach.springrest.mysql.SpringRestMySqlApplication

  4. Hi,

    Great tutorial, however when I tried to deploy the spring boot part as a war file on tomcat and spring boot and call it from the angular part I wasn’t able to make contact with the methods in the war file. Even checking from advanced rest api client give me back the following:-

    Error404 – Not Found

    Any pointers as to where to start looking?


    1. To add, I changed the main class to extend SpringBootServletInitializer and added the following:-

      	protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
      		return application.sources(SpringRestMySqlApplication.class);

      It was also packaged as a war file and the tomcat thingy in the dependency was set to provided.

      It looked better when deploying, but no joy when trying to call:-


      1. OK, sorted, not related to the tutorial, but I had to include the name of the application in the link in baseURL in the customer.service.ts file

        private baseUrl = ‘http://localhost:8080/spring-boot-rest-mysql-0.0.1-SNAPSHOT/api/customers’;

  5. Hi,

    I’m having this error :

    Access to XMLHttpRequest at ‘http://localhost:8080/api/customers/create’ from origin ‘http://localhost:4200’ has been blocked by CORS policy: Response to preflight request doesn’t pass access control check: No ‘Access-Control-Allow-Origin’ header is present on the requested resource.

    Any help please ?

    1. Hi vamsi,

      Please check the code above:
      – In customer.service.ts:

      export class CustomerService {
        // ... 
        updateCustomer(id: number, value: any): Observable {
          return this.http.put(`${this.baseUrl}/${id}`, value);

      – In customer-details/customer-details.component.ts:

      export class CustomerDetailsComponent implements OnInit {
        // ...
        updateActive(isActive: boolean) {
            { name: this.customer.name, age: this.customer.age, active: isActive })
              data => {
                this.customer = data as Customer;
              error => console.log(error));


    1. Hi Tien,

      You can use Spring Tool Suite: New -> Spring Starter Project.
      Or you can access that url.


  6. Its showing error like

    ERROR in src/app/customer.service.ts(15,22): error TS2339: Property ‘get’ does not exist on type ‘HttpClient’.
    src/app/customer.service.ts(19,22): error TS2339: Property ‘post’ does not exist on type ‘HttpClient’.
    src/app/customer.service.ts(23,22): error TS2339: Property ‘put’ does not exist on type ‘HttpClient’.
    src/app/customer.service.ts(27,22): error TS2339: Property ‘delete’ does not exist on type ‘HttpClient’.
    src/app/customer.service.ts(31,22): error TS2339: Property ‘get’ does not exist on type ‘HttpClient’.
    src/app/customer.service.ts(35,22): error TS2339: Property ‘get’ does not exist on type ‘HttpClient’.
    src/app/customer.service.ts(39,22): error TS2339: Property ‘delete’ does not exist on type ‘HttpClient’.

  7. I have faced the following error. can you please help me?

    Access to XMLHttpRequest at ‘http://localhost:8080/api/customers/create’ from origin ‘http://localhost:4200’ has been blocked by CORS policy: Response to preflight request doesn’t pass access control check: It does not have HTTP ok status.


  8. how to fix this?

    Microsoft Windows [Version 10.0.17134.1]
    (c) 2018 Microsoft Corporation. All rights reserved.

    C:\Users\farsb\Downloads\Angular6SpringBoot-Client\Angular6SpringBoot-Client>npm install
    ‘npm’ is not recognized as an internal or external command,
    operable program or batch file.


  9. hi! can you rebuild this angular architecture and show customers details in table and search also in table(not a separate part). Moreover delete and active update funtions in customers-details.ts file. thanks

  10. hi
    i download two file Source Code
    – Angular6SpringBoot-Client
    – SpringRestMySQL-Server

    the Angular6SpringBoot-Client has run
    but in intellij idea when i open – SpringRestMySQL-Server ,,, a run button is disable
    i know run with main class but i can not enable this
    please help me

Leave a Reply

Your email address will not be published. Required fields are marked *