vendredi 17 juillet 2015

JAX-RS AsyncResponse.resume() with Location header

According to RFC 7231 HTTP/1.1 Semantics and Control, a POSTshould return 201 CREATED and supply the new resource's location in the header:

the origin server SHOULD send a 201 (Created) response containing a Location header field that provides an identifier for the primary resource created (Section 7.1.2) and a representation that describes the status of the request while referring to the new resource(s).

When writing a synchronous REST Server, the javax.ws.rs.core.Responseoffers the Response.created() shorthand which does exactly that.

I would save the new entity, build an URI and return

return Response.created(createURL(created)).build();

However, when I switch to an asynchronous approach utilizing a

@Suspended javax.ws.rs.container.AsyncResponse

the HTTP request on the client will hang infinitely:

@POST
public void createUser(@Valid User user, @Suspended AsyncResponse asyncResponse) {
    executorService.submit(() -> {
        User created = userService.create(user);
        asyncResponse.resume(
                Response.created(createURL(created)).build()
        );
    });
}

Through trial-and-error I found out that the modified location header is responsible. If I return my entity and set the 201 Created, without touching the header, the request will eventually resolve:

@POST
public void createUser(@Valid User user, @Suspended AsyncResponse asyncResponse) {
    executorService.submit(() -> {
        User created = userService.create(user);
        asyncResponse.resume(
                Response.status(Status.CREATED).entity(created).build()  //this works
                //Response.created(createURL(created)).build()
        );
    });
}

So what's the problem? Am I misunderstanding the concepts?

I am running RestEasy on GlassFish4.1 If you need more information, please comment!

Aucun commentaire:

Enregistrer un commentaire