Проблема с проверкой ввода формы при использовании @Valid и BindingResult в приложении Spring Boot - PullRequest
0 голосов
/ 17 апреля 2019

Я пытаюсь добавить проверку кода на мою форму.Я опираюсь на этот урок: https://www.javacodegeeks.com/2017/10/validation-thymeleaf-spring.html - но без усилий.

У меня есть сущность InvoiceData:

@Data
@Document
@NoArgsConstructor
public class InvoiceData {

    @Id private String id;
    private ContractorData data;
    @NotNull
    @DateTimeFormat(pattern = "yyyy-MM-dd")
    private Date receptionDate;
    @NotNull
    @DateTimeFormat(pattern = "yyyy-MM-dd")
    private Date orderDate;
    @NotNull
    @DateTimeFormat(pattern = "yyyy-MM-dd")
    private Date invoiceIssueDate;
    @NotNull
    @DateTimeFormat(pattern = "yyyy-MM-dd")
    @NotNull
    private Date contractDate;
    @NotBlank
    private String invoiceNumber;
    private String additionalCosts;
    private String contractorComment;
    @NotEmpty
    private List<InvoiceTask> invoiceTasks = new ArrayList<>();

И метод контроллера:

@RequestMapping(value = "/addinvoice/{contractorId}", method = RequestMethod.POST, produces = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
    public String addInvoice(@PathVariable("contractorId") String contractorId, @ModelAttribute @Valid InvoiceData data, Model model, BindingResult result, RedirectAttributes attr, HttpSession session) {
        if (result.hasErrors()) {
            System.out.println("BINDING RESULT ERROR");
            attr.addFlashAttribute("org.springframework.validation.BindingResult.data", result);
            attr.addFlashAttribute("register", result);
            return "redirect:/add";
        } else {
            Contractor contractor = contractorRepository.findById(contractorId).get();
            data.setData(contractor.getContractorData());
            if (contractor.getInvoices() == null) {
                contractor.setInvoices(new ArrayList<InvoiceData>());
            }
            contractor.getInvoices().add(data);
            invoiceDataRepository.save(data);
            contractorRepository.save(contractor);
            model.addAttribute("contractor", contractor);
            return "index";
        }
    }

И небольшой кусочек тимелина для ясности (все остальные поля похожи на это)

<form action="#" th:action="@{addinvoice/{id}(id=${contractorid})}" th:object="${invoicedata}" method="post">
    <ul class="form-style-1">
        <li>
            <label>Reception date<span class="required">*</span></label>
            <input type="date" th:field="*{receptionDate}" id="receptionDate">
        </li>

Проблема в том, что когда я пытаюсь отправить неверную форму, меня не перенаправляют на /add, но я получаю страницу с сообщением:

Произошла непредвиденная ошибка (тип = Плохой запрос, статус = 400).Проверка не удалась для object = 'invoiceData'.Количество ошибок: 6

И трассировка стека (для ясности только из одного поля):

Ошибка поля в объекте 'invoiceData' в поле 'invoiceIssueDate': отклоненное значение[ноль];коды [NotNull.invoiceData.invoiceIssueDate, NotNull.invoiceIssueDate, NotNull.java.util.Date, NotNull];arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [invoiceData.invoiceIssueDate, invoiceIssueDate];аргументы [];сообщение по умолчанию [invoiceIssueDate]];сообщение по умолчанию [не должно быть нулевым]

Так что я предполагаю, что это одно из действий, которые я могу объяснить с помощью валидатора.

Но есть одна вещь, когда я устанавливаю точку останова в контроллере, в начале метода, где начинается оператор if, и я посылаю неверную форму, отладчик никогда не останавливается на этом, поэтомуКажется, что этот код никогда не достигается ...

Но когда я отправляю правильно заполненную форму - все идет хорошо, код работает, данные отправляются в базу данных и т.д ...

Myвопрос: это нормальное поведение валидатора?Что я могу сделать, чтобы код выполнялся, когда форма недействительна, чтобы я мог получить BindingResult и показать пользователю вывод некоторых ошибок?

1 Ответ

1 голос
/ 17 апреля 2019

Необходимо переместить параметр BindingResult прямо рядом с параметром, имеющим аннотацию @Valid.

@RequestMapping(value = "/addinvoice/{contractorId}", method = RequestMethod.POST, produces = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
public String addInvoice(@PathVariable("contractorId") String contractorId, @ModelAttribute @Valid InvoiceData data, BindingResult result, Model model , RedirectAttributes attr, HttpSession session) {
    if (result.hasErrors()) {
        System.out.println("BINDING RESULT ERROR");
        attr.addFlashAttribute("org.springframework.validation.BindingResult.data", result);
        attr.addFlashAttribute("register", result);
        return "redirect:/add";
    } else {
        Contractor contractor = contractorRepository.findById(contractorId).get();
        data.setData(contractor.getContractorData());
        if (contractor.getInvoices() == null) {
            contractor.setInvoices(new ArrayList<InvoiceData>());
        }
        contractor.getInvoices().add(data);
        invoiceDataRepository.save(data);
        contractorRepository.save(contractor);
        model.addAttribute("contractor", contractor);
        return "index";
    }
}

Теперь переменная BindingResult будет присоединена к переменной InvoiceData. Также, если вы проверяете несколько параметров в API, вам потребуется объявить соответствующую переменную BindingResult рядом со всеми этими.

...