简体   繁体   中英

Attempting Spring Boot form validation with thymeleaf, but getting an error that I can't figure out

Edit: The page is working exactly as intended now and I've updated the below code to reflect my changes. The problem was that I needed to add the Booking attribute to the model in the GetMapping for the webpage. I also needed to correct the form tag on the webpage.

I have a demo web application that I'm attempting to add error checking on the form to with error messages that will display next the the related inputs. However, after implementing a method that I found here , I get a Whitelabel Error Page when I attempt to navigate to the web page with the form that I'm attempting to implement validation for. It says "Caused by: java.lang.IllegalStateException: Neither BindingResult nor plain target object for bean name 'Booking' available as request attribute" .

Here is the problematic web page:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Reserve Booking</title>
</head>
<body>
    <h1>Reserve Booking</h1>
    <form th:object="${Booking}">
        <label for="flightId">Flight ID</label>
        <input name="flightId" type="text" th:field="*{flightId}"/>
        <label th:if="${#fields.hasErrors('flightId')}" th:errors="*{flightId}">Flight ID Error</label>
        </br>
        <label for="seatNum">Seat Number</label>
        <input name="seatNum" type="text" th:field="*{seatNum}"/>
        <label th:if="${#fields.hasErrors('seatNum')}" th:errors="*{seatNum}">Seat Number Error</label>
        </br>
        <input type="submit" formmethod="post" value="Submit"/>
        </br>
        <button formaction="/index.html">Back to Index</button>
    </form >
</body>
</html>

Here's the Booking class which uses Lombok for the getters and setters:

@Data
public class Booking {
    String confNum;

    @NotBlank(message = "Must enter a flight ID")
    @Size(min = 3, max = 3, message = "Flight ID must be 3 digits in length")
    String flightId;

    @NotBlank(message = "Must select a seat number")
    @Size(min = 1, max = 2)
    String seatNum;

    public Booking(){
        UUID uuid = UUID.randomUUID();
        confNum = uuid.toString().substring(0,5);
    }
}

Here's the related code for the controller:

@Controller
@RequestMapping(value = "/booking")
public class BookingController{
    @Autowired
    BookingData bookingData;

    @GetMapping(value = "/reserve")
    public String ReserveHandler(Model model){
        if(!model.containsAttribute("Booking")){
            model.addAttribute("Booking", new Booking());
        }
        return "booking/reserve";
    }

    @PostMapping(value = "/reserve")
    public String ReserveSeat(
        @Valid @ModelAttribute("Booking") Booking booking, 
        BindingResult bindingResult, 
        Model model
    ){
        String redirect;

        if(bindingResult.hasErrors()){
            redirect = "booking/reserve";
        }else{
            model.addAttribute("bookingList", bookingData.getAllBookings());
            bookingData.addNewBooking(booking);
            redirect = "booking/show";
        }

        return redirect;
    }
}

Everything worked great before trying to implement the error checking on the form. The error checking has nothing to do with BookingData which is why I haven't included it. It simply has an array list of booked seats and methods for returning the list, as well as adding and removing from it.

You're not adding the model in the controller, to match the th:Object in the form. In your ReserveHandler you need to add the model attribute. I'm not sure how things have changed (if at all) recently, but I've done this before (using some of your model names in this case):

public String myGetRequest(Model model) {
    if (!model.containsAttribute("Booking")) {
        // Add the named model attribute here
        model.addAttribute("Booking", new Booking());
    }
    return "booking/reserve";
}

@PostMapping(...)
public String myPostRequest(
    @Valid @ModelAttribute Booking booking,
    final BindingResult bindingResult,
    final RedirectAttributes redirectAttributes
) {
    if (bindingResult.hasErrors()) {
        // Adds the validation errors
        redirectAttributes.addFlashAttribute("org.springframework.validation.BindingResult.Booking", bindingResult);

        // Set the model attribute
        redirectAttributes.addFlashAttribute("Booking", booking);
        return "redirect:/booking/reserve";
    }
    // Otherwise...
    return "redirect:/booking/show";
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM