작성
·
353
·
수정됨
0
[질문 템플릿]
1. 강의 내용과 관련된 질문인가요? (예)
2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예)
3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예)
[질문 내용]
강의 잘 듣고 있습니다! 학습을 위해 예제 코드를 조금 응용해서 TODO 앱를 만들어보고 있는데 의도한 기능대로 작동이 안 됩니다. 강의 내용과는 조금 방향이 다르지만 BindingResult
관련 질문이기도 하고 하루종일 해봐도 모르겠어서 질문 올립니다.
강의 예제의 [회원 가입] 폼에서 이름을 비워두고 제출한 경우 @Valid
검증 오류가 발생 하여 return "members/createMemberForm"
되고, View에서 <p th:if="${#fields.hasErrors('name')}" th:errors="*{name}"><p>
가 삽입되면서 MemberForm
의 @NotEmpty
에러 메세지가 출력되는 기능을 조금 바꿔서 해 수정 기능에 적용해 보려고 했습니다.
의도한 기능은 이렇습니다. (코드는 밑에 있습니다)
할 일(task) 수정을 누르면 @GetMapping("/tasks/{taskId}/edit")
와 매핑된 메서드가 전달된 파라미터의 taskId
로 할일 객체를 찾아 TaskForm
(할일 Form 객체)에 값을 세팅합니다. 그리고 이 TaskForm
객체를 Model
에 "form"이라는 이름으로 값을 담아 전달합니다.
View(할일 수정 폼)에서 수정하고자 하는 할일의 현재 name
값, priority
값를 보여줍니다. (수정을 위해 현재 값을 표시해줌)
수정 폼을 채우고 제출을 누르면 @PostMapping("/tasks/{taskId}/edit")
에 매핑됩니다. 만약 검증에 오류가 있는 경우 return "task/editTaskForm";
를 합니다. 즉 editTaskForm.html
문서를 엽니다.
문제 상황 :
그런데 editTaskForm.html
파싱에 실패합니다. 해당 Task의 현재 값을 미리보기 해주려면 ${form.name}
을 참고해야 하는데 form
이 넘어가지 않아서 인 것 같습니다. 그래서 @SessionAttributes("form")
로 세션에 저장해주었습니다(스프링 2.7입니다).
2. 이제 파싱은 되고 해당 Task의 현재 값 미리보기도 됩니다. 그런데 여전히 <p>
태그가 생성되지 않아서 오류 메세지도 출력이 안 됩니다. BindingResult
가 날아간 것 같습니다.
3.방법을 바꿔서 View를 바로 여는 게 아니라 @GetMapping
으로 리다이렉트를 해보았는데 역시 Model
이 초기화되면서 BindingResult
가 날아가는 것 같습니다 ㅠㅠ
검색해보니 RedirectAttributes
를 써야 한다는데 저는 강의와 똑같이 스프링 2.7을 쓰고 있는데 3.1 미만 버전에서는 GET 파라미터로 전달하는 것 외엔 방법이 없을까요?
@Controller
@RequiredArgsConstructor
@SessionAttributes("form")
public class TaskController {
private final TaskService taskService;
@ModelAttribute("form")
public TaskForm getTaskFrom() {
return new TaskForm();
}
@GetMapping("/tasks/{taskId}/edit")
public String editTaskForm(@PathVariable Long taskId, Model model) {
Task task = taskService.findOne(taskId);
TaskForm form = new TaskForm();
form.setName(task.getName());
form.setPriority(task.getPriority());
model.addAttribute("form", form);
return "task/editTaskForm";
}
@PostMapping("/tasks/{taskId}/edit")
public String editTask(@PathVariable Long taskId, @Valid TaskForm form,
BindingResult result,
SessionStatus sessionStatus) {
if (result.hasErrors()) {
return "task/editTaskForm";
}
taskService.editTask(taskId, form.getName(), form.getPriority());
sessionStatus.setComplete();
return "redirect:/tasks";
}
}
JPA 활용 2편까지도 들었고 MVC 1까지도 들었는데.. MVC 2의 BindingResult 강의를 듣고 다시 해보는게 좋을까요?
하지만 너무 해결하고 싶습니다.........🥺 어느 부분을 체크해보면 좋을까요?
답변 1
0
안녕하세요. 하루님, 공식 서포터즈 y2gcoder입니다.
도움을 드리고 싶지만 질문 내용만으로는 답변을 드리기 어렵습니다.
위의 코드에서는 사실 @ModelAttribute 를 명시적으로 달아야 하는 생각밖에는 들지 않습니다. 그리고 @SessionAttribute를 사용하는게 맞는가 하는 의문도 듭니다.
가능하시다면 실제 동작하는 전체 프로젝트를 압축해서 구글 드라이브로 공유해서 링크를 남겨주세요.
구글 드라이브 업로드 방법은 다음을 참고해주세요.
주의: 업로드시 링크에 있는 권한 문제 꼭 확인해주세요
추가로 다음 내용도 코멘트 부탁드립니다.
1. 문제 영역을 실행할 수 있는 방법
2. 문제가 어떻게 나타나는지에 대한 상세한 설명
감사합니다.
보내주신 코드 살펴보았습니다.
결과적으로 말씀드리면 위에 말씀드렸던대로
위와 같이 @ModelAttribute를 명시적으로 달아준 후 name 속성을 이용해주면 다음과 같이
에러 메시지가 정상적으로 보이는 모습을 볼 수 있습니다.
그 이유는 @ModelAttribute의 name 속성을 명시적으로 달아주지 않고 @ModelAttribute만 달아주면 스프링은 기본적으로 대상 클래스의 첫 글자만 소문자로 처리한 이름으로 모델에 해당 객체를 등록해버립니다.
그래서 이제까지 "taskForm"이라는 이름으로 모델에 등록되어 있고 editTaskForm.html에서는 "form" 이라는 이름으로 계속 해당 모델 객체를 찾고 있기 때문에 해당 에러가 발생한 것으로 보입니다.
*추가로 redirect가 아니라 강의와 같이 바로 뷰 이름을 리턴해주셔야 정상 작동합니다 :) 해당 부분은 MVC2 강의를 다시 참고해주십쇼!
안녕하세요, 빠른 답변 감사합니다.
프로젝트 파일 구글 링크와 질문 정정해서 다시 올립니다!
✅ 구글 링크 :
https://drive.google.com/file/d/15aIaJSTRP5azUw4ZcYr8qb424Zuk06nl/view?usp=share_link
✅ 원했던 기능 :
강의 예제에서 위와 같이 이름 필드를 비워두고 [회원 등록]을 시도할 경우 화면에 오류 메세지를 출력하는 것을 만들고 싶었습니다.
제가 만든 앱에서 [할 일 등록]의 경우는 원하는 대로 아래처럼 오류 메세지가 잘 출력이 되었습니다.
✅ 문제가 어떻게 나타나는지 :
그런데 [할 일 수정]의 경우에는 @Valid에 오류가 있는 경우 폼을 다시 보여주기는 하지만 오류 메세지가 출력이 되지 않았습니다. 제목 밑에 오류 메세지를 출력하려면 어떻게 해야 할까요?
✅ 문제 영역을 실행하는 방법 :
localhost:8080/ 을 실행하면 DB에 샘플 데이터가 삽입되고 할일 목록이 출력됩니다.
리스트에서 Edit 링크를 누르면 수정 폼으로 이동합니다.
제목을 비워두고 제출을 누르면
TaskController
에서@PostMapping("/tasks/{taskId}/edit")
이 실행됩니다.if (result.hasErrors()) {
에서 조건문이 참이기 때문에 다시 수정 폼으로 리다이렉트가 됩니다. 하지만 화면에서 오류 메세지가 출력되지 않습니다.return "redirect:/tasks/{taskId}/edit";
}