users@jersey.java.net

[Jersey] Re: Creating a new WebTarget from an existing one

From: cowwoc <cowwoc_at_bbs.darktech.org>
Date: Thu, 17 Apr 2014 00:07:58 -0400

Robert,

I am not sharing server-side code with the client. CompaniesResources
implements my application's communication protocol on top of WebTarget.
Think of it as WebTarget plus business logic and helper methods.

I'm not saying that the 2.x API is a step backward on all fronts. I'm
just saying that in this particular instance I see no benefit of forcing
the user to lug around a Client instance when more often it's clear
which Client needs to be used. Take a look at Jersey's WebTarget
implementation: it takes in a Client, saves a copy of its config, and
discards the Client. It could very easily just keep a reference to the
Client instead. The external API would remain unchanged, and you could
add back the uri() method.

Gili

On 16/04/2014 11:59 PM, Robert DiFalco wrote:
> Yeah, for me it is pretty simple to do what you are saying. I just
> create a new target. I would never use my REST resource classes
> (CompaniesResource) on my client side except maybe to get a path
> annotation for unit testing. Your mileage may vary, but I found the
> 2.x API a VAST improvement.
>
>
> On Wed, Apr 16, 2014 at 7:28 PM, cowwoc <cowwoc_at_bbs.darktech.org
> <mailto:cowwoc_at_bbs.darktech.org>> wrote:
>
> Hi Robert,
>
>
> On 16/04/2014 6:23 PM, Robert DiFalco wrote:
>> Not sure what a WebResource is in 2.0 but isn't what you want to
>> do as simple as:
>>
>> client.target( response.getLocation() );
>
> In Jersey 1 you just needed to keep a reference to a WebResource.
> In Jersey 2, you need to keep a reference to both a Client and URI.
>
>
>> Or something equally simple? if it's relative you can use your
>> existing target and just do something like:
>>
>> target.path( relPath );
>
> Unfortunately, I'm talking about an (absolute) URI, not a relative
> path. I'll give you a concrete (client-side) example:
>
> * CompaniesResource.get() invokes HTTP GET /companies
> * The method returns a List<CompanyResource>, one entry per
> company returned by the response.
> * Each CompanyResource contains its own WebResource.
> * In Jersey 1, it was enough for a CompaniesResource to hold a
> reference to its own WebResource in order to construct a
> CompanyResource. In Jersey 2 it needs to keep a reference to
> both the Client and its own URI. Two references instead of one.
> * Consider:
> o This is a very common use-case (navigating links)
> o The user doesn't really care about the Client. This is
> almost an implementation detail for us (how often do we
> need multiple Clients?).
> o A single Client is shared across multiple resources, yet
> we're forced to store one reference per resource.
>
> And finally... According to "How to Design a Good API and Why it
> Matters" found at http://lcsd05.cs.tamu.edu/slides/keynote.pdf
>
> If you open page 28 you will find:
>
> * Don't make the Client Do Anything the Module Could Do:
> * Reduce the need for boilerplate code
>
> I believe this falls under the category of boilerplate code.
>
> Gili
>
>> On Wed, Apr 16, 2014 at 3:13 PM, cowwoc <cowwoc_at_bbs.darktech.org
>> <mailto:cowwoc_at_bbs.darktech.org>> wrote:
>>
>> Hi,
>>
>> In Jersey 1.0 we could create one WebResource from another as
>> follows:
>>
>> WebResource first = ...;
>> WebResource second = first.uri(newAddress);
>>
>> Naturally, when a resource returns a link we want to
>> construct a new resource using the new link using the same
>> Client. By removing support for this very common use-case,
>> you are forcing users to re-implement this themselves over
>> and over again in their code.
>>
>> Why was this use-case removed in Jersey 2.0?
>>
>> Thanks,
>> Gili
>>
>>
>
>