sinha-shaurya
sinha-shaurya

Reputation: 577

Endpoint overloading in Rest controller

I have a REST Controller in my Spring Boot application as follows:

@RestController
public class StudentController {
    
    @Autowired
    private StudentDao studentDao;

    @GetMapping("/students")
    public List<Student> getAllStudents(){
        return studentDao.getStudent();
    }
    
    @GetMapping("/students")
    public Student getStudent(@RequestParam(name="id") int id){
        return studentDao.getStudent(id);
    }
}

Upon trying to start the application, I get the following error:

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'requestMappingHandlerMapping' defined in class path resource [org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfiguration$EnableWebMvcConfiguration.class]: Invocation of init method failed; nested exception is java.lang.IllegalStateException: Ambiguous mapping. Cannot map 'studentController' method 
com.example.rest.webservice.restwebservice.StudentController#getStudent(int)
to {GET [/students]}: There is already 'studentController' bean met

Upon changing the endpoints(in the getmapping part), this works perfectly. I fail to understand that since it does not recognise one with query param and one without as 2 separate points, then what is the possible fix for this? I am still a beginner so it would be great if someone could help.

hod

Upvotes: 0

Views: 1158

Answers (5)

user10260739
user10260739

Reputation:

Generally in REST API to fetch all students or create a new student we use "/students" endpoint and to get/delete/update a particular Student based on ID we use "/students/{id}" where id can be accessed through @PathVariable.

@GetMapping("/students")
public List<Student> getAllStudents(){
  return studentDao.getStudent();
}
    
@GetMapping("/students/{id}")
public Student getStudent(@PathVariable(name="id") int id){
   return studentDao.getStudent(id);
}

But as per your code, you can do the same by specifying params="id" while fetching a particular student by id.

@GetMapping("/students")
public List<Student> getAllStudents(){
  return studentDao.getStudent();
}
    
@GetMapping(value = "students", params = "id")
public Student getStudent(@RequestParam(name="id") int id){
   return studentDao.getStudent(id);
}

Upvotes: 0

Hassan Liasu
Hassan Liasu

Reputation: 111

In addition, upon starting the application, springboot container tends to register the endpoints in the StudentController, however because you have duplicate routes mapping with the same HttpMethod(@GetMapping("/students")) it resulted to an Ambiguous mapping. Although you can have the same route name if you're using different HttpMethod types.


   @GetMapping("/students")
    public List<Student> getAllStudents(){
        return studentService.getStudent();
    }
    
    @PostMapping("/students")
    public StudentResponse postStudent(@RequestBody StudentDto student){
        return studentService.postStudent(student);
    }

Upvotes: 0

Sergey Afinogenov
Sergey Afinogenov

Reputation: 2212

Use value and params in GetMapping to use overloaded endpoints:

@GetMapping(value = "students")
public List<Student> getAllStudents(){
  return studentDao.getStudent();
}
    
@GetMapping(value = "students", params = {"id"})
public Student getStudent(@RequestParam(name="id") int id){
   return studentDao.getStudent(id);
}

Upvotes: 2

Petr Aleksandrov
Petr Aleksandrov

Reputation: 1514

The value for GetMapping needs to include ID:

@GetMapping("/students/{id}")
public Student getStudent(@RequestParam(name="id") int id){
   return studentDao.getStudent(id);
}

Upvotes: 1

pirho
pirho

Reputation: 12215

Usually in REST when you want a list of all students you make it

@GetMapping("/students")

as you have done.

If you need just one one specific student by id the id is a path variable like:

@GetMapping("/students/{id}")
public Student getStudent(@PathVariable(name="id") int id)

So not exactly overloading.

Check also this

Upvotes: 8

Related Questions