Home > OS >  Postman is returning a 404 error on my Spring Boot API
Postman is returning a 404 error on my Spring Boot API

Time:04-08

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.

CodePudding user response:

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
}

CodePudding user response:

Remove global url @RequestMapping("/api/v1") from contoller and add this url in application.properties configuration file like server.servlet.context-path=/api/v1. Remove pre path /api/v1 from all mapping in controller.

application.properties:

server.servlet.context-path=/api/v1

Now your controller should become:

@RestController
public class StudentController {
    
    @Autowired
    private StudentService studentService;
    
    @PostMapping("/addStudent")
    public Student addStudent(@RequestBody Student student) {
    return studentService.saveStudent(student);
    }
    
    @PostMapping("/addStudents")
    public List<Student> addStudents(@RequestBody List<Student> students) {
        return studentService.saveStudents(students);
        }
    @GetMapping("/students")
    public List<Student> findAllStudents(){
        return studentService.getStudents();
    }
    @GetMapping("/students/{id}")
    public Student findStudentById(@PathVariable long id) {
        return studentService.getStudentById(id);
    }
    @GetMapping("/students/{name}")
    public Student findStudentByFirstName(@PathVariable String FirstName) {
        return studentService.getStudentByFirstName(FirstName);
    }
    
    @PutMapping("/update")
    public Student updateStudent(@RequestBody Student student) {
    return studentService.updateStudent(student);
    }
    
    @DeleteMapping("/delete/{id}")
    public String deleteStudent(@PathVariable long id) {
        return studentService.deleteStudent(id);
    }   
}

This is another mistake in your code:

  • Remove the @Component annotation from controller because it is stereotype annotation is used for automatically detect custom beans.

  • Remove the @Component annotation from Service class beacuse @Service annotation is is stereotype annotation but in service layer @Service annotation is mandatory.

  • Remove the @Component annotation from Repository interface and add @Repository annotation beacuse @Repository annotation is is stereotype annotation but in DAO layer @Repository annotation is mandatory.

For futher information about stereotype annotation see here https://www.baeldung.com/spring-component-annotation

  • Related