为什么我的 Jersey REST API 上的 POST 收到 500 响应?

Why am I getting a 500 response for my POST on my Jersey REST API?

我刚刚开始实施我的第一个 Drowizard 项目。这是我的第一个资源 class:

@Path("/bill")
public class CommandResource {
    //...

    @POST
    @Consumes(MediaType.APPLICATION_JSON)
    @Path("/createBillForStudy")
    public Response handleCreateBillForStudyCommand(CreateBillForStudyCommand cmd, @Context UriInfo uriInfo)
    {
        System.out.println("Creating bill for command: " + cmd);

        UUID newId = billCreator.handle(cmd);

        URI location = uriInfo.getBaseUriBuilder().path(CommandResource.class).path("/" + newId).build();

        return Response.accepted(cmd).contentLocation(location).build();
    }
}

我想使用 Postman 对此进行测试,但以下请求导致 500 响应,我不明白为什么:

POST /bill/createBillForStudy HTTP/1.1
Host: localhost:8080
Content-Type: application/JSON
Cache-Control: no-cache

{ "idAccount": "123", "idStudy": "456", "timeStamp": "2014-01-01" }

这是我在 Dropwizard 控制台中看到的:

ERROR [2015-05-07 16:43:08,558] org.glassfish.jersey.message.internal.WriterInterceptorExecutor: MessageBodyWriter not found for media type=application/xml, type=class com.statista.billing.domain.commands.CreateBillForStudyCommand, genericType=class com.statista.billing.domain.commands.CreateBillForStudyCommand.
0:0:0:0:0:0:0:1 - - [07/Mai/2015:16:43:08 +0000] "POST /bill/createBillForStudy/ HTTP/1.1" 500 332 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.135 Safari/537.36" 8

对我来说,这听起来好像 Content-Type header 拧坏了或丢失了,但正如您在上面看到的,它已正确设置为 "application/JSON"。

有什么想法吗?

Response.accepted(Object)。这将 return 表示给客户。为了确定响应的Content-Type,我们需要指定它,它应该由Accept请求指定header.

如果您要 return 表示,您应该始终确保使用 @Produces 注释指定支持的格式。如果你想要 return JSON(与你接受 JSON 的方式相同,那么只需使用

@Produces(MediaType.APPLICATION_JSON)

当前的问题是响应正试图编组到 XML,如错误

所指定
MessageBodyWriter not found for media type=application/xml, 
          type=class com.s.b.d.c.CreateBillForStudyCommand

它默认为 XMl,因为您没有在 @Produces 中指定或客户端设置没有 Accept header。如果有 Accept: application/json,则没有 @Produces,它将寻找 MessageBodyWriter 来处理 JSON。

顺便说一句...

accepted (202 Accepted) 表示

The request has been accepted for processing, but the processing has not been completed.

你应该改用 created (201 Created):

The request has been fulfilled and resulted in a new resource being created. The newly created resource can be referenced by the URI(s) returned in the entity of the response, with the most specific URI for the resource given by a Location header field.

使用created,你不需要显式调用location,你传递给方法的URI将被设置为Location header.如果要加一个body,可以链entity(body)


编辑:

此外,如果您不想在响应中发送表示,您可以简单地调用 no-arg accepted() 方法。这不会发出响应 body,您应该不会再收到异常。