Show List

Full Stack Angular Spring Boot Web Application

In this full stack web application example, we will be creating the back end using Spring Boot Rest API and front end will be developed using Angular. The application will be to display Student details on the website and to allow add/delete the student from the database.

Spring Boot Rest API (Back End)

We are going to use H2 (In memory) database to store the student details. Below is the structure of the project we are going to create for this example. Web folder will contain angular application code that we will cover in the later section below.
1. Go to Spring initializr website and create a Java Maven Project with dependencies: H2, Spring Data JPA and Web. Download the project zip and extract to a folder.

2. Import the project into IDE (I am using IntelliJ Idea). Pom.xml:
<?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.7.3</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>demo</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>11</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>

<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>

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

</project>
2. Create Student class in the com.example.demo.model package. 
package com.example.demo.model;

import javax.persistence.*;

@Entity
@Table
public class Student {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long student_id;
private String name;
private String grade;

public Student(){

}
public Student( String name, String grade) {
this.name = name;
this.grade = grade;
}

public Long getStudent_id() {
return student_id;
}

public void setStudent_id(Long student_id) {
this.student_id = student_id;
}

public String getName() {
return name;
}

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

public String getGrade() {
return grade;
}

public void setGrade(String grade) {
this.grade = grade;
}
}
3. Create StudentRepo class extending CrudRepository. CrudRepository will provide the Create, Read, Update and Delete methods.
package com.example.demo.dao;

import com.example.demo.model.Student;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface StudentRepo extends CrudRepository<Student, Long> {}
4. Create controller class StudentController. 
  • @RestController is combination of @Controller and @ResponseBody. @Controller means this class will handle the requests. @ResponseBody means that object returned is automatically serialized into JSON.
  • @GetMapping, @PostMapping, @DeleteMapping, @PutMapping are to map the handler methods. Handler methods call the repo class for database updates.
package com.example.demo.controller;

import com.example.demo.dao.StudentRepo;
import com.example.demo.model.Student;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

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

@RestController
public class StudentController {

@Autowired
private StudentRepo repo;

@GetMapping("/students")
private List<Student> getAllStudents(){
return (List<Student>) repo.findAll();
}

@GetMapping("/student/{id}")
private Optional<Student> getStudents(@PathVariable Long id){
return repo.findById(id);
}

@PostMapping("/students")
private Student addStudent(@RequestBody Student newStudent){
return repo.save(newStudent);
}

@DeleteMapping("/students/{id}")
private void removeStudent(@PathVariable Long id){
repo.deleteById(id);
}

@PutMapping("/students/{id}")
private Student updateStudent(@RequestBody Student newStudent, @PathVariable Long id){
return repo.findById(id)
.map(student -> {
student.setName(newStudent.getName());
student.setGrade(newStudent.getGrade());
return repo.save(student);
})
.orElseGet(() -> {
newStudent.setStudent_id(Math.toIntExact(id));
return repo.save(newStudent);
});
}
}
5. Create LoadData class in the com.example.demo.dataload package to load sample data in the H2 database when the application loads.
 package com.example.demo.dataload;

import com.example.demo.dao.StudentRepo;
import com.example.demo.model.Student;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.context.annotation.Configuration;

@Configuration
public class LoadData implements ApplicationRunner {

@Autowired
StudentRepo repo;

@Override
public void run(ApplicationArguments args) throws Exception {
repo.save(new Student("Ana", "One"));
repo.save(new Student("Bob", "Two"));
repo.save(new Student("Charlie", "One"));
repo.save(new Student("David", "Three"));
}
}

6. Add below line in the application.properties file under resources folder. This will make JPA queries appear in the log
 spring.jpa.show-sql=true
7. Run the Spring Boot application and test using web service client (such as Postman)
 "C:\Program Files\Java\jdk-11.0.15\bin\java.exe" "-javaagent:C:\Program Files\JetBrains\IntelliJ IDEA Community Edition 2021.2\lib\idea_rt.jar=49311:C:\Program Files\JetBrains\IntelliJ IDEA Community Edition 2021.2\bin" -Dfile.encoding=UTF-8 -classpath C:\Users\mail2\Downloads\Spring-Boot-angular-full-stack\target\classes;D:\.m2\repository\org\springframework\boot\spring-boot-starter-data-jpa\2.7.3\spring-boot-starter-data-jpa-2.7.3.jar;D:\.m2\repository\org\springframework\boot\spring-boot-starter-aop\2.7.3\spring-boot-starter-aop-2.7.3.jar;D:\.m2\repository\org\springframework\spring-aop\5.3.22\spring-aop-5.3.22.jar;D:\.m2\repository\org\aspectj\aspectjweaver\1.9.7\aspectjweaver-1.9.7.jar;D:\.m2\repository\org\springframework\boot\spring-boot-starter-jdbc\2.7.3\spring-boot-starter-jdbc-2.7.3.jar;D:\.m2\repository\com\zaxxer\HikariCP\4.0.3\HikariCP-4.0.3.jar;D:\.m2\repository\org\springframework\spring-jdbc\5.3.22\spring-jdbc-5.3.22.jar;D:\.m2\repository\jakarta\transaction\jakarta.transaction-api\1.3.3\jakarta.transaction-api-1.3.3.jar;D:\.m2\repository\jakarta\persistence\jakarta.persistence-api\2.2.3\jakarta.persistence-api-2.2.3.jar;D:\.m2\repository\org\hibernate\hibernate-core\5.6.10.Final\hibernate-core-5.6.10.Final.jar;D:\.m2\repository\org\jboss\logging\jboss-logging\3.4.3.Final\jboss-logging-3.4.3.Final.jar;D:\.m2\repository\net\bytebuddy\byte-buddy\1.12.13\byte-buddy-1.12.13.jar;D:\.m2\repository\antlr\antlr\2.7.7\antlr-2.7.7.jar;D:\.m2\repository\org\jboss\jandex\2.4.2.Final\jandex-2.4.2.Final.jar;D:\.m2\repository\com\fasterxml\classmate\1.5.1\classmate-1.5.1.jar;D:\.m2\repository\org\hibernate\common\hibernate-commons-annotations\5.1.2.Final\hibernate-commons-annotations-5.1.2.Final.jar;D:\.m2\repository\org\glassfish\jaxb\jaxb-runtime\2.3.6\jaxb-runtime-2.3.6.jar;D:\.m2\repository\org\glassfish\jaxb\txw2\2.3.6\txw2-2.3.6.jar;D:\.m2\repository\com\sun\istack\istack-commons-runtime\3.0.12\istack-commons-runtime-3.0.12.jar;D:\.m2\repository\com\sun\activation\jakarta.activation\1.2.2\jakarta.activation-1.2.2.jar;D:\.m2\repository\org\springframework\data\spring-data-jpa\2.7.2\spring-data-jpa-2.7.2.jar;D:\.m2\repository\org\springframework\data\spring-data-commons\2.7.2\spring-data-commons-2.7.2.jar;D:\.m2\repository\org\springframework\spring-orm\5.3.22\spring-orm-5.3.22.jar;D:\.m2\repository\org\springframework\spring-context\5.3.22\spring-context-5.3.22.jar;D:\.m2\repository\org\springframework\spring-tx\5.3.22\spring-tx-5.3.22.jar;D:\.m2\repository\org\springframework\spring-beans\5.3.22\spring-beans-5.3.22.jar;D:\.m2\repository\org\slf4j\slf4j-api\1.7.36\slf4j-api-1.7.36.jar;D:\.m2\repository\org\springframework\spring-aspects\5.3.22\spring-aspects-5.3.22.jar;D:\.m2\repository\com\h2database\h2\2.1.214\h2-2.1.214.jar;D:\.m2\repository\org\springdoc\springdoc-openapi-ui\1.6.4\springdoc-openapi-ui-1.6.4.jar;D:\.m2\repository\org\springdoc\springdoc-openapi-webmvc-core\1.6.4\springdoc-openapi-webmvc-core-1.6.4.jar;D:\.m2\repository\org\springdoc\springdoc-openapi-common\1.6.4\springdoc-openapi-common-1.6.4.jar;D:\.m2\repository\io\swagger\core\v3\swagger-core\2.1.12\swagger-core-2.1.12.jar;D:\.m2\repository\org\apache\commons\commons-lang3\3.12.0\commons-lang3-3.12.0.jar;D:\.m2\repository\com\fasterxml\jackson\dataformat\jackson-dataformat-yaml\2.13.3\jackson-dataformat-yaml-2.13.3.jar;D:\.m2\repository\io\swagger\core\v3\swagger-annotations\2.1.12\swagger-annotations-2.1.12.jar;D:\.m2\repository\io\swagger\core\v3\swagger-models\2.1.12\swagger-models-2.1.12.jar;D:\.m2\repository\jakarta\validation\jakarta.validation-api\2.0.2\jakarta.validation-api-2.0.2.jar;D:\.m2\repository\org\webjars\swagger-ui\4.1.3\swagger-ui-4.1.3.jar;D:\.m2\repository\org\webjars\webjars-locator-core\0.50\webjars-locator-core-0.50.jar;D:\.m2\repository\com\fasterxml\jackson\core\jackson-core\2.13.3\jackson-core-2.13.3.jar;D:\.m2\repository\io\github\classgraph\classgraph\4.8.138\classgraph-4.8.138.jar;D:\.m2\repository\org\springframework\boot\spring-boot-starter\2.7.3\spring-boot-starter-2.7.3.jar;D:\.m2\repository\org\springframework\boot\spring-boot\2.7.3\spring-boot-2.7.3.jar;D:\.m2\repository\org\springframework\boot\spring-boot-autoconfigure\2.7.3\spring-boot-autoconfigure-2.7.3.jar;D:\.m2\repository\org\springframework\boot\spring-boot-starter-logging\2.7.3\spring-boot-starter-logging-2.7.3.jar;D:\.m2\repository\ch\qos\logback\logback-classic\1.2.11\logback-classic-1.2.11.jar;D:\.m2\repository\ch\qos\logback\logback-core\1.2.11\logback-core-1.2.11.jar;D:\.m2\repository\org\apache\logging\log4j\log4j-to-slf4j\2.17.2\log4j-to-slf4j-2.17.2.jar;D:\.m2\repository\org\apache\logging\log4j\log4j-api\2.17.2\log4j-api-2.17.2.jar;D:\.m2\repository\org\slf4j\jul-to-slf4j\1.7.36\jul-to-slf4j-1.7.36.jar;D:\.m2\repository\jakarta\annotation\jakarta.annotation-api\1.3.5\jakarta.annotation-api-1.3.5.jar;D:\.m2\repository\org\yaml\snakeyaml\1.30\snakeyaml-1.30.jar;D:\.m2\repository\jakarta\xml\bind\jakarta.xml.bind-api\2.3.3\jakarta.xml.bind-api-2.3.3.jar;D:\.m2\repository\jakarta\activation\jakarta.activation-api\1.2.2\jakarta.activation-api-1.2.2.jar;D:\.m2\repository\org\springframework\spring-core\5.3.22\spring-core-5.3.22.jar;D:\.m2\repository\org\springframework\spring-jcl\5.3.22\spring-jcl-5.3.22.jar;D:\.m2\repository\org\springframework\boot\spring-boot-starter-web\2.7.3\spring-boot-starter-web-2.7.3.jar;D:\.m2\repository\org\springframework\boot\spring-boot-starter-json\2.7.3\spring-boot-starter-json-2.7.3.jar;D:\.m2\repository\com\fasterxml\jackson\core\jackson-databind\2.13.3\jackson-databind-2.13.3.jar;D:\.m2\repository\com\fasterxml\jackson\core\jackson-annotations\2.13.3\jackson-annotations-2.13.3.jar;D:\.m2\repository\com\fasterxml\jackson\datatype\jackson-datatype-jdk8\2.13.3\jackson-datatype-jdk8-2.13.3.jar;D:\.m2\repository\com\fasterxml\jackson\datatype\jackson-datatype-jsr310\2.13.3\jackson-datatype-jsr310-2.13.3.jar;D:\.m2\repository\com\fasterxml\jackson\module\jackson-module-parameter-names\2.13.3\jackson-module-parameter-names-2.13.3.jar;D:\.m2\repository\org\springframework\boot\spring-boot-starter-tomcat\2.7.3\spring-boot-starter-tomcat-2.7.3.jar;D:\.m2\repository\org\apache\tomcat\embed\tomcat-embed-core\9.0.65\tomcat-embed-core-9.0.65.jar;D:\.m2\repository\org\apache\tomcat\embed\tomcat-embed-el\9.0.65\tomcat-embed-el-9.0.65.jar;D:\.m2\repository\org\apache\tomcat\embed\tomcat-embed-websocket\9.0.65\tomcat-embed-websocket-9.0.65.jar;D:\.m2\repository\org\springframework\spring-web\5.3.22\spring-web-5.3.22.jar;D:\.m2\repository\org\springframework\spring-webmvc\5.3.22\spring-webmvc-5.3.22.jar;D:\.m2\repository\org\springframework\spring-expression\5.3.22\spring-expression-5.3.22.jar com.example.demo.DemoApplication

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::                (v2.7.3)

