SpringbootAngularLabs
SpringbootAngularLabs
net/publication/384040618
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.
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.
1
Spring boot + Angular Labs 5 CS Dr Benabderrezak
➔ 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
- 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>
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
@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
@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)
);
}
}
6
Spring boot + Angular Labs 5 CS Dr Benabderrezak
Practical Example : build a Spring Boot application that performs CRUD operations on a products
● 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
<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>
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>
- 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
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
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
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
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;
}
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
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
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
@Autowired
@Override
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
private String SECRET_KEY = "secret"; // Secret key for signing JWT tokens
18
Spring boot + Angular Labs 5 CS Dr Benabderrezak
return claimsResolver.apply(claims);
return Jwts.parser().setSigningKey(SECRET_KEY).parseClaimsJws(token).getBody();
19
Spring boot + Angular Labs 5 CS Dr Benabderrezak
.signWith(SignatureAlgorithm.HS256, SECRET_KEY).compact();
// Validate token
- 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
@Autowired
@Autowired
@Override
FilterChain chain)
21
Spring boot + Angular Labs 5 CS Dr Benabderrezak
jwt = authorizationHeader.substring(7);
username = jwtTokenUtil.extractUsername(jwt);
if (jwtTokenUtil.validateToken(jwt, userDetails)) {
authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(authentication);
chain.doFilter(request, response);
}}
22
Spring boot + Angular Labs 5 CS Dr Benabderrezak
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
23
Spring boot + Angular Labs 5 CS Dr Benabderrezak
@Autowired
@Autowired
@Override
auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
@Override
http.csrf().disable()
.and().sessionManagement()
@Bean
24
Spring boot + Angular Labs 5 CS Dr Benabderrezak
@Override
@Bean
return super.authenticationManagerBean();
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")
@Autowired
@Autowired
@Autowired
@PostMapping("/login")
// Perform authentication
authenticationManager.authenticate(
);
// Generate token
return jwtTokenUtil.generateToken(userDetails);
26
Spring boot + Angular Labs 5 CS Dr Benabderrezak
class AuthRequest {
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"
27
Spring boot + Angular Labs 5 CS Dr Benabderrezak
Objective command
install Angular CLI globally if you haven't already npm install -g @angular/cli
Install Required Packages : Bootstrap & `ngx-toastr` (for notifications) npm install bootstrap
"styles": [
"src/styles.css",
"node_modules/bootstrap/dist/css/bootstrap.min.css"
],
28
Spring boot + Angular Labs 5 CS Dr Benabderrezak
@Injectable({
providedIn: 'root',
})
localStorage.setItem('jwtToken', token);
29
Spring boot + Angular Labs 5 CS Dr Benabderrezak
return localStorage.getItem('jwtToken');
getDecodedToken(): any {
if (token) {
return jwtDecode(token);
return null;
logout(): void {
localStorage.removeItem('jwtToken');
this.router.navigate(['/login']);
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
@Injectable()
if (token) {
// Clone the request and add the JWT token in the Authorization header
req = req.clone({
setHeaders: {
},
});
31
Spring boot + Angular Labs 5 CS Dr Benabderrezak
return next.handle(req);
@NgModule({
providers: [
],
})
// src/app/components/login/login.component.ts
32
Spring boot + Angular Labs 5 CS Dr Benabderrezak
@Component({
selector: 'app-login',
templateUrl: './login.component.html',
styleUrls: ['./login.component.css'],
})
constructor(
) {}
login(): void {
this.authService.login(this.username, this.password).subscribe(
(response) => {
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');
);
<h2>Login</h2>
<form (submit)="login()">
<div class="mb-3">
<input type="text"
id="username"
class="form-control"
[(ngModel)]="username"
</div>
34
Spring boot + Angular Labs 5 CS Dr Benabderrezak
<div class="mb-3">
</div>
</form>
</div>
@Injectable({
providedIn: 'root',
})
35
Spring boot + Angular Labs 5 CS Dr Benabderrezak
getAll(): Observable<Product[]> {
return this.http.get<Product[]>(this.apiUrl);
// Update product by ID
// Delete product by ID
return this.http.delete<void>(`${this.apiUrl}/${id}`);
id: number;
name: string;
36
Spring boot + Angular Labs 5 CS Dr Benabderrezak
price: number;
description: string;
// src/app/components/product/product.component.ts
@Component ({
selector: 'app-product',
templateUrl: './product.component.html',
styleUrls: ['./product.component.css'],
})
constructor(
37
Spring boot + Angular Labs 5 CS Dr Benabderrezak
) {}
ngOnInit(): void {
this.loadProducts();
loadProducts(): void {
this.productService.getAll().subscribe(
);
addProduct(): void {
this.productService.create(this.newProduct).subscribe(
() => {
this.loadProducts();
},
);
this.productService.delete(id).subscribe(
38
Spring boot + Angular Labs 5 CS Dr Benabderrezak
() => {
this.loadProducts();
},
);
<h2>Product Management</h2>
<div class="mb-3">
</div>
<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>
<td>
Delete
</button>
</td>
</tr>
</tbody>
</table>
40
Spring boot + Angular Labs 5 CS Dr Benabderrezak
</div>
// src/app/app-routing.module.ts
];
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule],
})
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 :
@Injectable({
providedIn: 'root',
})
canActivate(): boolean {
if (this.authService.isAuthenticated()) {
return true;
} else {
this.router.navigate(['/login']);
return false;
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
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