具有 HTTP 状态 500 而不是 HTTP 状态 400 的 JAX-RS 响应
JAX-RS response with HTTP status 500 instead of HTTP status 400
有时 JAR-RS 客户端会发送错误的语法请求正文。服务器应响应 HTTP status 400 (Bad Request), but it responses with HTTP status 500 (Internal Server Error).
代码:
JAX-B 模型 class:
@XmlRootElement(namespace = "http://www.test.com/test")
@XmlAccessorType(value = XmlAccessType.FIELD)
public class TestModel {
@XmlElement
private String id;
}
JAX-RS 资源class:
@Path("test")
public class TestResource {
@POST
@Consumes(MediaType.APPLICATION_JSON)
public void create(TestModel testModel) {
// some code
}
}
CXF 配置:
<jaxrs:server address="/rest" id="test" staticSubresourceResolution="true">
<jaxrs:serviceBeans>
<ref bean="testResource" />
</jaxrs:serviceBeans>
<jaxrs:providers>
<bean class="com.fasterxml.jackson.jaxrs.json.JacksonJaxbJsonProvider" />
</jaxrs:providers>
</jaxrs:server>
示例:
请求正文:
{"id2": "test"}
id2
是错误的,所以客户应该得到HTTP status 400, but it gets HTTP status 500。
服务器日志:
Caused by: com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "id2" (class test.TestModel), not marked as ignorable (one known property: "id"])
at [Source: org.apache.cxf.transport.http.AbstractHTTPDestination@6f30793d; line: 1, column: 10] (through reference chain: test.TestModel["id2"])
at com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException.from(UnrecognizedPropertyException.java:51)
at com.fasterxml.jackson.databind.DeserializationContext.reportUnknownProperty(DeserializationContext.java:839)
at com.fasterxml.jackson.databind.deser.std.StdDeserializer.handleUnknownProperty(StdDeserializer.java:1045)
at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.handleUnknownProperty(BeanDeserializerBase.java:1352)
at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.handleUnknownVanilla(BeanDeserializerBase.java:1330)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:264)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:125)
at com.fasterxml.jackson.databind.ObjectReader._bind(ObjectReader.java:1470)
at com.fasterxml.jackson.databind.ObjectReader.readValue(ObjectReader.java:912)
at com.fasterxml.jackson.jaxrs.base.ProviderBase.readFrom(ProviderBase.java:811)
at org.apache.cxf.jaxrs.utils.JAXRSUtils.readFromMessageBodyReader(JAXRSUtils.java:1343)
at org.apache.cxf.jaxrs.utils.JAXRSUtils.readFromMessageBody(JAXRSUtils.java:1294)
at org.apache.cxf.jaxrs.utils.JAXRSUtils.processParameter(JAXRSUtils.java:826)
at org.apache.cxf.jaxrs.utils.JAXRSUtils.processParameters(JAXRSUtils.java:789)
at org.apache.cxf.jaxrs.interceptor.JAXRSInInterceptor.processRequest(JAXRSInInterceptor.java:212)
... 68 more
有没有一种方法可以将 Jackson and/or CXF 配置为 return HTTP 状态 400,用于没有 schema validation or bean validation 的错误语法请求正文?
问题是未映射到响应(通过 ExceptionMapper
s)的异常会转换为一般服务器错误响应,因为运行时不知道如何处理异常。
jackson-jaxrs-provider
模块有 ExceptionMapper
来处理 Jackson 基础异常 class JsonMappingException
和 JsonParseException
。映射器分别为 JsonMappingExceptionMapper
and JsonParseExceptionMapper
。这些映射器会将异常映射到 400 响应以及作为响应主体的异常消息。如果你不喜欢这个响应体,你可以自己写一个映射器。
有时 JAR-RS 客户端会发送错误的语法请求正文。服务器应响应 HTTP status 400 (Bad Request), but it responses with HTTP status 500 (Internal Server Error).
代码:
JAX-B 模型 class:
@XmlRootElement(namespace = "http://www.test.com/test")
@XmlAccessorType(value = XmlAccessType.FIELD)
public class TestModel {
@XmlElement
private String id;
}
JAX-RS 资源class:
@Path("test")
public class TestResource {
@POST
@Consumes(MediaType.APPLICATION_JSON)
public void create(TestModel testModel) {
// some code
}
}
CXF 配置:
<jaxrs:server address="/rest" id="test" staticSubresourceResolution="true">
<jaxrs:serviceBeans>
<ref bean="testResource" />
</jaxrs:serviceBeans>
<jaxrs:providers>
<bean class="com.fasterxml.jackson.jaxrs.json.JacksonJaxbJsonProvider" />
</jaxrs:providers>
</jaxrs:server>
示例:
请求正文:
{"id2": "test"}
id2
是错误的,所以客户应该得到HTTP status 400, but it gets HTTP status 500。
服务器日志:
Caused by: com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "id2" (class test.TestModel), not marked as ignorable (one known property: "id"])
at [Source: org.apache.cxf.transport.http.AbstractHTTPDestination@6f30793d; line: 1, column: 10] (through reference chain: test.TestModel["id2"])
at com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException.from(UnrecognizedPropertyException.java:51)
at com.fasterxml.jackson.databind.DeserializationContext.reportUnknownProperty(DeserializationContext.java:839)
at com.fasterxml.jackson.databind.deser.std.StdDeserializer.handleUnknownProperty(StdDeserializer.java:1045)
at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.handleUnknownProperty(BeanDeserializerBase.java:1352)
at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.handleUnknownVanilla(BeanDeserializerBase.java:1330)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:264)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:125)
at com.fasterxml.jackson.databind.ObjectReader._bind(ObjectReader.java:1470)
at com.fasterxml.jackson.databind.ObjectReader.readValue(ObjectReader.java:912)
at com.fasterxml.jackson.jaxrs.base.ProviderBase.readFrom(ProviderBase.java:811)
at org.apache.cxf.jaxrs.utils.JAXRSUtils.readFromMessageBodyReader(JAXRSUtils.java:1343)
at org.apache.cxf.jaxrs.utils.JAXRSUtils.readFromMessageBody(JAXRSUtils.java:1294)
at org.apache.cxf.jaxrs.utils.JAXRSUtils.processParameter(JAXRSUtils.java:826)
at org.apache.cxf.jaxrs.utils.JAXRSUtils.processParameters(JAXRSUtils.java:789)
at org.apache.cxf.jaxrs.interceptor.JAXRSInInterceptor.processRequest(JAXRSInInterceptor.java:212)
... 68 more
有没有一种方法可以将 Jackson and/or CXF 配置为 return HTTP 状态 400,用于没有 schema validation or bean validation 的错误语法请求正文?
问题是未映射到响应(通过 ExceptionMapper
s)的异常会转换为一般服务器错误响应,因为运行时不知道如何处理异常。
jackson-jaxrs-provider
模块有 ExceptionMapper
来处理 Jackson 基础异常 class JsonMappingException
和 JsonParseException
。映射器分别为 JsonMappingExceptionMapper
and JsonParseExceptionMapper
。这些映射器会将异常映射到 400 响应以及作为响应主体的异常消息。如果你不喜欢这个响应体,你可以自己写一个映射器。