users@jax-rs-spec.java.net

[jax-rs-spec users] [jsr339-experts] Re: Re: Re: InvocationCallback changing?

From: Marek Potociar <marek.potociar_at_oracle.com>
Date: Thu, 28 Jun 2012 17:49:43 +0200

On Jun 28, 2012, at 5:05 PM, Bill Burke wrote:

>
>
> On 6/28/12 10:24 AM, Marek Potociar wrote:
>> Actually the latest example is what I'm looking at -
>> the InvocationCallback generic type itself (and not the generic type of
>> the response inside the InvocationCallback generic type). With my change
>> the implementations can all rely on the same type-inference code
>> implemented in the GenericType, like this:
>>
>> submit(InvocationCallback<T> callback) {
>> // ...execute request..
>> Class<?> responseClass = callback.getRawType();
>> Type responseType = callback.getType();
>>
>
> Why would application code need responseType and responseClass?

This is about JAX-RS implementations, not application code.

>
>> // ...read the response entity as the proper type and invoke the callback...
>> }
>>
>> Without extending InvocationCallback from GenericType (and with a lack
>> of any decent type-inference utilities in Java SE), all implementations
>> would need to find their own ways of computing the actual callback
>> response type, which is not as straightforward as it may seem.
>>
>
> With an interface, clients could still do:
>
> class MyGenericCallback<T> implements InvocationCallback<T> {
> }
>
> class MySpecificCallback extends MyGenericCallback<String> {}
>
> or just
>
> submit(new MyGenericCallback<String>(){});

But you MUST do the sub-classing trick and it is not an obvious thing. It's not even obvious why (to an average Java programmer). Errors the user would get if they forget to properly sub-class as it is done above may be very confusing as the problem is not easy to explain via an exception message IMO. In GenericType the problem is described in javadoc and if you failed to sub-class in this case, you would get an error during the instantiation. IOW, GenericType enforces the sub-classing as well as it documents it.

>
> or they could just use GenericType:
>
>
> class MyGenericCallback extends InvocationCallback<Response>
> {
>
> <T> T getEntity(GenericType<T> type)
> {
> response.readEntity(type);
> }
> }
>
> or, in the very weird off chance you need to get generic type information from the callback object itself,
>
> class MyGenericCallback extends InvocationResponse<Response>
> {
> public MyGenericCallback(GenericType genericType) {
> this.genericType = genericType;
> }
>
> public GenericType getGenericType() { return genericType; }
>
> ...
> }
>

As I tried to explain, this issue is not about specifying response type in the user application code. It is about getting the InvocationCallback generic type information in JAX-RS implementations (Jersey, CXF, RestEasy...). It is also about making sure the users avoid pitfalls with reification failures discussed above by failing early and in a documented way.

>
> Anyways, a few last questions: Isn't the use case you're describing an extreme edge case? If so, why are you designing towards a specific edge case when there are workarounds for that edge case? Why is this particular edge case more important than the edgecase where you'd want your callback class to extend an existing application abstract class?

Maybe it is... But I thought that it would still be good if our implementations shared the same code that computes the actual generic type - given it is readily available in the API anyway. But perhaps it was a bad idea.

>
> i.e. where you'd want:
>
> class MyCallback extends FooBar implements InvocationCallback<SomeType> {
> ...
> }
>
> There's just so many ways abstract classes constrict class design and there's simple workarounds for the particular edge case you're designing to.

As I said, there is more behind my reasons why I did the change, but maybe you're right.

Marek

>
>
>
> --
> Bill Burke
> JBoss, a division of Red Hat
> http://bill.burkecentral.com
>
>