Alright :)
After having a chat with Santiago, I tried to prototype "real provider"
approach, which would result in code like:
Client rxClient =client.register(CompletionStageRxInvokerProvider.class);
CompletionStage<UserPojo> cs =
rxClient.target("
http://foo.bar")
.request()
.rx(CompletionStage.class)
.get(UserPojo.class);
(let's not talk about built-in support for CompletionStage and consider
this as a valid extension, provided by CompletionStageRxInvokerProvider
registered to the client).
The major change here is the "rx" method signature, which would be:
public interface Invocation {
// ...
public static interface Builderextends SyncInvoker {
// ...
public <T> RxInvoker<T> rx(Class<T> clazz);
}
}
The major change here is the return type. It is no longerT ? extends
RxInvoker, it is RxInvoker<T>. And that brings and issue I don't know
how to deal with. To be able to do the example code (first code
snippet), we'd need something like:
public interface RxInvoker<T> {
// ...
public <R>T<R> get(Class<R> responseType);
}
Problem is that this is not a valid Java syntax. We simply cannot do
T<R>. Let's compare that to previous proposal:
public interface Invocation {
// ...public static interface Builderextends SyncInvoker {
// ...public <T extends RxInvoker>T rx(Class<?extends RxInvokerProvider<T>> clazz);
}
}
public interface RxInvoker<T> {
// ...public <R>T get(GenericType<R> responseType);
}
The main difference (and the reason why it works) is the return type if
Invocation.Builder#rx(..) is an instance of subclass of RxInvoker, not
of a RxInvoker<T>. That allows to override return type of
RxInvoker#get(..) method, exactly as it is done in
CompletionStageRxInvoker:
public interface CompletionStageRxInvokerextends RxInvoker<CompletionStage> {
// ...
@Override public <T> CompletionStage<T> get(Class<T> responseType);
}
Does anyone know how to solve this issue? (because if not, I don't see
how we can design/support "real provider" case). I'm looking forward to
any comments. If you want to play with latest change, feel free to clone
[1], the example is [2], Invocation.Builder#rx [3] and RxInvoker [4].
Thanks and regards, Pavel [1]
https://github.com/pavelbucek/jax-rs [2]
https://github.com/pavelbucek/jax-rs/blob/rx-client/jaxrs-api/src/test/java/javax/ws/rs/core/RxClientTest.java#L110
[3]
https://github.com/pavelbucek/jax-rs/blob/rx-client/jaxrs-api/src/main/java/javax/ws/rs/client/Invocation.java#L338
[4]
https://github.com/pavelbucek/jax-rs/blob/rx-client/jaxrs-api/src/main/java/javax/ws/rs/client/RxInvoker.java#L86
On 17/01/2017 17:41, Ondrej Mihályi wrote:
> +1
> ||
> 2017-01-17 16:57 GMT+01:00 Santiago Pericasgeertsen
> <santiago.pericasgeertsen_at_oracle.com
> <mailto:santiago.pericasgeertsen_at_oracle.com>>:
>
>> On Jan 13, 2017, at 6:19 PM, Ondrej Mihályi
>> <ondrej.mihalyi_at_gmail.com <mailto:ondrej.mihalyi_at_gmail.com>> wrote:
>> Actually, I like the unwrap method more than the current
>> proposal. It makes it explicit what I want to get when I write
>> code. The current proposal is similar, but requires me to
>> remember the name of the invoker on top of the rx interface I
>> want to get.
>> Compare:
>> _Current proposal _
>> CompletionStage<List<String>> cs = client.request()
>> .rx(CompletionStageRxInvokerProvider.class)
>> .get(new GenericType<List<String>>() {
>> });
> Perhaps we should explore turning this into a "real provider”.
> I.e., something that is registered in the runtime and looked up by
> the JAX-RS implementation. In which case, the param to rx() could
> be CompletionStage.class instead. This would be more inline with,
> say, ParamConverters.
> — Santiago
>