How to Build a CRM System with Spring Boot and Angular

Introduction

Customer Relationship Management (CRM) systems are widely used in various industries to manage interactions with customers and streamline sales processes. In this tutorial, we will learn how to build a CRM system from scratch using Spring Boot and Angular.

We will use Spring Boot to create a backend API for CRUD operations on customer data, and Angular for building a front-end user interface to interact with the CRM system.

By the end of this tutorial, you will have a fully functional CRM system that allows you to create, retrieve, update, and delete customer data.

Prerequisites

To follow along with this tutorial, you will need:

  • Java Development Kit (JDK) installed on your machine
  • Node.js and npm installed on your machine
  • Angular CLI installed globally on your machine
  • Your favorite text editor or Integrated Development Environment (IDE)

Setting Up the Backend API

Let’s start by setting up the backend API using Spring Boot.

Step 1: Create a new Spring Boot project

To create a new Spring Boot project, open your terminal or command prompt and run the following command:

$ mkdir crm-backend
$ cd crm-backend
$ curl https://start.spring.io/starter.zip -o Initial.zip
$ unzip Initial.zip
$ rm Initial.zip

This will create a new directory called crm-backend and download a zip file containing the initial project setup from start.spring.io. We then extract the contents of the zip file and remove it.

Step 2: Configure project dependencies

Open the pom.xml file in your favorite text editor or IDE and add the following dependencies in the <dependencies> section:

<dependencies>
  ...
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
  </dependency>
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
  </dependency>
  <dependency>
    <groupId>org.postgresql</groupId>
    <artifactId>postgresql</artifactId>
  </dependency>
</dependencies>

These dependencies will include the necessary libraries for creating a web application with Spring Boot, handling JPA (Java Persistence API) data access, and connecting to a PostgreSQL database.

Step 3: Configure the database connection

Now, we need to configure the database connection in the application.properties file. Create a new file called application.properties in the src/main/resources directory and add the following content:

spring.datasource.url=jdbc:postgresql://localhost:5432/crmdb
spring.datasource.username=your_username
spring.datasource.password=your_password
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.format_sql=true
spring.jpa.hibernate.ddl-auto=update

Replace your_username and your_password with your PostgreSQL credentials. This configuration specifies the URL, username, and password for the PostgreSQL database connection, as well as some additional properties for Hibernate (the JPA implementation).

Step 4: Create the customer entity

Next, let’s create the customer entity class. In the src/main/java/com/example/crmbackend directory, create a new package called entity and inside it, create a new file called Customer.java with the following content:

package com.example.crmbackend.entity;

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

@Entity
public class Customer {

  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  private Long id;

  private String firstName;
  private String lastName;
  private String email;

  // getters and setters
  // ...
}

This class represents the customer entity with four properties: id, firstName, lastName, and email. The @Entity annotation indicates that this class is an entity managed by Hibernate.

Step 5: Create the customer repository

Next, let’s create the customer repository interface. In the same entity package, create a new file called CustomerRepository.java with the following content:

package com.example.crmbackend.entity;

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

public interface CustomerRepository extends JpaRepository<Customer, Long> {
}

This interface extends the JpaRepository interface provided by Spring Data JPA. It provides the necessary CRUD operations (create, retrieve, update, and delete) for the customer entity.

Step 6: Create the customer controller

Now, let’s create the customer controller class to handle HTTP requests related to the customer data. In the src/main/java/com/example/crmbackend directory, create a new package called controller and inside it, create a new file called CustomerController.java with the following content:

package com.example.crmbackend.controller;

import com.example.crmbackend.entity.Customer;
import com.example.crmbackend.entity.CustomerRepository;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
@RequestMapping("/api/customers")
public class CustomerController {

  private final CustomerRepository customerRepository;

  public CustomerController(CustomerRepository customerRepository) {
    this.customerRepository = customerRepository;
  }

  @GetMapping
  public List<Customer> getAllCustomers() {
    return customerRepository.findAll();
  }

