When i use th:action and method attribute together in form tag in Thymeleaf, it is giving me exception

huangapple go评论86阅读模式
英文:

When i use th:action and method attribute together in form tag in Thymeleaf, it is giving me exception

问题

这是非常奇怪的,当我在表单标签中使用th:action和method属性时,它会抛出异常,但是当我从表单标签中移除method属性时,就不会出现异常。我的意思是:

当我使用:

<form id="deliveryAddressForm" action="#" th:action="@{/product/save-address}" method="post" th:object="${address}">

会发生异常。

但是当我移除method="post"时:

<form id="deliveryAddressForm" action="#" th:action="@{/product/save-address}" th:object="${address}">

移除后就没有异常了。

我不明白为什么会出现这种情况。

请查看以下附带的代码:

  1. HTML代码
<form id="deliveryAddressForm" action="#" th:action="@{/product/save-address}" method="post" th:object="${address}">
    <!-- 其他表单元素 -->
</form>
  1. 模型(Model)
package com.ij.ikimall.bean;

import org.springframework.stereotype.Component;

import java.io.Serializable;

@Component
public class AddressBean implements Serializable {
    // 属性
}
  1. 控制器(Controller)
@GetMapping("/checkout/{productEncId}")
public String checkout(@PathVariable(value = "productEncId") String productEncId, Model model) {
    // 控制器逻辑
    return "view/checkout";
}

此外,请查看以下生成的详细异常:

2020-08-28 15:51:08.507 ERROR 20228 --- [nio-8989-exec-8] org.thymeleaf.TemplateEngine : [THYMELEAF][http-nio-8989-exec-8] Exception processing template "view/checkout": An error happened during template parsing (template: "class path resource [templates/view/checkout.html]")

org.thymeleaf.exceptions.TemplateInputException: An error happened during template parsing (template: "class path resource [templates/view/checkout.html]")
    at org.thymeleaf.templateparser.markup.AbstractMarkupTemplateParser.parse(AbstractMarkupTemplateParser.java:241) ~[thymeleaf-3.0.9.RELEASE.jar:3.0.9.RELEASE]

Caused by: org.attoparser.ParseException: Error during execution of processor 'org.thymeleaf.spring5.processor.SpringActionTagProcessor' (template: "view/checkout" - line 41, col 79)
    at org.attoparser.MarkupParser.parseDocument(MarkupParser.java:393) ~[attoparser-2.0.4.RELEASE.jar:2.0.4.RELEASE]
    at org.attoparser.MarkupParser.parse(MarkupParser.java:257) ~[attoparser-2.0.4.RELEASE.jar:2.0.4.RELEASE]
    at org.thymeleaf.templateparser.markup.AbstractMarkupTemplateParser.parse(AbstractMarkupTemplateParser.java:230) ~[thymeleaf-3.0.9.RELEASE.jar:3.0.9.RELEASE]
Caused by: org.thymeleaf.exceptions.TemplateProcessingException: Error during execution of processor 'org.thymeleaf.spring5.processor.SpringActionTagProcessor' (template: "view/checkout" - line 41, col 79)
    at org.thymeleaf.processor.element.AbstractAttributeTagProcessor.doProcess(AbstractAttributeTagProcessor.java:117) ~[thymeleaf-3.0.9.RELEASE.jar:3.0.9.RELEASE]
    at org.thymeleaf.processor.element.AbstractElementTagProcessor.process(AbstractElementTagProcessor.java:95) ~[thymeleaf-3.0.9.RELEASE.jar:3.0.9.RELEASE]

Caused by: java.lang.IllegalStateException: Cannot create a session after the response has been committed
    at org.apache.catalina.connector.Request.doGetSession(Request.java:2999) ~[tomcat-embed-core-9.0.36.jar:9.0.36]
    at org.apache.catalina.connector.Request.getSession(Request.java:2441) ~[tomcat-embed-core-9.0.36.jar:9.0.36]

2020-08-28 15:51:08.524 ERROR 20228 --- [nio-8989-exec-8] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.thymeleaf.exceptions.TemplateInputException: An error happened during template parsing (template: "class path resource [templates/view/checkout.html]")] with root cause

