Spring Boot and Angular: Building a Full-Stack Web App

Spring Boot and Angular: Building a Full-Stack Web App

Combining Spring Boot and Angular allows developers to create powerful and efficient full-stack web applications. Spring Boot provides a robust backend framework while Angular offers a dynamic and responsive frontend. In this article, we’ll guide you through building a simple full-stack web app using Spring Boot for the backend and Angular for the frontend.

Prerequisites

Before you begin, ensure you have the following installed:

  • Java Development Kit (JDK)
  • Node.js and npm (Node Package Manager)
  • Angular CLI
  • Spring Boot CLI or an IDE like IntelliJ IDEA

Step 1: Setting Up the Backend with Spring Boot

1.1 Create a Spring Boot Application

Create a new Spring Boot application using Spring Initializr (https://start.spring.io/) with the following dependencies:

  • Spring Web
  • Spring Data JPA
  • H2 Database

1.2 Define the Model

Create a simple model class, User, in the com.example.demo.model package:

package com.example.demo.model;

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

@Entity
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
    private String name;
    private String email;

    // Getters and setters
    public Long getId() { return id; }
    public void setId(Long id) { this.id = id; }

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

    public String getEmail() { return email; }
    public void setEmail(String email) { this.email = email; }
}

1.3 Create a Repository

Create a repository interface, UserRepository, in the com.example.demo.repository package:

package com.example.demo.repository;

import com.example.demo.model.User;
import org.springframework.data.jpa.repository.JpaRepository;

public interface UserRepository extends JpaRepository<User, Long> {
}

1.4 Implement the Service

Create a service class, UserService, in the com.example.demo.service package:

package com.example.demo.service;

import com.example.demo.model.User;
import com.example.demo.repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class UserService {

    @Autowired
    private UserRepository userRepository;

    public List<User> getAllUsers() {
        return userRepository.findAll();
    }

    public User getUserById(Long id) {
        return userRepository.findById(id).orElse(null);
    }

    public User saveUser(User user) {
        return userRepository.save(user);
    }

    public void deleteUser(Long id) {
        userRepository.deleteById(id);
    }
}

1.5 Create a Controller

Create a REST controller, UserController, in the com.example.demo.controller package:

package com.example.demo.controller;

import com.example.demo.model.User;
import com.example.demo.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
@RequestMapping("/api/users")
@CrossOrigin(origins = "http://localhost:4200") // Allow requests from Angular app
public class UserController {

    @Autowired
    private UserService userService;

    @GetMapping
    public List<User> getAllUsers() {
        return userService.getAllUsers();
    }

    @GetMapping("/{id}")
    public User getUserById(@PathVariable Long id) {
        return userService.getUserById(id);
    }

    @PostMapping
    public User createUser(@RequestBody User user) {
        return userService.saveUser(user);
    }

    @PutMapping("/{id}")
    public User updateUser(@PathVariable Long id, @RequestBody User user) {
        user.setId(id);
        return userService.saveUser(user);
    }

    @DeleteMapping("/{id}")
    public void deleteUser(@PathVariable Long id) {
        userService.deleteUser(id);
    }
}

1.6 Run the Application

Run the Spring Boot application using your IDE or the command line:

./mvnw spring-boot:run

Step 2: Setting Up the Frontend with Angular

2.1 Create a New Angular Application

Use Angular CLI to create a new Angular project:

ng new user-management
cd user-management
ng serve

2.2 Generate Components and Services

Generate components and a service for user management:

ng generate component user-list
ng generate component user-form
ng generate service user

2.3 Define the User Model

Create a User model in src/app/user.ts:

export interface User {
  id: number;
  name: string;
  email: string;
}

2.4 Implement the User Service

Update src/app/user.service.ts to interact with the Spring Boot backend:

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';
import { User } from './user';

@Injectable({
  providedIn: 'root'
})
export class UserService {
  private apiUrl = 'http://localhost:8080/api/users';

  constructor(private http: HttpClient) {}

  getUsers(): Observable<User[]> {
    return this.http.get<User[]>(this.apiUrl);
  }

  getUser(id: number): Observable<User> {
    return this.http.get<User>(`${this.apiUrl}/${id}`);
  }

