트러블 슈팅 모음집 - Inssagram-CloneCode/backend_server GitHub Wiki
develop에서 main으로 넘겨 배포 테스트 하는 도중 문제가 생김. (develop에서 main 넘길 때 확인이 되었으나 merge 해버려서 main에서 hotfix)
직접 IDE 열어 확인해보니 클래스가 존재하지 않는 Import 문 발견.
log에 친절히 원인이 나와있어 따로 검색하지 않고 바로 수정으로 들어감.
기존의 코드를 아래와 같이 수정
-
Ctrl + Alt + O 를 눌러 import 문 자동 정리 실행.
-
팀원들에게 `Optimize imports on the fly 옵션 사용 권고.(올바른 방법인진 모르겠지만, 본인은 매번 단축키로 정렬하는 것이 번거로워 설정.)
기본 게시물 작성 메소드 구현 후 앱을 돌렸는데 계속해서 *user_Id**가 비어있다는 에러 메세지를 받았다.
2022-08-24 16:36:33.715 WARN 16508 --- [nio-8080-exec-6] o.h.engine.jdbc.spi.SqlExceptionHelper : SQL Error: 1048, SQLState: 23000
2022-08-24 16:36:33.715 ERROR 16508 --- [nio-8080-exec-6] o.h.engine.jdbc.spi.SqlExceptionHelper : Column 'user_id' cannot be null
2022-08-24 16:36:33.727 ERROR 16508 --- [nio-8080-exec-6] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.dao.DataIntegrityViolationException: could not execute statement; SQL [n/a]; constraint [null]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement] with root cause
java.sql.SQLIntegrityConstraintViolationException: Column 'user_id' cannot be null
디버거를 찍어보았고 @AuthenticationPrincipal 어노테이션을 통해 가져오려고 한 유저의 정보를 제대로 가져오지 못하고 있는 것을 확인했다.
에러를 찾아봤지만 어노테이션이 작동하지 않는 정확한 이유는 알 수 없었다. 팀원 중 한 명은 이전에도 같은 문제를 겪었었다고 한다. 결국 유저 정보를 가지고 있는 tokenProvider를 가져와서 거기서 유저 정보를 뽑아오기로 했다.
문제 2 : AnnotationException: Associations marked as mappedBy must not define database mappings like @JoinTable or @JoinColumn
Image 엔티티를 만든 후 @ManytoOne과 @OnetoMany 어노테이션을 사용해 Image와 Post 에 연관관계를 설정하고 실행을 시켰을 때 난 오류.
Caused by: org.hibernate.AnnotationException: Associations marked as mappedBy must not define database mappings like @JoinTable or @JoinColumn:
나는 @OnetoMany(mappedby="") 와 @JoinColumn 을 Post 엔티티에 같이 사용했다.
하지만 @JoinColumn 은 주인관계 엔티티에서 사용해야 하고, 참조하는 엔티티에서는 mappedby* 를 사용해 관계 정의해줘야 한다.
For read: Difference between joincoulum and mappedby
Post 엔티티에서 @JoinColumn 제거했다.
코드를 썼을 때, Image 엔티티가 post_Id 를 외래키로 가지도록 연관 관계를 설정했다. 그런데 실행을 하고 데이터베이스를 확인하면 Image 엔티티의 post_Id 항목이 null로 떴다.
코드의 순서에 문제가 있었다. 파일을 S3 bucket에 업로드했을 때 Image db에는 열이 생긴다. 하지만 게시물은 Post db에 저장되기 전이었기 때문에 post_Id는 생성되지 않은 상태였고 Image 엔티티에 저장될 id 자체가 없었다.
순서를 바꿔서 게시물을 먼저 저장해주고 그 전에는 만들지 않았던 Image repository를 만들어서 거기에 다시 저장을 해줌으로써 앞에서 post를 저장할 때 생긴 post_id를 가져올 수 있게 했다.
게시글 조회 기능을 실행했는데 proxy 관련 오류가 떴다.
2022-08-25 10:06:35.012 ERROR 11720 --- [nio-8080-exec-2] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.hibernate.LazyInitializationException: could not initialize proxy [com.clonecode.inssagram.domain.User#1] - no Session] with root cause
org.hibernate.LazyInitializationException: could not initialize proxy [com.clonecode.inssagram.domain.User#1] - no Session
at org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:176) ~[hibernate-core-5.6.10.Final.jar:5.6.10.Final]
at org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:322) ~[hibernate-core-5.6.10.Final.jar:5.6.10.Final]
at org.hibernate.proxy.pojo.bytebuddy.ByteBuddyInterceptor.intercept(ByteBuddyInterceptor.java:45) ~[hibernate-core-5.6.10.Final.jar:5.6.10.Final]
at org.hibernate.proxy.ProxyConfiguration$InterceptorDispatcher.intercept(ProxyConfiguration.java:95) ~[hibernate-core-5.6.10.Final.jar:5.6.10.Final]
@OnetoMany 관계에서 fetchType.LAZY로 되어있을 경우, 프록시 객체를 통해 지연 로딩되는 객체를 가져오려고 할 때 이미 세션이 사라져서 발생하는 에러이다. FetchType.EAGER로 바꾸면 해결된다고 했는데 내 경우에는 해결이 되지 않았다. 그리고 좋은 방법도 아니라고 한다.
@Transactional 어노테이션을 게시글 조회 method 위에 추가했다.
Join Fetch 를 사용하는 게 가장 좋은 해결방법이라고 하는데 이 부분은 나중에 찾아보기...
앱 실행을 했을 때 dto를 참조하는 proxy 오류가 났다.
WARN 14236 --- [nio-8080-exec-9] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.http.converter.HttpMessageNotWritableException: Could not write JSON: could not initialize proxy [com.clonecode.inssagram.domain.User#1] - no Session; nested exception is com.fasterxml.jackson.databind.JsonMappingException: could not initialize proxy [com.clonecode.inssagram.domain.User#1] - no Session (through reference chain: com.clonecode.inssagram.dto.response.ResponseDto["data"]->java.util.ArrayList[0]->com.clonecode.inssagram.dto.response.PostAllResponseDto["user"]->com.clonecode.inssagram.domain.User$HibernateProxy$3WV4xhH2["createdAt"])]
Rest API에서 Entity로 리턴하는 값이 있으면 Json parser에 의해서 에러가 발생할 수 있다.
ResponseDto에서 불러오던 엔티티들을 다 dto로 만들어 반환해줬다. 아래처럼 UserProfileDto 생성.
그 후 PostAllResponseDto에서 User 엔티티를 부르던 것을 UserProfileDto 로 변경해줬다.
프론트엔드에서 서버를 불러올 때 사진 이미지들이 뜨지 않고 권한이 없다는 오류가 뜬다.
<Error>
<Code>AccessDenied</Code>
<Message>Access Denied</Message>
<RequestId>2M0MEN0GTBW1E993</RequestId>
<HostId>QTZrLa+/D+M7RpGdTxg1bqpQFhO9i7vmyG9n7dPv8z+dfZkHwuNqIfgb+Wl9EUCDSQaT8nNuO3E=</HostId>
</Error>
S3 bucket의 퍼블릭이 아닌 객체에 익명의 요청이 온다면 해당 오류가 난다.
버켓에서 Permissions 설정을 바꿔줬다.
먼저 'Block public access' 세팅을 꺼서 모든 파일이 퍼블릭 엑세스가 가능하도록 바꿔주었다.
그리고 익명의 사용자가 사진을 읽을 수 있도록 버킷 정책을 추가했다.
To check other bucket policies : Bucket policy example
게시글이 없을 때는 마이페이지 조회 시 문제가 없는데, 게시글을 등록하면 마이페이지 조회 시 NullPointerException 발생.
Post의 heartNum을 다 더해서 totalHeartNum을 구하는데, hearNum 값을 초기화하지 않아서 null 값임.
null 값을 sum하려고 하니까 totalHeartsByUser에서 문제가 생기고, NullPointerException이 발생함.
기존의 코드를 아래와 같이 수정
Post post = new Post(user, requestDto, 0L);
Post 생성할 때 heartNum을 0L로 초기화.