java.lang.IllegalStateException: Cannot create a session after the response has been committed
    at org.apache.catalina.connector.Request.doGetSession(Request.java:2999) ~[tomcat-embed-core-9.0.36.jar:9.0.36]

2020-08-28 15:51:08.640 ERROR 20228 --- [nio-8989-exec-8] s.e.ErrorMvcAutoConfiguration$StaticView : Cannot render error page for request [/product/checkout/fvssrg5OLcM=] and exception [An error happened during template parsing (template: "class path resource [templates/view/checkout.html]")] as the response has already been committed. As a result, the response may have the wrong status code.
英文:

This is very weird that when i th:action and method attribute in form tag, it is giving me exceptions but when i remove method attribute from the form tag, no exception occur. What i mean is
When is use

&lt;form id=&quot;deliveryAddressForm&quot; action=&quot;#&quot; th:action=&quot;@{/product/save-address}&quot; method=&quot;post&quot; th:object=&quot;${address}&quot;&gt;

Exception occurs

&lt;form id=&quot;deliveryAddressForm&quot; action=&quot;#&quot; th:action=&quot;@{/product/save-address}&quot; th:object=&quot;${address}&quot;&gt;

No exception after removing method="post"

I don't understand why it is behaving like this.

Please find the code attached below

  1. Html Code

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-html -->

