Spring未返回默认的验证错误响应。

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

Spring not returning default validation error responses

问题

我试图让默认的Spring 400约束违规错误起作用。
我期望得到以下结果:

{
....
"status": 400,
"error": "Bad Request",
"errors": [
{
....
"defaultMessage": "must not be null",
....
}
],
"message": "Validation failed for object='notNullRequest'. Error count: 1",
....
}

但我得到了:

{
"timestamp": "2020-07-31T08:30:06.992+00:00",
"status": 400,
"error": "Bad Request",
"message": "",
"path": "/v0.1/checkouts/1"
}

我的POM:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.3.1.RELEASE</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>
	<groupId>hidden</groupId>
	<artifactId>hidden</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>hidden</name>
	<description>hidden</description>

	<properties>
		<java.version>11</java.version>
		<org.mapstruct.version>1.3.1.Final</org.mapstruct.version>
		<org.projectlombok.version>1.18.12</org.projectlombok.version>
		<spring-cloud.version>Hoxton.SR6</spring-cloud.version>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-actuator</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-data-jpa</artifactId>
		</dependency>
		<dependency>
			<groupId>org.postgresql</groupId>
			<artifactId>postgresql</artifactId>
			<scope>runtime</scope>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<dependency>
			<groupId>io.micrometer</groupId>
			<artifactId>micrometer-registry-prometheus</artifactId>
		</dependency>
		<dependency>
			<groupId>org.mapstruct</groupId>
			<artifactId>mapstruct</artifactId>
			<version>${org.mapstruct.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-validation</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
			<exclusions>
				<exclusion>
					<groupId>org.junit.vintage</groupId>
					<artifactId>junit-vintage-engine</artifactId>
				</exclusion>
			</exclusions>
		</dependency>
		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
			<version>${org.projectlombok.version}</version>
			<scope>provided</scope>
		</dependency>
	</dependencies>

	<dependencyManagement>
		<dependencies>
			<dependency>
				<groupId>org.springframework.cloud</groupId>
				<artifactId>spring-cloud-dependencies</artifactId>
				<version>${spring-cloud.version}</version>
				<type>pom</type>
				<scope>import</scope>
			</dependency>
		</dependencies>
	</dependencyManagement>

	<repositories>
		<repository>
			<id>hidden</id>
			<name>hidden</name>
			<url>hidden</url>
		</repository>
	</repositories>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>3.8.1</version>
				<configuration>
					<source>11</source>
					<target>11</target>
					<annotationProcessorPaths>
						<path>
							<groupId>org.mapstruct</groupId>
							<artifactId>mapstruct-processor</artifactId>
							<version>${org.mapstruct.version}</version>
						</path>
						<path>
							<groupId>org.projectlombok</groupId>
							<artifactId>lombok</artifactId>
							<version>${org.projectlombok.version}</version>
						</path>
					</annotationProcessorPaths>
				</configuration>
			</plugin>
		</plugins>
	</build>

</project>

我试图验证的REST资源:

@PutMapping(value = "/{id}", produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<CheckoutDto> createCheckout(@PathVariable Long id,
                                                  @Valid @RequestBody CheckoutProcessRequest request) {

DTO有类似的验证:

@NotNull
@JsonProperty("payment_type")
private PaymentType paymentType;

而且我在日志中得到了正确的消息:

2020-07-31 11:30:06.983  WARN 93126 --- [nio-8080-exec-1] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.web.bind.MethodArgumentNotValidException: Validation failed for argument [1] in public org.springframework.http.ResponseEntity<com.hidden.payments.rest.model.CheckoutDto> com.hidden.payments.rest.CheckoutsResource.createCheckout(java.lang.Long,com.hidden.payments.rest.model.CheckoutProcessRequest): [Field error in object 'checkoutProcessRequest' on field 'paymentType': rejected value [null]; codes [NotNull.checkoutProcessRequest.paymentType,NotNull.paymentType,NotNull.com.hidden.payments.rest.model.PaymentType,NotNull]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [checkoutProcessRequest.paymentType,paymentType]; arguments []; default message
<details>
<summary>英文:</summary>
I&#39;m trying to get the default Spring 400 constrain violation errors working.
I&#39;m expecting this:
{
....
&quot;status&quot;: 400,
&quot;error&quot;: &quot;Bad Request&quot;,
&quot;errors&quot;: [
{
....
&quot;defaultMessage&quot;: &quot;must not be null&quot;,
....
}
],
&quot;message&quot;: &quot;Validation failed for object=&#39;notNullRequest&#39;. Error count: 1&quot;,
....
}
But I get:
{
&quot;timestamp&quot;: &quot;2020-07-31T08:30:06.992+00:00&quot;,
&quot;status&quot;: 400,
&quot;error&quot;: &quot;Bad Request&quot;,
&quot;message&quot;: &quot;&quot;,
&quot;path&quot;: &quot;/v0.1/checkouts/1&quot;
}
My POM:
```&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
&lt;project xmlns=&quot;http://maven.apache.org/POM/4.0.0&quot; xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;
xsi:schemaLocation=&quot;http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd&quot;&gt;
&lt;modelVersion&gt;4.0.0&lt;/modelVersion&gt;
&lt;parent&gt;
&lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
&lt;artifactId&gt;spring-boot-starter-parent&lt;/artifactId&gt;
&lt;version&gt;2.3.1.RELEASE&lt;/version&gt;
&lt;relativePath/&gt; &lt;!-- lookup parent from repository --&gt;
&lt;/parent&gt;
&lt;groupId&gt;hidden&lt;/groupId&gt;
&lt;artifactId&gt;hidden&lt;/artifactId&gt;
&lt;version&gt;0.0.1-SNAPSHOT&lt;/version&gt;
&lt;name&gt;hidden&lt;/name&gt;
&lt;description&gt;hidden&lt;/description&gt;
&lt;properties&gt;
&lt;java.version&gt;11&lt;/java.version&gt;
&lt;org.mapstruct.version&gt;1.3.1.Final&lt;/org.mapstruct.version&gt;
&lt;org.projectlombok.version&gt;1.18.12&lt;/org.projectlombok.version&gt;
&lt;spring-cloud.version&gt;Hoxton.SR6&lt;/spring-cloud.version&gt;
&lt;/properties&gt;
&lt;dependencies&gt;
&lt;dependency&gt;
&lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
&lt;artifactId&gt;spring-boot-starter-actuator&lt;/artifactId&gt;
&lt;/dependency&gt;
&lt;dependency&gt;
&lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
&lt;artifactId&gt;spring-boot-starter-data-jpa&lt;/artifactId&gt;
&lt;/dependency&gt;
&lt;dependency&gt;
&lt;groupId&gt;org.postgresql&lt;/groupId&gt;
&lt;artifactId&gt;postgresql&lt;/artifactId&gt;
&lt;scope&gt;runtime&lt;/scope&gt;
&lt;/dependency&gt;
&lt;dependency&gt;
&lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
&lt;artifactId&gt;spring-boot-starter-web&lt;/artifactId&gt;
&lt;/dependency&gt;
&lt;dependency&gt;
&lt;groupId&gt;io.micrometer&lt;/groupId&gt;
&lt;artifactId&gt;micrometer-registry-prometheus&lt;/artifactId&gt;
&lt;/dependency&gt;
&lt;dependency&gt;
&lt;groupId&gt;org.mapstruct&lt;/groupId&gt;
&lt;artifactId&gt;mapstruct&lt;/artifactId&gt;
&lt;version&gt;${org.mapstruct.version}&lt;/version&gt;
&lt;/dependency&gt;
&lt;dependency&gt;
&lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
&lt;artifactId&gt;spring-boot-starter-validation&lt;/artifactId&gt;
&lt;/dependency&gt;
&lt;dependency&gt;
&lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
&lt;artifactId&gt;spring-boot-starter-test&lt;/artifactId&gt;
&lt;scope&gt;test&lt;/scope&gt;
&lt;exclusions&gt;
&lt;exclusion&gt;
&lt;groupId&gt;org.junit.vintage&lt;/groupId&gt;
&lt;artifactId&gt;junit-vintage-engine&lt;/artifactId&gt;
&lt;/exclusion&gt;
&lt;/exclusions&gt;
&lt;/dependency&gt;
&lt;dependency&gt;
&lt;groupId&gt;org.projectlombok&lt;/groupId&gt;
&lt;artifactId&gt;lombok&lt;/artifactId&gt;
&lt;version&gt;${org.projectlombok.version}&lt;/version&gt;
&lt;scope&gt;provided&lt;/scope&gt;
&lt;/dependency&gt;
&lt;/dependencies&gt;
&lt;dependencyManagement&gt;
&lt;dependencies&gt;
&lt;dependency&gt;
&lt;groupId&gt;org.springframework.cloud&lt;/groupId&gt;
&lt;artifactId&gt;spring-cloud-dependencies&lt;/artifactId&gt;
&lt;version&gt;${spring-cloud.version}&lt;/version&gt;
&lt;type&gt;pom&lt;/type&gt;
&lt;scope&gt;import&lt;/scope&gt;
&lt;/dependency&gt;
&lt;/dependencies&gt;
&lt;/dependencyManagement&gt;
&lt;repositories&gt;
&lt;repository&gt;
&lt;id&gt;hidden&lt;/id&gt;
&lt;name&gt;hidden&lt;/name&gt;
&lt;url&gt;hidden&lt;/url&gt;
&lt;/repository&gt;
&lt;/repositories&gt;
&lt;build&gt;
&lt;plugins&gt;
&lt;plugin&gt;
&lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
&lt;artifactId&gt;spring-boot-maven-plugin&lt;/artifactId&gt;
&lt;/plugin&gt;
&lt;plugin&gt;
&lt;groupId&gt;org.apache.maven.plugins&lt;/groupId&gt;
&lt;artifactId&gt;maven-compiler-plugin&lt;/artifactId&gt;
&lt;version&gt;3.8.1&lt;/version&gt;
&lt;configuration&gt;
&lt;source&gt;11&lt;/source&gt;
&lt;target&gt;11&lt;/target&gt;
&lt;annotationProcessorPaths&gt;
&lt;path&gt;
&lt;groupId&gt;org.mapstruct&lt;/groupId&gt;
&lt;artifactId&gt;mapstruct-processor&lt;/artifactId&gt;
&lt;version&gt;${org.mapstruct.version}&lt;/version&gt;
&lt;/path&gt;
&lt;path&gt;
&lt;groupId&gt;org.projectlombok&lt;/groupId&gt;
&lt;artifactId&gt;lombok&lt;/artifactId&gt;
&lt;version&gt;${org.projectlombok.version}&lt;/version&gt;
&lt;/path&gt;
&lt;/annotationProcessorPaths&gt;
&lt;/configuration&gt;
&lt;/plugin&gt;
&lt;/plugins&gt;
&lt;/build&gt;
&lt;/project&gt;

REST Resource I'm trying to validate:

@PutMapping(value = &quot;/{id}&quot;, produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity&lt;CheckoutDto&gt; createCheckout(@PathVariable Long id,
@Valid @RequestBody CheckoutProcessRequest request) {

The DTO has validations like:

@NotNull
@JsonProperty(&quot;payment_type&quot;)
private PaymentType paymentType;

And I get a proper message in the log:

2020-07-31 11:30:06.983  WARN 93126 --- [nio-8080-exec-1] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.web.bind.MethodArgumentNotValidException: Validation failed for argument [1] in public org.springframework.http.ResponseEntity&lt;com.hidden.payments.rest.model.CheckoutDto&gt; com.hidden.payments.rest.CheckoutsResource.createCheckout(java.lang.Long,com.hidden.payments.rest.model.CheckoutProcessRequest): [Field error in object &#39;checkoutProcessRequest&#39; on field &#39;paymentType&#39;: rejected value [null]; codes [NotNull.checkoutProcessRequest.paymentType,NotNull.paymentType,NotNull.com.hidden.payments.rest.model.PaymentType,NotNull]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [checkoutProcessRequest.paymentType,paymentType]; arguments []; default message [paymentType]]; default message [must not be null]] ]

So any ideas what could interfering with the response?
I have no recollection of ever having to do anything specific to get the proper constraint violation responses in latest Spring versions.

Thanks!

答案1

得分: 17

Spring Boot 2.3默认情况下在错误响应中省略了errorsmessage字段,以降低包含敏感信息的响应的机会。您可以通过设置以下属性来恢复先前的行为:

server.error.include-message=always
server.error.include-binding-errors=always

有关更多信息,请参阅2.3版本的发布说明文档

英文:

Spring Boot 2.3 omits the errors and message fields in error responses by default to reduce the chance that sensitive information is included in a response. You can restore the previous behavior by setting the following properties:

server.error.include-message=always
server.error.include-binding-errors=always

See the 2.3 release notes and documentation for more information.

答案2

得分: 1

Sprint Boot 2.3存在验证消息问题,或者行为发生了变化。
在https://stackoverflow.com/questions/63110587/size-annotation-in-spring-boot-is-returning-400-bad-request/63187267#63187267下重复提出的问题。

英文:

Sprint Boot 2.3 has issues with validation messages, or behaviour changed.
Duplicated question under
https://stackoverflow.com/questions/63110587/size-annotation-in-spring-boot-is-returning-400-bad-request/63187267#63187267

huangapple
  • 本文由 发表于 2020年7月31日 16:39:55
  • 转载请务必保留本文链接:https://go.coder-hub.com/63188531.html
匿名

发表评论

匿名网友

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

确定