> > looks promising so far, but as it is a rather lot of classes and
> methods you possible might have expected correctly already that I will
> have a lot of comments to post... ;-) So here they are.
> >
> > * As we are heavily using Java EE, we are running our clients in Java
> EE Application Client Containers, and the web resource is located in
> the same domain's server container. So it is very annoying that the
> client application must provide the URI of the web resource. With JAX-
> WS it gets the end point injected. It would therefore be really good to
> get injected a WebResource into the client. Handling of the Client must
> be provided by the Java EE Application Client Container in that case.
> For Java EE Fat Client vendors this would be a highly appreciated
> feature, which got already discussed between Paul Sandoz and the Java
> EE team AFAIK. This certainly enforces that a Java EE compliant
> Application Client Container MUST provide an implementation of the JAX-
> RS Client API. Obviously it makes sense to extend this to all Java EE
> containers, as any Java EE component could be a client in turn.
>
> I wonder what would be the type of the injected instance. In JAX-WS
> it's obviously the typed web service proxy since
> JAX-WS is an RPC based architecture. But what are you suggesting to be
> injected in the case of a RESTful API?
>
> Do you have in mind something like:
>
> @Path("somePath")
> MyResource { ... }
>
> MyClient {
> @ResourceRef(MyResource.class) WebResource resource; // URI
> calculated automatically
> ...
> }
>
> ?
Yes exactly that.
> > * Support for HTTP/1.1 sessions: I did not find information in the
> JavaDoc how an application can tell whether a HTTP call shall run in
> the same or in a different HTTP/1.1 session against the same
> WebResource (since WebResource is not called WebResourceSession, I
> expect that it handles sessions internally).
>
> Is that something you would need in a RESTful API? What would be the
> use case?
Hm... good question. Seems I had something in mind with per-session data. On the other had, REST is by definition stateless, so maybe it was just a bad idea.
> > * I'm not a big friend of abstract classes since it reduces the
> freedom of the provider. Why not just providing an interface for
> ClientFilter? I doubt that anybody is unable to write that single code
> line that keeps the "next" reference. Also, as a WebResource is only to
> be created by a builder and the builder is to be provided by a JAX-RS
> implementation, I do not see a need to provide more than the
> WebResource's interface as part of the spec. It should be completely up
> to the implementation how WebResource works internally and what it
> extends from.
>
> This is going to be redesigned as part of the task #99.
>
> As for the interface vs. abstract class, I prefer interfaces too, but
> we need to understand that there is a serious
> limitation: you cannot add new methods into an interface in a future
> release without breaking BW compatibility.
I think this could be solved, e. g. by versioned interfaces as Microsoft did in the Win32 API or by additional interfaces for new methods. We use the latter pattern a lot as having a single interface for a task often is typical but actually not needed.
Or we accept that breaking BW compatibility is not that big issue as we all might think: Nobody is forced to switch to the next generation of Java EE. If one does, he actually has much bigger problems that the need to recompile...
> > * I'm not a mathematical expert, but WebResourceBase's .hashCode()
> implementation looks rather complex. I think "return
> this.getClass().hashCode() ^ this.uri.hashCode()" would do and would be
> much simpler? Looks like some black magic currently. ;-)
> >
>
> Me neither, that's why I used my IDE to generate it for me. I would be
> happy to change it if you can prove that your
> version provides a widely spread hash codes :)
What mass of WebResource instances do you plan to create at runtime that hashCode performance will be an issue actual? Do you even plan to use WebResource in any kind of Collection (otherwise nobody would call hashCode anyways)?
And: Can your IDE proof that your algorithm is better spread than mine? ;-) As all I do is calling existing JVM hash code methods (which should be done well) and XORing them to not lose too much information, I expect them to be rather well spread for the target use. :-)
> > * Why insisting on ClientRequest being Cloneable?
>
> Since it seems we will have a fully mutable request, to be able to
> reuse a preconfigured request in multiple
> invocations, having it cloneable may come handy IMO.
Can you give an example of ClientRequest reuse? Why not just using the same instance?
> > * Is it essential to keep the ordering of cookies? If not, why then
> returning List<NewCookie> instead of just Collection<NewCookie>?
>
> Is there any signinficant advantage behind that generalization? List
> provides more manipulation methods compared to
> collection. How about Set?
You are reducing the freedom of the user of the Collection without any particular need.
It is a default pattern of mine to use the topmost generalization whenever possible, to give the user the most possible freedom.
Set would be better than List as it at least has a use: It expresses that a Cookie cannot be duplicate.
But again, why *not* Collection?
What benefit does the caller have from List? Why should a caller manipulate the contents?
> > * Can you provide a use case when a user will apply the
> ClientResponse.bufferEntity() method?
>
> E.g. you want to execute XQuery on the returned XML stream?
Still didn't get the point (sorry I am using XPath a lot but am not used to XQuery). How will that work? If I will run XPath for example, I would just pick the entity, surround it with JAXBSource and run JAXP. No need for that method so far. So what is it actually good for?
> > * The current proposal seems to expect that a WebResources get
> filtered ever or never, but it might be the case where filtering is
> dependend of the current session. So the question is where we need to
> support that. Currently it won't work as removing a filter while an
> asynchrounous request is pending might lead to unknown behaviour.
>
> Can you share the use case in particular? I am confused by the notion
> of the session - I thought we are shooting for a
> stateless API.
Yes and no. First, it was a hypothetical question. Second, the question is whether we need to support something like sessions (client-side, not server-side). See, the service's is stateless, but one might have a need to have some kind of transaction (not in the database sense), or let's better call it, a business process. That process involves lots of GET and PUT, which in the end create what the user wants (like a money transfer involves many GETs and PUTs on different resources). Each single invocation is stateless, but the process itself is definitively there and must keep state on the client (it must track the state of both accounts whilst the transfer is running and if one method fails it has to decide what to do with both accounts now). To model that, it might be beneficial to have sessions (aka business processes). Now it could happen that one such session needs a filter, while another does not. For example, if your credit card was stolen, the ATM (= client) shall track all communication with your account. Not with the bank server in generel, only with YOUR account. So the filter will be account dependent, not server or JAX-RS-Resource dependent.
> > * I am the maintainer of the WebDAV package for JAX-RS and so I am
> heavily interested in providing a WebDAVMethodInvoker as a replacement
> for the HttpMethodInvoker. But I did not find a way how a calling
> application could register interest is that. How to do that?
>
> So basically you want something like unwrap(Class<T> clazz) on a web
> resource?
I don't know if I want that ;-)
The question more is: How does a client obtain an instance of HttpMethodInvoker to call one of the convenience methods? That mechanism shall be extendible, so a client can obtain an instance of WebDAVMethodInvoker instead to call .propfind() or .search() instead of .put() and .post().
> > * A GUI might be heavily interested in getting updated after
> receivering another HTTP chunk. I didn't find a way how an application
> could register for such events. This is essential to show a progress
> bar with long-lasting downloads.
>
> Let me have a look at that - added new subtask #105. But it seems to me
> that this is something that should be done at
> the transport layer.
Yes but the problem is that the client has no influence on the transport layer. A client on Java SE cannot register at the transport level as it is up to the JAX RS Engine to select or implement the transport layer. Or did I miss something, like "Client.getTransport()" where a client could register for such events?
Regards
Markus