&lt;form id=&quot;deliveryAddressForm&quot; action=&quot;#&quot; th:action=&quot;@{/product/save-address}&quot; method=&quot;post&quot; th:object=&quot;${address}&quot;&gt;
&lt;!-- Invoice Address--&gt;
&lt;h3 class=&quot;mb-4&quot;&gt; Invoice address&lt;/h3&gt;
&lt;div class=&quot;row&quot;&gt;
&lt;div class=&quot;form-group col-md-6&quot;&gt;
&lt;label class=&quot;form-label&quot; for=&quot;fullname_invoice&quot;&gt;Full Name&lt;/label&gt;
&lt;input class=&quot;form-control&quot; type=&quot;text&quot; th:field=&quot;*{name}&quot; placeholder=&quot;Joe Black&quot; id=&quot;fullname_invoice&quot;&gt;
&lt;/div&gt;
&lt;div class=&quot;form-group col-md-6&quot;&gt;
&lt;label class=&quot;form-label&quot; for=&quot;emailaddress_invoice&quot;&gt;Email Address&lt;/label&gt;
&lt;input class=&quot;form-control&quot; type=&quot;text&quot; th:field=&quot;*{email}&quot; placeholder=&quot;joe.black@gmail.com&quot; id=&quot;emailaddress_invoice&quot;&gt;
&lt;/div&gt;
&lt;div class=&quot;form-group col-md-6&quot;&gt;
&lt;label class=&quot;form-label&quot; for=&quot;phonenumber_invoice&quot;&gt;Phone Number&lt;/label&gt;
&lt;input class=&quot;form-control&quot; type=&quot;text&quot; th:field=&quot;*{mobile}&quot; placeholder=&quot;Phone Number&quot; id=&quot;phonenumber_invoice&quot;&gt;
&lt;/div&gt;
&lt;div class=&quot;form-group col-md-6&quot;&gt;
&lt;label class=&quot;form-label&quot; for=&quot;street_invoice&quot;&gt;Street&lt;/label&gt;
&lt;input class=&quot;form-control&quot; type=&quot;text&quot; th:field=&quot;*{street}&quot; placeholder=&quot;123 Main St.&quot; id=&quot;street_invoice&quot;&gt;
&lt;/div&gt;
&lt;div class=&quot;form-group col-md-6&quot;&gt;
&lt;label class=&quot;form-label&quot; for=&quot;city_invoice&quot;&gt;City&lt;/label&gt;
&lt;input class=&quot;form-control&quot; type=&quot;text&quot; th:field=&quot;*{city}&quot; placeholder=&quot;City&quot; id=&quot;city_invoice&quot;&gt;
&lt;/div&gt;
&lt;div class=&quot;form-group col-md-6&quot;&gt;
&lt;label class=&quot;form-label&quot; for=&quot;zip_invoice&quot;&gt;Pincode&lt;/label&gt;
&lt;input class=&quot;form-control&quot; type=&quot;text&quot; th:field=&quot;*{pincode}&quot; placeholder=&quot;Postal code&quot; id=&quot;zip_invoice&quot;&gt;
&lt;/div&gt;
&lt;div class=&quot;form-group col-md-6&quot;&gt;
&lt;label class=&quot;form-label&quot; for=&quot;state_invoice&quot;&gt;Land Mark&lt;/label&gt;
&lt;input class=&quot;form-control&quot; type=&quot;text&quot; th:field=&quot;*{landmark}&quot; placeholder=&quot;State&quot; id=&quot;state_invoice&quot;&gt;
&lt;/div&gt;
&lt;div class=&quot;form-group col-12 mt-3&quot;&gt;
&lt;div class=&quot;custom-control custom-checkbox&quot;&gt;
&lt;input class=&quot;custom-control-input&quot; id=&quot;show-shipping-address&quot; type=&quot;checkbox&quot; name=&quot;clothes-brand&quot;&gt;
&lt;label class=&quot;custom-control-label align-middle&quot; for=&quot;show-shipping-address&quot; data-toggle=&quot;collapse&quot; data-target=&quot;#shippingAddress&quot;&gt;Use a different shipping address&lt;/label&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;!-- /Invoice Address--&gt;
&lt;!-- Shippping Address--&gt;
&lt;div class=&quot;collapse&quot; id=&quot;shippingAddress&quot;&gt;
&lt;h3 class=&quot;my-4&quot;&gt;Shipping address &lt;/h3&gt;
&lt;div class=&quot;row&quot;&gt;
&lt;div class=&quot;form-group col-md-6&quot;&gt;
&lt;label class=&quot;form-label&quot; for=&quot;street_shipping&quot;&gt;Street&lt;/label&gt;
&lt;input class=&quot;form-control&quot; type=&quot;text&quot; th:field=&quot;*{street1}&quot; placeholder=&quot;123 Main St.&quot; id=&quot;street_shipping&quot;&gt;
&lt;/div&gt;
&lt;div class=&quot;form-group col-md-6&quot;&gt;
&lt;label class=&quot;form-label&quot; for=&quot;city_shipping&quot;&gt;City&lt;/label&gt;
&lt;input class=&quot;form-control&quot; type=&quot;text&quot; th:field=&quot;*{city1}&quot; placeholder=&quot;City&quot; id=&quot;city_shipping&quot;&gt;
&lt;/div&gt;
&lt;div class=&quot;form-group col-md-6&quot;&gt;
&lt;label class=&quot;form-label&quot; for=&quot;zip_shipping&quot;&gt;Pin&lt;/label&gt;
&lt;input class=&quot;form-control&quot; type=&quot;text&quot; th:field=&quot;*{pincode1}&quot; placeholder=&quot;Postal code&quot; id=&quot;zip_shipping&quot;&gt;
&lt;/div&gt;
&lt;div class=&quot;form-group col-md-6&quot;&gt;
&lt;label class=&quot;form-label&quot; for=&quot;state_shipping&quot;&gt;Land Mark&lt;/label&gt;
&lt;input class=&quot;form-control&quot; type=&quot;text&quot; th:field=&quot;*{landmark1}&quot; placeholder=&quot;State&quot; id=&quot;state_shipping&quot;&gt;
&lt;/div&gt;
&lt;div class=&quot;form-group col-md-6&quot;&gt;
&lt;label class=&quot;form-label&quot; for=&quot;phonenumber_shipping&quot;&gt;Phone Number&lt;/label&gt;
&lt;input class=&quot;form-control&quot; type=&quot;text&quot; th:field=&quot;*{mobile1}&quot; placeholder=&quot;Phone Number&quot; id=&quot;phonenumber_shipping&quot;&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;!-- /Shipping Address--&gt;
&lt;div class=&quot;my-5 d-flex justify-content-between flex-column flex-lg-row&quot;&gt;&lt;a class=&quot;btn btn-link text-muted&quot; href=&quot;#&quot;&gt; &lt;i class=&quot;fa fa-angle-left mr-2&quot;&gt;&lt;/i&gt;Back &lt;/a&gt;&lt;a class=&quot;btn btn-dark forward-btn&quot; data-pan=&quot;1&quot; href=&quot;javascript:void(0)&quot; id=&quot;saveDeliveryAddressForm&quot;&gt;Choose delivery method&lt;i class=&quot;fa fa-angle-right ml-2&quot;&gt;&lt;/i&gt;&lt;/a&gt;&lt;/div&gt;
&lt;/form&gt;

