RestEasy ExceptionMapper NotAllowedException 序列化错误 MediaType octet-stream
RestEasy ExceptionMapper NotAllowedException Serialization Error MediaType octet-stream
我在这里展示简单的休息服务来说明我收到的异常。
服务A
@Path("/A")
public class ServiceA {
@GET
@Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
public Response show() {
return Response.ok(new User("John", "Doe")).build();
}
}
型号:
用户
@XmlRootElement
public class User {
private String firstName;
private String lastName;
public User() {
}
public User(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
}
错误响应
@XmlRootElement
public class ErrorResponse {
private String errorType;
private String errorMessage;
public ErrorResponse() {
}
public ErrorResponse(String errorType, String errorMessage) {
this.errorType = errorType;
this.errorMessage = errorMessage;
}
public String getErrorType() {
return errorType;
}
public void setErrorType(String errorType) {
this.errorType = errorType;
}
public String getErrorMessage() {
return errorMessage;
}
public void setErrorMessage(String errorMessage) {
this.errorMessage = errorMessage;
}
}
最后我的 ExceptionMapper 看起来像这样:
@Provider
public class GenericExceptionMapper implements ExceptionMapper<Exception> {
private final Logger LOG = LoggerFactory.getLogger(GenericExceptionMapper.class);
@Override
public Response toResponse(Exception exception) {
ErrorResponse errorResponse = new ErrorResponse(exception.getClass().getSimpleName(), exception.getMessage());
if (exception instanceof WebApplicationException) {
LOG.error("Type: {}", exception.getClass().getSimpleName());
LOG.error("Message: {}", exception.getMessage());
WebApplicationException webApplicationException = (WebApplicationException) exception;
return Response.status(webApplicationException.getResponse().getStatus()).entity(errorResponse).build();
}
return Response.serverError().entity(errorResponse).build();
}
}
在 URI 上调用 GET 我得到正确的响应:
Accept: application/json
GET http://localhost:8080/exception-mapper-example/rest/A
{"firstName":"John","lastName":"Doe"}
但是在这个 URI 上调用 POST 我得到一个异常:
2017-01-13 16:53:46,859 ERROR [com.aizaz.samples.exceptionmapper.GenericExceptionMapper] (default task-35) Type: NotAllowedException
2017-01-13 16:53:46,860 ERROR [com.aizaz.samples.exceptionmapper.GenericExceptionMapper] (default task-35) Message: RESTEASY003650: No resource method found for POST, return 405 with Allow header
2017-01-13 16:53:46,860 ERROR [io.undertow.request] (default task-35) UT005023: Exception handling request to /exception-mapper-example/rest/A: org.jboss.resteasy.spi.UnhandledException: org.jboss.resteasy.core.NoMessageBodyWriterFoundFailure: Could not find MessageBodyWriter for response object of type: com.aizaz.samples.model.ErrorResponse of media type: application/octet-stream
at org.jboss.resteasy.core.SynchronousDispatcher.writeException(SynchronousDispatcher.java:180)
at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:199)
at org.jboss.resteasy.plugins.server.servlet.ServletContainerDispatcher.service(ServletContainerDispatcher.java:221)
at org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher.service(HttpServletDispatcher.java:56)
at org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher.service(HttpServletDispatcher.java:51)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:790)
at io.undertow.servlet.handlers.ServletHandler.handleRequest(ServletHandler.java:85)
at io.undertow.servlet.handlers.security.ServletSecurityRoleHandler.handleRequest(ServletSecurityRoleHandler.java:62)
at io.undertow.servlet.handlers.ServletDispatchingHandler.handleRequest(ServletDispatchingHandler.java:36)
at org.wildfly.extension.undertow.security.SecurityContextAssociationHandler.handleRequest(SecurityContextAssociationHandler.java:78)
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at io.undertow.servlet.handlers.security.SSLInformationAssociationHandler.handleRequest(SSLInformationAssociationHandler.java:131)
at io.undertow.servlet.handlers.security.ServletAuthenticationCallHandler.handleRequest(ServletAuthenticationCallHandler.java:57)
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at io.undertow.security.handlers.AbstractConfidentialityHandler.handleRequest(AbstractConfidentialityHandler.java:46)
at io.undertow.servlet.handlers.security.ServletConfidentialityConstraintHandler.handleRequest(ServletConfidentialityConstraintHandler.java:64)
at io.undertow.security.handlers.AuthenticationMechanismsHandler.handleRequest(AuthenticationMechanismsHandler.java:60)
at io.undertow.servlet.handlers.security.CachedAuthenticatedSessionHandler.handleRequest(CachedAuthenticatedSessionHandler.java:77)
at io.undertow.security.handlers.NotificationReceiverHandler.handleRequest(NotificationReceiverHandler.java:50)
at io.undertow.security.handlers.AbstractSecurityContextAssociationHandler.handleRequest(AbstractSecurityContextAssociationHandler.java:43)
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at org.wildfly.extension.undertow.security.jacc.JACCContextIdHandler.handleRequest(JACCContextIdHandler.java:61)
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at io.undertow.servlet.handlers.ServletInitialHandler.handleFirstRequest(ServletInitialHandler.java:284)
at io.undertow.servlet.handlers.ServletInitialHandler.dispatchRequest(ServletInitialHandler.java:263)
at io.undertow.servlet.handlers.ServletInitialHandler.access[=16=]0(ServletInitialHandler.java:81)
at io.undertow.servlet.handlers.ServletInitialHandler.handleRequest(ServletInitialHandler.java:174)
at io.undertow.server.Connectors.executeRootHandler(Connectors.java:202)
at io.undertow.server.HttpServerExchange.run(HttpServerExchange.java:793)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
Caused by: org.jboss.resteasy.core.NoMessageBodyWriterFoundFailure: Could not find MessageBodyWriter for response object of type: com.aizaz.samples.model.ErrorResponse of media type: application/octet-stream
at org.jboss.resteasy.core.ServerResponseWriter.writeNomapResponse(ServerResponseWriter.java:66)
at org.jboss.resteasy.core.SynchronousDispatcher.writeException(SynchronousDispatcher.java:176)
... 32 more
相关部分
Caused by: org.jboss.resteasy.core.NoMessageBodyWriterFoundFailure:
Could not find MessageBodyWriter for response object of type:
com.aizaz.samples.model.ErrorResponse of media type: application/octet-stream
显然序列化失败,因为媒体类型:application/octet-stream。
我知道我可以在构建响应时明确指定媒体类型,例如
Response.ok().type(MediaType.APPLICATION_JSON).build();
但我不想那样做;因为我同时接受 JSON/XML 接受 headers 并希望以 JSON 或 XML 格式发回适当的回复。
- 我怎样才能做到这一点?
- 为什么在这种情况下使用媒体类型 octet-stream 创建响应?
我的意思是,如果我创建自定义异常,它由代码中描述的同一个 ExceptionMapper 映射;响应 object 不需要明确指定 MediaType.
如果有人能提供给我就太好了his/her宝贵的智慧
您可以使用 JAX-RS API 的 HttpHeaders
来管理 ExceptionMapper
返回的适当格式,并获取请求实体的 MediaType
,对比 javadoc:http://docs.oracle.com/javaee/7/api/javax/ws/rs/core/HttpHeaders.html#getMediaType--
所以你的代码如下:
@Provider
public class GenericExceptionMapper implements ExceptionMapper<Exception> {
@Context
private HttpHeaders m_headers;
private final Logger LOG = LoggerFactory.getLogger(GenericExceptionMapper.class);
@Override
public Response toResponse(Exception exception) {
ErrorResponse errorResponse = new ErrorResponse(exception.getClass().getSimpleName(), exception.getMessage());
if (exception instanceof WebApplicationException) {
LOG.error("Type: {}", exception.getClass().getSimpleName());
LOG.error("Message: {}", exception.getMessage());
WebApplicationException webApplicationException = (WebApplicationException) exception;
return Response.status(webApplicationException.getResponse().getStatus()).entity(errorResponse).build();
}
return Response.serverError().entity(errorResponse).type(m_headers.getMediaType()).build();
}
}
如果出现扩展 WebApplicationException
的自定义异常,例如
public class MyCustomException extends WebApplicationException
不需要显式 ExceptionMapper<MyCustomerException>
来处理异常和创建响应。
ExceptionMapper 对于处理源自 Exception
(或其子classes)而非 WebApplicationException
(及其子classes)的异常非常有帮助(注意 WebApplicationException
也是 Exception
的 child class)
例如,ExceptionMapper 可用于处理 IllegalArgumentException
等异常并创建响应。
在上述两种情况下,响应都可以根据在 Resource 方法中指定的 @Produces
进行序列化。
然而,在查看了 RestEasy 的规范实现后,我发现,即使 WebApplicationException
(s),如果 ExceptionMapper 被 rest 服务 @Provided
,它也会被触发。
resteasy-jaxrs:3.1.0.Final
class: ExceptionHandler
method: public Response handleException(HttpRequest request, Throwable e)
// First try and handle it with a mapper
if ((jaxrsResponse = executeExceptionMapper(e)) != null) {
return jaxrsResponse;
}
所以我要么确保 ExceptionMapper 用于某些特定的异常,例如 ExceptionMapper<IllegalArgumentException>
,而不是如上代码 ExceptionMapper<Exception>
所示捕获所有异常,或者只是 return 响应如下代码所示:
if (exception instanceof WebApplicationException) {
WebApplicationException webApplicationException = (WebApplicationException) exception;
return webApplicationException.getResponse();
}
不会出现序列化错误。为什么?因为框架会处理这个(基于 @Produces
注释,它将序列化基于 NON WebApplicationException 的响应的响应。对于基于 WebApplicationException
的响应,如上所示,框架也会处理响应(因为从未使用过 ErrorResponse 实体)
然而来到这张工单中提到的问题。 NotAllowedException
出现在规范实现代码 之前 与 URI 关联的方法被执行。因此 @Produces
注释不会生效,并且在编组响应时,使用默认的 MediaType octet-stream。
resteasy-jaxrs:3.1.0.Final
class: SegmentNode
method: public Match match(List<Match> matches, String httpMethod, HttpRequest request)
所以当出现以下异常时;
默认选项方法异常
不允许异常
不支持异常
NotAcceptableException
请求属性 RESTEASY_CHOSEN_ACCEPT
未设置
request.setAttribute(RESTEASY_CHOSEN_ACCEPT, sortEntry.getAcceptType());
return sortEntry.match;
当服务器尝试写入响应时,它找不到 MediaType(因为我们在创建响应时从未设置它 object)
resteasy-jaxrs:3.1.0.Final
class: ServerResponseWriter
method: public static void writeNomapResponse(BuiltResponse jaxrsResponse, final HttpRequest request, ...
if (jaxrsResponse.getEntity() != null && jaxrsResponse.getMediaType() == null) {
setDefaultContentType(request, jaxrsResponse, providerFactory, method);
}
它尝试从方法注释中设置它;如前所述,它从未设置过,因为 NotAllowedException
发生在 RESTEASY_CHOSEN_ACCEPT
可以设置之前。
它发现一个通配符,因为没有指定接受 headers,因此设置了八位字节流
resteasy-jaxrs:3.1.0.Final
class: ServerResponseWriter
method: protected static void setDefaultContentType(HttpRequest request, BuiltResponse ...
if (chosen.isWildcardType()) {
chosen = MediaType.APPLICATION_OCTET_STREAM_TYPE;
}
(这只是一个总结;有关详细步骤,我必须返回规范实现代码)
因此我必须指定媒体类型。这可以通过查看 @Context
中的 HttpHeaders
来使其动态化,或者如果在 headers 中没有指定任何内容,就像我的情况一样,我提供了一个默认的 MediaType Application/XML
用于序列化继续。
希望这对同样面临同样问题的人有所帮助。
我在这里展示简单的休息服务来说明我收到的异常。
服务A
@Path("/A")
public class ServiceA {
@GET
@Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
public Response show() {
return Response.ok(new User("John", "Doe")).build();
}
}
型号:
用户
@XmlRootElement
public class User {
private String firstName;
private String lastName;
public User() {
}
public User(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
}
错误响应
@XmlRootElement
public class ErrorResponse {
private String errorType;
private String errorMessage;
public ErrorResponse() {
}
public ErrorResponse(String errorType, String errorMessage) {
this.errorType = errorType;
this.errorMessage = errorMessage;
}
public String getErrorType() {
return errorType;
}
public void setErrorType(String errorType) {
this.errorType = errorType;
}
public String getErrorMessage() {
return errorMessage;
}
public void setErrorMessage(String errorMessage) {
this.errorMessage = errorMessage;
}
}
最后我的 ExceptionMapper 看起来像这样:
@Provider
public class GenericExceptionMapper implements ExceptionMapper<Exception> {
private final Logger LOG = LoggerFactory.getLogger(GenericExceptionMapper.class);
@Override
public Response toResponse(Exception exception) {
ErrorResponse errorResponse = new ErrorResponse(exception.getClass().getSimpleName(), exception.getMessage());
if (exception instanceof WebApplicationException) {
LOG.error("Type: {}", exception.getClass().getSimpleName());
LOG.error("Message: {}", exception.getMessage());
WebApplicationException webApplicationException = (WebApplicationException) exception;
return Response.status(webApplicationException.getResponse().getStatus()).entity(errorResponse).build();
}
return Response.serverError().entity(errorResponse).build();
}
}
在 URI 上调用 GET 我得到正确的响应:
Accept: application/json
GET http://localhost:8080/exception-mapper-example/rest/A
{"firstName":"John","lastName":"Doe"}
但是在这个 URI 上调用 POST 我得到一个异常:
2017-01-13 16:53:46,859 ERROR [com.aizaz.samples.exceptionmapper.GenericExceptionMapper] (default task-35) Type: NotAllowedException
2017-01-13 16:53:46,860 ERROR [com.aizaz.samples.exceptionmapper.GenericExceptionMapper] (default task-35) Message: RESTEASY003650: No resource method found for POST, return 405 with Allow header
2017-01-13 16:53:46,860 ERROR [io.undertow.request] (default task-35) UT005023: Exception handling request to /exception-mapper-example/rest/A: org.jboss.resteasy.spi.UnhandledException: org.jboss.resteasy.core.NoMessageBodyWriterFoundFailure: Could not find MessageBodyWriter for response object of type: com.aizaz.samples.model.ErrorResponse of media type: application/octet-stream
at org.jboss.resteasy.core.SynchronousDispatcher.writeException(SynchronousDispatcher.java:180)
at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:199)
at org.jboss.resteasy.plugins.server.servlet.ServletContainerDispatcher.service(ServletContainerDispatcher.java:221)
at org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher.service(HttpServletDispatcher.java:56)
at org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher.service(HttpServletDispatcher.java:51)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:790)
at io.undertow.servlet.handlers.ServletHandler.handleRequest(ServletHandler.java:85)
at io.undertow.servlet.handlers.security.ServletSecurityRoleHandler.handleRequest(ServletSecurityRoleHandler.java:62)
at io.undertow.servlet.handlers.ServletDispatchingHandler.handleRequest(ServletDispatchingHandler.java:36)
at org.wildfly.extension.undertow.security.SecurityContextAssociationHandler.handleRequest(SecurityContextAssociationHandler.java:78)
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at io.undertow.servlet.handlers.security.SSLInformationAssociationHandler.handleRequest(SSLInformationAssociationHandler.java:131)
at io.undertow.servlet.handlers.security.ServletAuthenticationCallHandler.handleRequest(ServletAuthenticationCallHandler.java:57)
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at io.undertow.security.handlers.AbstractConfidentialityHandler.handleRequest(AbstractConfidentialityHandler.java:46)
at io.undertow.servlet.handlers.security.ServletConfidentialityConstraintHandler.handleRequest(ServletConfidentialityConstraintHandler.java:64)
at io.undertow.security.handlers.AuthenticationMechanismsHandler.handleRequest(AuthenticationMechanismsHandler.java:60)
at io.undertow.servlet.handlers.security.CachedAuthenticatedSessionHandler.handleRequest(CachedAuthenticatedSessionHandler.java:77)
at io.undertow.security.handlers.NotificationReceiverHandler.handleRequest(NotificationReceiverHandler.java:50)
at io.undertow.security.handlers.AbstractSecurityContextAssociationHandler.handleRequest(AbstractSecurityContextAssociationHandler.java:43)
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at org.wildfly.extension.undertow.security.jacc.JACCContextIdHandler.handleRequest(JACCContextIdHandler.java:61)
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at io.undertow.servlet.handlers.ServletInitialHandler.handleFirstRequest(ServletInitialHandler.java:284)
at io.undertow.servlet.handlers.ServletInitialHandler.dispatchRequest(ServletInitialHandler.java:263)
at io.undertow.servlet.handlers.ServletInitialHandler.access[=16=]0(ServletInitialHandler.java:81)
at io.undertow.servlet.handlers.ServletInitialHandler.handleRequest(ServletInitialHandler.java:174)
at io.undertow.server.Connectors.executeRootHandler(Connectors.java:202)
at io.undertow.server.HttpServerExchange.run(HttpServerExchange.java:793)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
Caused by: org.jboss.resteasy.core.NoMessageBodyWriterFoundFailure: Could not find MessageBodyWriter for response object of type: com.aizaz.samples.model.ErrorResponse of media type: application/octet-stream
at org.jboss.resteasy.core.ServerResponseWriter.writeNomapResponse(ServerResponseWriter.java:66)
at org.jboss.resteasy.core.SynchronousDispatcher.writeException(SynchronousDispatcher.java:176)
... 32 more
相关部分
Caused by: org.jboss.resteasy.core.NoMessageBodyWriterFoundFailure:
Could not find MessageBodyWriter for response object of type:
com.aizaz.samples.model.ErrorResponse of media type: application/octet-stream
显然序列化失败,因为媒体类型:application/octet-stream。
我知道我可以在构建响应时明确指定媒体类型,例如
Response.ok().type(MediaType.APPLICATION_JSON).build();
但我不想那样做;因为我同时接受 JSON/XML 接受 headers 并希望以 JSON 或 XML 格式发回适当的回复。
- 我怎样才能做到这一点?
- 为什么在这种情况下使用媒体类型 octet-stream 创建响应?
我的意思是,如果我创建自定义异常,它由代码中描述的同一个 ExceptionMapper 映射;响应 object 不需要明确指定 MediaType.
如果有人能提供给我就太好了his/her宝贵的智慧
您可以使用 JAX-RS API 的 HttpHeaders
来管理 ExceptionMapper
返回的适当格式,并获取请求实体的 MediaType
,对比 javadoc:http://docs.oracle.com/javaee/7/api/javax/ws/rs/core/HttpHeaders.html#getMediaType--
所以你的代码如下:
@Provider
public class GenericExceptionMapper implements ExceptionMapper<Exception> {
@Context
private HttpHeaders m_headers;
private final Logger LOG = LoggerFactory.getLogger(GenericExceptionMapper.class);
@Override
public Response toResponse(Exception exception) {
ErrorResponse errorResponse = new ErrorResponse(exception.getClass().getSimpleName(), exception.getMessage());
if (exception instanceof WebApplicationException) {
LOG.error("Type: {}", exception.getClass().getSimpleName());
LOG.error("Message: {}", exception.getMessage());
WebApplicationException webApplicationException = (WebApplicationException) exception;
return Response.status(webApplicationException.getResponse().getStatus()).entity(errorResponse).build();
}
return Response.serverError().entity(errorResponse).type(m_headers.getMediaType()).build();
}
}
如果出现扩展 WebApplicationException
的自定义异常,例如
public class MyCustomException extends WebApplicationException
不需要显式 ExceptionMapper<MyCustomerException>
来处理异常和创建响应。
ExceptionMapper 对于处理源自 Exception
(或其子classes)而非 WebApplicationException
(及其子classes)的异常非常有帮助(注意 WebApplicationException
也是 Exception
的 child class)
例如,ExceptionMapper 可用于处理 IllegalArgumentException
等异常并创建响应。
在上述两种情况下,响应都可以根据在 Resource 方法中指定的 @Produces
进行序列化。
然而,在查看了 RestEasy 的规范实现后,我发现,即使 WebApplicationException
(s),如果 ExceptionMapper 被 rest 服务 @Provided
,它也会被触发。
resteasy-jaxrs:3.1.0.Final
class: ExceptionHandler
method: public Response handleException(HttpRequest request, Throwable e)
// First try and handle it with a mapper
if ((jaxrsResponse = executeExceptionMapper(e)) != null) {
return jaxrsResponse;
}
所以我要么确保 ExceptionMapper 用于某些特定的异常,例如 ExceptionMapper<IllegalArgumentException>
,而不是如上代码 ExceptionMapper<Exception>
所示捕获所有异常,或者只是 return 响应如下代码所示:
if (exception instanceof WebApplicationException) {
WebApplicationException webApplicationException = (WebApplicationException) exception;
return webApplicationException.getResponse();
}
不会出现序列化错误。为什么?因为框架会处理这个(基于 @Produces
注释,它将序列化基于 NON WebApplicationException 的响应的响应。对于基于 WebApplicationException
的响应,如上所示,框架也会处理响应(因为从未使用过 ErrorResponse 实体)
然而来到这张工单中提到的问题。 NotAllowedException
出现在规范实现代码 之前 与 URI 关联的方法被执行。因此 @Produces
注释不会生效,并且在编组响应时,使用默认的 MediaType octet-stream。
resteasy-jaxrs:3.1.0.Final
class: SegmentNode
method: public Match match(List<Match> matches, String httpMethod, HttpRequest request)
所以当出现以下异常时; 默认选项方法异常 不允许异常 不支持异常 NotAcceptableException
请求属性 RESTEASY_CHOSEN_ACCEPT
未设置
request.setAttribute(RESTEASY_CHOSEN_ACCEPT, sortEntry.getAcceptType());
return sortEntry.match;
当服务器尝试写入响应时,它找不到 MediaType(因为我们在创建响应时从未设置它 object)
resteasy-jaxrs:3.1.0.Final
class: ServerResponseWriter
method: public static void writeNomapResponse(BuiltResponse jaxrsResponse, final HttpRequest request, ...
if (jaxrsResponse.getEntity() != null && jaxrsResponse.getMediaType() == null) {
setDefaultContentType(request, jaxrsResponse, providerFactory, method);
}
它尝试从方法注释中设置它;如前所述,它从未设置过,因为 NotAllowedException
发生在 RESTEASY_CHOSEN_ACCEPT
可以设置之前。
它发现一个通配符,因为没有指定接受 headers,因此设置了八位字节流
resteasy-jaxrs:3.1.0.Final
class: ServerResponseWriter
method: protected static void setDefaultContentType(HttpRequest request, BuiltResponse ...
if (chosen.isWildcardType()) {
chosen = MediaType.APPLICATION_OCTET_STREAM_TYPE;
}
(这只是一个总结;有关详细步骤,我必须返回规范实现代码)
因此我必须指定媒体类型。这可以通过查看 @Context
中的 HttpHeaders
来使其动态化,或者如果在 headers 中没有指定任何内容,就像我的情况一样,我提供了一个默认的 MediaType Application/XML
用于序列化继续。
希望这对同样面临同样问题的人有所帮助。