【问题标题】:Why am I getting a 500 response for my POST on my Jersey REST API?为什么我在 Jersey REST API 上的 POST 收到 500 响应?
【发布时间】:2015-07-18 09:24:35
【问题描述】:

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

@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 标头有问题或缺失,但正如您在上面看到的,它已正确设置为“application/JSON”。

有什么想法吗?

【问题讨论】:

    标签: java jersey dropwizard postman


    【解决方案1】:

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

    如果您要返回一个表示,您应该始终确保使用@Produces 注释指定支持的格式。如果您想返回 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 标头。如果有Accept: application/json,那么没有@Produces,它将寻找MessageBodyWriter 来处理JSON。

    顺便说一句……

    accepted (202 Accepted) 表示

    请求已被接受处理,但处理尚未完成。

    您应该改用created(已创建201):

    请求已完成并导致创建新资源。新创建的资源可以被响应实体中返回的 URI 引用,该资源的最具体的 URI 由 Location 头字段给出。

    使用created,您无需显式调用location,您传递给方法的URI 将被设置为Location 标头。如果要加body,可以链entity(body)


    编辑:

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

    【讨论】:

    • 使用接受是一个有意识的决定。我无法返回已创建资源的表示,因为创建将是异步的。 (还没有实现它,但我知道我必须这样做。)那么我应该返回命令的 JSON 表示吗?对我来说似乎是多余的,但当然不会成为问题。
    • 有一个不带参数的accepted。我还要说,在大多数情况下它多余的。
    • 酷。无参数方法应该是我所需要的。我一回来工作就试试。你想编辑你的答案以便我接受吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-01-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-20
    相关资源
    最近更新 更多