일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- Kakao
- 자바파이썬
- #스파르타코딩클럽후기 #내일배움캠프후기
- terminate
- Morphological analysis #Corpus
- expression statement is not assignment or call html
- github
- 플젝후체크
- PID
- 카우치코딩 #couchcoding #6주포트폴리오 #6주협업프로젝트v
- 모바일웹스킨
- 서버사이드렌더링
- 비동기
- 카우치코딩 #couchcoding #6주포트폴리오 #6주협업프로젝트
- Anaconda
- gitbash
- 필사
- Machine Learning
- 파이콘
- address
- 코딩온라인
- 파이썬
- 출처: 자바의 신 8장
- taskkill
- khaiii
- SSR
- 마크다운
- github markdown
- 클라이언트사이드렌더링
- Technical Writing
- Today
- Total
개발 일기
스프링부트 Posting 통신에러 해결 - Deserialize error, 400, 500, 200 에러 본문
스프링부트 Posting 통신에러 해결 - Deserialize error, 400, 500, 200 에러
flow123 2021. 12. 1. 23:53첫 에러메시지
2021-12-01 17:19:04.925 WARN 28048 --- [nio-8080-exec-9] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Cannot deserialize value of type `java.lang.String` from Array value (token `JsonToken.START_ARRAY`); nested exception is com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot deserialize value of type `java.lang.String` from Array value (token `JsonToken.START_ARRAY`)<LF> at [Source: (PushbackInputStream); line: 1, column: 45] (through reference chain: com.example.thebestmeal_test.dto.PostDto["postingCat"])]
(2) 형변환 일치
Posting Emo는 [] 배열에 넘어왔기 때문에, List<String>으로 받아야한다.
@Getter
@Setter
public class PostDto {
private String postingFoodName;
private List<String> postingEmo;
private List<String> postingCat;
private String foodImgUrl;
private String postingMemo;
}
원래 regex split 을 쓰려고 했는데, String이 들어가야 해서 List 가 아닌 String 형을 썼었다.
알고보니, 내가 코드 형변환을 잘못 이해하고 있었다.
(1) split들어간 regex코드 삭제해야함
나는 애초에 btn_val =[]로 받아왔기 때문에 array, 리스트로 보냈다.
다시보니, 해당 예제는 String으로 받았기 때문에, 구분자로 regex 를 써서, 다시 List 로 형변환을 해야했다.
반면, 내 코드는 애초에 [] 빈칸에 배열을 받기 때문에, 변환코드를 쓸 필요가 없다!
해당 코드를 삭제하고,
List<String> items1 = Arrays.asList(postDto.getPostingTag().split("\\s*,\\s*"));
items1을 postDto.getPostingTag로 바로 넣어주면 된다.
#
서버와 프론트간의 데이터 불일치 확인하는 법.
(1)400 에러가 났다.
위의 api 에 값을 넘겨줄 때, 값이 잘 매핑이 안되서 나는 에러는 400 코드로 표시된다.
-Dto의 key값과, 프론트js의 ajax에서 보내주는 key 값이 일치하지 않았을 때,
이를 확인할 수 있는 법은 (1) 콘솔에서 브레이크 포인트를 찍어서 js 를 날리면, 아래에 객체속성을 확인할 수 있다.
(2) 프론트 단에서는 콘솔 -> 네트워크 -> post ->
(2) 500에러
값은 매핑이 되어서 로직은 잘 탔음. 그런데 Api 에는 진입을 했는데. Unique result가 아니라는 에러가 나옴
이건 Internal server error 임. 이 코드에서 멈춰서 해결이 안되었다. food 객체에서 문제가 있다는 것(즉 food 가 중복되고 있다는 뜻이다) 알고보니 아래 food 2가 고유값이어야 하는데, (getPostingFoodName)을 기준으로 찾아오니까. 여러값을 찾아서 서버가 이게 뭐지? 하고 혼란스러워하고 있다.
Foodfood=newFood(postDto);
Food food2 = foodRepository.findByName(postDto.getPostingFoodName());
(3)
*200에러는 아직 해결중이다.
200에러: 서버는 제대로 도는 데, 프론트에서 뭔가 로직에 이상이 있어서 로딩이 안되는 듯.
200이 에러 -> API 는 정상이다라는 뜻이다.
(5) 이럴 때 알아보는 법. Food 에 브레이크 포인트 찍고 영속성 확인..
브레이크 포인트 찍고, save(posting 요청 눌러지느 전송 버튼) 누르면 postDto 객체 내부에 컬럼들이 나옴
front 와 서버단의 객체 데이터가 일치한다. Payload로 보면 console.log를 일일이 안찍어도 되서 편하다.
#
Db에서 직접 조회.
query console확인하는 법. 이걸로 SQL Select 문을 날려보면 실제로 중복 데이터가 있는지 확인할 수 있다.
당연히 중복데이터가 없을 것이라고 확신했는데 알고보니 js 쿼리를 여러번 날리면서 여러번 저장되었다 ㅜ.ㅜ
쉽게 확신하지 말고 DB 뜯어보자.
PostController 의 핵심 기능은 repository 에 음식 정보를 save하는 것이다. 그러니 data에 어떤 변화가 일어나는지 감지해야한다. 나는 프론트단에서 통신이 되지 않으니, 당연히 db가 넘어가지도 않을 것이라고 생각했다.
-> 추측하는 게 아니라 확인하고 다음스텝 확인.
아래 쿼리는 FOODNAME 기준으로 테이블에 존재하는 지 확인하는 SQL 문이다.
select food0_.id as id1_1_, food0_.created_at as created_2_1_, food0_.modified_at as modified3_1_, food0_.image_url as image_ur4_1_, food0_.name as name5_1_ from food food0_ where food0_.name='호박삼겹살'
그렇기 때문에, UI 없이 postman/arc 로 API통신을 하는 것이 중요하다. Postman으로 확인하는 것은 console로 찍는 것, payload 로 보는거랑 똑같다. 프론트와 백엔드가 같이 있으면 뭐가 잘못됐는지 확인하기가 더 복잡하다. 디버깅은 프로젝트 경험이 쌓이면서 느는데, 지금은 디버깅 실력이 높지 않으니, 최대한 잘게 쪼개서 해결해야해. #이것보다 더 가벼운 것: testcode 만들기가 있는데 다음에 시도해보자.
참고로 로그인 데이터도 (token 이 있는) postman 통신이 가능하다. headers 에 token 옵션을 넣어준다면!
최초 코드
@PostMapping("/post")
public void postFood(@RequestBody PostDto postDto, @AuthenticationPrincipal UserDetailsImpl userDetails) {
User user = userRepository.findByUsername(userDetails.getUsername()).orElseThrow(
() -> new NullPointerException("그런 사람 없는데요?")
);
//food
Food food = new Food(postDto);
foodRepository.save(food);
//category
List<String> items1 = Arrays.asList(postDto.getPostingTag().split("\\s*,\\s*"));
List<Tag> tags1 = items1.stream().map(tag -> new Tag(food, tag, "emotion")).collect(Collectors.toList());
tagRepository.saveAll(tags1);
//emotion
List<String> items2 = Arrays.asList(postDto.getPostingCat().split("\\s*,\\s*"));
List<Tag> tags2 = items2.stream().map(tag -> new Tag(food, tag, "category")).collect(Collectors.toList());
tagRepository.saveAll(tags2);
//posting 저장 (foodId, userId, post 내용 저장)
Food food2 = foodRepository.findByName(postDto.getPostingFoodName());
Posting posting = new Posting(postDto, user, food2);
postingRepository.save(posting);
}
}
최종코드
@PostMapping("/post")
public void postFood(@RequestBody PostDto postDto, @AuthenticationPrincipal UserDetailsImpl userDetails) {
User user = userRepository.findByUsername(userDetails.getUsername()).orElseThrow(
() -> new NullPointerException("그런 사람 없는데요?")
);
//food
Food food = new Food(postDto);
foodRepository.save(food);
//category
List<Tag> tags1 = postDto.getPostingEmo().stream().map(tag -> new Tag(food, tag, "emotion")).collect(Collectors.toList());
tagRepository.saveAll(tags1);
//emotion
List<Tag> tags2 = postDto.getPostingCat().stream().map(tag -> new Tag(food, tag, "category")).collect(Collectors.toList());
tagRepository.saveAll(tags2);
//posting 저장 (foodId, userId, post 내용 저장)
Food food2 = foodRepository.findByName(postDto.getPostingFoodName());
Posting posting = new Posting(postDto, user, food2);
postingRepository.save(posting);
}
}
#
이미 있는 호박죽 데이터를 보내면 500에러가 뜬다.
DB에는 저장이 되는데, getPostingFoodname 을넣어서 food2에 foodid 를 받아올 떄, 중복값이라서 500에러가 생긴다.
새로 데이터를 보내면 통신성공이다!
'Java&Spring > Project' 카테고리의 다른 글
[Editor -> File Type ] 인텔리제이에서 특정 클래스가 인식 되지 않을 때 (0) | 2022.07.08 |
---|---|
스프링 프로젝트 최종 회고록 (0) | 2021.12.31 |
UserApiController -> 서비스 분리 (0) | 2021.12.15 |
S3 에 파일 업로드 (0) | 2021.12.06 |