sggnology
하늘속에서IT
sggnology
전체 방문자
오늘
어제
  • 분류 전체보기 (83)
    • Algorithm (31)
      • Programmers (27)
      • Baekjoon (4)
    • WIKI (4)
      • VirtualBox (1)
      • Power Toys (1)
    • NodeJS (4)
      • nvm (1)
      • React (1)
      • Vue (1)
    • Dev Language (3)
      • Java (2)
      • Kotlin (1)
    • Spring Boot (17)
      • Gradle (1)
      • JPA (3)
    • DB (4)
      • MariaDB (3)
      • Redis (0)
    • Android (6)
      • Debug (3)
    • Nginx (3)
      • Debug (1)
    • Intellij (0)
    • Network (1)
    • Git (2)
      • GitHub (2)
    • Chrome Extension (0)
    • ETC (5)
      • Monitoring (2)
    • Linux (1)
      • WSL (1)
    • Visual Studio (1)
    • Side Project (0)

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

인기 글

태그

  • 알고리즘
  • 고득점KIT
  • JPA
  • nginx
  • 오블완
  • DB
  • Android Studio
  • spring boot
  • docker
  • 안드로이드 스튜디오
  • 티스토리챌린지
  • 레벨2
  • 백준
  • kotlin
  • 연습문제
  • 고득점 Kit
  • java
  • 레벨3
  • mariadb
  • 프로그래머스

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
sggnology

하늘속에서IT

[Spring Boot] @ModelAttribute 로 맵핑하려는 대상의 depth 가 2 이상일 때 요청하였는데 오류가 난다면?(feat. kotlin)
Spring Boot

[Spring Boot] @ModelAttribute 로 맵핑하려는 대상의 depth 가 2 이상일 때 요청하였는데 오류가 난다면?(feat. kotlin)

2023. 10. 16. 21:40
728x90

발단

EndPoint 에서 RequestBody 가 아닌 ModelAttribute 를 통해 핸들링할 때 DTO 가 2-depth 가 되며 생긴 문제를 공유하고자 합니다.

 

예시 코드

@RestController
@RequestMapping("")
class TestController {

	@PostMapping("")
    fun hiPost(
        @ModelAttribute body: TestDto,
    ){
			...
    }
}

data class TestDto(
    var name: String = "",
    var testInnerDto: TestInnerDto
)

data class TestInnerDto(
    var age: Int
)

 

오류 발생

 

1차 시도

java.lang.NullPointerException: Parameter specified as non-null is null: method com.test.TestDto.<init>, parameter testInnerDto

요약 : non-null 로 선언한 파라미터가 null 이기 때문에 NullPointerException 발생

즉, TestDto 를 deserialize 하는 과정에서 testInnerDto 의 값이 입력되지 못해 NullPointerException 이 발생하였다.

 

2차 시도 - TestDto.testInnerDto 를 nullable 타입으로 수정

java.lang.NoSuchMethodException: com.test.TestInnerDto.<init>()

요약 : TestInnerDto 의 비어있는 생성자가 없으니 NoSuchMethodException 발생

생성자가 없다고 하는 것을 보니 reflection 을 통해 TestInnerDto 를 구성하려 시도하였지만 비어있는 생성자가 없어 오류가 발생한 듯 보인다.

  • 특수한 경우를 제외하고 Kotlin 의 Data Class 는 기본 생성자를 따로 제공해주지 않습니다.

 


 

해결

 

해결책1

@RestController
@RequestMapping("")
class TestController {
    @PostMapping("")
    fun hiPost(
        @ModelAttribute body: TestDto,
    ){
			...
    }
}

data class TestDto(
    var name: String = "",
    var testInnerDto: TestInnerDto?
)

class TestInnerDto{
    var age: Int = 0

    constructor(){
    }

    constructor(age: Int){
        this.age = age
    }
}
  1. TestDto.testInnerDto 를 nullable type 으로 수정
  2. TestInnerDto 를 Data Class -> Class 일반 클래스로 수정
  3. TestInnerDto 에 대해 비어있는 생성자 구현

 

설명

  • TestDto 의 비어있는 생성자가 없어 발생한 오류에 대한 책임을 TestInnerDto 로 전가
  • TestInnerDto 의 구조를 Data Class -> Class 로 변경하고 deserialize 를 위한 기본 생성자를 생성

 

해결책2

...

data class TestDto(
    var name: String = "",
    var testInnerDto: TestInnerDto = TestInnerDto()
)

...
  1. TestDto.testInnerDto 에 대한 default value 설정

 

설명

  • Kotlin 은 모든 변수가 default value 로 세팅되어 있을 경우 기본 생성자를 제공
  • TestDto Deserialize 과정에서 기본 생성자를 통해 인스턴스 생성하여 사용

 

결론

2-depth 이상을 @ModelAttribute 로써 다루고자 할 때 kotlin 에서는 방법이 위와 같은 방식을 사용해야 합니다.

 

혹여나 제가 모르는 해결책이 있다면 댓글로 링크나 설명부탁드립니다!

728x90

'Spring Boot' 카테고리의 다른 글

[Spring] Custom Enum Value 를 Swagger 문서에 노출시키고 싶으면 어떻게 해야할까?  (0) 2024.05.21
[Spring Boot] Access denied for user 'root'@'localhost'(using password: yes)  (1) 2024.04.24
[Spring Boot] Spring 에서 Redis 를 사용할 때 ConnectionFactory 를 왜 Bean 으로 등록해서 사용해야 할까?(feat. Kotlin, Lettuce, LettuceConnectionFactory was not initialized through afterPropertiesSet())  (0) 2023.06.10
[Spring Boot] custom error page 적용(feat. 예제, ErrorController)  (0) 2023.05.26
[Spring Boot] JWT 라이브러리를 의존성 추가했음에도 빌드 오류가 나는건 왜일까?(feat. `io.jsonwebtoken:jjwt-api`)  (2) 2023.05.25
    'Spring Boot' 카테고리의 다른 글
    • [Spring] Custom Enum Value 를 Swagger 문서에 노출시키고 싶으면 어떻게 해야할까?
    • [Spring Boot] Access denied for user 'root'@'localhost'(using password: yes)
    • [Spring Boot] Spring 에서 Redis 를 사용할 때 ConnectionFactory 를 왜 Bean 으로 등록해서 사용해야 할까?(feat. Kotlin, Lettuce, LettuceConnectionFactory was not initialized through afterPropertiesSet())
    • [Spring Boot] custom error page 적용(feat. 예제, ErrorController)
    sggnology
    sggnology
    하늘은 파란색이니까 내 삶도 파란색이길 ㅎㅎ

    티스토리툴바