Bạn có chắc chắn muốn xóa bài viết này không ?
Bạn có chắc chắn muốn xóa bình luận này không ?
Angular + Spring JPA + PostgreSQL example | Angular 4 Http Client - Spring Boot RestApi Server
Angular + Spring JPA + PostgreSQL example | Angular 4 Http Client - Spring Boot RestApi Server
In this tutorial, grokonez shows you Angular 4 Http Client & Spring Boot Server example that uses Spring JPA to interact with PostgreSQL and Angular 4 as a front-end technology to make request and receive response.
Related Posts:
- How to use Spring JPA with PostgreSQL | Spring Boot
- Spring JPA + PostgreSQL + AngularJS example | Spring Boot
- How to use Angular Http Client to fetch Data from SpringBoot RestAPI – Angular 4
- How to use Angular HttpClient to POST, PUT, DELETE data on SpringBoot Rest APIs – Angular 4
Updated:
I. Technologies
– Java 1.8
– Maven 3.3.9
– Spring Tool Suite – Version 3.8.4.RELEASE
– Spring Boot: RELEASE
– Angular 4
II. Overview
1. Spring Boot Server
For more details about Spring JPA - PostgreSQL, please visit:
How to use Spring JPA with PostgreSQL | Spring Boot
2. Angular 4 Client
For more details:
- About Angular 4 Routing: How to work with Angular Routing – Spring Boot + Angular 4
- About Angular Http Client to GET/POST/DELETE:
- How to use Angular Http Client to fetch Data from SpringBoot RestAPI – Angular 4
- How to use Angular HttpClient to POST, PUT, DELETE data on SpringBoot Rest APIs – Angular 4
III. Practice
1. Project Structure
1.1 Spring Boot Server
- Class Customer corresponds to entity and table customer, it should be implemented Serializable.
- 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:
getAll
,postCustomer
,delete
,findByLastName
. - Configuration for Spring Datasource and Spring JPA properties in application.properties
-
Dependencies for Spring Boot and PostgreSQL in pom.xml
1.2 Angular 4 Client
In this example, we focus on:
- 4 components: customers, customer-details, create-customer, search-customer.
- 3 modules: FormsModule, HttpModule, AppRoutingModule.
- customer.ts: class Customer (id, firstName, lastName)
- data.service.ts: DataService for Http Client methods
- proxy.conf.json for integrating Angular Client with Spring Boot Server.
2. How to do
2.1 Spring Boot Server
2.1.1 Dependency
<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>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<scope>runtime</scope>
</dependency>
2.1.2 Customer - Data Model
package com.javasampleapproach.jpapostgresqlangular4.model;
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
@Entity
@Table(name = "customer")
public class Customer implements Serializable {
private static final long serialVersionUID = -3009157732242241606L;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private long id;
@Column(name = "firstname")
private String firstName;
@Column(name = "lastname")
private String lastName;
protected Customer() {
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public Customer(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
@Override
public String toString() {
return String.format("Customer[id=%d, firstName='%s', lastName='%s']", id, firstName, lastName);
}
}
2.1.3 JPA Repository
package com.javasampleapproach.jpapostgresqlangular4.repo;
import java.util.List;
import org.springframework.data.repository.CrudRepository;
import com.javasampleapproach.jpapostgresqlangular4.model.Customer;
public interface CustomerRepository extends CrudRepository {
List findByLastName(String lastName);
}
2.1.4 REST Controller
package com.javasampleapproach.jpapostgresqlangular4.controller;
import java.util.ArrayList;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
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.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import com.javasampleapproach.jpapostgresqlangular4.model.Customer;
import com.javasampleapproach.jpapostgresqlangular4.repo.CustomerRepository;
@RestController
public class CustomerController {
@Autowired
CustomerRepository repository;
@GetMapping(value="/customer", produces=MediaType.APPLICATION_JSON_VALUE)
public List getAll() {
List list = new ArrayList();
Iterable customers = repository.findAll();
customers.forEach(list::add);
return list;
}
@PostMapping(value="/postcustomer")
public Customer postCustomer(@RequestBody Customer customer) {
repository.save(new Customer(customer.getFirstName(), customer.getLastName()));
return customer;
}
@GetMapping(value="/findbylastname/{lastName}", produces=MediaType.APPLICATION_JSON_VALUE)
public List findByLastName(@PathVariable String lastName) {
List customers = repository.findByLastName(lastName);
return customers;
}
@DeleteMapping(value="/customer/{id}")
public void deleteCustomer(@PathVariable long id){
repository.delete(id);
}
}
2.1.5 Configuration for Spring Datasource & JPA properties
spring.datasource.url=jdbc:postgresql://localhost/testdb
spring.datasource.username=postgres
spring.datasource.password=123
spring.jpa.generate-ddl=true
2.2 Angular 4 Client
2.2.0 Model
export class Customer {
public id: number;
public firstName: string;
public lastName: string;
}
2.2.1 DataService
import { Injectable } from '@angular/core';
import { Headers, Http } from '@angular/http';
import 'rxjs/add/operator/toPromise';
import { Customer } from './customer';
@Injectable()
export class DataService {
private customersUrl = 'customer'; // URL to web API
private headers = new Headers({'Content-Type': 'application/json'});
constructor(private http: Http) {}
// Get all customers
getCustomers(): Promise {
return this.http.get(this.customersUrl)
.toPromise()
.then(response => response.json() as Customer[])
.catch(this.handleError);
}
getCustomersByLastName(lastName: string): Promise {
const url = `findbylastname/${lastName}`;
return this.http.get(url)
.toPromise()
.then(response => response.json() as Customer)
.catch(this.handleError);
}
create(customer: Customer): Promise {
return this.http
.post("postcustomer", JSON.stringify(customer), {headers : this.headers})
.toPromise()
.then(res => res.json() as Customer)
.catch(this.handleError);
}
delete(id: number): Promise {
const url = `${this.customersUrl}/${id}`;
return this.http.delete(url, {headers: this.headers})
.toPromise()
.then(() => null)
.catch(this.handleError);
}
private handleError(error: any): Promise {
console.error('Error', error); // for demo purposes only
return Promise.reject(error.message || error);
}
}
2.2.2 Components
- CustomersComponent:
import { Component, OnInit } from '@angular/core'; import { Customer } from '../customer'; import { DataService } from '../data.service';
@Component({
selector: 'customers-list',
templateUrl: './customers.component.html',
styleUrls: ['./customers.component.css'],
})
export class CustomersComponent implements OnInit {
customers: Customer[];
selectedCustomer: Customer;
constructor(private dataService: DataService) {}
getCustomers() {
this.dataService.getCustomers().then(customers => this.customers = customers);
}
ngOnInit(): void {
this.getCustomers();
}
onSelect(cust: Customer): void {
this.selectedCustomer = cust;
}
}
<ul>
<li *ngFor="let cust of customers"
[class.selected]="cust === selectedCustomer" (click)="onSelect(cust)">
<h4>{{cust.id}} - {{cust.firstName}} {{cust.lastName}}</h4>
</li>
</ul>
<customer-detail [customer]="selectedCustomer"></customer-detail>
- CustomerDetailsComponent:
import { Component, Input } from '@angular/core';
import { Customer } from '../customer';
import { DataService } from '../data.service';
@Component({
selector: 'customer-detail',
templateUrl: './customer-details.component.html',
styleUrls: ['./customer-details.component.css'],
providers: [DataService]
})
export class CustomerDetailsComponent {
@Input() customer: Customer;
constructor(private dataService: DataService) {}
delete(): void {
this.dataService.delete(this.customer.id).then(() => this.goBack());
}
goBack(): void {
window.location.replace('');
}
}
<div *ngIf="customer">
<h2>{{customer.firstName}} details:</h2>
<div>
<label>id: </label> {{customer.id}}
</div>
<div>
<label>First Name: </label> {{customer.firstName}}
</div>
<div>
<label>Last Name: </label> {{customer.lastName}}
</div>
<button class="btn btn-danger" (click)="delete()">Delete</button>
</div>
- CreateCustomerComponent:
import {Customer} from '../customer'; import {DataService} from '../data.service'; import {Component, OnInit} from '@angular/core'; import {Location} from '@angular/common';
@Component({
selector: 'app-create-customer',
templateUrl: './create-customer.component.html',
styleUrls: ['./create-customer.component.css']
})
export class CreateCustomerComponent implements OnInit {
customer = new Customer;
submitted = false;
constructor(private dataService: DataService,
private location: Location) {}
ngOnInit() {
}
newCustomer(): void {
this.submitted = false;
this.customer = new Customer();
}
private save(): void {
this.dataService.create(this.customer);
}
onSubmit() {
this.submitted = true;
this.save();
}
goBack(): void {
this.location.back();
}
}
<h3>Create Customer Form</h3>
<div [hidden]="submitted" style="width: 300px;">
<form (ngSubmit)="onSubmit()">
<div class="form-group">
<label for="firstname">First Name</label> <input type="text"
class="form-control" id="firstname" required
[(ngModel)]="customer.firstName" name="firstname">
</div>
<div class="form-group">
<label for="lastname">Last Name</label> <input type="text"
class="form-control" id="lastname" required
[(ngModel)]="customer.lastName" name="lastname">
</div>
<div class="btn-group">
<button class="btn btn-primary" (click)="goBack()">Back</button>
<button type="submit" class="btn btn-success">Submit</button>
</div>
</form>
</div>
<div [hidden]="!submitted">
<div class="btn-group ">
<h4>You submitted successfully!</h4>
<button class="btn btn-primary" (click)="goBack()">Back</button>
<button class="btn btn-success" (click)="newCustomer()">Add</button>
</div>
</div>
- SearchCustomersComponent:
import {Component, OnInit} from '@angular/core'; import {Customer} from '../customer'; import {DataService} from '../data.service';
@Component({
selector: 'app-search-customers',
templateUrl: './search-customers.component.html',
styleUrls: ['./search-customers.component.css']
})
export class SearchCustomersComponent implements OnInit {
lastName: string;
customers: Customer[];
constructor(private dataService: DataService) {}
ngOnInit() {
this.lastName = "";
}
private searchCustomers() {
this.dataService.getCustomersByLastName(this.lastName).then(customers => this.customers = customers);
}
onSubmit() {
this.searchCustomers();
}
}
<h3>Find By Last Name</h3>
<div style="width: 300px;">
<form (ngSubmit)="onSubmit()">
<div class="form-group">
<label for="lastname">Last Name</label> <input type="text"
class="form-control" id="lastname" required [(ngModel)]="lastName"
name="lastname">
</div>
<div class="btn-group">
<button type="submit" class="btn btn-success">Submit</button>
</div>
</form>
</div>
<ul>
<li *ngFor="let cust of customers">
<h4>{{cust.id}} - {{cust.firstName}} {{cust.lastName}}</h4>
</li>
</ul>
2.2.3 AppRoutingModule
import {CreateCustomerComponent} from './create-customer/create-customer.component';
import {CustomersComponent} from './customers/customers.component';
import {SearchCustomersComponent} from './search-customers/search-customers.component';
import {NgModule} from '@angular/core';
import {RouterModule, Routes} from '@angular/router';
const routes: Routes = [
{path: '', redirectTo: 'customer', pathMatch: 'full'},
{path: 'customer', component: CustomersComponent},
{path: 'add', component: CreateCustomerComponent},
{path: 'findbylastname', component: SearchCustomersComponent},
];
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule {}
And AppComponent HTML for routing:
<div style="padding: 20px;">
<h2 style="color: blue">JSA - Angular Application!</h2>
<nav>
<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="findbylastname" class="btn btn-primary active" role="button" routerLinkActive="active">Search</a>
</nav>
<router-outlet></router-outlet>
</div>
2.2.4 AppModule
import {AppRoutingModule} from './app-routing.module';
import {BrowserModule} from '@angular/platform-browser';
import {NgModule} from '@angular/core';
import {FormsModule} from '@angular/forms';
import {HttpModule} from '@angular/http';
import {AppComponent} from './app.component';
import {CustomerDetailsComponent} from './customer-details/customer-details.component';
import {CustomersComponent} from './customers/customers.component';
import {DataService} from './data.service';
import {CreateCustomerComponent} from './create-customer/create-customer.component';
import {enableProdMode} from '@angular/core';
import {SearchCustomersComponent} from './search-customers/search-customers.component';
@NgModule({
declarations: [
AppComponent,
CustomerDetailsComponent,
CustomersComponent,
CreateCustomerComponent,
SearchCustomersComponent
],
imports: [
BrowserModule,
FormsModule,
HttpModule,
AppRoutingModule
],
providers: [DataService],
bootstrap: [AppComponent]
})
export class AppModule {}
2.2.5 Integrate Angular Client with Spring Boot Server
- Add proxy.conf.json to root folder of the project:
– Edit package.json file for “start” script:{ "/": { "target": "http://localhost:8080", "secure": false } }
... "scripts": { "ng": "ng", "start": "ng serve --proxy-config proxy.conf.json", "build": "ng build", "test": "ng test", "lint": "ng lint", "e2e": "ng e2e" }, ...
3. Run & Check Result
-
Build and Run Spring Boot project with commandlines:
mvn clean install
andmvn spring-boot:run
. Run the Angular App with command:
npm start
.Open browser for url
http://localhost:4200/
:
Add Customer:
Show Customers & click on any Customer:
Go back to ShowCustomers, chose a Customer and click on Delete Customer:
IV. Source Code






