mardi 21 juillet 2015

JAX-RS AsyncResponse.resume() with Location header

UPDATE

Some more digging showed that thrown Exceptions were dropped and the actual problem is that an injected UriInfo could not be resolved in the AsyncResponse's thread!

Accessing @Context UriInfo uriInfo; during AsyncResponse.resume() gives the following LoggableFailure's message:

Unable to find contextual data of type: javax.ws.rs.core.UriInfo

ORIGINAL

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!

edit

As soon as I change any link or the header, the request will hang.

Aucun commentaire:

Enregistrer un commentaire