소프트웨어 마에스트로에서 "온라인 강의 큐레이션 서비스 - curady"를 개발하며 생긴 일
{
"requestTendencies": [
{
"tendencyType": "language",
"tendencyName": "java"
},
{
"tendencyType": "language",
"tendencyName": "python"
}
],
"nickname": "string",
"gitUrl": "string",
"blogUrl": "string",
"description": "string"
}
로직에 문제가 없고 테스트 해봤을 때 잘 동작했기 때문에 머지 리퀘스트를 올렸고,
팀원도 approve해줘서 배포에 반영이 되었다.
근데 프론트엔드 팀원이 500 server erroor가 뜨니 확인해달라고 한다...
도대체 뭐가 문제일지 모르겠어서 머리가 아팠는데..
팀원이 나와 같은 테스트데이터로 요청을 날리고 있었고
진짜 바보같고 내가 한심했지만, 이것 또한 경험이지 않을까....라고 생각하며
unique column에 대한 예외를 핸들링해주기로 했다 !!
java.sql.SQLIntegrityConstraintViolationException: (conn=591) Duplicate entry 'string' for key 'UK_s0axwawn9qd2tpt1v8alx9o0v'
at org.mariadb.jdbc.export.ExceptionFactory.createException(ExceptionFactory.java:288) ~[mariadb-java-client-3.0.6.jar:na]
at org.mariadb.jdbc.export.ExceptionFactory.create(ExceptionFactory.java:368) ~[mariadb-java-client-3.0.6.jar:na]
at org.mariadb.jdbc.message.ClientMessage.readPacket(ClientMessage.java:137) ~[mariadb-java-client-3.0.6.jar:na]
at org.mariadb.jdbc.client.impl.StandardClient.readPacket(StandardClient.java:824) ~[mariadb-java-client-3.0.6.jar:na]
at org.mariadb.jdbc.client.impl.StandardClient.readResults(StandardClient.java:763) ~[mariadb-java-client-3.0.6.jar:na]
at org.mariadb.jdbc.client.impl.StandardClient.readResponse(StandardClient.java:682) ~[mariadb-java-client-3.0.6.jar:na]
at org.mariadb.jdbc.client.impl.StandardClient.execute(StandardClient.java:625) ~[mariadb-java-client-3.0.6.jar:na]
SQLIntegrityConstraintViolationException이 발생했다.
그래서 tryCatch 구문으로 구현했다.
나에게 왜 이런 시련을.....
하지만 곧 바로 SODD(Stack Overflow Driven Development)를 통해 해결할 수 있었다.
DataIntegrityViolationException
이라는 생전 처음보는 Exception으로 처리하니까 잘 catch되었다..
그래서 다시 한 번 잘 살펴보니, 위에 에러 구문 바로 위에 이런게 있었다.
2022-10-07 02:48:29.120 ERROR 91412 — [o-auto-1-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.springframework.dao.DataIntegrityViolationException: could not execute statement; SQL [n/a]; constraint [UK_n4swgcf30j6bmtb4l4cjryuym]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement] with root cause
Spring 초보로서 내린 결론은 다음과 같다.
스프링 내부의 dispatcherServlet에서 내가 잡고싶은 예외인 SQLIntegrityConstraintViolationException
를 먼저 잡은 뒤DataIntegrityViolationException
으로 던져주는게 아닐까?
spring bean으로 관리되고 있는 Servlet 인터페이스를 통해
dispatcherServlet을 찾을 수 있었다.
이렇게 handlerExceptionResolver를 리스트로 관리하고 있었고,
initHandlerExceptionResolvers() 에서 빈으로 등록된 HandlerExceptionResolver를 리스트에 추가한다.
그리고 processHandlerException() 에서 리스트를 돌면서 resolve한다.
이런 흐름이라면
리스트를 직접 확인하기 위해 디버깅을 시도했지만, 이걸 계속 하다가는 눈알이 빠질 것 같아서 잠시 보류한다. 좀 더 공부를해서 돌아오겠다.
별거 아니라고 생각했던 unique key로부터 시작해서 spring의 dispatcher servlet도 까보고 아주 조금이지만 동작도 이해해볼 수 있었다.