Of course, but only because I now know there is a race condition. A better
design would prevent users from shooting themselves in the foot. Because
that design exists I may, in a unit test, be tempted to test the Future
result even thought my implementation uses the Callback. But now, after
trying that, I now know that it hurts when I do that. I suppose there must
be a reason both are present (future and callback) but I'm not sure what
that reason is.
On Fri, Jan 23, 2015 at 8:42 AM, Mikael Ståldal <
mikael.staldal_at_appearnetworks.com> wrote:
> But can't you just ignore the Future return value when you use a callback?
>
> On Fri, Jan 23, 2015 at 5:33 PM, Robert DiFalco <robert.difalco_at_gmail.com>
> wrote:
>
>> Agreed. Then you don't have to worry about the whole race condition
>> problem between future.get() #readEntity and callback.complete #readEntity.
>>
>> On Fri, Jan 23, 2015 at 12:43 AM, Mikael Ståldal <
>> mikael.staldal_at_appearnetworks.com> wrote:
>>
>>> To me i seems strange that the same API method both takes a callback and
>>> returns a Furure. It should be either or, not both.
>>>
>>> On Thu, Jan 22, 2015 at 7:48 PM, Robert DiFalco <
>>> robert.difalco_at_gmail.com> wrote:
>>>
>>>> Marek, the issue I had is that the behavior of getting a
>>>> Future<Response> with a callback is indeterminate. There seems to be a race
>>>> condition with readEntity such that even if you request the entity to be
>>>> buffered it can still end up as malformed in either the Future#get or the
>>>> InvocationCallback#completed.
>>>>
>>>> On Thu, Jan 22, 2015 at 9:34 AM, Mikael Ståldal <
>>>> mikael.staldal_at_appearnetworks.com> wrote:
>>>>
>>>>> > 1. InvocationCallback<Order> is run from some other thread (i.e.
>>>>> asynchronously) that has issued the request
>>>>>
>>>>> Yes, so far so good. But then I cannot access the response metadata
>>>>> (HTTP status, response headers).
>>>>>
>>>>> > 2. The callback is only invoked AFTER the
>>>>> Response.readEntity(Order.class) has completed. So having an
>>>>> InvocationCallback<Response> and invoking Response.readEntity(..) inside is
>>>>> not making things worse.
>>>>>
>>>>> So if I do like this:
>>>>>
>>>>> Invocation invocation = client.target(someURL).request().buildGet();
>>>>> invocation.submit(new InvocationCallback<Response> {
>>>>> public void completed(Response response) {
>>>>> int statusCode = response.getStatus();
>>>>>
>>>>> Order order = response.readEntity(Order.class); // blocking? process(statusCode, order);
>>>>> }
>>>>> public void failed(Throwable throwable) {
>>>>> error();
>>>>> }
>>>>> });
>>>>>
>>>>>
>>>>> It will not block on I/O when invoking response.readEntity(Order.
>>>>> class)?
>>>>> If so, my understanding of how it works was wrong, and the issue is
>>>>> invalid.
>>>>>
>>>>> > Perhaps you are looking for a non-blocking I/O API support
>>>>>
>>>>> I am, but this particular issue is not really about that.
>>>>>
>>>>> > Something like Response.readEntity(Order.class, order -> { … }) ?
>>>>>
>>>>> If it works the way you say (Response.readEntity is non-blocking since
>>>>> it just return something which has already been read, parsed and buffered
>>>>> in memory), that shouldn't be necessary.
>>>>>
>>>>> > Btw. do you know that you can easily check the response code from a
>>>>> JAX-RS ClientResponseFilter
>>>>> <https://jax-rs-spec.java.net/nonav/2.0-rev-a/apidocs/javax/ws/rs/client/ClientResponseFilter.html>
>>>>> ?
>>>>>
>>>>> To me, it seems quite clumsy if I would have to use a filter in this
>>>>> use case.
>>>>>
>>>>>
>>>>> On Thu, Jan 22, 2015 at 1:42 PM, Marek Potociar <
>>>>> marek.potociar_at_oracle.com> wrote:
>>>>>
>>>>>> Hi Mikael,
>>>>>>
>>>>>> Please see inline.
>>>>>>
>>>>>> On 12 Jan 2015, at 11:29, Mikael Ståldal <
>>>>>> mikael.staldal_at_appearnetworks.com> wrote:
>>>>>>
>>>>>> No, I did not get any answer to this. And neither to the JIRA issues
>>>>>> I have filed:
>>>>>>
>>>>>> https://java.net/jira/browse/JERSEY-2682
>>>>>>
>>>>>>
>>>>>> C&Ping my comment from the issue:
>>>>>>
>>>>>> I have looked at the issue and I’m not sure I understand the problem
>>>>>> you are pointing out:
>>>>>>
>>>>>> 1. InvocationCallback<Order> is run from some other thread (i.e.
>>>>>> asynchronously) that has issued the request
>>>>>> 2. The callback is only invoked AFTER the
>>>>>> Response.readEntity(Order.class) has completed. So having an
>>>>>> InvocationCallback<Response> and invoking Response.readEntity(..) inside is
>>>>>> not making things worse.
>>>>>>
>>>>>> Perhaps you are looking for a non-blocking I/O API support, which is
>>>>>> planned for the next release of JAX-RS
>>>>>> <https://jcp.org/en/jsr/detail?id=370>? Something like
>>>>>> Response.readEntity(Order.class, order -> { … }) ?
>>>>>> Btw. do you know that you can easily check the response code from a
>>>>>> JAX-RS ClientResponseFilter
>>>>>> <https://jax-rs-spec.java.net/nonav/2.0-rev-a/apidocs/javax/ws/rs/client/ClientResponseFilter.html>
>>>>>> ?
>>>>>>
>>>>>>
>>>>>> To me, it seems like the async part of the JAX-RS 2.0 client API is
>>>>>> flawed (not to mention the default implementation in Jeresy:
>>>>>> https://java.net/jira/browse/JERSEY-2058).
>>>>>>
>>>>>>
>>>>>> The primary problem is in lack of NIO support in the current JAX-RS
>>>>>> API. We’re looking into fixing it for the next JAX-RS release, as noted
>>>>>> above. Obviously, we will first try to make it work in Jersey, so Jersey
>>>>>> users should have a working solution long before JAX-RS.next is released. I
>>>>>> do not have any ETA at this point though.
>>>>>>
>>>>>>
>>>>>> It's a pity, since the synchronous client API in JAX-RS 2.0 (and its
>>>>>> implementation in Jersey) is really nice.
>>>>>>
>>>>>> I am considering using something else for async REST client, such as
>>>>>> https://github.com/AsyncHttpClient/async-http-client or Jetty client.
>>>>>>
>>>>>>
>>>>>> FWIW, our grizzly connector is actually wrapped into async HTTP
>>>>>> client API. But again, current lack of NIO support in JAX-RS APIs is making
>>>>>> it difficult to come up with a good async client solution. That said, we’re
>>>>>> already trying, stay tuned.
>>>>>>
>>>>>> Marek
>>>>>>
>>>>>>
>>>>>> On Wed, Dec 31, 2014 at 9:06 PM, Robert DiFalco <
>>>>>> robert.difalco_at_gmail.com> wrote:
>>>>>>
>>>>>>> Did you ever get an answer to this?
>>>>>>>
>>>>>>> On Mon, Oct 6, 2014 at 7:45 AM, Mikael Ståldal <
>>>>>>> mikael.staldal_at_appearnetworks.com> wrote:
>>>>>>>
>>>>>>>> Consider using Jersey client in async mode with an
>>>>>>>> InvocationCallback<Response>, and then use readEntity() on the Response.
>>>>>>>> Order is a custom domain object for which we have a MessageBodyReader
>>>>>>>> available.
>>>>>>>>
>>>>>>>> Invocation invocation = client.target(someURL).request().buildGet();
>>>>>>>> invocation.submit(new InvocationCallback<Response> {
>>>>>>>> public void completed(Response response) {
>>>>>>>> int status = response.getStatus();
>>>>>>>> if (status == 200) {
>>>>>>>> Order order = response.readEntity(Order.class); //
>>>>>>>> blocking ?
>>>>>>>> process(order);
>>>>>>>> } else {
>>>>>>>> error();
>>>>>>>> }
>>>>>>>> }
>>>>>>>> public void failed(Throwable throwable) {
>>>>>>>> error();
>>>>>>>> }
>>>>>>>> });
>>>>>>>>
>>>>>>>> Is the response.readEntity() call blocking? Is it I/O bound if the
>>>>>>>> response is large? Or is the whole response read from network before the
>>>>>>>> completed() callback is invoked?
>>>>>>>>
>>>>>>>> Will the asynchronicity be improved if I do
>>>>>>>> InvocationCallback<Order> instead? What if I want to get other information
>>>>>>>> from the Response?
>>>>>>>>
>>>>>>>> --
>>>>>>>> Mikael Ståldal
>>>>>>>> Chief Software Architect
>>>>>>>> *Appear*
>>>>>>>> Phone: +46 8 545 91 572
>>>>>>>> Email: mikael.staldal_at_appearnetworks.com
>>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>
>>>>>>
>>>>>> --
>>>>>> Mikael Ståldal
>>>>>> Chief Software Architect
>>>>>> *Appear*
>>>>>> Phone: +46 8 545 91 572
>>>>>> Email: mikael.staldal_at_appearnetworks.com
>>>>>>
>>>>>>
>>>>>>
>>>>>
>>>>>
>>>>> --
>>>>> Mikael Ståldal
>>>>> Chief Software Architect
>>>>> *Appear*
>>>>> Phone: +46 8 545 91 572
>>>>> Email: mikael.staldal_at_appearnetworks.com
>>>>>
>>>>
>>>>
>>>
>>>
>>> --
>>> Mikael Ståldal
>>> Chief Software Architect
>>> *Appear*
>>> Phone: +46 8 545 91 572
>>> Email: mikael.staldal_at_appearnetworks.com
>>>
>>
>>
>
>
> --
> Mikael Ståldal
> Chief Software Architect
> *Appear*
> Phone: +46 8 545 91 572
> Email: mikael.staldal_at_appearnetworks.com
>