jsr339-experts@jax-rs-spec.java.net

[jsr339-experts] HEADS-UP: Decide on fluent client API atributes: simplicity vs. consistency

From: Marek Potociar <marek.potociar_at_oracle.com>
Date: Thu, 25 Aug 2011 11:11:08 +0200

Dear experts,

over the last few days we've been debating about the recent update of the client API proposal[1] and the alternative
proposal submitted by Bill Burke[2]. (FWIW, as I finished this email I have noticed that Bill sent out a revised
proposal[3], but I did not have the time to look at it in detail yet. --Marek)

C1: Both proposals are shooting for allowing the fluent API with the HTTP verb at the end of the invocation chain, e.g.:

client.target(uri).request().accept("text/plain").get();

The main discussion evolves around fluent API simplicity vs. fluent context conistency.

Oracle position is that a major attribute of any fluent API is to be able to detect as many semantic errors statically
as reasonable at expense of an increased complexity in the class hierarchy. We believe that by introducing additional
intermediate builder interfaces the fluent API should actively prevent users from writing inconsistent or semantically
incorrect code, e.g.:

C2: client.target(uri).request().accept("text/plain").invoke(); // what method is invoked?
C3: client.target("http://someuri").request().path("http://otheruri").get() // fluently switching target uri in request?
C4: client.target(uri).request().method("PUT").type("text/plain").entity("Hello").get(); // should this be legal?

We believe that intermediate interfaces in the fluent API should also actively support IDE code completion in suggesting
only meaningful methods in the given fluent context - once you use "method("GET")" it should not offer you method
"put()" as a follow up, once you are done crafting the request uri and move to specifying headers, you should not be
able to go back to the uri crafting again in a single fluent invocation chain. We also believe that such API is better
described in examples as opposed to plain list of documented classes and methods, since most of the intermediate classes
and even methods might not make much sense outside the fluent invocation context. A good example of such API is a Google
Guice Binder API[4].

In contrast with the position described above, Bill is leaning towards the simplicity of the fluent API class hierarchy
that can be sufficiently described by a simple javadoc. The fluent API should be able to cover semantically meaningful
invocations such as in the code example C1. He argues that the fluent API should however not care too much about
statically preventing errors such as C2, C3, C4, since the larger problem cannot be fully solved anyway without
dramatically increasing the class hierarchy complexity. IOW, the code examples C2, C3, C4, should compile without any
errors (this statement might not fully apply to the revised Bill's proposal[3] --Marek).
Bill: Hope I have accurately described your high-level position regarding the client API. Feel free to elaborate on your
position if my description is incomplete or inaccurate.

As you can see, we are coming from completely opposing directions. To resolve this situation we need your feedback.
Please kindly step up and share your opinion with us!

Many thanks,
Marek & Santiago

[1] http://java.net/projects/jax-rs-spec/sources/git/show/src/jax-rs-api/src/main/java/javax/ws/rs/client/
[2] https://github.com/patriot1burke/redhat-jaxrs-2.0-proposals-rev2
[3] https://github.com/patriot1burke/redhat-jaxrs-2.0-proposals-rev2/tree/master/jax-rs-api-r3/src
[4] http://google-guice.googlecode.com/svn/trunk/javadoc/com/google/inject/Binder.html