- Java-17
- Spring Boot -3x
- Spring Data JPA
- lombok
- Validation
- MySQL
- Postman
- Swagger UI
- Student Modules
Swagger UI Documentation - http://localhost:8080/swagger-ui/
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
https://localhost:8080/
http://localhost:8080/swagger-ui/
user this data for checking purpose.
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)
Run the application and get All API Response similar types.
- For rest api
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
- For Getter and Setter
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
- For Validation
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
- For Swagger
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
<version>2.3.0</version>
</dependency>
- For Mysql and JPA
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
@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;
}
@Repository
public interface StudentRepository extends JpaRepository<Student, Long> {
boolean existsByEmail(String email);
boolean existsByMobile(String mobile);
List<Student> findByFullNameContainingIgnoreCase(String fullname);
}
public interface StudentService {
// create Student
public StudentDto createStudent(StudentDto dto);
// get All student Details
public List<StudentDto> getAllStudent();
// get All student in page Format
public Page<StudentDto> 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<StudentDto> searchByName(String name);
}
@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<StudentDto> getAllStudent() {
List<Student> studentList = studentRepository.findAll();
List<StudentDto> studentDtoList = studentList.stream().map(this::mapTODto).collect(Collectors.toUnmodifiableList());
return studentDtoList;
}
@Override
public Page<StudentDto> getAllStudentPage(Pageable pageable) {
Page<Student> studentPage = studentRepository.findAll(pageable);
List<StudentDto> 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<StudentDto> searchByName(String name) {
List<Student> studentList = studentRepository.findByFullNameContainingIgnoreCase(name);
List<StudentDto> studentDtoList = studentList.stream().map(this::mapTODto).collect(Collectors.toUnmodifiableList());
return studentDtoList;
}
}
@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;
}
@Setter
@Getter
@NoArgsConstructor
@AllArgsConstructor
public class ApiResponse<T> {
private boolean success;
private String massage;
private T Data;
}
@RestControllerAdvice
public class GlobalExceptionHandler {
// General error handler
@ExceptionHandler(Exception.class)
public ResponseEntity<ApiResponse<Object>> handleGeneral(Exception ex) {
ApiResponse<Object> response = new ApiResponse<>(false, ex.getMessage(), null);
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(response);
}
// UserNotFoundException handler
@ExceptionHandler(UserNotFoundException.class)
public ResponseEntity<ApiResponse<Object>> handleUserNotFound(UserNotFoundException ex) {
ApiResponse<Object> response = new ApiResponse<>(false, ex.getMessage(), null);
return ResponseEntity.status(HttpStatus.NOT_FOUND).body(response);
}
// IllegalArgumentException Handler
@ExceptionHandler(IllegalArgumentException.class)
public ResponseEntity<ApiResponse<Object>> IllegalArgumentExceptionHandle(IllegalArgumentException ex) {
ApiResponse<Object> response = new ApiResponse<>(false, ex.getMessage(), null);
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(response);
}
// MethodArgumentNotValidException handler
@ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseEntity<ApiResponse<Object>> handlerInvalidArgument(MethodArgumentNotValidException ex) {
Map<String, String> errorMsg = new HashMap<>();
ex.getBindingResult().getFieldErrors()
.forEach(error -> errorMsg.put(error.getField(), error.getDefaultMessage()));
ApiResponse<Object> response = new ApiResponse<>(false, "Something went wrong", errorMsg);
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(response);
}
}
public class UserNotFoundException extends RuntimeException{
public UserNotFoundException(String message) {
super(message);
}
}
@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<ApiResponse<?>> 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<ApiResponse<?>> getAllStudent() {
List<StudentDto> allStudent = studentService.getAllStudent();
ApiResponse<List<StudentDto>> 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<ApiResponse<?>> getAllStudentPage(@RequestParam(defaultValue = "0") int page, @RequestParam(defaultValue = "2") int size) {
Page<StudentDto> allStudentPage = studentService.getAllStudentPage(PageRequest.of(page, size));
if (!allStudentPage.isEmpty()){
ApiResponse<Page<StudentDto>> allStudentDetailsInPage = new ApiResponse<>(true, "All student details in page", allStudentPage);
return ResponseEntity.status(200).body(allStudentDetailsInPage);
}
ApiResponse<Object> 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<ApiResponse<?>> getStudent(@PathVariable Long id) {
StudentDto student = studentService.getStudent(id);
ApiResponse<StudentDto> 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<ApiResponse<?>> updateStudent(@PathVariable Long id, @Valid @RequestBody StudentDto dto) {
StudentDto studentDto = studentService.updateStudent(id, dto);
ApiResponse<StudentDto> 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<ApiResponse<?>> deleteStudent(@PathVariable Long id) {
StudentDto student = studentService.deleteStudent(id);
ApiResponse<StudentDto> 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<ApiResponse<?>> searchByName(@RequestParam(required = false) String name) {
List<StudentDto> studentDtos = studentService.searchByName(name);
if (!studentDtos.isEmpty()) {
ApiResponse<List<StudentDto>> studentFoundByName = new ApiResponse<>(true, "Student Found by name", studentDtos);
return ResponseEntity.status(HttpStatusCode.valueOf(HttpStatus.FOUND.value())).body(studentFoundByName);
}
ApiResponse<Object> noStudentFoundByName = new ApiResponse<>(false, "No student Found by name", null);
return ResponseEntity.status(HttpStatusCode.valueOf(HttpStatus.NOT_FOUND.value())).body(noStudentFoundByName);
}
}
// 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 = "mailmekundanchourasiya@gmail.com"
)
),
servers = @Server(
url = "http://localhost:8080",
description = "Crud Operations with custom Api Response url"
)
)
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