본문 바로가기

Kotlin/Spring

(Spring) BeanCreationException : Ambiguous mapping. Cannot map 'todoController' method 해결 방법

웹을 기획하고 Api를 작성하고 DTO 및 컨트롤러를 작성하고 실행하는 도중에 해당 애러가 발생했다

2024-05-14T21:03:55.435+09:00 ERROR 45937 --- [mytodo] [           main] o.s.boot.SpringApplication               : Application run failed

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]: Ambiguous mapping. Cannot map 'todoController' method

 

해당 애러 내용을 읽어보니 Ambiguous mapping. Cannot map 'todoController' method 이라는 것이다 즉 애메모호한 맵핑이 되었다고 한다

 

일단 이 상황의 가장 큰 경우는 각 맵핑이 겹쳤는지 확인을 했다

    @PostMapping("/signUp")
    fun signUp(@RequestBody membershipRequestDto: MembershipRequestDto): UserResponseDto {
        TODO()
    }

    @PostMapping("/login")
    fun login(@RequestBody loginRequestDto: LoginRequestDto): UserResponseDto {
        TODO()
    }

    @PutMapping("/{user_id}/profile")
    fun updateUserProfile(
        @PathVariable("user_id") userId: Long,
        @RequestBody membershipUpdateRequestDto: MembershipUpdateRequestDto): UserResponseDto {
        TODO()
    }

    @PutMapping("/{correction_id}/{user_id}/profile")
    fun updateAdminUserProfile(
        @PathVariable("correction_id") correctionId: Long,
        @PathVariable("user_id") userId: Long,
        @RequestBody membershipUpdateAdminRequestDto: MembershipUpdateAdminRequestDto
    ): UserResponseDto {
        TODO()
    }

    @PostMapping("/logout")
    fun logout(){
        TODO()
    }

    @DeleteMapping("/{correction_id}/{user_id}/profile")
    fun deleteAdminUserProfile(
        @PathVariable("correction_id") correctionId: Long,
        @PathVariable("user_id") userId: Long,
    ){
        TODO()
    }
    
    //////////////////////////////////////////////
    
    @PostMapping
    fun createComment(
        @PathVariable("todo_id") todoId: Long,
        @RequestBody commentCreateRequestDto: CommentCreateRequestDto)
    :CommentResponseDto{
        TODO()
    }

    @GetMapping
    fun getAllComments(@PathVariable("todo_id") todoId: Long)
    :List<CommentResponseDto>{
        TODO()
    }

    @PutMapping("/{comment_id}")
    fun updateComment(
        @PathVariable("todo_id") todoId: Long,
        @PathVariable("comment_id") commentId: Long,
        @RequestBody commentUpdateRequestDto: CommentUpdateRequestDto
    ):CommentResponseDto{
        TODO()
    }

    @DeleteMapping("/{comment_id}")
    fun deleteComment(
        @PathVariable("todo_id") todoId: Long,
        @PathVariable("comment_id") commentId: Long,
        ){
        TODO()
    }
    
    /////////////////////////////////////
    
        @GetMapping("/{todo_id}")
    fun getTodoById(@PathVariable("todo_id") todoId: Long):TodoResponseDto {
        TODO()
    }

    @GetMapping
    fun getTodoList(): List<TodoResponseDto> {
        TODO()
    }

    @GetMapping("/day")
    fun getTodayToDoList(): List<TodoResponseDto> {
        TODO()
    }

    @PostMapping
    fun createTodo(
        @RequestBody todoCreateRequestDto: TodoCreateRequestDto)
    :TodoResponseDto {
        TODO()
    }

    @PutMapping("/{todo_id}")
    fun updateTodoById(
        @PathVariable("todo_id") todoId: Long,
        @RequestBody todoUpdateRequestDto: TodoUpdateRequestDto):TodoResponseDto {
        TODO()
    }

    @DeleteMapping("/{todo_id}")
    fun deleteTodoById(@PathVariable("todo_id") todoId: Long) {
        TODO()
    }

 

일단 애러 내용이 모호한 맵핑이고 따로 위치가 주어진 것도 아니어서 우선 Controller에서 맵핑이 어떻게 되어있는지 확인했는데 딱히 안보였다

 

그러면 클래스에 RequestMapping이 겹쳐서 이런 식으로 된건가?? 싶어서 그 쪽을 한번 봤는데 

 

@RestController
@RequestMapping("/todo")
class TodoController {

@RestController
@RequestMapping("/todo/{todo_id}")
class CommentController {

 

이 부분이 보이는 건데 따로 겹치는 게 안보였는데 이게 보였다

 @GetMapping
    fun getAllComments(@PathVariable("todo_id") todoId: Long)
    :List<CommentResponseDto>{
        TODO()
    }
    
    
   @GetMapping("/{todo_id}")
    fun getTodoById(@PathVariable("todo_id") todoId: Long):TodoResponseDto {
        TODO()
    }

 

얘네 둘이 상위 맵핑을 합치면 겹치는 것을 확인할 수 있었다 그리고 API 설계도를 보니 이런 부분을 제대로 파악하지 않고 설계한 것이 보였다

 

  • 해결
    • CommentController 부분에 /Comment라고 맵핑을 추가 해줬다
    • API 설계도를 다시 수정해줬다

위 대로 하니까 역시나 제대로 작동했다

 

  • 결론
    • 사실 이번 문제는 코드를 잘못 짠 부분 보다는 API를 설계하는 부분에서 맵핑이 겹칠 것을 고려하지 않고 설계하였기 때문에 추후에 API를 설계할 때 해당 부분도 고려를 하면서 설계를 하는 것이 좋다고 생각이 들었다