2022-09-11 09:51:16.437  INFO 21112 --- [           main] com.example.demo.DemoApplication         : Starting DemoApplication using Java 11.0.15 on sm15 with PID 21112 (C:\Users\mail2\Downloads\Spring-Boot-angular-full-stack\target\classes started by mail2 in C:\Users\mail2\Downloads\Spring-Boot-angular-full-stack)
2022-09-11 09:51:16.441  INFO 21112 --- [           main] com.example.demo.DemoApplication         : No active profile set, falling back to 1 default profile: "default"
2022-09-11 09:51:17.518  INFO 21112 --- [           main] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data JPA repositories in DEFAULT mode.
2022-09-11 09:51:17.593  INFO 21112 --- [           main] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 59 ms. Found 1 JPA repository interfaces.
2022-09-11 09:51:18.618  INFO 21112 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 8080 (http)
2022-09-11 09:51:18.631  INFO 21112 --- [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
2022-09-11 09:51:18.631  INFO 21112 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet engine: [Apache Tomcat/9.0.65]
2022-09-11 09:51:18.789  INFO 21112 --- [           main] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2022-09-11 09:51:18.789  INFO 21112 --- [           main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 2260 ms
2022-09-11 09:51:19.013  INFO 21112 --- [           main] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Starting...
2022-09-11 09:51:19.327  INFO 21112 --- [           main] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Start completed.
2022-09-11 09:51:19.407  INFO 21112 --- [           main] o.hibernate.jpa.internal.util.LogHelper  : HHH000204: Processing PersistenceUnitInfo [name: default]
2022-09-11 09:51:19.492  INFO 21112 --- [           main] org.hibernate.Version                    : HHH000412: Hibernate ORM core version 5.6.10.Final
2022-09-11 09:51:19.747  INFO 21112 --- [           main] o.hibernate.annotations.common.Version   : HCANN000001: Hibernate Commons Annotations {5.1.2.Final}
2022-09-11 09:51:19.940  INFO 21112 --- [           main] org.hibernate.dialect.Dialect            : HHH000400: Using dialect: org.hibernate.dialect.H2Dialect
Hibernate: drop table if exists student CASCADE 
Hibernate: create table student (student_id bigint generated by default as identity, grade varchar(255), name varchar(255), primary key (student_id))
2022-09-11 09:51:20.638  INFO 21112 --- [           main] o.h.e.t.j.p.i.JtaPlatformInitiator       : HHH000490: Using JtaPlatform implementation: [org.hibernate.engine.transaction.jta.platform.internal.NoJtaPlatform]
2022-09-11 09:51:20.649  INFO 21112 --- [           main] j.LocalContainerEntityManagerFactoryBean : Initialized JPA EntityManagerFactory for persistence unit 'default'
2022-09-11 09:51:21.293  WARN 21112 --- [           main] JpaBaseConfiguration$JpaWebConfiguration : spring.jpa.open-in-view is enabled by default. Therefore, database queries may be performed during view rendering. Explicitly configure spring.jpa.open-in-view to disable this warning
2022-09-11 09:51:22.369  INFO 21112 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path ''
2022-09-11 09:51:22.385  INFO 21112 --- [           main] com.example.demo.DemoApplication         : Started DemoApplication in 6.616 seconds (JVM running for 7.193)
Hibernate: insert into student (student_id, grade, name) values (default, ?, ?)
Hibernate: insert into student (student_id, grade, name) values (default, ?, ?)
Hibernate: insert into student (student_id, grade, name) values (default, ?, ?)
Hibernate: insert into student (student_id, grade, name) values (default, ?, ?)

If the API is returning the data, back end coding is complete. We will now move to create the Angular (Front End)

Angular Application (Front End)

To develop the angular application we need to have following installed on the computer:
  • Node
  • Angular CLI
  • Code Editor (Such as visual studio code)
Below are versions I am using for this example:
C:\Users\mail2>ng version

     _                      _                 ____ _     ___
    / \   _ __   __ _ _   _| | __ _ _ __     / ___| |   |_ _|
   / △ \ | '_ \ / _` | | | | |/ _` | '__|   | |   | |    | |
  / ___ \| | | | (_| | |_| | | (_| | |      | |___| |___ | |
 /_/   \_\_| |_|\__, |\__,_|_|\__,_|_|       \____|_____|___|
                |___/


Angular CLI: 14.2.2
Node: 16.10.0
Package Manager: npm 7.24.0
OS: win32 x64

Angular:
...

Package                      Version
------------------------------------------------------
@angular-devkit/architect    0.1402.2 (cli-only)
@angular-devkit/core         14.2.2 (cli-only)
@angular-devkit/schematics   14.2.2 (cli-only)
@schematics/angular          14.2.2 (cli-only) 
The Angular application is going to have top navigation bar with three buttons. Home button will display list of students with the option to delete the student from the list. Add button will display page to add a new student. About button will display the information about the website. Below are the screen shots:
Here is the quick overview of different steps that we are going to use to develop the Angular Application
  • Create new project
  • Add three components home, addstudent and about
  • Add a service that will call the back end Spring Boot API. Home and addstudent components will be using this service to interact with back end database. 
  • Add top nav bar and routes mapping
  • Add proxy details in the proxy.conf.json file to handle cors error and update start command in the package.json.
  • Add @angular/material for styling
Project structure:
1. Create new project: Under the Spring Boot project created above, open main folder in Visual Studio code. Open terminal and run below command. This will create the new angular project with name web. For Routing prompt select 'Yes' and for style select CSS.

ng new web

2. Create components: Change directory to web folder and run below commands to create three components.

ng g c home
ng g c addstudent
ng g c about

PS C:\Users\mail2\Downloads\Spring-Boot-angular-full-stack\src\main\web> ng g c home
CREATE src/app/home/home.component.html (19 bytes)
CREATE src/app/home/home.component.spec.ts (585 bytes)
CREATE src/app/home/home.component.ts (267 bytes)
CREATE src/app/home/home.component.css (0 bytes)
UPDATE src/app/app.module.ts (467 bytes)
PS C:\Users\mail2\Downloads\Spring-Boot-angular-full-stack\src\main\web> ng g c addstudent
CREATE src/app/addstudent/addstudent.component.html (25 bytes)
CREATE src/app/addstudent/addstudent.component.spec.ts (627 bytes)
CREATE src/app/addstudent/addstudent.component.ts (291 bytes)
CREATE src/app/addstudent/addstudent.component.css (0 bytes)
UPDATE src/app/app.module.ts (565 bytes)
PS C:\Users\mail2\Downloads\Spring-Boot-angular-full-stack\src\main\web> ng g c about
CREATE src/app/about/about.component.html (20 bytes)
CREATE src/app/about/about.component.spec.ts (592 bytes)
CREATE src/app/about/about.component.ts (271 bytes)
CREATE src/app/about/about.component.css (0 bytes)
UPDATE src/app/app.module.ts (643 bytes)
3. Create service: run below command to create the service with name api

ng g s api

PS C:\Users\mail2\Downloads\Spring-Boot-angular-full-stack\src\main\web> ng g s api
CREATE src/app/api.service.spec.ts (342 bytes)
CREATE src/app/api.service.ts (132 bytes)
4. Add Student module class that will be used to map the objects in request and response.

student.ts:
export class Student{
    student_id!:number;
    name!:String;
    grade!:String;
}
5. Add Routing and Top Nav Bar: Open app-routing.module.ts and add routing as below.
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { AboutComponent } from './about/about.component';
import { AddstudentComponent } from './addstudent/addstudent.component';
import { HomeComponent } from './home/home.component';

const routes: Routes = [

  { path: '', redirectTo: 'home', pathMatch: 'full'},
  { path: 'home', component: HomeComponent },
  { path: 'add', component: AddstudentComponent },
  { path: 'about', component: AboutComponent },

];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})
export class AppRoutingModule { }


In the app.component.html file update the code as below:
<mat-toolbar color="primary">  
  <button mat-button routerLink="/">Home</button>  
  <button mat-button routerLink="/add">Add</button>
  <button mat-button routerLink="/about">About</button></mat-toolbar>
<router-outlet></router-outlet>

6. Add proxy: Add file proxy.conf.json under the web folder with below code. This configuration means that when the requests are sent to end point /students from Angular, requests will be redirected to http://localhost:8080 which is the host for Spring Boot API.

proxy.conf.json:
{
    "/students": {
    "target": "http://localhost:8080",
    "secure": false
    }
}
In the package.json file change the start command from ng serve to ng serve --proxy-config proxy.conf.json. This means that when npm start is run ng serve --proxy-config proxy.conf.json will be executed.
{
  "name": "web",
  "version": "0.0.0",
  "scripts": {
    "ng": "ng",
    "start": "ng serve --proxy-config proxy.conf.json",
    "build": "ng build",
    "watch": "ng build --watch --configuration development",
    "test": "ng test"
  },
  "private": true,
  "dependencies": {
    "@angular/animations": "^14.2.0",
    "@angular/common": "^14.2.0",
    "@angular/compiler": "^14.2.0",
    "@angular/core": "^14.2.0",
    "@angular/forms": "^14.2.0",
    "@angular/platform-browser": "^14.2.0",
    "@angular/platform-browser-dynamic": "^14.2.0",
    "@angular/router": "^14.2.0",
    "rxjs": "~7.5.0",
    "tslib": "^2.3.0",
    "zone.js": "~0.11.4"
  },
  "devDependencies": {
    "@angular-devkit/build-angular": "^14.2.2",
    "@angular/cli": "~14.2.2",
    "@angular/compiler-cli": "^14.2.0",
    "@types/jasmine": "~4.0.0",
    "jasmine-core": "~4.3.0",
    "karma": "~6.4.0",
    "karma-chrome-launcher": "~3.1.0",
    "karma-coverage": "~2.2.0",
    "karma-jasmine": "~5.1.0",
    "karma-jasmine-html-reporter": "~2.0.0",
    "typescript": "~4.7.2"
  }
}


Note: This method of proxy server works only in development environment and not in production. For production, we must enable CORS on the server side using the @CrossOrigin annotation.


7. Add @angular/material: Run below command to add material and select Indigo/Pink theme.

ng add @angular/material

Update app.module.ts: ApiService has been added under providers as it is going to be used by home and addstudent components. Toolbar will be used in the home component html. FormsModule will be used in the addstudent component html. HttpClientModule is going to be used in the Api service.
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';

import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { HomeComponent } from './home/home.component';
import { AddstudentComponent } from './addstudent/addstudent.component';
import { AboutComponent } from './about/about.component';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { ApiService } from './api.service';
import { MatToolbarModule } from '@angular/material/toolbar';
import {MatIconModule} from '@angular/material/icon';
import {MatCardModule} from '@angular/material/card';
import {MatButtonModule} from '@angular/material/button';
import {MatProgressSpinnerModule } from '@angular/material/progress-spinner';
import { FormsModule } from '@angular/forms';
import { HttpClientModule } from '@angular/common/http';

@NgModule({
  declarations: [
    AppComponent,
    HomeComponent,
    AddstudentComponent,
    AboutComponent
  ],
  imports: [
    BrowserModule,
    AppRoutingModule,
    BrowserAnimationsModule,
    MatToolbarModule,
    MatIconModule,
    MatButtonModule,
    MatCardModule,
    MatProgressSpinnerModule,
    HttpClientModule,
    FormsModule
  ],
  providers: [ApiService],
  bootstrap: [AppComponent]
})
export class AppModule { }



To add Bootstrap support, add the scripts in index.html
<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>Web</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="preconnect" href="https://fonts.gstatic.com">
  <link href="https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500&display=swap" rel="stylesheet">
  <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
  <link href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.0/css/bootstrap.min.css" rel="stylesheet" id="bootstrap-css">
  <script src="//maxcdn.bootstrapcdn.com/bootstrap/3.3.0/js/bootstrap.min.js"></script>
  <script src="//code.jquery.com/jquery-1.11.1.min.js"></script>  
</head>
<body class="mat-typography">
  <app-root></app-root>
</body>
</html>


8. Progress Check: If we run the application now, we should be able to see the web page with the routing working.

Starting the application:
PS C:\Users\mail2\Downloads\Spring-Boot-angular-full-stack\src\main\web> npm start

> web@0.0.0 start
> ng serve --proxy-config proxy.conf.json

✔ Browser application bundle generation complete.

Initial Chunk Files   | Names         |  Raw Size
vendor.js             | vendor        |   3.16 MB |
polyfills.js          | polyfills     | 318.04 kB |
styles.css, styles.js | styles        | 289.29 kB |
main.js               | main          |  16.78 kB |
runtime.js            | runtime       |   6.50 kB |

                      | Initial Total |   3.78 MB

Build at: 2022-09-11T20:20:20.316Z - Hash: f2998443cce14455 - Time: 21330ms

** Angular Live Development Server is listening on localhost:4200, open your browser on http://localhost:4200/ **
Website:
We will now add methods to API service, add the HTML on the components and update their typescript (.ts) classes to call the service for display and update

9. Open api.service.ts file and update the code as below. The service will now provide methods to get students, create new student record and delete student.
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';  

@Injectable({
  providedIn: 'root'
})
export class ApiService {
  //private SERVER_URL = "http://localhost:8080/students";//This would through CORS error

  private SERVER_URL = "/students";//Using proxy.conf.json, the requests will be redirected to "http://localhost:8080 host
 
  constructor(private httpClient: HttpClient) { }

  public getAllStudents(){  
    return this.httpClient.get(this.SERVER_URL);  
  }


  public createStudent(student: object): Observable<object> {  
    return this.httpClient.post(this.SERVER_URL, student);  
  }  

  public deleteStudent(id: number): Observable<object> {  
    return this.httpClient.delete(`${this.SERVER_URL}/${id}`);  
  }  
}

10. When the home page loads, we want to display the student list and have the button on the screen to delete the student from the list. Update home.component.ts as below. So on initialization, home component will call API service to get the list of students and store in "students" array. This array will be used in the home.component.html to display the list of students. There is also method to delete the student using the student id. So UI would call this method passing the student id.

home.component.ts:
 import { Component, OnInit } from '@angular/core';
import { ApiService } from '../api.service';
import { Student } from 'src/student';

@Component({
  selector: 'app-home',
  templateUrl: './home.component.html',
  styleUrls: ['./home.component.css']
})
export class HomeComponent implements OnInit {
  students!: Student[] ;
  constructor(private apiService: ApiService) { }

  ngOnInit(): void {
    this.apiService.getAllStudents().subscribe((data: any)=>{  
      //console.log(data);  
     
      this.students = data;  
      //console.log(this.students);
    })      
  }

  public deleteStudent(id: number){
    //console.log("id = ", id);
    this.apiService.deleteStudent(id).subscribe(data => console.log(data), error => console.log(error));
   
  }

}


home.component.html:
<div style="padding: 13px;">
    <mat-spinner *ngIf="!students"></mat-spinner>

    <mat-card *ngFor="let student of students" style="margin-top:10px;">
        <mat-card-content>
            <p>
                Name: {{student.name}}
            </p>
            <p>
                Grade: {{student.grade}}
            </p>  
            <p>
                Student Id: {{student.student_id}}
            </p>                      
        </mat-card-content>
        <mat-card-actions>
      <button class="btn btn-warning" (click)="deleteStudent(student.student_id)"> Remove student</button>
    </mat-card-actions>
    </mat-card>
</div>

11. Add student page provides the feature to add a new student. So in the addstudent.component.ts we are adding the method to call createStudent of the API service. addstudent.component.html will call this method when new student is to be added. The Student object properties are bound to the UI fields and object is passed from the type script file.

addstudent.component.ts:
import { Component, OnInit } from '@angular/core';
import { ApiService } from '../api.service';
import { Student } from 'src/student';

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

  constructor(private apiService: ApiService) { }
  student : Student=new Student();  
  ngOnInit(): void {

  }

  public registerNow(){
    this.apiService.createStudent(this.student).subscribe(data => console.log(data), error => console.log(error));
  }

}


addstudent.component.html:

<div class="container">
    <div class="row">
        <div class="col-md-6">
            <form>
                <br>
                <fieldset>
                   
                    <legend class="text-center">Add Student</legend>

                    <div class="form-group">
                        <label for="Name"><span class="req">* </span> Student Name:  </label>
                        <input required type="text" [(ngModel)]="student.name" name="name" id="name"
                            class="form-control phone" maxlength="28" placeholder="Enter full name..." />
                    </div>

                    <div class="form-group">
                        <label for="firstname"><span class="req">* </span> Grade: </label>
                        <input class="form-control" type="text" [(ngModel)]="student.grade" name="grade" id="txt" required
                            placeholder="Enter student grade.." />
                        <div id="errFirst"></div>
                    </div>

                     <div class="form-group">
                        <input class="btn btn-success" type="submit" name="submit_reg" value="Register" (click)="registerNow()">
                    </div>
                </fieldset>
            </form><!-- ends register form -->
            <!-- second for to fiter user-->
        </div><!-- ends col-6 -->

    </div>
</div>


12. Update about.component.html to add some text to show information about the website. Sample text below.

about.component.html:
<mat-card style="margin:10px;"><mat-card-content><p>This angular application uses Spring Boot Rest Web Service to display the data</p>
</mat-card-content></mat-card>

13. Final Output: The application is now ready. You should be able to see the list of students and delete student from the home page. New student can be added from Add page.

Source Code:
https://github.com/NumeroUnoDeveloper/Spring-Boot-angular-full-stack

    Leave a Comment


  • captcha text