dev@jsr311.java.net

Re: JSR311: Targets for _at_*Param, _at_DefaultValue, _at_Encoded

From: Stephan Koops <Stephan.Koops_at_web.de>
Date: Thu, 20 Mar 2008 14:42:10 +0100

Hello Paul,

*Before discussing more:*
Do you (and all) agree, that the specification should primarily support
the default lifecycle (instantiation per request), but make other
lifecycles possible?
Perhaps you discussed this earlier, but I do not read this, because I
entered the discussion late?

*clarify missunderstanding* (solution proposal later)
> The use of: String s = tlCharSequence.get().toString();
> is really convoluted and ugly.
I think here is a misunderstanding. My proposals mean:

   @*Param(...) private CharSequence charSequence;

Default lifecycle runtime environments inject a String, singelton
runtimes inject a proxy CharSequence, which will return the String by
toString().
It is read by

   charSequence.toString();

and returns the String for the current Thread. Works for both lifecycles.

The other possibility:

   @*Param(...) private ThreadLocal<String> name;

it is read by

   name.get();

and will also return the String in both cases. Works also for both
lifecycles.
> Same (really convoluted and ugly) goes for the use of a concrete
> implementation of java.lang.Number for just primitive types. In
> general any user defined class that supports either a String
> constructor or a static valueOf cannot be supported.
Same as above, read by intValue() doubleValue() and so on instead of
toString().
> IMHO the concept *is* complicated :-) it introduces a whole new set of
> restricted rules for parameters that i see very little value in.
IMO it introduces no restrictions. In contrast it allows more flexibility.
If a concrete runtime implementation use non-default lifecycles or other
non-defaults, than you are right, the runtime has perhaps problems and
have to see how to handle them, perhaps by rejecting some root resource
classes (as you proposed).
> Choosing the life-cycle has certain consequences to the style of
> programming
Of course. The default lifecycle is defined as "By default a new
resource class instance is created for each request to that resource."
(chapter "Resources", section "Resource Classes", subsection "Lifecycle
and Environment 9"). Let's primarily support this. You agree?
> and i would prefer to specify some very simple and concise rules: for
> non-per-request life-cycle a root resource class must have all of the
> following:
>
> 1) A constructor with no per-request-based annotations
> (we already require this rule)
Sorry, this rule is not specified. The spec define: "A public
constructor MAY include parameters annotated with one of the following:
@Context, @HeaderParam, @CookieParam, @MatrixParam, @QueryParam or
@PathParam" (chapter "Resources", section "Resource Classes", subsection
"Constructor")
> 2) No annotated fields with per-request-based annotations
>
> i would also like a third (but i can live without it):
>
> 3) No annotated bean setter methods with per-request-based annotations
> Any root resource class with a non-per-request life-cycle that does
> not conform to the above rules will not be deployed and will result in
> an error.
I fully agree for non-default lifecycles. It is ok, if a concrete
runtime environment use non default lifecycles, but than it has to
handle the resulting problems and perhaps not deploy this classes. But
to support non-default, we can not forbid a lot of things that are
useful in the default lifecycle. BTW: If we want support no-defaults, I
think there are some other ideas to forbid something ... :-)

*solution proposal*
The idea of the proposal was to have possibilities for both lifecycles
on fields (and perhaps setters). We can willingly throw my proposal
fully away AND allow @*Param on fields (and perhaps setters), with the
discussed consequences for non-default-lifecycle environments. This is
(iii) or (v). If a resource class (all setters and so on) is ready for a
singelton-lifecycle, but the signatures don't show this, than the
resource class (or the setter) could be annotated with an annotation
like @javax.ws.rs.ext.SingeltonReady.

One point is, that @*Param could be also possible on non root resource
classes. Also here the specification say, that they are instantiated by
the application, as default per request. If an app developer use this
default lifecycle and do not use @*Param on fields, than everything
works fine.

Another problem with the singelton lifecycle is, that an app developer
is allowed to use instance variables. This is not forbidden, but it is
nearly required, if you use @*Param on a constructor, which is allowed.
A possibility for singelton lifecycles is, to forbid any instance
variables (except instances using ThreadLocal internally, e.g. @Context
annotated). Than a non-default-lifecycle-runtime-environment have to
check this before deploy the root resource classes.

best regards
   Stephan

---------------------------------------------------------------------------------
Simple things should be simple, complex things should be possible. (Alan
Kay)

