0% found this document useful (0 votes)
25 views

SpringbootAngularLabs

Uploaded by

handymelong237
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
25 views

SpringbootAngularLabs

Uploaded by

handymelong237
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 45

See discussions, stats, and author profiles for this publication at: https://www.researchgate.

net/publication/384040618

Spring boot + Angular Labs

Presentation · September 2024

CITATIONS READS
0 95

1 author:

Youcef Benabderrezak
University M'Hamed Bougara of Boumerdes
94 PUBLICATIONS 2 CITATIONS

SEE PROFILE

All content following this page was uploaded by Youcef Benabderrezak on 14 September 2024.

The user has requested enhancement of the downloaded file.


Spring boot + Angular Labs 5 CS Dr Benabderrezak

Spring Boot is an open-source Java framework used for programming standalone, production-grade
Spring-based applications with minimal effort.

Angular is an open-source, JavaScript framework written in TypeScript. Google maintains it, and its
primary purpose is to develop single-page applications. As a framework, Angular has clear advantages
while also providing a standard structure for developers to work with.

Here’s a comprehensive guide to learning Spring Boot as a REST API, setting up a development
environment on Linux Mint/Ubuntu, testing with Postman, documenting the API using Swagger, and
building a basic Angular frontend that communicates with the Spring Boot backend.

Part 1 : Setting Up the Development Environment


- Make sure your system is updated by running:
● sudo apt update && sudo apt upgrade
- Install the latest JDK (Java Development Kit), You can install OpenJDK:
● sudo apt install openjdk-17-jdk
- Verify the installation:
● java -version
- Install Maven, which is used to build Spring Boot applications.
● sudo apt install maven
- Verify Maven installation:
● mvn -v
- Install VS Code by:
1. downloading the `.deb` package from the : https://code.visualstudio.com
2. or running : sudo snap install --classic code
- Spring Boot CLI (Optional):.
● sudo snap install spring
- To test APIs, install Postman via Snap:
● sudo snap install postman

1
Spring boot + Angular Labs 5 CS Dr Benabderrezak

Part 2 : Initializing a Spring Boot project


- Initialize a Spring Boot Project :
1. You can use the Spring Initializr (via the web or CLI) to generate the project structure.
➔ Web Approach :
- Visit Spring Initializr https://start.spring.io/ and generate a project with the following :
- Project : Maven
- Language : Java
- Spring Boot Version : Latest
- Dependencies : Spring Web, Spring Data JPA, H2 Database (or MySQL if preferred)
- Packaging : Jar

➔ CLI Approach :
- Use the Spring Boot CLI to generate a project :
○ spring init --dependencies=web,data-jpa,h2 --package-name=com.example.demo demo

➔ Project Structure
- After downloading or generating the project, unzip it and open it in VS Code:
○ cd /path-to-your-project
○ code .
Part 3 : Start Creating a Spring Boot REST API
Create a new class `HelloController.java` inside the `src/main/java/com/example/demo/controller`
directory:

package com.example.demo.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/api")

2
Spring boot + Angular Labs 5 CS Dr Benabderrezak

public class HelloController {


@GetMapping("/hello")
public String sayHello() {
return "Hello, Spring Boot!";
}
}

- Run the Application : Use Maven to run your Spring Boot application:
● mvn spring-boot:run
- Now your Spring Boot application should be running at `http://localhost:8080/api/hello`.
- you should see the response: `"Hello, Spring Boot!"`
- Adding Swagger for API Documentation :
● Open the `pom.xml` file and add the Swagger dependencies under `<dependencies>`:

<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-boot-starter</artifactId>
<version>3.0.0</version>
</dependency>

- Enable Swagger in the Spring Boot Application :


● Create a `SwaggerConfig.java` class inside the `src/main/java/com/example/demo/config`
directory:

package com.example.demo.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.spi.DocumentationType;

3
Spring boot + Angular Labs 5 CS Dr Benabderrezak

import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
@Configuration
@EnableSwagger2
public class SwaggerConfig {
@Bean
public Docket api() {
return new Docket(DocumentationType.SWAGGER_2)
.select()
.apis(RequestHandlerSelectors.basePackage("com.example.demo.controller"))
.paths(PathSelectors.any())
.build();
}}

