users@jax-rs-spec.java.net

[jax-rs-spec users] Re: JAX-RS 2.1 - work schedule

From: Ondrej Mihályi <ondrej.mihalyi_at_gmail.com>
Date: Fri, 20 Jan 2017 12:56:20 +0100

Pavel raised a valid point, but it can really be solved by the GenericType
class, just moving the usage of the GenericType from method get to method
rx.

Here is a compilable and type-safe solution:

client.target("remote/forecast/{destination}")
      .resolveTemplate("destination", "mars")
      .request()
      .header("Rx-User", "Java8")
      .rx(new GenericType<CompletionStage<List<String>>>())
      .get();


with the new rx() method on Invocation.Builder defined simply like this:

public <T> RxInvoker<T> rx(GenericType<T> type);


You can play with the code in my fork here:
https://github.com/OndrejM/api/blob/reactive_provider_by_return_type/jaxrs-api/src/test/java/javax/ws/rs/core/RxClientTest.java#L105


However, this solution also provides cons:
  - it is uglier at first sight (although GenericType is always necessary
at some point sooner or later)
 - once converted to CompletionStage with proper type, it's not possible to
retrieve the generic Response object in a typesafe way (making the methods
like get(Class<R>) and get(GenericType<R> redundant - but maybe it;s a good
thing and simplifies the RxInvoker interface)


The ugly part can be simplified by any developer using a class that extends
GenericType like this (the code in my fork already shows that):

class CompletionStageType<T> extends GenericType<CompletionStage<T>>



And I don't think that the second drawback matters - if interested in
Response, it can be retrieved by

.rx(new GenericType<CompletionStage<Response>() {})
      .get();


and converted later if needed.


Ondrej

2017-01-19 19:31 GMT+01:00 Santiago Pericasgeertsen <
santiago.pericasgeertsen_at_oracle.com>:

>
> On Jan 19, 2017, at 1:12 PM, Markus KARG <markus_at_headcrashing.eu> wrote:
>
> Because in that "more complex" style you can write this then…
>
> Client rxClient = *client*.register(Java8.*class*); // i. e. *technically*
> a CompletionStageRxInvokerProvider, which effectively is part of
> JAX-RS!!!
>
>
>
> CompletionStage<UserPojo> cs =
>
> rxClient.target(*"http://foo.bar" <http://foo.bar/>*)
>
> .request()
>
> .rx(CompletionStage.*class*)
>
> .get(UserPojo.*class*);
>
>
> …so the average programmer clearly understands that this will *register
> Java 8* as one possible RX provider (possibly in addition to others), so
> he can *get a **CompletionStage*. It *feels* just more correct and
> simple, particular for JAX-RS beginners.
>
>
> Of course, but the point raised by Pavel is that this code again cannot
> (at least not obviously) be accepted by the Java type checker. Hence, the
> less desirable suggestion. Please read the rest of the e-mail thread.
>
> — Santiago
>
> They will not understand why they shall repeat *the provider* again and
> again, and they will not understand why rx(T) will return *not* return T.
> But I think they will accept to repeat *the stage* again and again, as
> stages are not reusable (they are used to do that with stages already).
>
> -Markus
>
> *From:* Santiago Pericasgeertsen [mailto:santiago.
> pericasgeertsen_at_oracle.com <santiago.pericasgeertsen_at_oracle.com>]
> *Sent:* Donnerstag, 19. Januar 2017 16:55
> *To:* jsr370-experts_at_jax-rs-spec.java.net
> *Subject:* Re: [jax-rs-spec users] JAX-RS 2.1 - work schedule
>
> Hi Pavel,
>
> Just catching up with this issue. I guess the two levels of indirection
> has led us into a generic wall :)
>
>
>
> Client rxClient = *client*.register(CompletionStageRxInvokerProvider.
> *class*);
>
>
>
> CompletionStage<UserPojo> cs =
>
> rxClient.target(*"http://foo.bar" <http://foo.bar/>*)
>
> .request()
>
> .rx(CompletionStage.*class*)
>
> .get(UserPojo.*class*);
>
> So what if we reduce indirection and write:
>
> .rx(CompletionStageRxInvoker.class)
>
> as before, still keeping the provider for it? Less ideal of course.
>
> — Santiago
>
>
>