As part of this example we're going to use following annotations to perform the CRUD operations.
As part of this below endpoints will be used to perform the CRUD operations.
Will perform the CRUD operation without using database storage.
@PostMapping annotation is a simplified compact version of
@RequestMapping(method-RequestMethod.POST)
@GetMapping annotation is a simplified compact version of
@RequestMapping(method-RequestMethod.GET)
@DeleteMapping annotation is a simplified compact version of
@RequestMapping(method-RequestMethod.DELETE)
@PutMapping annotation is a simplified compact version of
@RequestMapping(method-RequestMethod.PUT)
SpringBoot provides a web tool to generate a initial bootstrap application which is Spring Initializer. If you want to learn more about Spring initializer and how to use it to create the application visit following tutorial Create Springboot Application.
Tech stacks to develop CRUD operation
While generating the SpringBoot project, will make sure that to add following Maven dependencies.
<?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>3.3.0</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.sb.crud.example</groupId>
<artifactId>sb-curd-example</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>sb-curd-example</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>
package com.sb.crud.example;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class SbCurdExampleApplication {
public static void main(String[] args) {
SpringApplication.run(SbCurdExampleApplication.class, args);
}
}
package com.sb.crud.example.request;
import lombok.*;
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode
@Builder(toBuilder = true)
public class CustomerRequest {
private String customerName;
private int customerAge;
private String customerMobileNumber;
private String customerEmailAddress;
private String customerAddress;
}
@Getter: This annotation will help to enable all getter methods.
@Setter: This annotation will help to enable all setter methods.
@NoArgsConstructor: This annotation will help to enable the no argument NoArgsConstructor.
@AllArgsConstructor: This annotation will help to create the AllArgsConstructor.
@EqualsAndHashCode: This annotation will override the equals and hashCode method.
@Builder: This annotation will eliminate the need to write boilerplate code for constructors with
many
parameters. It generates the builder class and its methods automatically, allowing us to set only the
fields that are needed, making it easy to work with classes that have many optional attributes.
package com.sb.crud.example.controller;
import com.sb.crud.example.request.CustomerRequest;
import com.sb.crud.example.response.APIResponse;
import com.sb.crud.example.service.CustomerService;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/api/v1/customer")
@RequiredArgsConstructor
public class CustomerController {
private final CustomerService customerService;
@PostMapping("/create")
public ResponseEntity<APIResponse> createCustomer(@RequestBody CustomerRequest request) {
return customerService.createCustomer(request);
}
@GetMapping("/getAll")
public ResponseEntity<APIResponse> getAllCustomer() {
return customerService.getAllCustomers();
}
@GetMapping("/getById/{customerId}")
public ResponseEntity<APIResponse> getByCustomerId(@PathVariable long customerId) {
return customerService.getByCustomerId(customerId);
}
@DeleteMapping("/deleteById/{customerId}")
public ResponseEntity<APIResponse> deleteByCustomerId(@PathVariable long customerId) {
return customerService.deleteByCustomerId(customerId);
}
@PutMapping("/update/{customerId}")
public ResponseEntity<APIResponse> updateCustomer(@PathVariable long customerId, @RequestBody CustomerRequest request) {
return customerService.updateCustomer(customerId, request);
}
}
@RestController: This annotation is used to indicate that this class is a REST controller, which
means it handles incoming HTTP requests
and returns the corresponding responses.
@RequestMapping: This annotation is used to specify the base URL path for all the request mappings
defined within this controller.
@RequiredArgsConstructor: This annotation is used to generate the constructor with required arguments
to enable constructor injection in
the defined controller.
@PostMapping: This annotation is used to map the specified method to the HTTP POST method for the
base URL path.
@GetMapping: This annotation is used to handle the HTTP GET requests matched with the given URI
expression.
@DeleteMapping: This annotation is used to handle the HTTP DELETE requests matched with the given URI
expression.
@PutMapping: This annotation is used to map the specified method to the HTTP PUT method for the base
URL path.
@RequestBody: This annotation is used to bind the request body to the CustomerRequest object,
which represents the CustomerRequest items to be added.
ResponseEntity: This object is used to send the HTTP response back to the client.
This will be used as a common response object, rendering all our responses and sending them back to the client.
package com.sb.post.mapping.example.response;
import lombok.*;
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode
@Builder(toBuilder = true)
public class APIResponse {
private int errorCode;
private Object data;
}
package com.sb.crud.example.service;
import com.sb.crud.example.request.CustomerRequest;
import com.sb.crud.example.response.APIResponse;
import org.springframework.http.ResponseEntity;
public interface CustomerService {
ResponseEntity<APIResponse> createCustomer(CustomerRequest request);
ResponseEntity<APIResponse> getAllCustomers();
ResponseEntity<APIResponse> getByCustomerId(long customerId);
ResponseEntity<APIResponse> deleteByCustomerId(long customerId);
ResponseEntity<APIResponse> updateCustomer(long customerId, CustomerRequest request);
}
package com.sb.post.mapping.example.model;
import lombok.*;
import java.time.LocalDate;
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@ToString
@EqualsAndHashCode
@Builder(toBuilder = true)
public class CustomerModel {
private long customerId;
private String customerName;
private int customerAge;
private String customerMobileNumber;
private String customerEmailAddress;
private String customerAddress;
private LocalDate createdDate;
}
package com.sb.post.mapping.example.response;
import lombok.*;
import java.time.LocalDate;
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@ToString
@EqualsAndHashCode
@Builder(toBuilder = true)
public class CustomerResponse {
private long customerId;
private String customerName;
private int customerAge;
private String customerMobileNumber;
private String customerEmailAddress;
private String customerAddress;
private LocalDate createdDate;
}
package com.sb.crud.example.service.impl;
import com.sb.crud.example.model.CustomerModel;
import com.sb.crud.example.request.CustomerRequest;
import com.sb.crud.example.response.APIResponse;
import com.sb.crud.example.response.CustomerResponse;
import com.sb.crud.example.service.CustomerService;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.atomic.AtomicInteger;
import static com.sb.crud.example.mapper.CustomerMapper.modelToResponseMapper;
@Service
public class CustomerServiceImpl implements CustomerService {
private static List<CustomerModel> customers = new ArrayList<>();
private static AtomicInteger c = new AtomicInteger(1);
static {
customers.add(new CustomerModel(c.getAndIncrement(), "testUser1", 21, "7234567811", "testuser1@gmail.com", "Bangalore", LocalDate.now()));
customers.add(new CustomerModel(c.getAndIncrement(), "testUser2", 22, "7234567812", "testuser2@gmail.com", "Hyderabad", LocalDate.now()));
customers.add(new CustomerModel(c.getAndIncrement(), "testUser3", 23, "7234567813", "testuser3@gmail.com", "Chennai", LocalDate.now()));
customers.add(new CustomerModel(c.getAndIncrement(), "testUser4", 24, "7234567814", "testuser4@gmail.com", "Pune", LocalDate.now()));
}
@Override
public ResponseEntity<APIResponse> createCustomer(CustomerRequest request) {
CustomerModel customerModel = CustomerModel.builder()
.customerId(c.getAndIncrement())
.customerName(request.getCustomerName())
.customerAge(request.getCustomerAge())
.customerMobileNumber(request.getCustomerMobileNumber())
.customerEmailAddress(request.getCustomerEmailAddress())
.customerAddress(request.getCustomerAddress())
.createdDate(LocalDate.now())
.build();
customers.add(customerModel);
return ResponseEntity.ok(
APIResponse.builder()
.errorCode(000)
.data(CustomerResponse.builder()
.customerId(customerModel.getCustomerId())
.customerName(customerModel.getCustomerName())
.customerAge(customerModel.getCustomerAge())
.customerMobileNumber(customerModel.getCustomerMobileNumber())
.customerEmailAddress(customerModel.getCustomerEmailAddress())
.customerAddress(customerModel.getCustomerAddress())
.createdDate(customerModel.getCreatedDate())
.build()
)
.build()
);
}
@Override
public ResponseEntity<APIResponse> getAllCustomers() {
List<CustomerResponse> customerLists = customers.stream()
.map(customerModel -> modelToResponseMapper(customerModel))
.toList();
return ResponseEntity.ok(
APIResponse.builder()
.errorCode(000)
.data(customerLists)
.build()
);
}
@Override
public ResponseEntity<APIResponse> getByCustomerId(long customerId) {
Optional<CustomerResponse> customerResponseOptional = customers.stream()
.filter(customerModel -> customerModel.getCustomerId() == customerId)
.map(customerModel -> modelToResponseMapper(customerModel))
.findFirst();
return customerResponseOptional.map(
customerResponse -> ResponseEntity.ok(
APIResponse.builder()
.errorCode(0)
.data(customerResponse)
.build()
)
).orElseGet(() -> ResponseEntity.ok(
APIResponse.builder()
.errorCode(999)
.data("Customer is not available")
.build())
);
}
@Override
public ResponseEntity<APIResponse> deleteByCustomerId(long customerId) {
boolean isRemoved = customers.removeIf(customerModel -> customerModel.getCustomerId() == customerId);
if (isRemoved) {
return ResponseEntity.ok(
APIResponse.builder()
.errorCode(0)
.data("Successfully Removed")
.build()
);
} else {
return ResponseEntity.ok(
APIResponse.builder()
.errorCode(999)
.data("Customer is not available")
.build()
);
}
}
@Override
public ResponseEntity<APIResponse> updateCustomer(long customerId, CustomerRequest request) {
Optional<CustomerModel> customerModelOptional = customers.stream()
.filter(customerModel -> customerModel.getCustomerId() == customerId)
.map(customerModel -> {
customerModel.setCustomerName(request.getCustomerName());
customerModel.setCustomerAge(request.getCustomerAge());
customerModel.setCustomerMobileNumber(request.getCustomerMobileNumber());
customerModel.setCustomerEmailAddress(request.getCustomerEmailAddress());
customerModel.setCustomerAddress(request.getCustomerAddress());
return customerModel;
})
.findFirst();
return customerModelOptional.map(customerResponse -> ResponseEntity.ok(
APIResponse.builder()
.errorCode(000)
.data(CustomerResponse.builder()
.customerId(customerResponse.getCustomerId())
.customerName(customerResponse.getCustomerName())
.customerAge(customerResponse.getCustomerAge())
.customerMobileNumber(customerResponse.getCustomerMobileNumber())
.customerEmailAddress(customerResponse.getCustomerEmailAddress())
.customerAddress(customerResponse.getCustomerAddress())
.createdDate(customerResponse.getCreatedDate())
.build()
)
.build()
)).orElseGet(() -> ResponseEntity.ok(
APIResponse.builder()
.errorCode(999)
.data("Customer is not available")
.build()
));
}
}
spring.application.name=sb-curd-example
server.port=8085
Register customer through Postman API
Get all the customers
Get customer by id
Delete a customer by id
Update a customer by id and object
Full source code is available in following GitHub repository: CRUD example