  createUser(user: User): Observable<User> {
    return this.http.post<User>(this.apiUrl, user);
  }

  updateUser(user: User): Observable<User> {
    return this.http.put<User>(`${this.apiUrl}/${user.id}`, user);
  }

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

2.5 Implement the User List Component

Update src/app/user-list/user-list.component.ts to display the list of users:

import { Component, OnInit } from '@angular/core';
import { UserService } from '../user.service';
import { User } from '../user';

@Component({
  selector: 'app-user-list',
  templateUrl: './user-list.component.html',
  styleUrls: ['./user-list.component.css']
})
export class UserListComponent implements OnInit {
  users: User[] = [];

  constructor(private userService: UserService) {}

  ngOnInit(): void {
    this.userService.getUsers().subscribe((data: User[]) => {
      this.users = data;
    });
  }
}

Update src/app/user-list/user-list.component.html to display users in a table:

<h2>User List</h2>
<table>
  <tr>
    <th>ID</th>
    <th>Name</th>
    <th>Email</th>
    <th>Actions</th>
  </tr>
  <tr *ngFor="let user of users">
    <td>{{ user.id }}</td>
    <td>{{ user.name }}</td>
    <td>{{ user.email }}</td>
    <td>
      <!- - Add edit and delete buttons here - - >
    </td>
  </tr>
</table>

2.6 Implement the User Form Component

Update src/app/user-form/user-form.component.ts to handle form submissions:

import { Component, OnInit } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import { UserService } from '../user.service';
import { User } from '../user';

@Component({
  selector: 'app-user-form',
  templateUrl: './user-form.component.html',
  styleUrls: ['./user-form.component.css']
})
export class UserFormComponent implements OnInit {
  user: User = { id: 0, name: '', email: '' };
  isEdit: boolean = false;

  constructor(
    private userService: UserService,
    private route: ActivatedRoute,
    private router: Router
  ) {}

  ngOnInit(): void {
    const id = this.route.snapshot.paramMap.get('id');
    if (id) {
      this.isEdit = true;
      this.userService.getUser(Number(id)).subscribe((data: User) => {
        this.user = data;
      });
    }
  }

  onSubmit(): void {
    if (this.isEdit) {
      this.userService.updateUser(this.user).subscribe(() => {
        this.router.navigate(['/users']);
      });
    } else {
      this.userService.createUser(this.user).subscribe(() => {
        this.router.navigate(['/users']);
      });
    }
  }
}

Update src/app/user-form/user-form.component.html to include a form:

<h2>{{ isEdit ? 'Edit User' : 'Create User' }}</h2>
<form (ngSubmit)="onSubmit()">
  <label for="name">Name:</label>
  <input type="text" id="name" [(ngModel)]="user.name" name="name" required>
  <br>
  <label for="email">Email:</label>
  <input type="email" id="email" [(ngModel)]="user.email" name="email" required>
  <br>
  <button type="submit">{{ isEdit ? 'Update' : 'Create' }}</button>
</form>

2.7 Configure Routing

Update src/app/app-routing.module.ts to define routes for the application:

import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { UserListComponent } from './user-list/user-list.component';
import { UserFormComponent } from './user-form/user-form.component';

const routes: Routes = [
  { path: 'users', component: UserListComponent },
  { path: 'add-user', component: UserFormComponent },
  { path: 'edit-user/:id', component: UserFormComponent },
  { path: '', redirectTo: '/users', pathMatch: 'full' }
];

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

2.8 Run the Angular Application

Start the Angular application using the Angular CLI:

ng serve

Conclusion

In this article, we’ve walked through the steps to create a simple full-stack web application using Spring Boot and Angular. The backend was implemented with Spring Boot, providing RESTful APIs to manage user data, while the frontend was built with Angular to create a dynamic and responsive user interface. This combination of technologies allows for the development of scalable, maintainable, and performant web applications.

Hashtags

#SpringBoot #Angular #FullStackDevelopment #WebDevelopment #Java #TypeScript #RESTAPI #SpringDataJPA #SpringWeb #FrontendDevelopment #BackendDevelopment #FullStackWebApp #Programming #Coding #WebAppDevelopment

Leave a Reply