You are currently viewing Angular 9 and Spring Boot CRUD Tutorial – Feature 1 Display list of records in browser

Angular 9 and Spring Boot CRUD Tutorial – Feature 1 Display list of records in browser

Hey in this post we will quickly create spring boot and angular 9 application and create rest endpoint to retrieve the list of records. We will also make HTTP GET requests from the angular application to the rest endpoint which is exposed by spring boot application. let’s begin…

Create Spring Boot Application using Spring Initializer





There are many ways to create spring boot application, the quick and easy way to create a spring boot application is from Spring InitializrOne thing about spring initializer is that it keeps updating, so when you navigate this website you may not see the screen which is showing the above. Make sure the enter the details correctly –

  • Project – Maven
  • Language – Java
  • Spring boot version – 2.3.1 (this may varies time to time)
  • Project metadata
    • Group – in.bushansirgur
    • Artifact – expensetracker
    • Name – Expense Tracker
    • Description – Full stack application with Angular and spring boot
    • Package name – in.bushansirgur.expensetracker
    • Packaging – jar
    • Java – 8
  • Dependencies
    • Spring web
    • Spring boot devtools
    • Lombok
    • Spring Data JPA
    • Mysql driver

Create generate button, this will download the project in zip format, extract it, open it in any IDE eclipse/sts/IntelliJ

Spring Boot Project Structure


Let’s open the files one by one and add the following code…

pom.xml contains the following dependencies


<?xml version="1.0" encoding="UTF-8"?>
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.3.1.RELEASE</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>
	<groupId>in.bushansirgur</groupId>
	<artifactId>expensetracker</artifactId>
	<version>v1</version>
	<name>expensetracker</name>
	<description>Expense tracking application</description>

	<properties>
		<java.version>1.8</java.version>
		<maven-jar-plugin.version>2.6</maven-jar-plugin.version>
	</properties>

	<dependencies>
		<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.springframework.boot</groupId>
			<artifactId>spring-boot-devtools</artifactId>
			<scope>runtime</scope>
			<optional>true</optional>
		</dependency>
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<scope>runtime</scope>
		</dependency>
		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
			<optional>true</optional>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
			<exclusions>
				<exclusion>
					<groupId>org.junit.vintage</groupId>
					<artifactId>junit-vintage-engine</artifactId>
				</exclusion>
			</exclusions>
		</dependency>
	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>

</project>

Configure the database


As we added the dependency MySQL driver, now let’s configure the database inside the application.properties file.

spring.datasource.url=jdbc:mysql://localhost:3306/expensetracker?useSSL=false
spring.datasource.username=expensetracker
spring.datasource.password=expensetracker

spring.jpa.generate-ddl=true

spring.jpa.generate-ddl=true this will help us to create tables inside the database when we run the application.

Make sure the that you already have database created with name expensetracker inside the mysql database




Create an entity class – Expense.java


if you remember, we have added the Lombok dependency while creating the spring boot application, its a java library, helps us to reduce all the boilerplate code, we don’t need to override the setters and getters inside the entity class instead we can use @Setter and @Getter annotation, Lombok behind the scenes creates setters and getters for us.

package in.bushansirgur.expensetracker.model;

import java.math.BigDecimal;

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

import lombok.Getter;
import lombok.Setter;

@Entity
@Table(name="tbl_expenses")
@Setter
@Getter
public class Expense {
	
	@Id
	@GeneratedValue(strategy=GenerationType.IDENTITY)
	private Long id;
	
	private String expense;
	
	private String description;
	
	private BigDecimal amount;
}

Create a repository to perform database operations – ExpenseRepository.java


package in.bushansirgur.expensetracker.repository;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

import in.bushansirgur.expensetracker.model.Expense;

@Repository
public interface ExpenseRepository extends JpaRepository<Expense, Long> {

}

Create service and implementation class to communicate with the repository


ExpenseService.java

package in.bushansirgur.expensetracker.service;

import java.util.List;

import in.bushansirgur.expensetracker.model.Expense;

public interface ExpenseService {
	
	List<Expense> findAll();
	
}

ExpenseServiceImpl.java

package in.bushansirgur.expensetracker.service;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import in.bushansirgur.expensetracker.model.Expense;
import in.bushansirgur.expensetracker.repository.ExpenseRepository;

@Service
public class ExpenseSerivceImpl implements ExpenseService {

	@Autowired
	ExpenseRepository expenseRepository;
	
	@Override
	public List<Expense> findAll() {
		return expenseRepository.findAll();
	}

}

Create a controller class to expose the rest endpoints – ExpenseController.java


package in.bushansirgur.expensetracker.controller;

import java.util.List;

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.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import in.bushansirgur.expensetracker.model.Expense;
import in.bushansirgur.expensetracker.service.ExpenseService;

@CrossOrigin("*")
@RestController
@RequestMapping("/api/v1")
public class ExpenseController {

	@Autowired
	ExpenseService expenseService;
	