  @PostMapping
  public Customer createCustomer(@RequestBody Customer customer) {
    return customerRepository.save(customer);
  }

  @GetMapping("/{id}")
  public Customer getCustomerById(@PathVariable Long id) {
    return customerRepository.findById(id).orElse(null);
  }

  @PutMapping("/{id}")
  public Customer updateCustomer(@PathVariable Long id, @RequestBody Customer customerDetails) {
    Customer customer = customerRepository.findById(id).orElse(null);
    if (customer != null) {
      customer.setFirstName(customerDetails.getFirstName());
      customer.setLastName(customerDetails.getLastName());
      customer.setEmail(customerDetails.getEmail());
      return customerRepository.save(customer);
    }
    return null;
  }

  @DeleteMapping("/{id}")
  public void deleteCustomer(@PathVariable Long id) {
    customerRepository.deleteById(id);
  }
}

This class is annotated with @RestController, which indicates that it will handle HTTP requests and return JSON responses. We define several methods to handle different HTTP methods and perform the corresponding CRUD operations using the customer repository.

Step 7: Run the application

Finally, let’s run the Spring Boot application to start the backend API. Open your terminal or command prompt, navigate to the crm-backend directory, and run the following command:

$ mvn spring-boot:run

If everything is set up correctly, you should see some log output indicating that the application has started successfully.

Setting Up the Frontend UI

Now that we have the backend API set up, let’s move on to building the frontend user interface using Angular.

Step 1: Create a new Angular project

To create a new Angular project, open your terminal or command prompt and run the following command:

$ ng new crm-frontend
$ cd crm-frontend

This will create a new directory called crm-frontend and generate a new Angular project inside it.

Step 2: Create the customer service

Next, let’s create the customer service in Angular to interact with the backend API. In the src/app directory, create a new file called customer.service.ts with the following content:

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

export interface Customer {
  id: number;
  firstName: string;
  lastName: string;
  email: string;
}

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

  private apiUrl = '/api/customers';

  constructor(private http: HttpClient) {}

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

  createCustomer(customer: Customer): Observable<Customer> {
    return this.http.post<Customer>(this.apiUrl, customer);
  }

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

  updateCustomer(id: number, customer: Customer): Observable<Customer> {
    return this.http.put<Customer>(`${this.apiUrl}/${id}`, customer);
  }

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

This service uses the Angular HttpClient to send HTTP requests to the backend API and retrieve the customer data. It defines several methods to perform the corresponding CRUD operations.

Step 3: Create the customer list component

Now, let’s create the customer list component to display the list of customers. In the src/app directory, create a new file called customer-list.component.ts with the following content:

import { Component, OnInit } from '@angular/core';
import { Customer, CustomerService } from './customer.service';

@Component({
  selector: 'app-customer-list',
  template: `
    <h2>Customer List</h2>
    <table>
      <thead>
        <tr>
          <th>ID</th>
          <th>First Name</th>
          <th>Last Name</th>
          <th>Email</th>
          <th>Actions</th>
        </tr>
      </thead>
      <tbody>
        <tr *ngFor="let customer of customers">
          <td>{{ customer.id }}</td>
          <td>{{ customer.firstName }}</td>
          <td>{{ customer.lastName }}</td>
          <td>{{ customer.email }}</td>
          <td>
            <button (click)="editCustomer(customer)">Edit</button>
            <button (click)="deleteCustomer(customer.id)">Delete</button>
          </td>
        </tr>
      </tbody>
    </table>
  `,
  providers: [CustomerService]
})
export class CustomerListComponent implements OnInit {

  customers: Customer[] = [];

  constructor(private customerService: CustomerService) {}

  ngOnInit() {
    this.loadCustomers();
  }

  loadCustomers() {
    this.customerService.getAllCustomers().subscribe(customers => {
      this.customers = customers;
    });
  }

  editCustomer(customer: Customer) {
    // TODO: Implement edit functionality
  }

  deleteCustomer(id: number) {
    this.customerService.deleteCustomer(id).subscribe(() => {
      this.loadCustomers();
    });
  }
}

