https://github.com/kundanchourasiya/crud-operations-with-custom-api-response
In this Api we customize Api Response.
https://github.com/kundanchourasiya/crud-operations-with-custom-api-response
java java8-stream lombok mysql postman spring-jpa springboot swagger-ui validation
Last synced: about 2 months ago
JSON representation
In this Api we customize Api Response.
- Host: GitHub
- URL: https://github.com/kundanchourasiya/crud-operations-with-custom-api-response
- Owner: KundanChourasiya
- Created: 2025-04-08T12:07:39.000Z (about 2 months ago)
- Default Branch: main
- Last Pushed: 2025-04-08T15:14:37.000Z (about 2 months ago)
- Last Synced: 2025-04-08T15:25:19.033Z (about 2 months ago)
- Topics: java, java8-stream, lombok, mysql, postman, spring-jpa, springboot, swagger-ui, validation
- Language: Java
- Homepage: https://documenter.getpostman.com/view/27398506/2sB2cVgNdY
- Size: 28.3 KB
- Stars: 0
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# Crud-Operations-With-Custom-Api-Response
> [!NOTE]
> ### In this Api we customize Api Response.## Tech Stack
- Java
- Spring Framework
- Spring Boot
- Spring Data JPA
- lombok
- Validation
- MySQL
- Postman
- Swagger UI## Modules
* Student Modules## Documentation
Swagger UI Documentation - http://localhost:8080/swagger-ui/## Installation & Run
Before running the API server, you should update the database config inside the application.properties file.
Update the port number, username and password as per your local database config.
```
spring.datasource.url=jdbc:mysql://localhost:3306/mydb;
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.username=root
spring.datasource.password=root
```## API Root Endpoint
```
https://localhost:8080/
http://localhost:8080/swagger-ui/
user this data for checking purpose.
```
## Step To Be Followed
> 1. Create Rest Api will return to Student Details.
>
> **Project Documentation**
> - **Entity** - Student (class)
> - **Payload** - StudentDto, ApiResponceDto (class)
> - **Repository** - StudentRepository (interface)
> - **Service** - StudentService (interface), StudentServiceImpl (class)
> - **Controller** - StudentController (Class)
> - **Global Exception** - GlobalException, UserNotFoundException (class)
>
> 2. Run the application and get All API Response similar types.## Important Dependency to be used
1. For rest api
```
org.springframework.boot
spring-boot-starter-web
```2. For Getter and Setter
```
org.projectlombok
lombok
true
```3. For Validation
```
org.springframework.boot
spring-boot-starter-validation```
4. For Swagger
```org.springdoc
springdoc-openapi-starter-webmvc-ui
2.3.0```
5. For Mysql and JPA
```com.mysql
mysql-connector-j
runtime
org.springframework.boot
spring-boot-starter-data-jpa```
## Create Student class in Entity Package.
```
package com.it.Entity;import jakarta.persistence.*;
import lombok.Getter;
import lombok.Setter;
import org.hibernate.annotations.CreationTimestamp;
import org.hibernate.annotations.UpdateTimestamp;import java.time.LocalDateTime;
@Getter
@Setter
@Entity
@Table(name = "student")
public class Student {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id", nullable = false)
private Long id;@Column(name = "FullName", nullable = false)
private String fullName;@Column(name = "Email", nullable = false, unique = true)
private String email;@Column(name = "Password")
private String password;@Column(name = "Mobile", nullable = false, unique = true)
private String mobile;@Column(name = "Age", nullable = false)
private Long age;@Column(name = "Gender", nullable = false)
private String gender;@CreationTimestamp
@Column(name = "CreateDate", updatable = false)
private LocalDateTime createDate;@UpdateTimestamp
@Column(name = "UpdateDate", insertable = false)
private LocalDateTime updateDate;}
```## Create StudentRepository interface in repository package.
```package com.it.Repository;
import com.it.Entity.Student;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;import java.util.List;
@Repository
public interface StudentRepository extends JpaRepository {boolean existsByEmail(String email);
boolean existsByMobile(String mobile);List findByFullNameContainingIgnoreCase(String fullname);
}
```## Create StudentService interface and StudentServiceImpl class in Service package.
### *StudentService*
```
public interface StudentService {// create Student
public StudentDto createStudent(StudentDto dto);// get All student Details
public List getAllStudent();// get All student in page Format
public Page getAllStudentPage(Pageable pageable);// get single Student details
public StudentDto getStudent(Long id);// Update Student Details
public StudentDto updateStudent(Long id, StudentDto dto);// Delete Student Details
public StudentDto deleteStudent(Long id);// Search Student details using name
public List searchByName(String name);}
```### *StudentService*
```
@Service
public class StudentServiceImpl implements StudentService {
private StudentRepository studentRepository;public StudentServiceImpl(StudentRepository studentRepository) {
this.studentRepository = studentRepository;
}// map to dto
private StudentDto mapTODto(Student student) {
StudentDto dto = new StudentDto();
dto.setId(student.getId());
dto.setFullName(student.getFullName());
dto.setEmail(student.getEmail());
dto.setPassword(student.getPassword());
dto.setMobile(student.getMobile());
dto.setGender(student.getGender());
dto.setAge(student.getAge());
return dto;
}// map to Entity
private Student mapToEntity(StudentDto dto) {
Student student = new Student();
student.setId(dto.getId());
student.setFullName(dto.getFullName());
student.setEmail(dto.getEmail());
student.setPassword(dto.getPassword());
student.setMobile(dto.getMobile());
student.setGender(dto.getGender());
student.setAge(dto.getAge());
return student;
}@Override
public StudentDto createStudent(StudentDto dto) {
Student student = new Student();
student.setId(dto.getId());
student.setFullName(dto.getFullName());
student.setEmail(dto.getEmail());
student.setPassword(dto.getPassword());
student.setGender(dto.getGender());
student.setAge(dto.getAge());
student.setMobile(dto.getMobile());if (studentRepository.existsByEmail(dto.getEmail())) {
throw new IllegalArgumentException("User email already exist.");
}
if (studentRepository.existsByMobile(dto.getMobile())) {
throw new IllegalArgumentException("User Mobile no. already exist.");
}Student saveStudent = studentRepository.save(student);
StudentDto studentDto = mapTODto(saveStudent);
return studentDto;
}@Override
public List getAllStudent() {
List studentList = studentRepository.findAll();
List studentDtoList = studentList.stream().map(this::mapTODto).collect(Collectors.toUnmodifiableList());
return studentDtoList;
}@Override
public Page getAllStudentPage(Pageable pageable) {
Page studentPage = studentRepository.findAll(pageable);
List studentDtoList = studentPage.getContent().stream().map(this::mapTODto).collect(Collectors.toList());
return new PageImpl<>(studentDtoList, pageable, studentPage.getTotalPages());
}@Override
public StudentDto getStudent(Long id) {
Student student = studentRepository.findById(id).orElseThrow(() -> new UserNotFoundException("Student Not Found By Id"));
StudentDto studentDto = mapTODto(student);
return studentDto;
}@Override
public StudentDto updateStudent(Long id, StudentDto dto) {
Student student = studentRepository.findById(id).orElseThrow(() -> new UserNotFoundException("Student Not Found By Id"));
student.setId(id);
student.setFullName(dto.getFullName());
student.setEmail(dto.getEmail());
student.setPassword(dto.getPassword());
student.setGender(dto.getGender());
student.setAge(dto.getAge());
student.setMobile(dto.getMobile());
Student save = studentRepository.save(student);
StudentDto studentDto = mapTODto(save);
return studentDto;
}@Override
public StudentDto deleteStudent(Long id) {
Student student = studentRepository.findById(id).orElseThrow(() -> new UserNotFoundException("Student Not Found By Id"));
studentRepository.deleteById(student.getId());
StudentDto studentDto = mapTODto(student);
return studentDto;
}@Override
public List searchByName(String name) {
List studentList = studentRepository.findByFullNameContainingIgnoreCase(name);
List studentDtoList = studentList.stream().map(this::mapTODto).collect(Collectors.toUnmodifiableList());
return studentDtoList;
}
}
```## Create ApiResponse and StudentDto class inside the Payload Package.
### *StudentDto*
```
@Data
public class StudentDto {private Long id;
@NotBlank(message = "This Filed is required")
private String fullName;@NotBlank(message = "This Filed is required")
@Email(message = "Enter the Valid mail id")
private String email;@NotBlank(message = "This Filed is required")
@Pattern(regexp = "^(?=.*\\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[a-zA-Z]).{8,}$", message = "Password must have of minimum 8 Characters and at least one uppercase letter, one lowercase letter, one number and one special character")
@JsonProperty(access = JsonProperty.Access.WRITE_ONLY)
private String password;@NotNull(message = "This Filed is required")
@Size(min = 10, max = 10, message = "size must be 10 digits.")
@Pattern(regexp = "^\\d{10}$", message = "Phone number must be exactly 10 digits Only.")
private String mobile;@NotNull(message = "This Filed is required")
@Min(18)
@Max(60)
private Long age;@NotBlank(message = "This Filed is required")
private String gender;
}```
### *ApiResponseDto*
```
@Setter
@Getter
@NoArgsConstructor
@AllArgsConstructor
public class ApiResponse {private boolean success;
private String massage;
private T Data;}
```### *Create GlobalException class and UserNotFoundException class inside the GlobalException Package.*
### *GlobalException*
```
@RestControllerAdvice
public class GlobalExceptionHandler {// General error handler
@ExceptionHandler(Exception.class)
public ResponseEntity> handleGeneral(Exception ex) {
ApiResponse response = new ApiResponse<>(false, ex.getMessage(), null);
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(response);
}// UserNotFoundException handler
@ExceptionHandler(UserNotFoundException.class)
public ResponseEntity> handleUserNotFound(UserNotFoundException ex) {
ApiResponse response = new ApiResponse<>(false, ex.getMessage(), null);
return ResponseEntity.status(HttpStatus.NOT_FOUND).body(response);
}// IllegalArgumentException Handler
@ExceptionHandler(IllegalArgumentException.class)
public ResponseEntity> IllegalArgumentExceptionHandle(IllegalArgumentException ex) {
ApiResponse response = new ApiResponse<>(false, ex.getMessage(), null);
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(response);
}// MethodArgumentNotValidException handler
@ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseEntity> handlerInvalidArgument(MethodArgumentNotValidException ex) {Map errorMsg = new HashMap<>();
ex.getBindingResult().getFieldErrors()
.forEach(error -> errorMsg.put(error.getField(), error.getDefaultMessage()));
ApiResponse response = new ApiResponse<>(false, "Something went wrong", errorMsg);
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(response);
}
}
```### *UserNotFoundException*
```
public class UserNotFoundException extends RuntimeException{
public UserNotFoundException(String message) {
super(message);
}
}
```### *Create StudentController class inside the Controller Package.*
```
@RestController
@RequestMapping("/student")
public class StudentController {private StudentService studentService;
public StudentController(StudentService studentService) {
this.studentService = studentService;
}//URL : http://localhost:8080/student/create
@PostMapping("/create")
public ResponseEntity> createUser(@Valid @RequestBody StudentDto dto) {
StudentDto student = studentService.createStudent(dto);
ApiResponse> apiResponse = new ApiResponse<>(true, "Student saved!!!", student);
return ResponseEntity.status(200).body(apiResponse);
}//URL : http://localhost:8080/student/all-student
@GetMapping("/all-student")
public ResponseEntity> getAllStudent() {
List allStudent = studentService.getAllStudent();
ApiResponse> allStudentDetails = new ApiResponse<>(true, "All student details", allStudent);
return ResponseEntity.status(200).body(allStudentDetails);
}//URL : http://localhost:8080/student/allstudent
//URL : http://localhost:8080/student/allstudent?page=0
//URL : http://localhost:8080/student/allstudent?page=0&size=2
@GetMapping("/allstudent")
public ResponseEntity> getAllStudentPage(@RequestParam(defaultValue = "0") int page, @RequestParam(defaultValue = "2") int size) {
Page allStudentPage = studentService.getAllStudentPage(PageRequest.of(page, size));
if (!allStudentPage.isEmpty()){
ApiResponse> allStudentDetailsInPage = new ApiResponse<>(true, "All student details in page", allStudentPage);
return ResponseEntity.status(200).body(allStudentDetailsInPage);
}
ApiResponse noStudentDetailsInPage = new ApiResponse<>(false, "No student Found ", null);
return ResponseEntity.status(HttpStatusCode.valueOf(HttpStatus.NOT_FOUND.value())).body(noStudentDetailsInPage);
}//URL : http://localhost:8080/student/get/3
@GetMapping("/get/{id}")
public ResponseEntity> getStudent(@PathVariable Long id) {
StudentDto student = studentService.getStudent(id);
ApiResponse studentDtoApiResponse = new ApiResponse<>(true, "Student record by Id", student);
return ResponseEntity.status(HttpStatusCode.valueOf(HttpStatus.ACCEPTED.value())).body(studentDtoApiResponse);
}//URL : http://localhost:8080/student/update/1
@PutMapping("/update/{id}")
public ResponseEntity> updateStudent(@PathVariable Long id, @Valid @RequestBody StudentDto dto) {
StudentDto studentDto = studentService.updateStudent(id, dto);
ApiResponse studentDtoApiResponse = new ApiResponse<>(true, "Student record update Successfully", studentDto);
return ResponseEntity.status(HttpStatusCode.valueOf(HttpStatus.OK.value())).body(studentDtoApiResponse);
}//URL : http://localhost:8080/student/delete/6
@DeleteMapping("/delete/{id}")
public ResponseEntity> deleteStudent(@PathVariable Long id) {
StudentDto student = studentService.deleteStudent(id);
ApiResponse studentDtoApiResponse = new ApiResponse<>(true, "Student id " + student.getId() + " Delete Successfully", null);
return ResponseEntity.status(HttpStatusCode.valueOf(HttpStatus.OK.value())).body(studentDtoApiResponse);
}//URL : http://localhost:8080/student/search?name=k
//URL : http://localhost:8080/student/search?name=sdghs
@GetMapping("/search")
public ResponseEntity> searchByName(@RequestParam(required = false) String name) {List studentDtos = studentService.searchByName(name);
if (!studentDtos.isEmpty()) {
ApiResponse> studentFoundByName = new ApiResponse<>(true, "Student Found by name", studentDtos);
return ResponseEntity.status(HttpStatusCode.valueOf(HttpStatus.FOUND.value())).body(studentFoundByName);
}
ApiResponse noStudentFoundByName = new ApiResponse<>(false, "No student Found by name", null);
return ResponseEntity.status(HttpStatusCode.valueOf(HttpStatus.NOT_FOUND.value())).body(noStudentFoundByName);
}
}```
## Configure **_Swagger Definition_** to use Api Documentation and all Controller Documentation.
### *Swegger Defination*
```
// configure swagger OpenAPIDefinition
@OpenAPIDefinition(
info = @Info(
title = "Crud Operations with custom Api Response",
version = "1.0",
description = "In this Api we customize Api Response.",
contact = @Contact(
name = "Kundan Kumar Chourasiya",
email = "[email protected]"
)
),
servers = @Server(
url = "http://localhost:8080",
description = "Crud Operations with custom Api Response url"
)
)
```### Following pictures will help to understand flow of API
### *Swagger*

### *PostMan Test Cases*
Url - http://localhost:8080/student/create
Url - http://localhost:8080/student/search?name=g
Url - http://localhost:8080/student/search?name=Armando
Url - http://localhost:8080/student/all-student
Url - http://localhost:8080/student/get/4
Url - http://localhost:8080/student/update/6
Url - http://localhost:8080/student/delete/6
URL : http://localhost:8080/student/allstudent
URL : http://localhost:8080/student/allstudent?page=0
URL : http://localhost:8080/student/allstudent?page=0&size=2