	@GetMapping("/expenses")
	public ResponseEntity<List<Expense>> get() {
		List<Expense> expenses = expenseService.findAll();
		return new ResponseEntity<List<Expense>>(expenses, HttpStatus.OK);
	}

}

Now this will expose the rest endpoint, http://localhost:8080/expenses

Next, let’s create angular 9 application and make HTTP GET request to above rest endpoint to get the list of expenses




Create angular project


We will create an angular project using Angular CLI, let enter the following command inside your command prompt

You can read more about angular cli here

ng new expense-tracker-frontend

this will ask you a couple of questions, the first question is to adding support for routing, enter no, later we will add manually, next it will ask which stylesheet to use, make sure to select CSS, that’s it, with this it will create an angular project for us.

Angular project structure


following is the directory structure for angular 9 project –

Create a model, component, and service using Angular CLI


To create a model class

ng g class models/expense --skipTests

–skipTests will not create the spec files

To create component

ng g c components/listExpenses --skipTests

To create service

ng g s services/expense --skipTests

Here c – component, s – service and g – generate

Let’s open index.html and add the bootstrap4 library for styling –

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>ExpenseTrackerFrontend</title>
  <base href="/">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="icon" type="image/x-icon" href="favicon.ico">
  <link rel="stylesheet" 
        href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css" 
        integrity="sha384-9aIt2nRpC12Uk9gS9baDl411NQApFmC26EwAOH8WgZl5MYYxFfc+NcPb1dKGj7Sk" 
        crossorigin="anonymous" />
  <link rel="stylesheet" 
        href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.14.0/css/all.min.css" />
</head>
<body>
  <app-root></app-root>
</body>
</html>

Next, open app.module.ts file and add the following code –

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { HttpClientModule } from "@angular/common/http";
import { RouterModule, Routes } from "@angular/router";
import { FormsModule } from "@angular/forms";

import { AppComponent } from './app.component';
import { ListExpensesComponent } from './components/list-expenses/list-expenses.component';
import { AddExpenseComponent } from './components/add-expense/add-expense.component';

const routers: Routes = [
  {path: 'expenses', component: ListExpensesComponent},
  {path: 'addexpense', component: AddExpenseComponent},
  {path: 'editexpense/:id', component: AddExpenseComponent},
  {path: '', redirectTo: '/expenses', pathMatch: 'full'}
];

@NgModule({
  declarations: [
    AppComponent,
    ListExpensesComponent,
    AddExpenseComponent
  ],
  imports: [
    BrowserModule,
    HttpClientModule,
    FormsModule,
    RouterModule.forRoot(routers)
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

So I have created 4 routes,

  • expenses – for displaying the list of expenses
  • addexpense – adding/editing an expense
  • editexpense/:id – getting a single expense
  • '' – this navigate to /expenses route

Next, open app.component.html and add the router-outlet to display the view template –

<div class="container">
    <h1>Expense Tracker</h1><hr/>
    <router-outlet></router-outlet>
</div>

Next, open expense.ts file and add the following code –

export class Expense {
    id: number;
    expense: string;
    amount: number;
    description: string;
}

Next, open expense.service.ts file and add the following code –

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
import { Expense } from '../models/expense';

@Injectable({
  providedIn: 'root'
})
export class ExpenseService {

  private getUrl: string = "http://localhost:8080/api/v1/expenses";

  constructor(private _httpClient: HttpClient) { }

  getExpenses(): Observable<Expense[]> {
    return this._httpClient.get<Expense[]>(this.getUrl).pipe(
      map(response => response)
    )
  }
}

Next, open list-expenses.component.ts and add the following code –

import { Component, OnInit } from '@angular/core';
import { Expense } from 'src/app/models/expense';
import { ExpenseService } from 'src/app/services/expense.service';

@Component({
  selector: 'app-list-expenses',
  templateUrl: './list-expenses.component.html',
  styleUrls: ['./list-expenses.component.css']
})
export class ListExpensesComponent implements OnInit {

  expenses: Expense[] = [];

  constructor(private _expenseService: ExpenseService) { }

  ngOnInit(): void {
    this.listExpenses();
  }

  listExpenses() {
    this._expenseService.getExpenses().subscribe(
      data => this.expenses = data
    )
  }
}

Now, open list-expenses.component.html and add the following code –




<div>
    <div class="card mt-1" *ngFor="let expense of expenses">
        <a href="#" class="card-body flex">
            <span class="text-capitalize font-weight-bold">{{expense.expense}}</span>
            <span class="float-right mr-2 badge badge-pill badge-warning font-weight-bold amount">{{expense.amount | currency: 'INR'}}</span>
        </a>
    </div>
</div>

With this in place, now if you run the application, you will see the following output –






IntroductionFeature – 2


You can find the Github repository here

You can find the step by step video series here

 

Bushan Sirgur

Hey guys, I am Bushan Sirgur from Banglore, India. Currently, I am working as an Associate project in an IT company.

Leave a Reply