springspring-mvcthymeleafspring-thymeleaf

Thymeleaf + Spring. Cannot create a session after the response has been committed


I have a web-app uses bootstrap form with thymeleaf :

<form th:method="POST" th:action="@{/main}" th:object="${order}">
                        <div class="mb-3">
                            <label for="companyNameInput" class="form-label">Company Name</label>
                            <input type="text" th:field="*{companyName}" class="form-control" id="companyNameInput" aria-describedby="companyHelp">
                            <div id="companyHelp" class="form-text">What is the name of your company?</div>
                            <div style="color:red" th:if="${#fields.hasErrors('companyName')}" th:errors="*{companyName}">IF::ERROR</div>
                        </div>
                        <div class="mb-3">
                            <label for="contactPersonInput" class="form-label">Contact Person</label>
                            <input type="text" th:field="*{contactName}" class="form-control" id="contactPersonInput" aria-describedby="nameHelp">
                            <div id="nameHelp" class="form-text">What is the name of the person we are going to talk to?</div>
                            <div style="color:red" th:if="${#fields.hasErrors('contactName')}" th:errors="*{contactName}">IF::ERROR</div>
                        </div>
                        <div class="mb-3">
                            <label for="contactNumberInput" class="form-label">Number</label>
                            <input type="text" th:field="*{number}" class="form-control" id="contactnumberInput" aria-describedby="numberHelp">
                            <div id="numberHelp" class="form-text">Leave us your number so we can contact with you to negotiate next steps!</div>
                            <div style="color:red" th:if="${#fields.hasErrors('number')}" th:errors="*{number}">IF::ERROR</div>
                        </div>
                        <div class="mb-3">
                            <label for="contactEmailInput" class="form-label">Email</label>
                            <input type="email" th:field="*{email}" class="form-control" id="contactEmailInput" aria-describedby="emailHelp">
                            <div id="emailHelp" class="form-text">We'll sent you an email to recall about your order when it's ready to go. We'll never share your email with anyone else.</div>
                            <div style="color:red" th:if="${#fields.hasErrors('email')}" th:errors="*{email}">IF::ERROR</div>
                        </div>
                        <div class="mb-3">
                            <label for="contactAdressInput" class="form-label">Address</label>
                            <input type="text" th:field="*{address}" class="form-control" id="contactAdressInput" aria-describedby="addressHelp">
                            <div id="addressHelp" class="form-text">Where would you like to get your order?</div>
                            <div style="color:red" th:if="${#fields.hasErrors('address')}" th:errors="*{address}">IF::ERROR</div>
                        </div>
                        <div class="mb-3">
                            <label for="categorySelect" class="form-label">Product Category</label>
                            <select class="form-select" th:field="*{category}" aria-label="categorySelect" id="categorySelect" aria-describedby="categoryHelp">
                                <option th:value="Cigarettes" selected>Cigarettes</option>
                                <option th:value="Vapes">Vapes</option>
                                <option th:value="Devices">Smoking Devices</option>
                                <option th:value="Drinks">Drinks</option>
                                <option th:value="Food">Food</option>
                            </select>
                            <div id="categoryHelp" class="form-text">Where would you like to get your order?</div>
                            <div style="color:red" th:if="${#fields.hasErrors('category')}" th:errors="*{category}">IF::ERROR</div>
                        </div>
                        <div class="mb-3">
                            <label for="additionalInformationTextarea" class="form-label">Additional Information</label>
                            <textarea class="form-control" th:field="*{additionalInformation}" id="additionalInformationTextarea" rows="5"></textarea>
                            <div style="color:red" th:if="${#fields.hasErrors('additionalInformation')}" th:errors="*{additionalInformation}">IF::ERROR</div>
                        </div>
                        <div class="mb-3 form-check">
                            <input type="checkbox" class="form-check-input js-checkbox" id="privacyCheck">
                            <label class="form-check-label" for="privacyCheck">I agree to all the company's terms and conditions and the data processing rule.</label>
                        </div>
                        <button type="submit" class="btn btn-primary js-button" disabled>Place an order</button>
                    </form>

And this controller to handle this one:

@GetMapping("/main")
    public String mainPage(@ModelAttribute("order") Order order) {
        return "main";
    }

    @PostMapping("/main")
    public String createOrder(@ModelAttribute("order") @Valid Order order, BindingResult bindingResult) {
        if (bindingResult.hasErrors()) {
            return "main";
        }

        order.setStatus(String.valueOf(OrderStatus.Pending));
        orderDetailsService.saveOrder(order);
        return "redirect:/main";
    }

But when I enter my website I get this exception and it looks like my website kinda frozen (like accordion or carousel doesn't work). But if I delete 'form' from html code the website will work again. If I reload page many times the form could be shown and the website stops to freeze.

2024-05-13T19:34:49.173+03:00  INFO 13472 --- [retailShop] [nio-8080-exec-2] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring DispatcherServlet 'dispatcherServlet'
2024-05-13T19:34:49.173+03:00  INFO 13472 --- [retailShop] [nio-8080-exec-2] o.s.web.servlet.DispatcherServlet        : Initializing Servlet 'dispatcherServlet'
2024-05-13T19:34:49.175+03:00  INFO 13472 --- [retailShop] [nio-8080-exec-2] o.s.web.servlet.DispatcherServlet        : Completed initialization in 2 ms
2024-05-13T19:34:49.432+03:00 ERROR 13472 --- [retailShop] [nio-8080-exec-2] org.thymeleaf.TemplateEngine             : [THYMELEAF][http-nio-8080-exec-2] Exception processing template "main": Error during execution of processor 'org.thymeleaf.spring6.processor.SpringActionTagProcessor' (template: "main" - line 383, col 44)

org.thymeleaf.exceptions.TemplateProcessingException: Error during execution of processor 'org.thymeleaf.spring6.processor.SpringActionTagProcessor' (template: "main" - line 383, col 44)
    at org.thymeleaf.processor.element.AbstractAttributeTagProcessor.doProcess(AbstractAttributeTagProcessor.java:117) ~[thymeleaf-3.1.2.RELEASE.jar:3.1.2.RELEASE]

2024-05-13T19:34:49.438+03:00 ERROR 13472 --- [retailShop] [nio-8080-exec-2] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed: org.thymeleaf.exceptions.TemplateProcessingException: Error during execution of processor 'org.thymeleaf.spring6.processor.SpringActionTagProcessor' (template: "main" - line 383, col 44)] with root cause

java.lang.IllegalStateException: Cannot create a session after the response has been committed


2024-05-13T19:34:49.453+03:00 ERROR 13472 --- [retailShop] [nio-8080-exec-2] s.e.ErrorMvcAutoConfiguration$StaticView : Cannot render error page for request [/main] as the response has already been committed. As a result, the response may have the wrong status code.

How can I fix this problem?


Solution

  • Looks like I handle it out!

    https://github.com/thymeleaf/thymeleaf-spring/issues/222

    I added this code to my SecurityConfig.class in method :

    public SecurityFilterChain filterChain(HttpSecurity http) {
        http.sessionManagement(httpSecuritySessionManagementConfigurer -> httpSecuritySessionManagementConfigurer.sessionCreationPolicy(SessionCreationPolicy.ALWAYS));
    }