<!-- end snippet -->

  1. Model
    package com.ij.ikimall.bean;
import org.springframework.stereotype.Component;
import java.io.Serializable;
@Component
public class AddressBean implements Serializable {
private String name;
private String email;
private String mobile;
private String street;
private String city;
private String pincode;
private String landmark;
private String mobile1;
private String street1;
private String city1;
private String pincode1;
private String landmark1;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getMobile() {
return mobile;
}
public void setMobile(String mobile) {
this.mobile = mobile;
}
public String getStreet() {
return street;
}
public void setStreet(String street) {
this.street = street;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getPincode() {
return pincode;
}
public void setPincode(String pincode) {
this.pincode = pincode;
}
public String getLandmark() {
return landmark;
}
public void setLandmark(String landmark) {
this.landmark = landmark;
}
public String getMobile1() {
return mobile1;
}
public void setMobile1(String mobile1) {
this.mobile1 = mobile1;
}
public String getStreet1() {
return street1;
}
public void setStreet1(String street1) {
this.street1 = street1;
}
public String getCity1() {
return city1;
}
public void setCity1(String city1) {
this.city1 = city1;
}
public String getPincode1() {
return pincode1;
}
public void setPincode1(String pincode1) {
this.pincode1 = pincode1;
}
public String getLandmark1() {
return landmark1;
}
public void setLandmark1(String landmark1) {
this.landmark1 = landmark1;
}
}
  1. controller
@GetMapping(&quot;/checkout/{productEncId}&quot;)
public String checkout(@PathVariable(value = &quot;productEncId&quot;)String productEncId,Model model) {
Product product = productService.findByEncryptedId(productEncId);
model.addAttribute(&quot;productEncId&quot;,productEncId);
AddressBean address = new AddressBean();
model.addAttribute(&quot;address&quot;,address);
return &quot;view/checkout&quot;;
}

Also please find the detail exceptions generated

2020-08-28 15:51:08.507 ERROR 20228 --- [nio-8989-exec-8] org.thymeleaf.TemplateEngine             : [THYMELEAF][http-nio-8989-exec-8] Exception processing template &quot;view/checkout&quot;: An error happened during template parsing (template: &quot;class path resource [templates/view/checkout.html]&quot;)
org.thymeleaf.exceptions.TemplateInputException: An error happened during template parsing (template: &quot;class path resource [templates/view/checkout.html]&quot;)
at org.thymeleaf.templateparser.markup.AbstractMarkupTemplateParser.parse(AbstractMarkupTemplateParser.java:241) ~[thymeleaf-3.0.9.RELEASE.jar:3.0.9.RELEASE]
Caused by: org.attoparser.ParseException: Error during execution of processor &#39;org.thymeleaf.spring5.processor.SpringActionTagProcessor&#39; (template: &quot;view/checkout&quot; - line 41, col 79)
at org.attoparser.MarkupParser.parseDocument(MarkupParser.java:393) ~[attoparser-2.0.4.RELEASE.jar:2.0.4.RELEASE]
at org.attoparser.MarkupParser.parse(MarkupParser.java:257) ~[attoparser-2.0.4.RELEASE.jar:2.0.4.RELEASE]
at org.thymeleaf.templateparser.markup.AbstractMarkupTemplateParser.parse(AbstractMarkupTemplateParser.java:230) ~[thymeleaf-3.0.9.RELEASE.jar:3.0.9.RELEASE]
Caused by: org.thymeleaf.exceptions.TemplateProcessingException: Error during execution of processor &#39;org.thymeleaf.spring5.processor.SpringActionTagProcessor&#39; (template: &quot;view/checkout&quot; - line 41, col 79)
at org.thymeleaf.processor.element.AbstractAttributeTagProcessor.doProcess(AbstractAttributeTagProcessor.java:117) ~[thymeleaf-3.0.9.RELEASE.jar:3.0.9.RELEASE]
at org.thymeleaf.processor.element.AbstractElementTagProcessor.process(AbstractElementTagProcessor.java:95) ~[thymeleaf-3.0.9.RELEASE.jar:3.0.9.RELEASE]
Caused by: java.lang.IllegalStateException: Cannot create a session after the response has been committed
at org.apache.catalina.connector.Request.doGetSession(Request.java:2999) ~[tomcat-embed-core-9.0.36.jar:9.0.36]
at org.apache.catalina.connector.Request.getSession(Request.java:2441) ~[tomcat-embed-core-9.0.36.jar:9.0.36]
2020-08-28 15:51:08.524 ERROR 20228 --- [nio-8989-exec-8] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.thymeleaf.exceptions.TemplateInputException: An error happened during template parsing (template: &quot;class path resource [templates/view/checkout.html]&quot;)] with root cause
java.lang.IllegalStateException: Cannot create a session after the response has been committed
at org.apache.catalina.connector.Request.doGetSession(Request.java:2999) ~[tomcat-embed-core-9.0.36.jar:9.0.36]
2020-08-28 15:51:08.640 ERROR 20228 --- [nio-8989-exec-8] s.e.ErrorMvcAutoConfiguration$StaticView : Cannot render error page for request [/product/checkout/fvssrg5OLcM=] and exception [An error happened during template parsing (template: &quot;class path resource [templates/view/checkout.html]&quot;)] as the response has already been committed. As a result, the response may have the wrong status code.

答案1

得分: 1

在SO上有多个关于类似问题的问题,但其中大多数除了这个答案链接1之外都没有答案。

在我的情况下,我进一步检查了这个问题,每次未设置或手动修改JSESSIONID时,都会出现这个错误。

我进行了一些小实验,以找出在哪种情况下这个问题会消失:

  1. 使用会话创建策略ALWAYS可以通过始终生成会话来解决问题。
    .and()
        .sessionManagement()
        .sessionCreationPolicy(SessionCreationPolicy.ALWAYS)
  1. 使用CSRF令牌存储库(如Spring Security问题3906中所述)也有助于通过主动创建来持久保存CSRF令牌(而不是使用惰性持久性)。还可以使用CookieCsrfTokenRepository
    .csrf()
		.csrfTokenRepository(new HttpSessionCsrfTokenRepository())

对于匿名用户,应用程序只会在需要时生成会话,因此在某些情况下,例如在较长的HTML文件中晚些时候呈现表单,请求CSRF令牌可能会导致此问题。

英文:

There are multiple questions on SO explaining similar problems but most of them had no answers apart from this answers here.

I inspected the issue further in my case, every time JSESSIONID was not set or modified manually, this error would appear.

I did some tiny experiments to figure out in which case the issue would go away:

  1. Using Session creation policy ALWAYS would make the problem go away by always generating a session.
    .and()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.ALWAYS)
  1. Using csrf token repository (as described in Spring Security Issue 3906) also helps to persist the csrf token (without using lazy persistence) by eagerly creating it. Also the CookieCsrfTokenRepository may be used.
    .csrf()
.csrfTokenRepository(new HttpSessionCsrfTokenRepository())

With anonymous user, the application only generates session if required and hence, requesting a CSRF token when rendering a form can cause this issue in certain conditions such as rendering the form late in a long html file.

答案2

得分: 0

错误提示说 org.thymeleaf.exceptions.TemplateInputException: 在解析模板时发生错误(模板:"class path resource [templates//view/checkout.html]")

注意 view 前面有双斜杠 //. 尝试在你的返回语句中去掉 view 前面的斜杠/。

英文:

Error says org.thymeleaf.exceptions.TemplateInputException: An error happened during template parsing (template: "class path resource [templates//view/checkout.html]")

Note the double // before view. Try removing / before view in your return statement

huangapple
  • 本文由 发表于 2020年8月28日 09:39:13
  • 转载请务必保留本文链接:https://go.coder-hub.com/63626289.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定