Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

"status": 404 Error for POST Request in in Spring Boot CRUD

I developed Spring Boot CRUD application. The database I have connected is PostgreSQL. @GetMapping is working properly and an empty array of objects can be retrieved by the GET request. But in @PostMapping, the POST request gives a 404 error.

📌SpringRecapApplication.java

package com.example.SpringRecap;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
@SpringBootApplication(exclude = SecurityAutoConfiguration.class)
//@RequestMapping("api/v1/customers")
//@EnableWebMvc
@RequestMapping(name = "api/v1/customers" ,method = RequestMethod.POST)

public class SpringRecapApplication {
    //dependency injection
    private static  CustomerRepository customerRepository;

    public SpringRecapApplication(CustomerRepository customerRepository) {
        this.customerRepository = customerRepository;
    }


    public static void main(String[] args) {
        SpringApplication.run(SpringRecapApplication.class, args);
    }

    @GetMapping
    public List<Customer> getCustomer() {

        return customerRepository.findAll();

    }

    record NewCustomerRequest(
            String name,
            String email,
            Integer age
    ) {
        @PostMapping
        public void addCustomer(@RequestBody NewCustomerRequest newCustomerRequest) {
            Customer customer = new Customer();
            customer.setAge(newCustomerRequest.age());
            customer.setName(newCustomerRequest.name());
            customer.setEmail(newCustomerRequest.email());
            customerRepository.save(customer);
        }
    }

}

customerRepository.save(customer); doesn’t allow to make the dependency injection final. ( private static CustomerRepository customerRepository;). IDEA suggests making it static. But it didn’t work. When I was using @RequestMapping("api/v1/customers"), a 405 error was received. Then I fixed that issue by doing as below,

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

 @RequestMapping(name = "api/v1/customers" ,method = RequestMethod.POST)

📌CustomerRepository.java

package com.example.SpringRecap;

import org.springframework.data.jpa.repository.JpaRepository;

public interface CustomerRepository extends JpaRepository<Customer,Integer> {
}

📌Customer.java

package com.example.SpringRecap;

import jakarta.persistence.*;

import java.util.Objects;

@Entity
public class Customer {
    @Id
    @SequenceGenerator(
            name = "customer_id_sequence",
            sequenceName = "customer_id_sequence",
            allocationSize = 1

    )
    @GeneratedValue(
            strategy = GenerationType.SEQUENCE,
            generator = "customer_id_sequence"

    )
    private Integer id;
    private String name;
    private String email;
    private Integer age;

    public Customer(Integer id, String name, String email, Integer age) {
        this.id = id;
        this.name = name;
        this.email = email;
        this.age = age;
    }

    public Customer() {

    }


    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Customer customer = (Customer) o;
        return Objects.equals(id, customer.id) && Objects.equals(name, customer.name) && Objects.equals(email, customer.email) && Objects.equals(age, customer.age);
    }

    @Override
    public int hashCode() {
        return Objects.hash(id, name, email, age);
    }

    @Override
    public String toString() {
        return "Customer{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", email='" + email + '\'' +
                ", age=" + age +
                '}';
    }
}

Postman:

Postman image

Please put a comment if further information is needed to get the solution.

>Solution :

The problem with your code is that you specified the POST endpoint as part of your DTO and not as part of your controller. As your DTO is not a Spring managed bean, Spring won’t map the URL to your endpoint. Anyways, you should move your endpoints into a seperate class. Example:

@RestController
@RequestMapping("api/v1/customers")
public class CustomerController {

    private final CustomerRepository customerRepository;

    public SpringRecapApplication(CustomerRepository customerRepository) {
        this.customerRepository = customerRepository;
    }

    @GetMapping
    public List<Customer> getCustomer() {
        return customerRepository.findAll();
    }
    
    @PostMapping
    public void addCustomer(@RequestBody NewCustomerRequest newCustomerRequest) {
        Customer customer = new Customer();
        customer.setAge(newCustomerRequest.age());
        customer.setName(newCustomerRequest.name());
        customer.setEmail(newCustomerRequest.email());
        customerRepository.save(customer);
    }

    // Helper classes

    record NewCustomerRequest(String name, String email, Integer age) { }

}

It would be best if you moved your DTO in a seperate class as well. I recommend placing the DTOs in a dto package and your controllers in a controller package.

Two side notes: you shouldn’t expose your entities via your API. You should use DTOs for incoming and outgoing data. Check out lombok and mapstruct, they make this pretty easy.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading