안녕하세요. 다메카솔입니다. 🐿️

개발중에 발생한 에러를 예방하기위해 원인과 해결방법을 정리해보았습니다.

발생 배경

API에 Request를 보낼때, 서버에서 다음과 같은 에러가 발생하였습니다.

오류 메시지

Cannot construct instance of `class` (no Creators, like default constructor, exist): cannot deserialize from Object value (no delegate- or property-based Creator))

원인

위 에러는  주로 Jackson 또는 다른 JSON 라이브러리를 사용하여 JSON 데이터를 해당 클래스의 객체로 변환하는 중에 발생합니다. 이러한 라이브러리들은 클래스를 직렬화하거나 역직렬화할 때 기본 생성자 (default constructor) 또는 특정 생성자를 사용하는데, 클래스에 기본 생성자가 없거나 또는 라이브러리가 사용할 수 있는 생성자가 없을 때 발생합니다.

블록을 조립한 레고 이미지

 

직렬화와 역직렬화에 대해 더 궁금하시다면 아래 글도 함께 읽기 좋습니다.

https://damecasol.tistory.com/33

 

[Java]Serializable 직렬화

가끔 인터페이스를 보다보면 Serializable 이란 인터페이스를 상속한 클래스를 볼 수 있었다. 검색해봤을땐 직렬화를 가능하게 해주는 인터페이스고, 그렇게 하여 파일이나과 인터넷으로 객체를

damecasol.tistory.com

 

해결방법

  • 기본생성자 추가

클래스에 기본 생성자를 추가합니다.. 기본 생성자란 매개변수를 가지지 않는 생성자입니다.

public class YourClass {
    public YourClass() {
        // 기본 생성자 내용
    }
}
  • 매개변수가 있는 생성자의 존재

클래스에 매개변수가 있는 생성자가 있는 경우, 해당 생성자도 정의되어 있는지 확인합니다. 만약 라이브러리가 특정 생성자를 필요로 하는데 그 생성자가 없다면 이 오류가 발생할 수 있습니다.

public class YourClass {
    public YourClass(String param1, int param2) {
        // 매개변수가 있는 생성자 내용
    }
}
  • @JsonCreator 어노테이션 사용

만약 여러 생성자가 있는 경우, Jackson 라이브러리에서 사용할 생성자를 명시하기 위해 @JsonCreator 어노테이션을 사용할 수 있습니다.

public class YourClass {
    private String param1;
    private int param2;

    @JsonCreator
    public YourClass(@JsonProperty("param1") String param1, @JsonProperty("param2") int param2) {
        this.param1 = param1;
        this.param2 = param2;
    }
}

참조

https://fasterxml.github.io/jackson-databind/javadoc/2.13/com/fasterxml/jackson/databind/ObjectMapper.html

 

ObjectMapper (jackson-databind 2.13.0 API)

Convenience method for doing two-step conversion from given value, into instance of given value type, by writing value into temporary buffer and reading from the buffer into specified target type. This method is functionally similar to first serializing gi

fasterxml.github.io

 

문의 사항이나 도움이 필요하신 분은 댓글 달아주세요!

'IT > JAVA' 카테고리의 다른 글

[Mybatis] CDATA 란?  (0) 2023.03.15
[Java]Serializable 직렬화  (0) 2022.06.12

자바로 애플리케이션 개발을 할 때 자주 사용하는 Mybatis와 CDATA에 대해 알아봅시다.

MyBatis란?

MyBatis는 SQL Mapper Framework 중 하나로, 자바 객체와 SQL문 사이의 자동 매핑을 지원합니다. 데이터베이스의 CRUD(Create, Read, Update, Delete) 작업을 간편하게 처리할 수 있도록 도와줍니다.

CDATA 태그란?

CDATA 태그는 XML 문서 안에 특수 문자를 포함시킬 때 사용됩니다. 특수 문자를 그대로 출력하게 해주는 역할을 합니다.

MyBatis에서 CDATA 태그 사용하기

MyBatis에서 SQL문을 작성할 때, 문자열 안에 특수 문자가 포함될 경우 문제가 발생할 수 있습니다. 이런 경우에 CDATA 태그를 사용하여 특수 문자를 그대로 출력할 수 있습니다.

예시

xmlCopy code

<select id="selectUserByName" parameterType="java.lang.String" resultType="User">
	SELECT * FROM users WHERE name = <![CDATA[#{name}]]> 
</select>


CDATA 태그를 사용하면 SQL문 안에서 작은 괄호(<, >)나 & 같은 특수 문자들이 자동으로 이스케이핑되지 않으므로, SQL문 작성 시 편리하게 사용할 수 있습니다.

MyBatis에서 CDATA 태그 사용 시 주의할 점

하지만 CDATA 태그를 사용할 때 주의할 점이 있습니다. 예를 들어, SQL문 안에 ]]> 문자열이 포함된 경우에는 CDATA 태그를 닫는 문자열과 혼동이 발생할 수 있습니다. 이런 경우에는 ]]>]]&gt;와 같이 문자열을 변경해 주어야 합니다.

공식문서

MyBatis 공식문서: https://mybatis.org/mybatis-3/ko/index.html

 

MyBatis – 마이바티스 3 | 소개

마이바티스는 무엇인가? 마이바티스는 개발자가 지정한 SQL, 저장프로시저 그리고 몇가지 고급 매핑을 지원하는 퍼시스턴스 프레임워크이다. 마이바티스는 JDBC로 처리하는 상당부분의 코드와

mybatis.org

XML 이스케이핑(MyBatis 공식문서): https://mybatis.org/mybatis-3/sqlmap-xml.html#XML_Escaping

 

mybatis – MyBatis 3 | Mapper XML Files

Mapper XML Files The true power of MyBatis is in the Mapped Statements. This is where the magic happens. For all of their power, the Mapper XML files are relatively simple. Certainly if you were to compare them to the equivalent JDBC code, you would immedi

mybatis.org

참고자료

MyBatis - SQL Mapper Framework: https://github.com/mybatis/mybatis-3

 

GitHub - mybatis/mybatis-3: MyBatis SQL mapper framework for Java

MyBatis SQL mapper framework for Java. Contribute to mybatis/mybatis-3 development by creating an account on GitHub.

github.com

CDATA Section (MDN Web Docs): https://developer.mozilla.org/ko/docs/Web/XML/CDATA

 

'IT > JAVA' 카테고리의 다른 글

[Java] Cannot construct instance of `class`  (1) 2023.11.18
[Java]Serializable 직렬화  (0) 2022.06.12

가끔 인터페이스를 보다보면 Serializable 이란 인터페이스를 상속한 클래스를 볼 수 있었다.

검색해봤을땐 직렬화를 가능하게 해주는 인터페이스고, 그렇게 하여 파일이나과 인터넷으로 객체를 저장할 수 있다는 설명을 보았는데, 의문점이 모두 해결이 안되서 조금 더 찾아보았다.

Serializable(직렬화)란?

객체를 직렬화 한다는 것은 객체의 상태바이트스트림으로 변환한다는 의미이다.

그럼으로써 바이트 스트림은 객체의 복사본으로 재변환될 수 있다.

 

Serialization & Deserialization in Java diagram

 

쓰임

바이트 스트림은 데이터를 송수신하거나 파일에 저장하는데 사용한다.

따라서 직렬화는 객체를 파일에 저장하거나(File.java, ObjectInputStream.java), 인터넷에 정보를 보내거나(URI.class), 데이터베이스에 저장할 떄(Hibernate, JPA, EJB)등에 사용하게 된다.

실제로 자바에서 Serializable 인터페이스를 구현한 클래스들을 찾아보면 확인할 수 있다.

 

file.java in IntelliJ Search

 

URI.java in IntelliJ Search

hibernate-mapping-3.0 dtd in IntelliJ Search

Use of Serialized Object

 

SeriaVersionUID

직렬화 실행은 각각의 직렬화 클래스의 SeriaVersionUID 라고 불리는 버전 번호와 연관되어 있다.

신뢰성을 위해 직렬화와 역직렬화 후 SeriaVersionUID를 비교하는데 이때 불일치하게되면 InvalidClassException이 발생하게 된다.

serialVersionUid는 static, final, Long으로 선언해야 한다.

ANY-ACCESS-MODIFIER static final long serialVersionUID = 42L;

명시적으로 SeriaVersionUID을 선언하지 않으면 기본값이 생성되긴 하지만, 이는 다양한 컴파일러구현체에 민감하게 영향을 받기 때문에, 직접 명시적으로 선언할 것을 강하게 권장하고 있다.

If a serializable class does not explicitly declare a serialVersionUID, then the serialization runtime will calculate a default serialVersionUID value for that class based on various aspects of the class, as described in the Java(TM) Object Serialization Specification. However, it is strongly recommended that all serializable classes explicitly declare serialVersionUID values, since the default serialVersionUID computation is highly sensitive to class details that may vary depending on compiler implementations, and can thus result in unexpected InvalidClassExceptions during deserialization.

 

참고

 

 

'IT > JAVA' 카테고리의 다른 글

[Java] Cannot construct instance of `class`  (1) 2023.11.18
[Mybatis] CDATA 란?  (0) 2023.03.15

+ Recent posts