update
some more digging showed thrown exceptions dropped , actual problem injected uriinfo not resolved in asyncresponse's thread!
accessing @context uriinfo uriinfo; during asyncresponse.resume() gives following loggablefailure's message:
unable find contextual data of type: javax.ws.rs.core.uriinfo
original
according rfc 7231 http/1.1 semantics , control, postshould return 201 created , supply new resource's location in header:
the origin server should send 201 (created) response containing location header field provides identifier primary resource created (section 7.1.2) , representation describes status of request while referring new resource(s).
when writing synchronous rest server, javax.ws.rs.core.responseoffers response.created() shorthand that.
i save new entity, build uri , return
return response.created(createurl(created)).build(); however, when switch asynchronous approach utilizing
@suspended javax.ws.rs.container.asyncresponse
the http request on client 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 found out modified location header responsible. if return entity , set 201 created, without touching header, request 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 problem? misunderstanding concepts?
i running resteasy on glassfish4.1 if need more information, please comment!
edit
as change link or header, request hang.
in case ever has same problem:
the problem created location header through injected @context uriinfo uriinfo using .getabsolutepathbuilder().
the approach working in synchronous server because thread accessed uriinfo still had same request context.
however, when switched async approach, underlying runnable had access uriinfo.getabsolutepathbuilder() not within context - throwing exception halted further execution.
the workaround:
in async method should return location header, .getabsolutepathbuilder() while still within context. uribuilder implemantion can used within async run:
@post public void createuser(@valid user user, @suspended asyncresponse asyncresponse) { uribuilder ub = uriinfo.getabsolutepathbuilder(); executorservice.submit(() -> { user created = userservice.create(user); asyncresponse.resume( response.created(createurl(ub, created)).build() ); }); } private uri createurl(uribuilder builder, apirepresentation entity) { return builder.path(entity.getid().tostring()).build(); }
Comments
Post a Comment