Reputation: 1
I've built a spring boot rest api. However, when I try to test it in Postman, I am getting a 404 error. I have linked the code below. Please note that there might be a random @component annotation in some files. This was my tired brain trying anything it can.
Student.java
package StudentModel;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
@Entity
@Table(name = "Student")
public class Student {
public enum status {
PAID,
UNPAID,
PARTIAL
}
@Column
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private long Id;
@Column(nullable = false)
private String FirstName;
@Column(nullable = false)
private String LastName;
@Column(nullable = false)
private long Phone;
@Column(nullable = false)
private String Email;
@Column(nullable = false)
private status PaymentStatus;
public long getId() {
return Id;
}
public void setId(long id) {
Id = id;
}
public String getFirstName() {
return FirstName;
}
public void setFirstName(String firstName) {
FirstName = firstName;
}
public String getLastName() {
return LastName;
}
public void setLastName(String lastName) {
LastName = lastName;
}
public long getPhone() {
return Phone;
}
public void setPhone(long phone) {
Phone = phone;
}
public String getEmail() {
return Email;
}
public void setEmail(String email) {
Email = email;
}
public status getPaymentStatus() {
return PaymentStatus;
}
public void setPaymentStatus(status paymentStatus) {
PaymentStatus = paymentStatus;
}
}
StudentController.java
package StudentController;
import java.util.List;
import java.util.Optional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import StudentModel.Student;
import StudentService.StudentService;
@Component
@RestController
@RequestMapping("/api/v1")
public class StudentController {
@Autowired
private StudentService studentService;
@PostMapping("/api/v1/addStudent")
public Student addStudent(@RequestBody Student student) {
return studentService.saveStudent(student);
}
@PostMapping("/api/v1/addStudents")
public List<Student> addStudents(@RequestBody List<Student> students) {
return studentService.saveStudents(students);
}
@GetMapping("/api/v1/students")
public List<Student> findAllStudents(){
return studentService.getStudents();
}
@GetMapping("/api/v1/students/{id}")
public Student findStudentById(@PathVariable long id) {
return studentService.getStudentById(id);
}
@GetMapping("/api/v1/students/{name}")
public Student findStudentByFirstName(@PathVariable String FirstName) {
return studentService.getStudentByFirstName(FirstName);
}
@PutMapping("/api/v1/update")
public Student updateStudent(@RequestBody Student student) {
return studentService.updateStudent(student);
}
@DeleteMapping("/api/v1/delete/{id}")
public String deleteStudent(@PathVariable long id) {
return studentService.deleteStudent(id);
}
}
StudentService.java
package StudentService;
import java.util.List;
import java.util.Optional;
import javax.transaction.Transactional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
import StudentModel.Student;
import StudentRepository.StudentRepository;
@Component
@Service
@Transactional
public class StudentService {
@Autowired
private StudentRepository studentRepository;
public Student saveStudent(Student student) {
return studentRepository.save(student);
}
public List<Student> saveStudents(List<Student> students) {
return studentRepository.saveAll(students);
}
public List<Student> getStudents() {
return studentRepository.findAll();
}
public Student getStudentById(long id){
return studentRepository.getById(id);
}
public Student getStudentByFirstName(String FirstName){
return studentRepository.findByFirstName(FirstName);
}
public Student getStudentByLastName(String LastName){
return studentRepository.findByLastName(LastName);
}
public Student getStudentByEmail(String Email){
return studentRepository.findByEmail(Email);
}
public Student getStudentByPhone(long Phone){
return studentRepository.findByPhone(Phone);
}
public String deleteStudent(long id) {
studentRepository.deleteById(id);
return "Student Deleted";
}
public Student updateStudent (Student student) {
Student existingStudent = studentRepository.getById(student.getId());
existingStudent.setFirstName(student.getFirstName());
existingStudent.setLastName(student.getLastName());
existingStudent.setEmail(student.getEmail());
existingStudent.setPhone(student.getPhone());
existingStudent.setPaymentStatus(student.getPaymentStatus());
return studentRepository.save(existingStudent);
}
}
StudentRepository.java
package StudentRepository;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Component;
import StudentModel.Student;
@Component
public interface StudentRepository extends JpaRepository <Student, Long>{
// Student saveStudent (Student student);
Student findByFirstName(String FirstName);
Student findByLastName(String LastName);
Student findByEmail(String Email);
Student findByPhone(long Phone);
// Student findById(long id);
}
StudentApplication.java
package com.BusyQA;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
@SpringBootApplication
@ComponentScan
public class BusyQaApplication extends SpringBootServletInitializer{
public static void main(String[] args) {
SpringApplication.run(BusyQaApplication.class, args);
}
}
Any help would be greatly appreciated. Thank you.
Upvotes: 0
Views: 8128
Reputation: 6520
To make it work, you need some improvements:
- For
Controller
(REST API
requests):
- remove
@Component
annotation;- remove
/api/v1/
from request mappings;- add
DTO
to only transfer the required information;- fix the name of the variables, following the convention.
import java.util.ArrayList;
import java.util.List;
import com.example.demo.dto.StudentDTO;
import com.example.demo.entity.Student;
import com.example.demo.service.StudentService;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/api/v1")
public class StudentController {
private final StudentService studentService;
public StudentController(StudentService studentService) {
this.studentService = studentService;
}
@PostMapping("/addStudent")
public Student addStudent(@RequestBody StudentDTO studentDTO) {
Student student = new Student(studentDTO);
return studentService.saveStudent(student);
}
@PostMapping("/addStudents")
public List<Student> addStudents(@RequestBody List<Student> students) {
return studentService.saveStudents(students);
}
@GetMapping("/students")
public List<StudentDTO> findAllStudents() {
List<StudentDTO> studentDTOList = new ArrayList<>();
List<Student> studentList = studentService.getStudents();
for (Student student : studentList) {
StudentDTO studentDTO = new StudentDTO(student);
studentDTOList.add(studentDTO);
}
return studentDTOList;
}
@GetMapping("/students/id/{id}")
public Student findStudentById(@PathVariable long id) {
return studentService.getStudentById(id);
}
@GetMapping("/students/firstName/{firstName}")
public Student findStudentByFirstName(@PathVariable String firstName) {
return studentService.getStudentByFirstName(firstName);
}
@PutMapping("/update")
public Student updateStudent(@RequestBody StudentDTO studentDTO) {
Student student = new Student(studentDTO);
return studentService.updateStudent(student);
}
@DeleteMapping("/delete/{id}")
public String deleteStudent(@PathVariable long id) {
return studentService.deleteStudent(id);
}
}
- For
Service
class (Business logic):
- remove
@Component
annotation;- remove
@Transactional
annotation;- use
findById()
to retrieve an entity by itsId
;
import java.util.List;
import java.util.Optional;
import com.example.demo.entity.Student;
import com.example.demo.repository.StudentRepository;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.persistence.EntityNotFoundException;
@Service
public class StudentService {
private final StudentRepository studentRepository;
public StudentService(StudentRepository studentRepository) {
this.studentRepository = studentRepository;
}
public Student saveStudent(Student student) {
return studentRepository.save(student);
}
public List<Student> saveStudents(List<Student> students) {
return studentRepository.saveAll(students);
}
public List<Student> getStudents() {
return studentRepository.findAll();
}
public Student getStudentById(long id) {
return studentRepository.findById(id).orElseThrow(EntityNotFoundException::new);
}
public Student getStudentByFirstName(String firstName) {
return studentRepository.findByFirstName(firstName);
}
public Student getStudentByLastName(String lastName) {
return studentRepository.findByLastName(lastName);
}
public Student getStudentByEmail(String email) {
return studentRepository.findByEmail(email);
}
public Student getStudentByPhone(long phone) {
return studentRepository.findByPhone(phone);
}
public String deleteStudent(long id) {
studentRepository.deleteById(id);
return "Student Deleted";
}
public Student updateStudent(Student student) {
Student existingStudent = studentRepository.getById(student.getId());
existingStudent.setFirstName(student.getFirstName());
existingStudent.setLastName(student.getLastName());
existingStudent.setEmail(student.getEmail());
existingStudent.setPhone(student.getPhone());
existingStudent.setPaymentStatus(student.getPaymentStatus());
return studentRepository.save(existingStudent);
}
}
- The
Model
class:
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import com.example.demo.dto.StudentDTO;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.Builder;
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Entity
public class Student {
public Student(StudentDTO studentDTO) {
this.id = studentDTO.getId();
this.firstName = studentDTO.getFirstName();
this.lastName = studentDTO.getLastName();
this.phone = studentDTO.getPhone();
this.email = studentDTO.getEmail();
this.paymentStatus = studentDTO.getPaymentStatus();
}
public enum Status {
PAID,
UNPAID,
PARTIAL
}
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column
private long id;
private String firstName;
private String lastName;
private long phone;
private String email;
private Status paymentStatus;
}
DTO
class:
import com.example.demo.entity.Student;
import com.fasterxml.jackson.annotation.JsonInclude;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
import static com.fasterxml.jackson.annotation.JsonInclude.Include.NON_NULL;
@Builder
@Data
@NoArgsConstructor
@AllArgsConstructor
@JsonInclude(NON_NULL)
public class StudentDTO implements Serializable {
public StudentDTO(Student student) {
this.id = student.getId();
this.firstName = student.getFirstName();
this.lastName = student.getLastName();
this.phone = student.getPhone();
this.email = student.getEmail();
this.paymentStatus = student.getPaymentStatus();
}
private long id;
private String firstName;
private String lastName;
private long phone;
private String email;
private Student.Status paymentStatus;
}
- The
Repository
class:
import com.example.demo.entity.Student;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface StudentRepository extends JpaRepository<Student, Long> {
Student findByFirstName(String firstName);
Student findByLastName(String lastName);
Student findByEmail(String email);
Student findByPhone(long phone);
}
and the main class of a Spring Boot
application:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
To test it, you can use endpoints by the same principle:
POST: localhost:8080/api/v1/addStudent
POST: localhost:8080/api/v1/addStudents
GET: localhost:8080/api/v1/students
GET: localhost:8080/api/v1/students/id/1
GET: localhost:8080/api/v1/students/firstName/testName
PUT: localhost:8080/api/v1/update
DELETE: localhost:8080/api/v1/delete/1
Upvotes: 2
Reputation: 2396
There are 2 reason behind 404 not found
You main class is in com.BusyQA
package and Controller class is in StudentController
package so you have to scan controller class in main class.
Your StudentApplication.java
class should become:
@SpringBootApplication
@ComponentScan(basePackageClasses = StudentController.class) // Scan the controller class in main class.
public class BusyQaApplication extends SpringBootServletInitializer{
public static void main(String[] args) {
SpringApplication.run(BusyQaApplication.class, args);
}
}
Remove pre path /api/v1
from all url mapping in controller. Now your mapping url should become
@RestController
@RequestMapping("/api/v1")
public class StudentController {
@Autowired
private StudentService studentService;
@PostMapping("/addStudent")
@PostMapping("/addStudents")
@GetMapping("/students")
@GetMapping("/students/{id}")
@GetMapping("/students/{name}")
@PutMapping("/update")
@DeleteMapping("/delete/{id}")
}
This is another mistake in your code:
Remove the @Component
annotation from controller.
Remove the @Component
annotation from Service class.
Remove the @Component
annotation from Repository interface and add @Repository
annotation.
Upvotes: 1
Reputation: 95
As Dilermando mentioned in the comments, your @RequestMapping("/api/v1")
is setting its mapping, then you're extending onto that with @PostMapping("/api/v1/addStudent")
making the address {url}/api/v1/api/v1/addStudent
. You can resolve this by removing the /api/v1 from the Post/get mappings:
@RequestMapping("/api/v1")
public class StudentController {
@Autowired
private StudentService studentService;
@PostMapping("/addStudent")
public Student addStudent(@RequestBody Student student) {
return studentService.saveStudent(student);
}
...etc
}
Upvotes: 1