This component retrieves the list of customers from the backend API using the CustomerService and displays them in a table. It also includes buttons to edit or delete each customer.

Step 4: Create the customer form component

Next, let’s create the customer form component to add or edit customer data. In the src/app directory, create a new file called customer-form.component.ts with the following content:

import { Component } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { Customer, CustomerService } from './customer.service';

@Component({
  selector: 'app-customer-form',
  template: `
    <h2>{{ isNew ? 'Add' : 'Edit' }} Customer</h2>
    <form [formGroup]="customerForm" (ngSubmit)="saveCustomer()">
      <div>
        <label for="firstName">First Name:</label>
        <input type="text" id="firstName" formControlName="firstName" required>
      </div>
      <div>
        <label for="lastName">Last Name:</label>
        <input type="text" id="lastName" formControlName="lastName" required>
      </div>
      <div>
        <label for="email">Email:</label>
        <input type="email" id="email" formControlName="email" required>
      </div>
      <button type="submit">{{ isNew ? 'Add' : 'Save' }}</button>
      <button type="button" (click)="cancel()">Cancel</button>
    </form>
  `,
  providers: [CustomerService]
})
export class CustomerFormComponent {

  customerForm: FormGroup;
  isNew = true;

  constructor(
    private formBuilder: FormBuilder,
    private customerService: CustomerService
  ) {
    this.customerForm = this.formBuilder.group({
      id: [],
      firstName: ['', Validators.required],
      lastName: ['', Validators.required],
      email: ['', [Validators.required, Validators.email]]
    });
  }

  saveCustomer() {
    if (this.customerForm.valid) {
      const customer: Customer = this.customerForm.value;
      if (this.isNew) {
        this.customerService.createCustomer(customer).subscribe(() => {
          // TODO: Implement successful save handling
          this.resetForm();
        });
      } else {
        this.customerService.updateCustomer(customer.id, customer).subscribe(() => {
          // TODO: Implement successful update handling
          this.resetForm();
        });
      }
    }
  }

  cancel() {
    // TODO: Implement cancel functionality
    this.resetForm();
  }

  resetForm() {
    this.customerForm.reset();
    this.isNew = true;
  }
}

This component contains a form to add or edit customer data. It uses the Angular FormBuilder and FormGroup classes to define form controls and validate user input. The CustomerService is used to save the customer data to the backend API.

Step 5: Update the app component

Finally, let’s update the app component to include the customer list and form components. In the src/app directory, open the app.component.ts file and update its content as follows:

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

@Component({
  selector: 'app-root',
  template: `
    <app-customer-list></app-customer-list>
    <hr>
    <app-customer-form></app-customer-form>
  `
})
export class AppComponent {
}

This component includes the app-customer-list and app-customer-form components to display the list of customers and the customer form.

Running the Application

Now that we have set up both the backend API and the frontend UI, let’s run the application to see it in action.

Step 1: Start the backend API

Open your terminal or command prompt, navigate to the crm-backend directory, and run the following command:

$ mvn spring-boot:run

Step 2: Start the frontend UI

Open another terminal or command prompt, navigate to the crm-frontend directory, and run the following command:

$ ng serve

This will start the Angular development server and compile the TypeScript code into JavaScript. If everything is set up correctly, you should see some log output indicating that the application has started successfully.

Step 3: Access the CRM system

Open your web browser and navigate to `http://localhost:4200`. You should see the customer list and form components rendered in the browser.

Step 4: Test the CRM system

You can now test the CRM system by adding, editing, and deleting customers. The data will be persisted in the PostgreSQL database through the backend API.

Congratulations! You have successfully built a CRM system with Spring Boot and Angular.

Conclusion

In this tutorial, we have learned how to build a CRM system from scratch using Spring Boot for the backend API and Angular for the frontend UI. We have set up the backend API to handle CRUD operations on customer data and the frontend UI to display the customer list and form components.

Feel free to expand on this project by adding additional features like authentication, searching/filtering, or more complex data relationships. Happy coding!

Related Post