- Access Swagger UI
Run your application and navigate to `http://localhost:8080/swagger-ui/` to view the interactive API
documentation.
Part 3 : Building the Frontend using Angular
- install Node.js and npm :
● sudo apt install nodejs npm
- Install the Angular CLI globally:
● sudo npm install -g @angular/cli
- Create a New Angular Project :
● ng new angular-client
- Navigate into the project directory:
● cd angular-client
● code .
- Install HttpClientModule to communicate with the Rest API built with spring boot

4
Spring boot + Angular Labs 5 CS Dr Benabderrezak

- In the `app.module.ts`, import `HttpClientModule`:

import { HttpClientModule } from '@angular/common/http';


@NgModule({
declarations: [...],
imports: [HttpClientModule, ...],
bootstrap: [...]
})
export class AppModule { }

- Create a Service to Communicate with the Spring Boot API


- Inside the `src/app` directory, create a service file `api.service.ts`:

import { Injectable } from '@angular/core';


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

@Injectable({
providedIn: 'root'
})
export class ApiService {
private baseUrl: string = 'http://localhost:8080/api';
constructor(private http: HttpClient) {}
getHelloMessage(): Observable<string> {
return this.http.get(`${this.baseUrl}/hello`, { responseType: 'text' });
}
}

5
Spring boot + Angular Labs 5 CS Dr Benabderrezak

- Create a Component to Display the API Data


- In the `app.component.ts`, inject the `ApiService` and call the API:

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


import { ApiService } from './api.service';

@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
message: string;
constructor(private apiService: ApiService) {}
ngOnInit() {
this.apiService.getHelloMessage().subscribe(
data => this.message = data,
error => console.error(error)
);
}
}

- In `app.component.html`, display the message:

<h1>{{ message }}</h1>

- Run the Angular Application


● ng serve
- Navigate to `http://localhost:4200/` to see the frontend fetching data from the Spring Boot backend.

6
Spring boot + Angular Labs 5 CS Dr Benabderrezak

Practical Example : build a Spring Boot application that performs CRUD operations on a products

1. Set Up Your Spring Boot Project

We'll create a project with the following dependencies:

● Spring Web
● Spring Data JPA
● MySQL Driver (or H2 for in-memory)
● Spring Security
● Spring Boot DevTools
● Lombok
● JWT (JSON Web Token)

2. Project Structure : Here’s what the project structure will look like:

src

├── main
│ ├── java
│ │ └── com.example.demo
│ │ ├── controller
│ │ ├── model
│ │ ├── repository
│ │ ├── service
│ │ ├── security
│ │ └── DemoApplication.java
│ └── resources
│ └── application.properties

7
Spring boot + Angular Labs 5 CS Dr Benabderrezak

3. Dependencies in pom.xml

- Ensure your pom.xml file has the following dependencies:

<dependencies>
<!-- Spring Web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Spring Data JPA -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<!-- Spring Security -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<!-- JWT for token-based security -->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>

<!-- Lombok for reducing boilerplate code -->


<dependency>
<groupId>org.projectlombok</groupId>

8
Spring boot + Angular Labs 5 CS Dr Benabderrezak

<artifactId>lombok</artifactId>
<scope>provided</scope>
</dependency>
<!-- MySQL Driver -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!-- Spring Boot DevTools for hot reload -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
</dependencies>

4. Configuring the Database in application.properties

- Update your application.properties file to configure MySQL or any database you're using:

# Database Configuration
spring.datasource.url=jdbc:mysql://localhost:3306/mydatabase?useSSL=false
spring.datasource.username=root
spring.datasource.password=root

# Hibernate Configurations
spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=update

9
Spring boot + Angular Labs 5 CS Dr Benabderrezak

5. Product Model

- Create a Product model in the model package:

package com.example.demo.model;
import lombok.Data;
import javax.persistence.*;
@Data
@Entity
@Table(name = "products")
public class Product {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY) // Auto-generate ID
private Long id;
@Column(nullable = false) // Name column, cannot be null
private String name;
@Column(nullable = false) // Price column, cannot be null
private Double price;
@Column // Quantity column, can be null
private Integer quantity;
}

6. Product Repository

- Create a repository interface for the Product model in the repository package:

package com.example.demo.repository;
import com.example.demo.model.Product;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

10
Spring boot + Angular Labs 5 CS Dr Benabderrezak

@Repository // Marks this class as a repository


public interface ProductRepository extends JpaRepository<Product, Long> {
// JpaRepository provides default CRUD operations (save, find, delete, etc.)
}

7. Product Service

- Create a ProductService class to manage product business logic in the service package:

package com.example.demo.service;
import com.example.demo.model.Product;
import com.example.demo.repository.ProductRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Optional;
@Service // Marks this as a service component
public class ProductService {
@Autowired // Inject the repository to interact with the database
private ProductRepository productRepository;
// Retrieve all products
public List<Product> getAllProducts() {
return productRepository.findAll();
}
// Retrieve a product by ID
public Optional<Product> getProductById(Long id) {
return productRepository.findById(id);
}

11
Spring boot + Angular Labs 5 CS Dr Benabderrezak

// Create a new product


public Product createProduct(Product product) {
return productRepository.save(product);
}
// Update an existing product
public Product updateProduct(Long id, Product updatedProduct) {
Optional<Product> productOptional = productRepository.findById(id);
if (productOptional.isPresent()) {
Product product = productOptional.get();
product.setName(updatedProduct.getName());
product.setPrice(updatedProduct.getPrice());
product.setQuantity(updatedProduct.getQuantity());
return productRepository.save(product); // Save updated product
}
return null; // Return null if the product is not found
}
// Delete a product by ID
public void deleteProduct(Long id) {
productRepository.deleteById(id);
}
}

8. Product Controller

- Create a REST controller in the controller package to expose the API endpoints for CRUD
operations:

package com.example.demo.controller;
import com.example.demo.model.Product;
import com.example.demo.service.ProductService;

12
Spring boot + Angular Labs 5 CS Dr Benabderrezak

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.Optional;
@RestController // Marks this as a REST controller
@RequestMapping("/api/products") // Base URL for all product-related endpoints
public class ProductController {
@Autowired // Inject the ProductService to handle product operations
private ProductService productService;
// Retrieve all products: GET /api/products
@GetMapping
public List<Product> getAllProducts() {
return productService.getAllProducts(); // Return all products
}
// Retrieve a single product by ID: GET /api/products/{id}
@GetMapping("/{id}")
public ResponseEntity<Product> getProductById(@PathVariable Long id) {
Optional<Product> product = productService.getProductById(id);
return product.map(ResponseEntity::ok)
.orElse(ResponseEntity.notFound().build()); // Return 404 if not found
}
// Create a new product: POST /api/products
@PostMapping
public Product createProduct(@RequestBody Product product) {
return productService.createProduct(product); // Create and return the new product
}

13
Spring boot + Angular Labs 5 CS Dr Benabderrezak

// Update a product: PUT /api/products/{id}


@PutMapping("/{id}")
public ResponseEntity<Product> updateProduct(@PathVariable Long id,
@RequestBody Product product)
{
Product updatedProduct = productService.updateProduct(id, product);
if (updatedProduct != null) {
return ResponseEntity.ok(updatedProduct); // Return the updated product
}
return ResponseEntity.notFound().build(); // Return 404 if the product is not found
}
// Delete a product: DELETE /api/products/{id}
@DeleteMapping("/{id}")
public ResponseEntity<Void> deleteProduct(@PathVariable Long id) {
productService.deleteProduct(id); // Delete the product by ID
return ResponseEntity.noContent().build(); // Return 204 No Content
}
}

9. Token-Based Authentication Using JWT

- Create a User Entity


➔ In a real-world application, you would also have users who can authenticate using a token.
➔ First, create a User entity in the model package:

package com.example.demo.model;
import lombok.Data;
import javax.persistence.*;
@Data
@Entity

14
Spring boot + Angular Labs 5 CS Dr Benabderrezak

@Table(name = "users")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(nullable = false, unique = true) // Username must be unique
private String username;
@Column(nullable = false)
private String password;
}

10. Implement JWT Authentication

JWT stands for JSON Web Token, and it is a commonly used stateless user authentication standard used
to securely transmit information between client and server in a JSON format

For JWT-based authentication, we need to handle the following steps:

● Generate JWT: After successful login, generate a JWT.


● Validate JWT: On each request, validate the JWT before allowing access to secured endpoints.

We'll proceed with these steps by implementing user authentication.

10.1. UserRepository

First, create a repository for the User entity to fetch user details from the database.

package com.example.demo.repository;

import com.example.demo.model.User;

15
Spring boot + Angular Labs 5 CS Dr Benabderrezak

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

import org.springframework.stereotype.Repository;

import java.util.Optional;

@Repository

public interface UserRepository extends JpaRepository<User, Long> {

// Find user by username

Optional<User> findByUsername(String username);

10.2. UserDetailsService Implementation

Next, implement UserDetailsService to load user-specific data.

package com.example.demo.security;

import com.example.demo.model.User;

import com.example.demo.repository.UserRepository;

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

import org.springframework.security.core.userdetails.UserDetails;

import org.springframework.security.core.userdetails.UserDetailsService;

import org.springframework.security.core.userdetails.UsernameNotFoundException;

import org.springframework.stereotype.Service;

16
Spring boot + Angular Labs 5 CS Dr Benabderrezak

@Service

public class CustomUserDetailsService implements UserDetailsService {

@Autowired

private UserRepository userRepository;

@Override

public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {

User user = userRepository.findByUsername(username)

.orElseThrow(() -> new UsernameNotFoundException("User not found: " + username));

return new org.springframework.security.core.userdetails.User(user.getUsername(), user.getPassword(), new


ArrayList<>());

10.3. JWT Utility Class

Create a utility class to handle JWT generation and validation.

package com.example.demo.security;

import io.jsonwebtoken.Claims;

import io.jsonwebtoken.Jwts;

17
Spring boot + Angular Labs 5 CS Dr Benabderrezak

import io.jsonwebtoken.SignatureAlgorithm;

import org.springframework.security.core.userdetails.UserDetails;

import org.springframework.stereotype.Component;

import java.util.Date;

import java.util.HashMap;

import java.util.Map;

import java.util.function.Function;

@Component

public class JwtTokenUtil {

private String SECRET_KEY = "secret"; // Secret key for signing JWT tokens

// Retrieve username from JWT token

public String extractUsername(String token) {

return extractClaim(token, Claims::getSubject);

// Retrieve expiration date from JWT token

public Date extractExpiration(String token) {

return extractClaim(token, Claims::getExpiration);

18
Spring boot + Angular Labs 5 CS Dr Benabderrezak

// Extract any claim from token

public <T> T extractClaim(String token, Function<Claims, T> claimsResolver) {

final Claims claims = extractAllClaims(token);

return claimsResolver.apply(claims);

private Claims extractAllClaims(String token) {

return Jwts.parser().setSigningKey(SECRET_KEY).parseClaimsJws(token).getBody();

private Boolean isTokenExpired(String token) {

return extractExpiration(token).before(new Date());

// Generate token for a user

public String generateToken(UserDetails userDetails) {

Map<String, Object> claims = new HashMap<>();

return createToken(claims, userDetails.getUsername());

private String createToken(Map<String, Object> claims, String subject) {

return Jwts.builder().setClaims(claims).setSubject(subject).setIssuedAt(new Date(System.currentTimeMillis()))

.setExpiration(new Date(System.currentTimeMillis() + 1000 * 60 * 60 * 10)) // Token valid for 10 hours

19
Spring boot + Angular Labs 5 CS Dr Benabderrezak

.signWith(SignatureAlgorithm.HS256, SECRET_KEY).compact();

// Validate token

public Boolean validateToken(String token, UserDetails userDetails) {

final String username = extractUsername(token);

return (username.equals(userDetails.getUsername()) && !isTokenExpired(token));

10.4. JWT Authentication Filter

- Create a filter to intercept requests and validate the JWT token in the request header.

package com.example.demo.security;

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

import org.springframework.security.core.userdetails.UserDetails;

import org.springframework.security.core.userdetails.UserDetailsService;

import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

import org.springframework.stereotype.Component;

import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;

20
Spring boot + Angular Labs 5 CS Dr Benabderrezak

import javax.servlet.ServletException;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import java.io.IOException;

import org.springframework.security.core.context.SecurityContextHolder;

import org.springframework.security.core.userdetails.UsernameNotFoundException;

import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;

@Component

public class JwtRequestFilter extends OncePerRequestFilter {

@Autowired

private CustomUserDetailsService userDetailsService;

@Autowired

private JwtTokenUtil jwtTokenUtil;

@Override

protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,

FilterChain chain)

throws ServletException, IOException {

final String authorizationHeader = request.getHeader("Authorization");

String username = null;

21
Spring boot + Angular Labs 5 CS Dr Benabderrezak

String jwt = null;

// Extract the JWT token from the "Authorization" header

if (authorizationHeader != null && authorizationHeader.startsWith("Bearer ")) {

jwt = authorizationHeader.substring(7);

username = jwtTokenUtil.extractUsername(jwt);

// Validate token and set security context

if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {

UserDetails userDetails = this.userDetailsService.loadUserByUsername(username);

if (jwtTokenUtil.validateToken(jwt, userDetails)) {

UsernamePasswordAuthenticationFilter authentication = new UsernamePasswordAuthenticationFilter();

authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));

SecurityContextHolder.getContext().setAuthentication(authentication);

chain.doFilter(request, response);

}}

22
Spring boot + Angular Labs 5 CS Dr Benabderrezak

10.5. Security Configuration

Configure Spring Security to allow login without a token and secure other endpoints.

package com.example.demo.security;

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

import org.springframework.context.annotation.Bean;

import org.springframework.context.annotation.Configuration;

import org.springframework.security.authentication.AuthenticationManager;

import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;

import org.springframework.security.config.annotation.web.builders.HttpSecurity;

import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;

import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

import org.springframework.security.config.http.SessionCreationPolicy;

import org.springframework.security.core.userdetails.UserDetailsService;

import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;

import org.springframework.security.crypto.password.PasswordEncoder;

import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

@Configuration

@EnableWebSecurity

public class SecurityConfig extends WebSecurityConfigurerAdapter {

23
Spring boot + Angular Labs 5 CS Dr Benabderrezak

@Autowired

private CustomUserDetailsService userDetailsService;

@Autowired

private JwtRequestFilter jwtRequestFilter;

@Override

protected void configure(AuthenticationManagerBuilder auth) throws Exception {

auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());

@Override

protected void configure(HttpSecurity http) throws Exception {

http.csrf().disable()

.authorizeRequests().antMatchers("/api/login").permitAll() // Allow login without token

.anyRequest().authenticated() // Secure all other endpoints

.and().sessionManagement()

.sessionCreationPolicy(SessionCreationPolicy.STATELESS); // Stateless session for REST API

http.addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class); // Add JWT filter

@Bean

public PasswordEncoder passwordEncoder() {

return new BCryptPasswordEncoder(); // Use BCrypt for password hashing

24
Spring boot + Angular Labs 5 CS Dr Benabderrezak

@Override

@Bean

public AuthenticationManager authenticationManagerBean() throws Exception {

return super.authenticationManagerBean();

10.6. Authentication Controller

Create a controller to handle login requests and return the JWT token upon successful authentication.

package com.example.demo.controller;

import com.example.demo.security.JwtTokenUtil;

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

import org.springframework.security.authentication.AuthenticationManager;

import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;

import org.springframework.security.core.userdetails.UserDetails;

import org.springframework.security.core.userdetails.UserDetailsService;

import org.springframework.web.bind.annotation.*;

@RestController

25
Spring boot + Angular Labs 5 CS Dr Benabderrezak

@RequestMapping("/api")

public class AuthController {

@Autowired

private AuthenticationManager authenticationManager;

@Autowired

private JwtTokenUtil jwtTokenUtil;

@Autowired

private UserDetailsService userDetailsService;

@PostMapping("/login")

public String createAuthenticationToken(@RequestBody AuthRequest authRequest) throws Exception {

// Perform authentication

authenticationManager.authenticate(

new UsernamePasswordAuthenticationToken(authRequest.getUsername(), authRequest.getPassword())

);

// Load user details

final UserDetails userDetails = userDetailsService.loadUserByUsername(authRequest.getUsername());

// Generate token

return jwtTokenUtil.generateToken(userDetails);

26
Spring boot + Angular Labs 5 CS Dr Benabderrezak

class AuthRequest {

private String username;

private String password;

// Getters and setters

11. Testing with Postman

Now that we have the application set up, follow these steps to test it using Postman:

1. Login:
○ Use the endpoint POST /api/login with a JSON body like this:

"username": "user1",

"password": "password123"

○ The response will contain the JWT token.


2. Use Token in CRUD Operations:
○ For each subsequent request (like GET /api/products), include the token in the
Authorization header

27
Spring boot + Angular Labs 5 CS Dr Benabderrezak

11. Set Up Angular Project

Objective command

install Angular CLI globally if you haven't already npm install -g @angular/cli

create a new Angular project ng new product-management-app

navigate to the project cd product-management-app

Install Required Packages : Bootstrap & `ngx-toastr` (for notifications) npm install bootstrap

npm install ngx-toastr --save

npm install jwt-decode

- Then, add Bootstrap CSS in your `angular.json` file:

"styles": [

"src/styles.css",

"node_modules/bootstrap/dist/css/bootstrap.min.css"

],

- Create Authentication Service


➔ The `AuthService` will handle authentication by sending login requests and managing JWT tokens.
➔ Create the service: ng generate service services/auth
➔ Now, implement the `AuthService` to handle login and token storage:

28
Spring boot + Angular Labs 5 CS Dr Benabderrezak

- create a file named “auth.service.ts” in : src/app/services/auth.service.ts

import { Injectable } from '@angular/core';

import { HttpClient } from '@angular/common/http';

import { Router } from '@angular/router';

import { Observable } from 'rxjs';

import jwtDecode from 'jwt-decode';

@Injectable({

providedIn: 'root',

})

export class AuthService {

private loginUrl = 'http://localhost:8080/api/login'; // Spring Boot login endpoint

constructor(private http: HttpClient, private router: Router) {}

// Perform login and store the JWT token

login(username: string, password: string): Observable<any> {

return this.http.post<any>(this.loginUrl, { username, password });

// Save token to localStorage

saveToken(token: string): void {

localStorage.setItem('jwtToken', token);

// Get token from localStorage

29
Spring boot + Angular Labs 5 CS Dr Benabderrezak

getToken(): string | null {

return localStorage.getItem('jwtToken');

// Decode the JWT to get the user info

getDecodedToken(): any {

const token = this.getToken();

if (token) {

return jwtDecode(token);

return null;

// Log out by clearing the token

logout(): void {

localStorage.removeItem('jwtToken');

this.router.navigate(['/login']);

// Check if user is authenticated

isAuthenticated(): boolean {

return !!this.getToken();

30
Spring boot + Angular Labs 5 CS Dr Benabderrezak

- Create Interceptor to Attach JWT to Requests : You need an interceptor to automatically add the
JWT token to HTTP requests.
● ng generate interceptor interceptors/jwt
- Then, implement it:

// src/app/interceptors/jwt.interceptor.ts

import { Injectable } from '@angular/core';

import { HttpInterceptor, HttpRequest, HttpHandler, HttpEvent } from '@angular/common/http';

import { AuthService } from '../services/auth.service';

import { Observable } from 'rxjs';

@Injectable()

export class JwtInterceptor implements HttpInterceptor {

constructor(private authService: AuthService) {}

intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {

const token = this.authService.getToken();

if (token) {

// Clone the request and add the JWT token in the Authorization header

req = req.clone({

setHeaders: {

Authorization: `Bearer ${token}`,

},

});

31
Spring boot + Angular Labs 5 CS Dr Benabderrezak

return next.handle(req);

- Don't forget to register this interceptor in the `app.module.ts` file:

import { HTTP_INTERCEPTORS } from '@angular/common/http';

import { JwtInterceptor } from './interceptors/jwt.interceptor';

@NgModule({

providers: [

{ provide: HTTP_INTERCEPTORS, useClass: JwtInterceptor, multi: true }

],

})

export class AppModule { }

- Create Login Component


- Generate the `LoginComponent` to allow users to authenticate:
● ng generate component components/login
- Now, implement the login logic in the component:

// src/app/components/login/login.component.ts

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

32
Spring boot + Angular Labs 5 CS Dr Benabderrezak

import { AuthService } from '../../services/auth.service';

import { Router } from '@angular/router';

import { ToastrService } from 'ngx-toastr';

@Component({

selector: 'app-login',

templateUrl: './login.component.html',

styleUrls: ['./login.component.css'],

})

export class LoginComponent {

username: string = '';

password: string = '';

constructor(

private authService: AuthService,

private router: Router,

private toastr: ToastrService

) {}

login(): void {

this.authService.login(this.username, this.password).subscribe(

(response) => {

// Save the JWT token

this.authService.saveToken(response);

this.toastr.success('Login successful');

33
Spring boot + Angular Labs 5 CS Dr Benabderrezak

this.router.navigate(['/products']);

},

(error) => {

this.toastr.error('Login failed');

);

- Create a simple login form in `login.component.html`:

<!-- src/app/components/login/login.component.html -->

<div class="container mt-5">

<h2>Login</h2>

<form (submit)="login()">

<div class="mb-3">

<label for="username" class="form-label">Username</label>

<input type="text"

id="username"

class="form-control"

[(ngModel)]="username"

name="username" required />

</div>

34
Spring boot + Angular Labs 5 CS Dr Benabderrezak

<div class="mb-3">

<label for="password" class="form-label">Password</label>

<input type="password" id="password" class="form-control" [(ngModel)]="password" name="password"


required />

</div>

<button type="submit" class="btn btn-primary">Login</button>

</form>

</div>

- Create Product Service for CRUD Operations :


● ng generate service services/product
- Now, implement the `ProductService` in src/app/services/product.service.ts

import { Injectable } from '@angular/core';

import { HttpClient } from '@angular/common/http';

import { Observable } from 'rxjs';

import { Product } from '../models/product.model';

@Injectable({

providedIn: 'root',

})

export class ProductService {

private apiUrl = 'http://localhost:8080/api/products'; // Spring Boot API URL

constructor(private http: HttpClient) {}

// Get all products

35
Spring boot + Angular Labs 5 CS Dr Benabderrezak

getAll(): Observable<Product[]> {

return this.http.get<Product[]>(this.apiUrl);

// Create new product

create(product: Product): Observable<Product> {

return this.http.post<Product>(this.apiUrl, product);

// Update product by ID

update(id: number, product: Product): Observable<Product> {

return this.http.put<Product>(`${this.apiUrl}/${id}`, product);

// Delete product by ID

delete(id: number): Observable<void> {

return this.http.delete<void>(`${this.apiUrl}/${id}`);

- Create Product Model


- Define a `Product` model to handle the product entity in src/app/models/product.model.ts

export interface Product {

id: number;

name: string;

36
Spring boot + Angular Labs 5 CS Dr Benabderrezak

price: number;

description: string;

- Generate a `ProductComponent` to display and manage products:


● ng generate component components/product
- Now, implement the product CRUD operations in the component:

// src/app/components/product/product.component.ts

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

import { ProductService } from '../../services/product.service';

import { Product } from '../../models/product.model';

import { ToastrService } from 'ngx-toastr';

@Component ({

selector: 'app-product',

templateUrl: './product.component.html',

styleUrls: ['./product.component.css'],

})

export class ProductComponent implements OnInit {

products: Product[] = [];

newProduct: Product = { id: 0, name: '', price: 0, description: '' };

constructor(

private productService: ProductService,

37
Spring boot + Angular Labs 5 CS Dr Benabderrezak

private toastr: ToastrService

) {}

ngOnInit(): void {

this.loadProducts();

loadProducts(): void {

this.productService.getAll().subscribe(

(products) => (this.products = products),

(error) => this.toastr.error('Failed to load products')

);

addProduct(): void {

this.productService.create(this.newProduct).subscribe(

() => {

this.toastr.success('Product added successfully');

this.loadProducts();

},

(error) => this.toastr.error('Failed to add product')

);

deleteProduct(id: number): void {

this.productService.delete(id).subscribe(

38
Spring boot + Angular Labs 5 CS Dr Benabderrezak

() => {

this.toastr.success('Product deleted successfully');

this.loadProducts();

},

(error) => this.toastr.error('Failed to delete product')

);

- Create a product management interface in `product.component.html`:

<!-- src/app/components/product/product.component.html -->

<div class="container mt-5">

<h2>Product Management</h2>

<div class="mb-3">

<input [(ngModel)]="newProduct.name" class="form-control" placeholder="Product Name" />

<input [(ngModel)]="newProduct.price" class="form-control" placeholder="Product Price" />

<input [(ngModel)]="newProduct.description" class="form-control" placeholder="Product


Description" />

<button class="btn btn-success mt-2" (click)="addProduct()">Add Product</button>

</div>

<table class="table table-striped">

<thead>

39
Spring boot + Angular Labs 5 CS Dr Benabderrezak

<tr>

<th>ID</th>

<th>Name</th>

<th>Price</th>

<th>Description</th>

<th>Actions</th>

</tr>

</thead>

<tbody>

<tr *ngFor="let product of products">

<td>{{ product.id }}</td>

<td>{{ product.name }}</td>

<td>{{ product.price }}</td>

<td>{{ product.description }}</td>

<td>

<button class="btn btn-danger" (click)="deleteProduct(product.id)">

Delete

</button>

</td>

</tr>

</tbody>

</table>

40
Spring boot + Angular Labs 5 CS Dr Benabderrezak

</div>

- Add Routing : Configure routing for login and product management:

// src/app/app-routing.module.ts

import { NgModule } from '@angular/core';

import { RouterModule, Routes } from '@angular/router';

import { LoginComponent } from './components/login/login.component';

import { ProductComponent } from './components/product/product.component';

import { AuthGuard } from './guards/auth.guard'; // Guard for protected routes

const routes: Routes = [

{ path: 'login', component: LoginComponent },

{ path: 'products', component: ProductComponent, canActivate: [AuthGuard] }, // Protect products


route

{ path: '', redirectTo: 'login', pathMatch: 'full' },

];

@NgModule({

imports: [RouterModule.forRoot(routes)],

exports: [RouterModule],

})

export class AppRoutingModule {}

41
Spring boot + Angular Labs 5 CS Dr Benabderrezak

- Protect Routes with Guards : Create an `AuthGuard` to protect the product route:
● ng generate guard guards/auth
- Then, implement the guard to check authentication in src/app/guards/auth.guard.ts :

import { Injectable } from '@angular/core';

import { CanActivate, Router } from '@angular/router';

import { AuthService } from '../services/auth.service';

@Injectable({

providedIn: 'root',

})

export class AuthGuard implements CanActivate {

constructor(private authService: AuthService, private router: Router) {}

canActivate(): boolean {

if (this.authService.isAuthenticated()) {

return true;

} else {

this.router.navigate(['/login']);

return false;

- Run the Application by starting the Angular development server:


● ng serve

42
Spring boot + Angular Labs 5 CS Dr Benabderrezak

HomeWork 1 :

In the context of an e-commerce system, you are tasked with building a full-stack application using Spring
Boot for the backend and Angularfor the frontend.

The problem revolves around creating a platform where users can browse a catalog of products, add items
to their shopping cart, and complete purchases.

The system must handle user registration and authentication, product management and order processing

The system requires the implementation of eight essential classes to handle core functionalities. The first
class is User, which represents the customers and administrators of the platform. Users should be able to
create accounts, log in, and manage their profiles. The system should differentiate between regular users
and admins, with admins having additional privileges such as managing product inventory.

Next is the Product Class, which will store details of items available for sale. Each product should have
attributes like a name, price, description, stock quantity, and category. The system must allow admins to
add, update, and delete products, while users should be able to browse and search through the catalog.

A Shopping Cart class will manage the items that users intend to purchase. The cart must support adding
and removing products, adjusting quantities, and calculating the total price in real time.

To handle transactions, an Order class will be required. This class will represent the purchases made by
users, including details such as the order date, the list of products, and the total amount.

Additionally, a Category class is needed to organize products into different groups, making it easier for
users to browse and for the system to filter products.

An Inventory class will keep track of stock levels, ensuring that users cannot purchase products that are
out of stock.

43
View publication stats

Spring boot + Angular Labs 5 CS Dr Benabderrezak

Overall, the challenge is to build a robust system where these classes work together to create a smooth
user experience, from product browsing to order fulfillment, using the power of Spring Boot and Angular
to manage both the backend and frontend operations.

44

You might also like