[jax-rs-spec users] Re: Suggestion to refactor rx invoker API

From: Pavel Bucek <>
Date: Mon, 16 Jan 2017 11:48:18 +0100

Hi Sergey,

please see inline.

On 16/01/2017 11:11, Sergey Beryozkin wrote:
> Pavel, see comments below
> On 15/01/17 18:15, Pavel Bucek wrote:
>> Ondrej,
>> thanks for the proposal. I will look into it later, now I just want
>> to react to some things which are already being discussed here..
>> Sergey, Markus, thanks for evaluating Ondrejs proposal.
>> Please see inline.
>> On 15/01/2017 17:20, Sergey Beryozkin wrote:
>>> IMHO rx() needs to remain in order to get the default, this is as
>>> simple as it can get. Doing more than rx() in order to get
>>> CompletionStage would be bad.
>>> But I'm warming to something similar to what you are suggesting.
>>> .unwrap() is redundant IMHO.
>>> either rx() for the default
>>> or, example,
>>> RxInvoker<Observable> rxInvoker = rx(Observable.class)
>>> The reason it works better than the prototype suggested by Pavel is
>>> that this code is *portable*.
>>> Clearly, in most cases, it won't be the users who will create
>>> RxInvoker<Observable>, etc but Jersey, CXF, RestEasy will have
>>> dedicated modules with META-INF linking, in this case, Observable
>>> to a specific RxInvoker. This will be documented and users willing
>>> to work with non-default rx() will add a given module to the
>>> classpath...
>> Ideally, RxInvoker<Observable> is not created by Jersey nor CXF nor
>> RestEasy, but by 3rd party library, which works on ALL JAX-RS
>> implementations. Ideally RxJava itself could provide RxInvokerFactory
>> (or however that will end up named).
> It won't happen, ideally may be, but it won't - why would one host
> such a library and then maintain and release it ? At least the JAX-RS
> 2.1 projects will do and it will guarantee the users these libraries
> are in good shape. Someone can decide to do such a library but would
> you recommend Jersey users wait till it happens ?

I'm not an oracle (haha) to know the future, I hope it will happen in
some form. Or someone else, not related to rxjava could do it, it might
become popular and JAX-RS users would include it in their projects.

Anyway, if there is a question on Jersey user list and Jersey doesn't
provide it (and I know about 3rd party compatible extension), I have no
issue with recommending that.

>> That would allow the real portability, since you won't need to care
>> about which implementation is underneath and which features does it
>> provide. It will just work everywhere.
> I don't understand. In your proposal we have
> .rx(CompletionStageRxInvokerProvider.class)
> Users will want to use something like that, ex, after JAX-RS 2.1 final
> is out, (for RxJava for ex), immediately. So are you saying they will
> have to wait for some kind of a market place to appear where these
> libraries will be made available but would be implementers ?
> Even it it will happen, JAX-RS 2.1 projects will def ship their own
> implementations, CXF will def do it. And here is my point,
> .rx(CompletionStageRxInvokerProvider.class)
> will introduce a CXF/etc package into the code.

and where is the problem? Do you expect that module with rx invoker
provider, which is part of CXF, won't work when used with other
implementation? If the interface implementation is written properly and
there are no casts to implementation specific classes, it shouldn't matter.

> .rx(CompletionStage.class)
> will work with whatever library the users will choose, from Jersey,
> some 3rd party library, etc

Mine issue with this is that you usually dont want to do
rx(CompletionStage.class). You most likely want
rx(CompletionStage<List<String>>.class), which is not valid Java syntax.
And I must admit I don't like GenericType and I'll be always trying to
find an alternative which won't force that.

Best regards,

> Thanks, Sergey
>> Thanks and regards,
>> Pavel
>>> Sergey
>>> On 14/01/17 14:28, Markus KARG wrote:
>>>> Sounds good for me, but actually I think it would be even simpler
>>>> if we name it "unwrap()", and do not fill in any parameters. As I
>>>> said, I think applications will typically use only one technology
>>>> at the time. So "unwrap()" simply can check if there is a @Provider
>>>> registered having a method with the same parameters as your
>>>> proposed "conver()", we finally have the requested plugability, no
>>>> additonal complexity, follow existing JAX-RS patterns, and get rid
>>>> of repeating lots of "rx(Class)". :-)
>>>> -Markus
>>>> *From:*Ondrej Mihályi []
>>>> *Sent:* Samstag, 14. Januar 2017 12:54
>>>> *To:*
>>>> *Subject:* Suggestion to refactor rx invoker API
>>>> I was thinking about an alternative to current rx API, to simplify
>>>> it in context of supporting extensibility.
>>>> My idea is to modify the CompletionStageRxInvoker, so that it
>>>> returns an extension to CompletionStage, which would contain
>>>> additional method to convert the interface to any other reactive
>>>> interface:
>>>> public interface RxCompletionStage<T> extends CompletionStage<T> {
>>>> <NEW> NEW convert(Function<CompletionStage<T>, NEW> converter);
>>>> }
>>>> With this, we would move all the complexity to this new interface,
>>>> which still can be used as a usual CompletionStage, but with the
>>>> additional convert method, it provides an extension point to other
>>>> interfaces. And it's based on standard CompletionStage, therefore
>>>> we don't need additional rx invokers.
>>>> We could remove RxInvokerProvider, the 2 rx() methods from the
>>>> Builder, which accept RxInvokerProvider, and even remove the
>>>> RxInvoker interface, as CompletionStageRxInvoker would be the only
>>>> required implementation.
>>>> Here is an example of what I mean, with RxJava2 as an example:
>>>> *client*.request().rx().get(). // we get the RxCompletionStage
>>>> here, which extends CompletionStage
>>>> .convert(this::flowableFromStage) // accepts a function that
>>>> converts the CompletionStage to another interface .subscribe(s
>>>> -> testResult = s, Throwable::printStackTrace);
>>>> An example of a working code here
>>>> <>
>>>> (although not using JAX-RS, just wrapping a method that returns a
>>>> CompletionStage).
>>>> Ondrej