BTW: tomorrow (Good Friday) and on monday it's public holiday in Germany
and I will not look into my mailbox.
> Paul.
>
> Stephan Koops wrote:
>> Hello,
>>
>> a new (a little bit extended looking) proposal:
>>
>> (preambel :-) )
>> The default lifecycle for root resource classes (abbr: rrcs) is, that
>> an instance is created for every request. And for the default
>> lifecycle the specification should be made, IMO, but allow other
>> lifecycles. If an implementation use another lifecycle, it has to
>> accept more work in a little number of cases, IMO.
>>
>> To support this: For rrcs we have the following cases (did I miss
>> something?):
>>
>> 1. no fields and @*Param annotated bean setters are available -> no
>> problem.
>> 2. all fields and bean setters have type ThreadLocal<Whatever> -> no
>> problem.
>> 3. at least one not ThreadLocal typed and @*Param annotated field:
>> can work, if the runtime could support a ThreadLocal
>> implementation for the given type (e.g. proxy subclass).
>> 4. at least one @*Param annotated bean setters have not type
>> ThreadLocal<Whatever>: can work (setter use ThreadLocal), but
>> runtime don't know.
>> 5. other, non @*Param-annotated, non @Context and non ThreadLocal
>> fields are be available -> will typically not work, because it is
>> used as normal instance variable.
>>
>> A bettering for case 3: We could also allow CharSequence with String
>> as default for fields and bean setter, so a String like type is also
>> available for runtime environments with singelton rrc lifecycle. I
>> think, that Strings (or more general CharSequences) are mostly used
>> for @*Param values. Perhaps we could also allow java.lang.Number with
>> Double as default, if a "." is available in the String to parse, or
>> Integer or Long, if no "." is available in the String to parse. An
>> implementation could also create a subclass thread local proxy.
>>
>> A solution for the last case could be an official annotation
>> @SingeltonReady on a rrc. If it is available on a rrc, also a
>> non-default lifecycle could be supported, also if checks 3 and 4 do
>> not pass.
>>
>> This concept looks complicated, but it has the following advantages:
>>
>> * nothing will change for implementations and app developers using
>> default rrc lifecycle (only add the injection in annotated fields
>> an bean setters), but
>> * a lot of flexibility for @*Param (everywhere (iv)/(v) on rrcs and
>> also on other resource classes)
>> * singelton lifecycle with detection of trouble creating rrcs is
>> available, but also
>> * allow rrcs to be runned as singelton, also if it's interface does
>> not show this. (e.g. setter with int parameter, but rrc maps this)
>>
>> The additional work for singelton lifecycle runtime environments is
>> to check, if the rrc is valid for this lifecycle (see 4 points at top).
>>
>> What do you think?
>>
>> Stephan
>>
>> Marc Hadley schrieb:
>>> On Mar 19, 2008, at 5:09 AM, Paul Sandoz wrote:
>>>> Option (v) seems a no go to me since AFAICT it is not possible to
>>>> cleanly and directly proxy non-interface based stuff, thus String
>>>> is not possible since it is final, makes it hard to support things
>>>> extending Number (Integer, BigDecimal etc), and there is no easy
>>>> solution for user-defined classes to process parameters. Hence one
>>>> would have to explicitly declare:
>>>>
>>>> @QueryParam("abc") ThreadLocal<String> abc;
>>>>
>>>> which sucks IMO.
>>>>
>>> Agreed, given this new information I think option (v) is a no-go.
>>>
>>>> If we really have to allow @*Param on fields and methods then
>>>> option (iv) seems better. It introduces an additional dependency on
>>>> life-cycle. In effect it is not just a Singleton resource, but
>>>> anything other than a per-request resource where an instance of the
>>>> resource class is retained beyond the scope of a request. (There is
>>>> an existing dependency on constructors).
>>>>
>>>> I would be inclined to say field and method (bean setter) are only
>>>> supported for per-request resources. Thus if a developer chooses a
>>>> non-per-request resource there are less ways for bullets to hit feet.
>>>>
>>> Seems like (iv) is closest to what the majority of the EG preferred
>>> so unless there's further discussion I think that is the option we
>>> should go for.
>>>
>>> Marc.
>>>> Marc Hadley wrote:
>>>>> There's been a lot of discussion of whether or not to expand the
>>>>> targets (i.e. what Java artifacts you can use the annotation on)
>>>>> of the @*Param annotations (i.e. @PathParam etc al). If we do add
>>>>> targets for these annotations I think we also need to do the same
>>>>> for @DefaultValue and @Encoded. I'm uncomfortable adding targets
>>>>> that are only supported in some implementations so if we do add
>>>>> targets they will be required to be supported on resource classes
>>>>> (not providers) in all implementations.
>>>>> Discussion so far has been between Bill, Stephan and myself, I'd
>>>>> like to hear from others hence this poll. Please choose from the
>>>>> following and reply to the list with your selection. Silence means
>>>>> you don't care what happens - how could that be ;-).
>>>>> Here are the options for target I see:
>>>>> (i) Parameter. The status quo. Works with any lifecycle.
>>>>> (ii) Parameter and field. Spec will warn that use on a field in a
>>>>> singleton resource isn't supported.
>>>>> (iii) Parameter and field. Spec will require use of a proxy for
>>>>> field injection. Pro: singletons can be supported. Con: will
>>>>> affect performance. Con: still won't work for simple types, spec
>>>>> will warn about this.
>>>>> (iv) Parameter, field and method (bean setter). Spec will warn
>>>>> that use on a field in a singleton resource isn't supported and
>>>>> that use on method will require application-managed thread-local
>>>>> handling. Pro: bean setter enable support for singletons. Con:
>>>>> complicated bean setters.
>>>>> (v) Parameter, field and method (bean setter). Spec will require
>>>>> use of a proxy for field and method injection. Same pros and cons
>>>>> as (iii).