From alex.buckley at oracle.com Mon Dec 3 12:30:10 2012 From: alex.buckley at oracle.com (Alex Buckley) Date: Mon, 03 Dec 2012 12:30:10 -0800 Subject: Retrofitting Java EE annotation types In-Reply-To: <503E67FE.7010807@oracle.com> References: <503E67FE.7010807@oracle.com> Message-ID: <50BD0BD2.9050400@oracle.com> Bill, Mike, Can you share your plans to retrofit existing EE annotation types to support repetition? Also, it would be helpful to know if your annotation-reading frameworks are working OK with the modified core reflection API. Alex On 8/29/2012 12:05 PM, Bill Shannon wrote: > Just to provide a little background for people here... > > This is something we've been asking for for some time to support our > use of annotations in Java EE. We worked with Alex to ensure that > this proposal will meet our needs. We believe it does, and we plan > to retrofit our existing annotations to take advantage of this new > feature when it's available. > > Thanks to Alex for putting this together and working through all the > details to make it a formal spec! > > Bill Shannon > Java EE Spec Lead > From alex.buckley at oracle.com Tue Dec 4 12:20:45 2012 From: alex.buckley at oracle.com (Alex Buckley) Date: Tue, 04 Dec 2012 12:20:45 -0800 Subject: Parameter reflection without MethodParameters attribute Message-ID: <50BE5B1D.1040100@oracle.com> The new java.lang.reflect.Parameter class exposes a parameter's 1) name, 2) finality, 3) author (via isSynthetic() and isSynthesized() - if neither is true, then author was human), 4) whether it's a variable arity parameter, 5) annotations, and 6) type. Sidebar: If you're wondering about "variable arity parameter", see JLS 8.4.1. The existence of synthetic parameters means that the last Parameter object from Executable.getParameters() might not be the variable arity parameter declared in source, so each Parameter object needs to expose whether it's variable arity. The methods for (5) return fundamentally the same info as Method.getParameterAnnotations(), so it's clear what to return when no annotation attributes are present: null values and empty arrays. But the methods for (1)-(4) are tricky when no MethodParameters attribute is available. Should a parameter's name be the empty string, with no modifiers set, and not flagged as synthetic or synthetized or variable arity? And then have an Executable.hasParameterMetadata() method to say whether these values are reliable? Maybe there should be Optional wrappers for parameter info ... only joking, this is not the place to solve Java's "missing value" woes. I think the best option is to sidestep these questions by having Executable.getParameters() return an empty array if no MethodParameters attribute is available. SE8 and greater class files may give an empty array, while pre-SE8 class files must give an empty array. (The same ought to apply for annotations: in a pre-SE5.0 class file, an attribute called RuntimeVisibleAnnotations means nothing, and ought to be ignored by core reflection, though I have a feeling it will be exposed.) Alex From alex.buckley at oracle.com Wed Dec 5 14:46:23 2012 From: alex.buckley at oracle.com (Alex Buckley) Date: Wed, 05 Dec 2012 14:46:23 -0800 Subject: Tweaking the language model API for repeating annotations Message-ID: <50BFCEBF.1060005@oracle.com> We discovered two small issues with section 1.3 of the spec: 1. The spec proposes a new method, Element.getAnnotations(). This method is proposed for consistency with AnnotatedElement.getAnnotations(), but it turns out to be difficult to implement in the context of the language model. The problem is that, at compile-time, there might not be instances of Class objects for the annotations we try to look at. The other new methods - Element.getAnnotation[s](Class) - do not have this issue since their callers must supply a Class object. It would be possible for Element.getAnnotations() to throw exceptions if necessary Class objects were not found, but there is no good unchecked exception type available in the language model API. It would also be possible to skip over annotations for which Class objects are unavailable, and return incomplete results, but this seems undesirable. I propose to drop the method. Essentially, it's fine in core reflection but too brittle for the language model. 2. The spec proposes to refine Element.getAnnotationMirrors() and Elements.getAllAnnotationMirrors(). If the language model API only has a class file available for the element on which annotation mirrors are requested, then the API cannot be sure that it's right to "look through" @FooContainer (if directly present on the element) and return @Foo mirrors. This is true even if FooContainer is a well-formed containing annotation type available to the API. The source code of the element - which the API strives to reflect - could literally have said @FooContainer(...). Unfortunately, a compiler has no way to mark a container annotation as "synthesized" during class file generation. It would be possible to adopt a policy of always looking through container annotations on an element. This requires the language model API to recognize container annotations, which in turn requires loading the annotation's class file, which might not always be available. I propose to adopt this policy, while allowing the methods to sometimes expose container annotations even if not present in source code. Alex From alex.buckley at oracle.com Thu Dec 6 12:01:22 2012 From: alex.buckley at oracle.com (Alex Buckley) Date: Thu, 06 Dec 2012 12:01:22 -0800 Subject: Spec updates for repeating annotations (reflection) In-Reply-To: <50BFCEBF.1060005@oracle.com> References: <50BFCEBF.1060005@oracle.com> Message-ID: <50C0F992.3040506@oracle.com> I have updated section 1.3 of the spec as proposed below. I have also 1) added remarks at the start of chapter 1 to explain the design, and 2) added examples in section 1.2 (core reflection) to cover more scenarios. The spec is at http://cr.openjdk.java.net/~abuckley/8misc.pdf as usual. Alex On 12/5/2012 2:46 PM, Alex Buckley wrote: > We discovered two small issues with section 1.3 of the spec: > > > 1. The spec proposes a new method, Element.getAnnotations(). > > This method is proposed for consistency with > AnnotatedElement.getAnnotations(), but it turns out to be difficult to > implement in the context of the language model. The problem is that, at > compile-time, there might not be instances of Class objects for the > annotations we try to look at. The other new methods - > Element.getAnnotation[s](Class) - do not have this issue since their > callers must supply a Class object. > > It would be possible for Element.getAnnotations() to throw exceptions if > necessary Class objects were not found, but there is no good unchecked > exception type available in the language model API. It would also be > possible to skip over annotations for which Class objects are > unavailable, and return incomplete results, but this seems undesirable. > > I propose to drop the method. Essentially, it's fine in core reflection > but too brittle for the language model. > > > 2. The spec proposes to refine Element.getAnnotationMirrors() and > Elements.getAllAnnotationMirrors(). > > If the language model API only has a class file available for the > element on which annotation mirrors are requested, then the API cannot > be sure that it's right to "look through" @FooContainer (if directly > present on the element) and return @Foo mirrors. > > This is true even if FooContainer is a well-formed containing annotation > type available to the API. The source code of the element - which the > API strives to reflect - could literally have said @FooContainer(...). > Unfortunately, a compiler has no way to mark a container annotation as > "synthesized" during class file generation. > > It would be possible to adopt a policy of always looking through > container annotations on an element. This requires the language model > API to recognize container annotations, which in turn requires loading > the annotation's class file, which might not always be available. > > I propose to adopt this policy, while allowing the methods to sometimes > expose container annotations even if not present in source code. > > > Alex From joe.darcy at oracle.com Thu Dec 6 17:22:49 2012 From: joe.darcy at oracle.com (Joseph Darcy) Date: Thu, 06 Dec 2012 17:22:49 -0800 Subject: Tweaking the language model API for repeating annotations In-Reply-To: <50BFCEBF.1060005@oracle.com> References: <50BFCEBF.1060005@oracle.com> Message-ID: <50C144E9.4040906@oracle.com> Hello, On 12/5/2012 2:46 PM, Alex Buckley wrote: > We discovered two small issues with section 1.3 of the spec: > > > 1. The spec proposes a new method, Element.getAnnotations(). > > This method is proposed for consistency with > AnnotatedElement.getAnnotations(), but it turns out to be difficult to > implement in the context of the language model. The problem is that, > at compile-time, there might not be instances of Class objects for the > annotations we try to look at. The other new methods - > Element.getAnnotation[s](Class) - do not have this issue since > their callers must supply a Class object. > > It would be possible for Element.getAnnotations() to throw exceptions > if necessary Class objects were not found, but there is no good > unchecked exception type available in the language model API. It would > also be possible to skip over annotations for which Class objects are > unavailable, and return incomplete results, but this seems undesirable. > > I propose to drop the method. Essentially, it's fine in core > reflection but too brittle for the language model. I vaguely recall that during JSR 269 we didn't provide the getAnnotations() method on javax.lang.model.element to avoid the problems of potentially missing Class objects so I agree we can drop this from the model API. > > > 2. The spec proposes to refine Element.getAnnotationMirrors() and > Elements.getAllAnnotationMirrors(). > > If the language model API only has a class file available for the > element on which annotation mirrors are requested, then the API cannot > be sure that it's right to "look through" @FooContainer (if directly > present on the element) and return @Foo mirrors. > > This is true even if FooContainer is a well-formed containing > annotation type available to the API. The source code of the element - > which the API strives to reflect - could literally have said > @FooContainer(...). Unfortunately, a compiler has no way to mark a > container annotation as "synthesized" during class file generation. > > It would be possible to adopt a policy of always looking through > container annotations on an element. This requires the language model > API to recognize container annotations, which in turn requires loading > the annotation's class file, which might not always be available. > > I propose to adopt this policy, while allowing the methods to > sometimes expose container annotations even if not present in source > code. > > There are existing cases where the answered returned by the language model depends on whether the "backing store" for the type is a source file or a class file: > However, the process of translating source code to executable output > may not permit recovering some aspects of the source code > representation. For example, annotations with source > > retention > > cannot be recovered from class files and class files might not be able > to provide source position information. The modifiers > > on an element may differ in some cases including > > * |strictfp| on a class or interface > * |final| on a parameter > * |protected|, |private|, and |static| on classes and interfaces > > Additionally, synthetic constructs in a class file, such as accessor > methods used in implementing nested classes and bridge methods used in > implementing covariant returns, are translation artifacts outside of > this model. http://download.java.net/jdk8/docs/api/javax/lang/model/element/package-summary.html So we might judge it acceptable to get different answers to the question of what annotation mirrors are present depending on source vs class file backing store. -Joe From joe.darcy at oracle.com Thu Dec 6 17:32:03 2012 From: joe.darcy at oracle.com (Joseph Darcy) Date: Thu, 06 Dec 2012 17:32:03 -0800 Subject: Parameter reflection without MethodParameters attribute In-Reply-To: <50BE5B1D.1040100@oracle.com> References: <50BE5B1D.1040100@oracle.com> Message-ID: <50C14713.5000207@oracle.com> On 12/4/2012 12:20 PM, Alex Buckley wrote: > The new java.lang.reflect.Parameter class exposes a parameter's 1) > name, 2) finality, 3) author (via isSynthetic() and isSynthesized() - > if neither is true, then author was human), 4) whether it's a variable > arity parameter, 5) annotations, and 6) type. > > Sidebar: If you're wondering about "variable arity parameter", > see JLS 8.4.1. The existence of synthetic parameters means that > the last Parameter object from Executable.getParameters() might > not be the variable arity parameter declared in source, so each > Parameter object needs to expose whether it's variable arity. > > The methods for (5) return fundamentally the same info as > Method.getParameterAnnotations(), so it's clear what to return when no > annotation attributes are present: null values and empty arrays. > > But the methods for (1)-(4) are tricky when no MethodParameters > attribute is available. Should a parameter's name be the empty string, > with no modifiers set, and not flagged as synthetic or synthetized or > variable arity? And then have an Executable.hasParameterMetadata() > method to say whether these values are reliable? Maybe there should be > Optional wrappers for parameter info ... only joking, this is not > the place to solve Java's "missing value" woes. > > I think the best option is to sidestep these questions by having > Executable.getParameters() return an empty array if no > MethodParameters attribute is available. > > SE8 and greater class files may give an empty array, while pre-SE8 > class files must give an empty array. (The same ought to apply for > annotations: in a pre-SE5.0 class file, an attribute called > RuntimeVisibleAnnotations means nothing, and ought to be ignored by > core reflection, though I have a feeling it will be exposed.) > Alternatively, I think it is friendlier for the user for the implementation of Executable.getParameters() to manufacture placeholder names if none are available, "arg0", "arg1", etc. This is the policy we use in our implementation of javax.lang.lang.model.VariableElement for method and constructor parameters when the type is backed by a class file rather than a source file. When a type is backed by a source file, we use the names in the source. -Joe From alex.buckley at oracle.com Fri Dec 7 13:59:10 2012 From: alex.buckley at oracle.com (Alex Buckley) Date: Fri, 07 Dec 2012 13:59:10 -0800 Subject: Spec updates for repeating annotations (reflection) In-Reply-To: <50C0F992.3040506@oracle.com> References: <50BFCEBF.1060005@oracle.com> <50C0F992.3040506@oracle.com> Message-ID: <50C266AE.8000605@oracle.com> I have added further examples in section 1.2 (core reflection) to cover what I believe to be all critical combinations of base annotations and container annotations under inheritance. Example 1.2-5 is interesting because it raises the question of whether getAnnotations() should expose an inherited container annotation when its containerized base annotations are overridden. Let's break it down: - With no container annotation inheritance, things are simple: 1.2-3: @Foo(0) @FooContainer({@Foo(1), at Foo(2)}) class A {} A.class.getAnnotations() = [ @Foo(0), @Foo(1), @Foo(2) ] 1.2-4: @Foo(0) class A {} @FooContainer({@Foo(1), at Foo(2)}) class B extends A {} B.class.getAnnotations() = [ @Foo(1), @Foo(2) ] - With container annotation inheritance + overriding, things are not simple: 1.2-5: @FooContainer({@Foo(1), at Foo(2)}) class A {} @Foo(0) class B extends A {} B.class.getAnnotations() = [ @Foo(0) /* and @FooContainer(..)? */ ] I tend to think that container annotations should be invisible unless requested explicitly via get[Declared]Annotation[s](FooContainer.class). Consequently, in 1.2-5, I do not show @FooContainer(..) being returned by getAnnotations() after Foo has become repeatable with FooContainer. Comments welcome. Alex On 12/6/2012 12:01 PM, Alex Buckley wrote: > I have updated section 1.3 of the spec as proposed below. > > I have also 1) added remarks at the start of chapter 1 to explain the > design, and 2) added examples in section 1.2 (core reflection) to cover > more scenarios. > > The spec is at http://cr.openjdk.java.net/~abuckley/8misc.pdf as usual. > > Alex > > On 12/5/2012 2:46 PM, Alex Buckley wrote: >> We discovered two small issues with section 1.3 of the spec: >> >> >> 1. The spec proposes a new method, Element.getAnnotations(). >> >> This method is proposed for consistency with >> AnnotatedElement.getAnnotations(), but it turns out to be difficult to >> implement in the context of the language model. The problem is that, at >> compile-time, there might not be instances of Class objects for the >> annotations we try to look at. The other new methods - >> Element.getAnnotation[s](Class) - do not have this issue since their >> callers must supply a Class object. >> >> It would be possible for Element.getAnnotations() to throw exceptions if >> necessary Class objects were not found, but there is no good unchecked >> exception type available in the language model API. It would also be >> possible to skip over annotations for which Class objects are >> unavailable, and return incomplete results, but this seems undesirable. >> >> I propose to drop the method. Essentially, it's fine in core reflection >> but too brittle for the language model. >> >> >> 2. The spec proposes to refine Element.getAnnotationMirrors() and >> Elements.getAllAnnotationMirrors(). >> >> If the language model API only has a class file available for the >> element on which annotation mirrors are requested, then the API cannot >> be sure that it's right to "look through" @FooContainer (if directly >> present on the element) and return @Foo mirrors. >> >> This is true even if FooContainer is a well-formed containing annotation >> type available to the API. The source code of the element - which the >> API strives to reflect - could literally have said @FooContainer(...). >> Unfortunately, a compiler has no way to mark a container annotation as >> "synthesized" during class file generation. >> >> It would be possible to adopt a policy of always looking through >> container annotations on an element. This requires the language model >> API to recognize container annotations, which in turn requires loading >> the annotation's class file, which might not always be available. >> >> I propose to adopt this policy, while allowing the methods to sometimes >> expose container annotations even if not present in source code. >> >> >> Alex From pbenedict at apache.org Fri Dec 7 14:06:32 2012 From: pbenedict at apache.org (Paul Benedict) Date: Fri, 7 Dec 2012 16:06:32 -0600 Subject: Spec updates for repeating annotations (reflection) In-Reply-To: <50C266AE.8000605@oracle.com> References: <50BFCEBF.1060005@oracle.com> <50C0F992.3040506@oracle.com> <50C266AE.8000605@oracle.com> Message-ID: Alex, What do you think about adding a new attribute on @ContainedFor (or vice-versa if I am wrong) that would specify if the container application should be returned by reflection? I am not fond of the current rules that try to make things "see through" based on esoteric conditions. I'd rather have it programatically controlled by the developer. Paul On Fri, Dec 7, 2012 at 3:59 PM, Alex Buckley wrote: > I have added further examples in section 1.2 (core reflection) to cover what > I believe to be all critical combinations of base annotations and container > annotations under inheritance. > > Example 1.2-5 is interesting because it raises the question of whether > getAnnotations() should expose an inherited container annotation when its > containerized base annotations are overridden. Let's break it down: > > - With no container annotation inheritance, things are simple: > > 1.2-3: > @Foo(0) @FooContainer({@Foo(1), at Foo(2)}) class A {} > > A.class.getAnnotations() = [ @Foo(0), @Foo(1), @Foo(2) ] > > 1.2-4: > @Foo(0) class A {} > @FooContainer({@Foo(1), at Foo(2)}) class B extends A {} > > B.class.getAnnotations() = [ @Foo(1), @Foo(2) ] > > - With container annotation inheritance + overriding, things are not simple: > > 1.2-5: > @FooContainer({@Foo(1), at Foo(2)}) class A {} > @Foo(0) class B extends A {} > > B.class.getAnnotations() = [ @Foo(0) /* and @FooContainer(..)? */ ] > > I tend to think that container annotations should be invisible unless > requested explicitly via get[Declared]Annotation[s](FooContainer.class). > Consequently, in 1.2-5, I do not show @FooContainer(..) being returned by > getAnnotations() after Foo has become repeatable with FooContainer. Comments > welcome. > > Alex > > On 12/6/2012 12:01 PM, Alex Buckley wrote: >> >> I have updated section 1.3 of the spec as proposed below. >> >> I have also 1) added remarks at the start of chapter 1 to explain the >> design, and 2) added examples in section 1.2 (core reflection) to cover >> more scenarios. >> >> The spec is at http://cr.openjdk.java.net/~abuckley/8misc.pdf as usual. >> >> Alex >> >> On 12/5/2012 2:46 PM, Alex Buckley wrote: >>> >>> We discovered two small issues with section 1.3 of the spec: >>> >>> >>> 1. The spec proposes a new method, Element.getAnnotations(). >>> >>> This method is proposed for consistency with >>> AnnotatedElement.getAnnotations(), but it turns out to be difficult to >>> implement in the context of the language model. The problem is that, at >>> compile-time, there might not be instances of Class objects for the >>> annotations we try to look at. The other new methods - >>> Element.getAnnotation[s](Class) - do not have this issue since their >>> callers must supply a Class object. >>> >>> It would be possible for Element.getAnnotations() to throw exceptions if >>> necessary Class objects were not found, but there is no good unchecked >>> exception type available in the language model API. It would also be >>> possible to skip over annotations for which Class objects are >>> unavailable, and return incomplete results, but this seems undesirable. >>> >>> I propose to drop the method. Essentially, it's fine in core reflection >>> but too brittle for the language model. >>> >>> >>> 2. The spec proposes to refine Element.getAnnotationMirrors() and >>> Elements.getAllAnnotationMirrors(). >>> >>> If the language model API only has a class file available for the >>> element on which annotation mirrors are requested, then the API cannot >>> be sure that it's right to "look through" @FooContainer (if directly >>> present on the element) and return @Foo mirrors. >>> >>> This is true even if FooContainer is a well-formed containing annotation >>> type available to the API. The source code of the element - which the >>> API strives to reflect - could literally have said @FooContainer(...). >>> Unfortunately, a compiler has no way to mark a container annotation as >>> "synthesized" during class file generation. >>> >>> It would be possible to adopt a policy of always looking through >>> container annotations on an element. This requires the language model >>> API to recognize container annotations, which in turn requires loading >>> the annotation's class file, which might not always be available. >>> >>> I propose to adopt this policy, while allowing the methods to sometimes >>> expose container annotations even if not present in source code. >>> >>> >>> Alex From pbenedict at apache.org Fri Dec 7 14:07:26 2012 From: pbenedict at apache.org (Paul Benedict) Date: Fri, 7 Dec 2012 16:07:26 -0600 Subject: Spec updates for repeating annotations (reflection) In-Reply-To: References: <50BFCEBF.1060005@oracle.com> <50C0F992.3040506@oracle.com> <50C266AE.8000605@oracle.com> Message-ID: Typo.. if the container annotation should be returned by reflection? > if the container > application should be returned by reflection? From alex.buckley at oracle.com Fri Dec 7 14:09:56 2012 From: alex.buckley at oracle.com (Alex Buckley) Date: Fri, 07 Dec 2012 14:09:56 -0800 Subject: Spec updates for repeating annotations (reflection) In-Reply-To: References: <50BFCEBF.1060005@oracle.com> <50C0F992.3040506@oracle.com> <50C266AE.8000605@oracle.com> Message-ID: <50C26934.7060905@oracle.com> Paul, this is a good option to consider for get[Declared]Annotations(). I am generally in favor of giving power to the authors of annotation type, for then it is clear who annotation readers should blame when reflection results change. Joe, Mike, any comment? Alex On 12/7/2012 2:06 PM, Paul Benedict wrote: > Alex, > > What do you think about adding a new attribute on @ContainedFor (or > vice-versa if I am wrong) that would specify if the container > application should be returned by reflection? I am not fond of the > current rules that try to make things "see through" based on esoteric > conditions. I'd rather have it programatically controlled by the > developer. > > Paul > > On Fri, Dec 7, 2012 at 3:59 PM, Alex Buckley wrote: >> I have added further examples in section 1.2 (core reflection) to cover what >> I believe to be all critical combinations of base annotations and container >> annotations under inheritance. >> >> Example 1.2-5 is interesting because it raises the question of whether >> getAnnotations() should expose an inherited container annotation when its >> containerized base annotations are overridden. Let's break it down: >> >> - With no container annotation inheritance, things are simple: >> >> 1.2-3: >> @Foo(0) @FooContainer({@Foo(1), at Foo(2)}) class A {} >> >> A.class.getAnnotations() = [ @Foo(0), @Foo(1), @Foo(2) ] >> >> 1.2-4: >> @Foo(0) class A {} >> @FooContainer({@Foo(1), at Foo(2)}) class B extends A {} >> >> B.class.getAnnotations() = [ @Foo(1), @Foo(2) ] >> >> - With container annotation inheritance + overriding, things are not simple: >> >> 1.2-5: >> @FooContainer({@Foo(1), at Foo(2)}) class A {} >> @Foo(0) class B extends A {} >> >> B.class.getAnnotations() = [ @Foo(0) /* and @FooContainer(..)? */ ] >> >> I tend to think that container annotations should be invisible unless >> requested explicitly via get[Declared]Annotation[s](FooContainer.class). >> Consequently, in 1.2-5, I do not show @FooContainer(..) being returned by >> getAnnotations() after Foo has become repeatable with FooContainer. Comments >> welcome. >> >> Alex >> >> On 12/6/2012 12:01 PM, Alex Buckley wrote: >>> >>> I have updated section 1.3 of the spec as proposed below. >>> >>> I have also 1) added remarks at the start of chapter 1 to explain the >>> design, and 2) added examples in section 1.2 (core reflection) to cover >>> more scenarios. >>> >>> The spec is at http://cr.openjdk.java.net/~abuckley/8misc.pdf as usual. >>> >>> Alex >>> >>> On 12/5/2012 2:46 PM, Alex Buckley wrote: >>>> >>>> We discovered two small issues with section 1.3 of the spec: >>>> >>>> >>>> 1. The spec proposes a new method, Element.getAnnotations(). >>>> >>>> This method is proposed for consistency with >>>> AnnotatedElement.getAnnotations(), but it turns out to be difficult to >>>> implement in the context of the language model. The problem is that, at >>>> compile-time, there might not be instances of Class objects for the >>>> annotations we try to look at. The other new methods - >>>> Element.getAnnotation[s](Class) - do not have this issue since their >>>> callers must supply a Class object. >>>> >>>> It would be possible for Element.getAnnotations() to throw exceptions if >>>> necessary Class objects were not found, but there is no good unchecked >>>> exception type available in the language model API. It would also be >>>> possible to skip over annotations for which Class objects are >>>> unavailable, and return incomplete results, but this seems undesirable. >>>> >>>> I propose to drop the method. Essentially, it's fine in core reflection >>>> but too brittle for the language model. >>>> >>>> >>>> 2. The spec proposes to refine Element.getAnnotationMirrors() and >>>> Elements.getAllAnnotationMirrors(). >>>> >>>> If the language model API only has a class file available for the >>>> element on which annotation mirrors are requested, then the API cannot >>>> be sure that it's right to "look through" @FooContainer (if directly >>>> present on the element) and return @Foo mirrors. >>>> >>>> This is true even if FooContainer is a well-formed containing annotation >>>> type available to the API. The source code of the element - which the >>>> API strives to reflect - could literally have said @FooContainer(...). >>>> Unfortunately, a compiler has no way to mark a container annotation as >>>> "synthesized" during class file generation. >>>> >>>> It would be possible to adopt a policy of always looking through >>>> container annotations on an element. This requires the language model >>>> API to recognize container annotations, which in turn requires loading >>>> the annotation's class file, which might not always be available. >>>> >>>> I propose to adopt this policy, while allowing the methods to sometimes >>>> expose container annotations even if not present in source code. >>>> >>>> >>>> Alex From alex.buckley at oracle.com Fri Dec 7 16:06:27 2012 From: alex.buckley at oracle.com (Alex Buckley) Date: Fri, 07 Dec 2012 16:06:27 -0800 Subject: Parameter reflection without MethodParameters attribute In-Reply-To: <50C14713.5000207@oracle.com> References: <50BE5B1D.1040100@oracle.com> <50C14713.5000207@oracle.com> Message-ID: <50C28483.9070604@oracle.com> On 12/6/2012 5:32 PM, Joseph Darcy wrote: > Alternatively, I think it is friendlier for the user for the > implementation of Executable.getParameters() to manufacture placeholder > names if none are available, "arg0", "arg1", etc. I concede that Executable.getParameters() can _always_ return somewhat useful results, namely Parameter objects which expose annotations (if present) and class/type info. Along with placeholder names/values, this is a good argument for always getting non-null Parameter values from getParameters(). At the same time, a reflective client might want to know if the Parameter objects it's getting are made of placeholders or made from a real MethodParameters attribute. Executable.hasEnhancedMetadata() is a possibility, but it goes toward "quality of service" (i.e. are names normative?) which is out of scope for SE 8. So for now, let's always return Parameter objects and synthesize placeholders as you suggest. I've updated the spec (section 2.2). Alex From pbenedict at apache.org Fri Dec 7 16:13:52 2012 From: pbenedict at apache.org (Paul Benedict) Date: Fri, 7 Dec 2012 18:13:52 -0600 Subject: Parameter reflection without MethodParameters attribute In-Reply-To: <50C28483.9070604@oracle.com> References: <50BE5B1D.1040100@oracle.com> <50C14713.5000207@oracle.com> <50C28483.9070604@oracle.com> Message-ID: Always returning Parameter objects seems like a good idea to me -- whether the information is available or not. However, if it's being manufactured (as the parameter names are absent), I question the utility of coming up with make-believe names. I would opt to have a Parameter object have a null name and a flag that says it's being synthesized. Paul On Fri, Dec 7, 2012 at 6:06 PM, Alex Buckley wrote: > On 12/6/2012 5:32 PM, Joseph Darcy wrote: >> >> Alternatively, I think it is friendlier for the user for the >> implementation of Executable.getParameters() to manufacture placeholder >> names if none are available, "arg0", "arg1", etc. > > > I concede that Executable.getParameters() can _always_ return somewhat > useful results, namely Parameter objects which expose annotations (if > present) and class/type info. Along with placeholder names/values, this is a > good argument for always getting non-null Parameter values from > getParameters(). > > At the same time, a reflective client might want to know if the Parameter > objects it's getting are made of placeholders or made from a real > MethodParameters attribute. Executable.hasEnhancedMetadata() is a > possibility, but it goes toward "quality of service" (i.e. are names > normative?) which is out of scope for SE 8. > > So for now, let's always return Parameter objects and synthesize > placeholders as you suggest. I've updated the spec (section 2.2). > > Alex From mike.duigou at oracle.com Fri Dec 7 17:11:53 2012 From: mike.duigou at oracle.com (Mike Duigou) Date: Fri, 7 Dec 2012 17:11:53 -0800 Subject: Parameter reflection without MethodParameters attribute In-Reply-To: References: <50BE5B1D.1040100@oracle.com> <50C14713.5000207@oracle.com> <50C28483.9070604@oracle.com> Message-ID: There's slightly less value informationally to arg0, arg1 etc but it's still useful. I'd rather refer to arg0 than "the third int parameter". If I imagine I was looking at System.arrayCopy prototype I'd prefer to see arg0, etc than just the type names. Seeing the real names would, of course, be even better because methods like arrayCopy are inscrutable without knowing the parameter names. Just looking at the types doesn't tell you enough. So, synthesized flag yes, non-null name yes please. Mike On Dec 7 2012, at 16:13 , Paul Benedict wrote: > Always returning Parameter objects seems like a good idea to me -- > whether the information is available or not. However, if it's being > manufactured (as the parameter names are absent), I question the > utility of coming up with make-believe names. > > I would opt to have a Parameter object have a null name and a flag > that says it's being synthesized. > > Paul > > On Fri, Dec 7, 2012 at 6:06 PM, Alex Buckley wrote: >> On 12/6/2012 5:32 PM, Joseph Darcy wrote: >>> >>> Alternatively, I think it is friendlier for the user for the >>> implementation of Executable.getParameters() to manufacture placeholder >>> names if none are available, "arg0", "arg1", etc. >> >> >> I concede that Executable.getParameters() can _always_ return somewhat >> useful results, namely Parameter objects which expose annotations (if >> present) and class/type info. Along with placeholder names/values, this is a >> good argument for always getting non-null Parameter values from >> getParameters(). >> >> At the same time, a reflective client might want to know if the Parameter >> objects it's getting are made of placeholders or made from a real >> MethodParameters attribute. Executable.hasEnhancedMetadata() is a >> possibility, but it goes toward "quality of service" (i.e. are names >> normative?) which is out of scope for SE 8. >> >> So for now, let's always return Parameter objects and synthesize >> placeholders as you suggest. I've updated the spec (section 2.2). >> >> Alex From joe.darcy at oracle.com Fri Dec 7 17:19:37 2012 From: joe.darcy at oracle.com (Joseph Darcy) Date: Fri, 07 Dec 2012 17:19:37 -0800 Subject: Parameter reflection without MethodParameters attribute In-Reply-To: References: <50BE5B1D.1040100@oracle.com> <50C14713.5000207@oracle.com> <50C28483.9070604@oracle.com> Message-ID: <50C295A9.4050706@oracle.com> I agree; I think the API would be quite inconvenient to use if the client had to test the result for null and then make up their own parameter name. -Joe On 12/7/2012 5:11 PM, Mike Duigou wrote: > There's slightly less value informationally to arg0, arg1 etc but it's still useful. I'd rather refer to arg0 than "the third int parameter". If I imagine I was looking at System.arrayCopy prototype I'd prefer to see arg0, etc than just the type names. Seeing the real names would, of course, be even better because methods like arrayCopy are inscrutable without knowing the parameter names. Just looking at the types doesn't tell you enough. > > So, synthesized flag yes, non-null name yes please. > > Mike > > On Dec 7 2012, at 16:13 , Paul Benedict wrote: > >> Always returning Parameter objects seems like a good idea to me -- >> whether the information is available or not. However, if it's being >> manufactured (as the parameter names are absent), I question the >> utility of coming up with make-believe names. >> >> I would opt to have a Parameter object have a null name and a flag >> that says it's being synthesized. >> >> Paul >> >> On Fri, Dec 7, 2012 at 6:06 PM, Alex Buckley wrote: >>> On 12/6/2012 5:32 PM, Joseph Darcy wrote: >>>> Alternatively, I think it is friendlier for the user for the >>>> implementation of Executable.getParameters() to manufacture placeholder >>>> names if none are available, "arg0", "arg1", etc. >>> >>> I concede that Executable.getParameters() can _always_ return somewhat >>> useful results, namely Parameter objects which expose annotations (if >>> present) and class/type info. Along with placeholder names/values, this is a >>> good argument for always getting non-null Parameter values from >>> getParameters(). >>> >>> At the same time, a reflective client might want to know if the Parameter >>> objects it's getting are made of placeholders or made from a real >>> MethodParameters attribute. Executable.hasEnhancedMetadata() is a >>> possibility, but it goes toward "quality of service" (i.e. are names >>> normative?) which is out of scope for SE 8. >>> >>> So for now, let's always return Parameter objects and synthesize >>> placeholders as you suggest. I've updated the spec (section 2.2). >>> >>> Alex From forax at univ-mlv.fr Sat Dec 8 04:52:07 2012 From: forax at univ-mlv.fr (Remi Forax) Date: Sat, 08 Dec 2012 13:52:07 +0100 Subject: Parameter reflection without MethodParameters attribute In-Reply-To: <50C295A9.4050706@oracle.com> References: <50BE5B1D.1040100@oracle.com> <50C14713.5000207@oracle.com> <50C28483.9070604@oracle.com> <50C295A9.4050706@oracle.com> Message-ID: <50C337F7.3090300@univ-mlv.fr> On 12/08/2012 02:19 AM, Joseph Darcy wrote: > I agree; I think the API would be quite inconvenient to use if the > client had to test the result for null and then make up their own > parameter name. > > -Joe for what it worth, I agree too. R?mi > > On 12/7/2012 5:11 PM, Mike Duigou wrote: >> There's slightly less value informationally to arg0, arg1 etc but >> it's still useful. I'd rather refer to arg0 than "the third int >> parameter". If I imagine I was looking at System.arrayCopy prototype >> I'd prefer to see arg0, etc than just the type names. Seeing the real >> names would, of course, be even better because methods like arrayCopy >> are inscrutable without knowing the parameter names. Just looking at >> the types doesn't tell you enough. >> >> So, synthesized flag yes, non-null name yes please. >> >> Mike >> >> On Dec 7 2012, at 16:13 , Paul Benedict wrote: >> >>> Always returning Parameter objects seems like a good idea to me -- >>> whether the information is available or not. However, if it's being >>> manufactured (as the parameter names are absent), I question the >>> utility of coming up with make-believe names. >>> >>> I would opt to have a Parameter object have a null name and a flag >>> that says it's being synthesized. >>> >>> Paul >>> >>> On Fri, Dec 7, 2012 at 6:06 PM, Alex Buckley >>> wrote: >>>> On 12/6/2012 5:32 PM, Joseph Darcy wrote: >>>>> Alternatively, I think it is friendlier for the user for the >>>>> implementation of Executable.getParameters() to manufacture >>>>> placeholder >>>>> names if none are available, "arg0", "arg1", etc. >>>> >>>> I concede that Executable.getParameters() can _always_ return somewhat >>>> useful results, namely Parameter objects which expose annotations (if >>>> present) and class/type info. Along with placeholder names/values, >>>> this is a >>>> good argument for always getting non-null Parameter values from >>>> getParameters(). >>>> >>>> At the same time, a reflective client might want to know if the >>>> Parameter >>>> objects it's getting are made of placeholders or made from a real >>>> MethodParameters attribute. Executable.hasEnhancedMetadata() is a >>>> possibility, but it goes toward "quality of service" (i.e. are names >>>> normative?) which is out of scope for SE 8. >>>> >>>> So for now, let's always return Parameter objects and synthesize >>>> placeholders as you suggest. I've updated the spec (section 2.2). >>>> >>>> Alex > From alex.buckley at oracle.com Mon Dec 10 11:30:12 2012 From: alex.buckley at oracle.com (Alex Buckley) Date: Mon, 10 Dec 2012 11:30:12 -0800 Subject: Parameter reflection without MethodParameters attribute In-Reply-To: <50C337F7.3090300@univ-mlv.fr> References: <50BE5B1D.1040100@oracle.com> <50C14713.5000207@oracle.com> <50C28483.9070604@oracle.com> <50C295A9.4050706@oracle.com> <50C337F7.3090300@univ-mlv.fr> Message-ID: <50C63844.3030301@oracle.com> Thanks all for comments. We're going to proceed on the basis of the current spec. (Executable.getParameters() always returns Parameter objects, synthesizing them if necessary, and no flag method to tell whether they were synthesized.) Alex On 12/8/2012 4:52 AM, Remi Forax wrote: > On 12/08/2012 02:19 AM, Joseph Darcy wrote: >> I agree; I think the API would be quite inconvenient to use if the >> client had to test the result for null and then make up their own >> parameter name. >> >> -Joe > > for what it worth, I agree too. > > R?mi > >> >> On 12/7/2012 5:11 PM, Mike Duigou wrote: >>> There's slightly less value informationally to arg0, arg1 etc but >>> it's still useful. I'd rather refer to arg0 than "the third int >>> parameter". If I imagine I was looking at System.arrayCopy prototype >>> I'd prefer to see arg0, etc than just the type names. Seeing the real >>> names would, of course, be even better because methods like arrayCopy >>> are inscrutable without knowing the parameter names. Just looking at >>> the types doesn't tell you enough. >>> >>> So, synthesized flag yes, non-null name yes please. >>> >>> Mike >>> >>> On Dec 7 2012, at 16:13 , Paul Benedict wrote: >>> >>>> Always returning Parameter objects seems like a good idea to me -- >>>> whether the information is available or not. However, if it's being >>>> manufactured (as the parameter names are absent), I question the >>>> utility of coming up with make-believe names. >>>> >>>> I would opt to have a Parameter object have a null name and a flag >>>> that says it's being synthesized. >>>> >>>> Paul >>>> >>>> On Fri, Dec 7, 2012 at 6:06 PM, Alex Buckley >>>> wrote: >>>>> On 12/6/2012 5:32 PM, Joseph Darcy wrote: >>>>>> Alternatively, I think it is friendlier for the user for the >>>>>> implementation of Executable.getParameters() to manufacture >>>>>> placeholder >>>>>> names if none are available, "arg0", "arg1", etc. >>>>> >>>>> I concede that Executable.getParameters() can _always_ return somewhat >>>>> useful results, namely Parameter objects which expose annotations (if >>>>> present) and class/type info. Along with placeholder names/values, >>>>> this is a >>>>> good argument for always getting non-null Parameter values from >>>>> getParameters(). >>>>> >>>>> At the same time, a reflective client might want to know if the >>>>> Parameter >>>>> objects it's getting are made of placeholders or made from a real >>>>> MethodParameters attribute. Executable.hasEnhancedMetadata() is a >>>>> possibility, but it goes toward "quality of service" (i.e. are names >>>>> normative?) which is out of scope for SE 8. >>>>> >>>>> So for now, let's always return Parameter objects and synthesize >>>>> placeholders as you suggest. I've updated the spec (section 2.2). >>>>> >>>>> Alex >> > From eamonn at mcmanus.net Mon Dec 10 14:51:07 2012 From: eamonn at mcmanus.net (Eamonn McManus) Date: Mon, 10 Dec 2012 14:51:07 -0800 Subject: Parameter reflection without MethodParameters attribute In-Reply-To: <50C63844.3030301@oracle.com> References: <50BE5B1D.1040100@oracle.com> <50C14713.5000207@oracle.com> <50C28483.9070604@oracle.com> <50C295A9.4050706@oracle.com> <50C337F7.3090300@univ-mlv.fr> <50C63844.3030301@oracle.com> Message-ID: Perhaps the synthesized names should have $ in them (e.g. arg$0 or $0), as is done for synthesized names elsewhere. ?amonn 2012/12/10 Alex Buckley > Thanks all for comments. We're going to proceed on the basis of the > current spec. (Executable.getParameters() always returns Parameter objects, > synthesizing them if necessary, and no flag method to tell whether they > were synthesized.) > > Alex > > > On 12/8/2012 4:52 AM, Remi Forax wrote: > >> On 12/08/2012 02:19 AM, Joseph Darcy wrote: >> >>> I agree; I think the API would be quite inconvenient to use if the >>> client had to test the result for null and then make up their own >>> parameter name. >>> >>> -Joe >>> >> >> for what it worth, I agree too. >> >> R?mi >> >> >>> On 12/7/2012 5:11 PM, Mike Duigou wrote: >>> >>>> There's slightly less value informationally to arg0, arg1 etc but >>>> it's still useful. I'd rather refer to arg0 than "the third int >>>> parameter". If I imagine I was looking at System.arrayCopy prototype >>>> I'd prefer to see arg0, etc than just the type names. Seeing the real >>>> names would, of course, be even better because methods like arrayCopy >>>> are inscrutable without knowing the parameter names. Just looking at >>>> the types doesn't tell you enough. >>>> >>>> So, synthesized flag yes, non-null name yes please. >>>> >>>> Mike >>>> >>>> On Dec 7 2012, at 16:13 , Paul Benedict wrote: >>>> >>>> Always returning Parameter objects seems like a good idea to me -- >>>>> whether the information is available or not. However, if it's being >>>>> manufactured (as the parameter names are absent), I question the >>>>> utility of coming up with make-believe names. >>>>> >>>>> I would opt to have a Parameter object have a null name and a flag >>>>> that says it's being synthesized. >>>>> >>>>> Paul >>>>> >>>>> On Fri, Dec 7, 2012 at 6:06 PM, Alex Buckley >>>>> wrote: >>>>> >>>>>> On 12/6/2012 5:32 PM, Joseph Darcy wrote: >>>>>> >>>>>>> Alternatively, I think it is friendlier for the user for the >>>>>>> implementation of Executable.getParameters() to manufacture >>>>>>> placeholder >>>>>>> names if none are available, "arg0", "arg1", etc. >>>>>>> >>>>>> >>>>>> I concede that Executable.getParameters() can _always_ return somewhat >>>>>> useful results, namely Parameter objects which expose annotations (if >>>>>> present) and class/type info. Along with placeholder names/values, >>>>>> this is a >>>>>> good argument for always getting non-null Parameter values from >>>>>> getParameters(). >>>>>> >>>>>> At the same time, a reflective client might want to know if the >>>>>> Parameter >>>>>> objects it's getting are made of placeholders or made from a real >>>>>> MethodParameters attribute. Executable.**hasEnhancedMetadata() is a >>>>>> possibility, but it goes toward "quality of service" (i.e. are names >>>>>> normative?) which is out of scope for SE 8. >>>>>> >>>>>> So for now, let's always return Parameter objects and synthesize >>>>>> placeholders as you suggest. I've updated the spec (section 2.2). >>>>>> >>>>>> Alex >>>>>> >>>>> >>> >> From pbenedict at apache.org Mon Dec 10 14:53:50 2012 From: pbenedict at apache.org (Paul Benedict) Date: Mon, 10 Dec 2012 16:53:50 -0600 Subject: Parameter reflection without MethodParameters attribute In-Reply-To: References: <50BE5B1D.1040100@oracle.com> <50C14713.5000207@oracle.com> <50C28483.9070604@oracle.com> <50C295A9.4050706@oracle.com> <50C337F7.3090300@univ-mlv.fr> <50C63844.3030301@oracle.com> Message-ID: Eamonn, it's interesting. However, since Alex doesn't want a flag to tell whether they were synthesized, the $ could provide a leak in that information wall. Paul On Mon, Dec 10, 2012 at 4:51 PM, Eamonn McManus wrote: > Perhaps the synthesized names should have $ in them (e.g. arg$0 or $0), as > is done for synthesized names elsewhere. > > ?amonn > > > > 2012/12/10 Alex Buckley > >> Thanks all for comments. We're going to proceed on the basis of the >> current spec. (Executable.getParameters() always returns Parameter objects, >> synthesizing them if necessary, and no flag method to tell whether they >> were synthesized.) >> >> Alex >> >> >> On 12/8/2012 4:52 AM, Remi Forax wrote: >> >>> On 12/08/2012 02:19 AM, Joseph Darcy wrote: >>> >>>> I agree; I think the API would be quite inconvenient to use if the >>>> client had to test the result for null and then make up their own >>>> parameter name. >>>> >>>> -Joe >>>> >>> >>> for what it worth, I agree too. >>> >>> R?mi >>> >>> >>>> On 12/7/2012 5:11 PM, Mike Duigou wrote: >>>> >>>>> There's slightly less value informationally to arg0, arg1 etc but >>>>> it's still useful. I'd rather refer to arg0 than "the third int >>>>> parameter". If I imagine I was looking at System.arrayCopy prototype >>>>> I'd prefer to see arg0, etc than just the type names. Seeing the real >>>>> names would, of course, be even better because methods like arrayCopy >>>>> are inscrutable without knowing the parameter names. Just looking at >>>>> the types doesn't tell you enough. >>>>> >>>>> So, synthesized flag yes, non-null name yes please. >>>>> >>>>> Mike >>>>> >>>>> On Dec 7 2012, at 16:13 , Paul Benedict wrote: >>>>> >>>>> Always returning Parameter objects seems like a good idea to me -- >>>>>> whether the information is available or not. However, if it's being >>>>>> manufactured (as the parameter names are absent), I question the >>>>>> utility of coming up with make-believe names. >>>>>> >>>>>> I would opt to have a Parameter object have a null name and a flag >>>>>> that says it's being synthesized. >>>>>> >>>>>> Paul >>>>>> >>>>>> On Fri, Dec 7, 2012 at 6:06 PM, Alex Buckley >>>>>> wrote: >>>>>> >>>>>>> On 12/6/2012 5:32 PM, Joseph Darcy wrote: >>>>>>> >>>>>>>> Alternatively, I think it is friendlier for the user for the >>>>>>>> implementation of Executable.getParameters() to manufacture >>>>>>>> placeholder >>>>>>>> names if none are available, "arg0", "arg1", etc. >>>>>>>> >>>>>>> >>>>>>> I concede that Executable.getParameters() can _always_ return somewhat >>>>>>> useful results, namely Parameter objects which expose annotations (if >>>>>>> present) and class/type info. Along with placeholder names/values, >>>>>>> this is a >>>>>>> good argument for always getting non-null Parameter values from >>>>>>> getParameters(). >>>>>>> >>>>>>> At the same time, a reflective client might want to know if the >>>>>>> Parameter >>>>>>> objects it's getting are made of placeholders or made from a real >>>>>>> MethodParameters attribute. Executable.**hasEnhancedMetadata() is a >>>>>>> possibility, but it goes toward "quality of service" (i.e. are names >>>>>>> normative?) which is out of scope for SE 8. >>>>>>> >>>>>>> So for now, let's always return Parameter objects and synthesize >>>>>>> placeholders as you suggest. I've updated the spec (section 2.2). >>>>>>> >>>>>>> Alex >>>>>>> >>>>>> >>>> >>> From alex.buckley at oracle.com Mon Dec 10 15:03:50 2012 From: alex.buckley at oracle.com (Alex Buckley) Date: Mon, 10 Dec 2012 15:03:50 -0800 Subject: Parameter reflection without MethodParameters attribute In-Reply-To: References: <50BE5B1D.1040100@oracle.com> <50C14713.5000207@oracle.com> <50C28483.9070604@oracle.com> <50C295A9.4050706@oracle.com> <50C337F7.3090300@univ-mlv.fr> <50C63844.3030301@oracle.com> Message-ID: <50C66A56.60800@oracle.com> $ has traditionally been used in _synthetic_ names (i.e. of compiler-specific artifacts) whereas the parameter names in question are _synthesized_ (i.e. the spec mandates their existence and format). As Joe said, the language model already has a good convention ("argI") for synthesized parameter names. Alex On 12/10/2012 2:53 PM, Paul Benedict wrote: > Eamonn, it's interesting. However, since Alex doesn't want a flag to > tell whether they were synthesized, the $ could provide a leak in that > information wall. > > Paul > > On Mon, Dec 10, 2012 at 4:51 PM, Eamonn McManus wrote: >> Perhaps the synthesized names should have $ in them (e.g. arg$0 or $0), as >> is done for synthesized names elsewhere. >> >> ?amonn >> >> >> >> 2012/12/10 Alex Buckley >> >>> Thanks all for comments. We're going to proceed on the basis of the >>> current spec. (Executable.getParameters() always returns Parameter objects, >>> synthesizing them if necessary, and no flag method to tell whether they >>> were synthesized.) >>> >>> Alex >>> >>> >>> On 12/8/2012 4:52 AM, Remi Forax wrote: >>> >>>> On 12/08/2012 02:19 AM, Joseph Darcy wrote: >>>> >>>>> I agree; I think the API would be quite inconvenient to use if the >>>>> client had to test the result for null and then make up their own >>>>> parameter name. >>>>> >>>>> -Joe >>>>> >>>> >>>> for what it worth, I agree too. >>>> >>>> R?mi >>>> >>>> >>>>> On 12/7/2012 5:11 PM, Mike Duigou wrote: >>>>> >>>>>> There's slightly less value informationally to arg0, arg1 etc but >>>>>> it's still useful. I'd rather refer to arg0 than "the third int >>>>>> parameter". If I imagine I was looking at System.arrayCopy prototype >>>>>> I'd prefer to see arg0, etc than just the type names. Seeing the real >>>>>> names would, of course, be even better because methods like arrayCopy >>>>>> are inscrutable without knowing the parameter names. Just looking at >>>>>> the types doesn't tell you enough. >>>>>> >>>>>> So, synthesized flag yes, non-null name yes please. >>>>>> >>>>>> Mike >>>>>> >>>>>> On Dec 7 2012, at 16:13 , Paul Benedict wrote: >>>>>> >>>>>> Always returning Parameter objects seems like a good idea to me -- >>>>>>> whether the information is available or not. However, if it's being >>>>>>> manufactured (as the parameter names are absent), I question the >>>>>>> utility of coming up with make-believe names. >>>>>>> >>>>>>> I would opt to have a Parameter object have a null name and a flag >>>>>>> that says it's being synthesized. >>>>>>> >>>>>>> Paul >>>>>>> >>>>>>> On Fri, Dec 7, 2012 at 6:06 PM, Alex Buckley >>>>>>> wrote: >>>>>>> >>>>>>>> On 12/6/2012 5:32 PM, Joseph Darcy wrote: >>>>>>>> >>>>>>>>> Alternatively, I think it is friendlier for the user for the >>>>>>>>> implementation of Executable.getParameters() to manufacture >>>>>>>>> placeholder >>>>>>>>> names if none are available, "arg0", "arg1", etc. >>>>>>>>> >>>>>>>> >>>>>>>> I concede that Executable.getParameters() can _always_ return somewhat >>>>>>>> useful results, namely Parameter objects which expose annotations (if >>>>>>>> present) and class/type info. Along with placeholder names/values, >>>>>>>> this is a >>>>>>>> good argument for always getting non-null Parameter values from >>>>>>>> getParameters(). >>>>>>>> >>>>>>>> At the same time, a reflective client might want to know if the >>>>>>>> Parameter >>>>>>>> objects it's getting are made of placeholders or made from a real >>>>>>>> MethodParameters attribute. Executable.**hasEnhancedMetadata() is a >>>>>>>> possibility, but it goes toward "quality of service" (i.e. are names >>>>>>>> normative?) which is out of scope for SE 8. >>>>>>>> >>>>>>>> So for now, let's always return Parameter objects and synthesize >>>>>>>> placeholders as you suggest. I've updated the spec (section 2.2). >>>>>>>> >>>>>>>> Alex >>>>>>>> >>>>>>> >>>>> >>>> From alex.buckley at oracle.com Mon Dec 10 15:57:22 2012 From: alex.buckley at oracle.com (Alex Buckley) Date: Mon, 10 Dec 2012 15:57:22 -0800 Subject: Parameter reflection without MethodParameters attribute In-Reply-To: <50C66A56.60800@oracle.com> References: <50BE5B1D.1040100@oracle.com> <50C14713.5000207@oracle.com> <50C28483.9070604@oracle.com> <50C295A9.4050706@oracle.com> <50C337F7.3090300@univ-mlv.fr> <50C63844.3030301@oracle.com> <50C66A56.60800@oracle.com> Message-ID: <50C676E2.8090800@oracle.com> Actually, it's not quite so clean, since $ in nested type names is _synthesized_ on account of being specified in JLS 13.1. Of course 13.1 is rather oddball since it's a compiler spec not a language spec. In any case, $ is by and large for synthetic names. Alex On 12/10/2012 3:03 PM, Alex Buckley wrote: > $ has traditionally been used in _synthetic_ names (i.e. of > compiler-specific artifacts) whereas the parameter names in question are > _synthesized_ (i.e. the spec mandates their existence and format). As > Joe said, the language model already has a good convention ("argI") for > synthesized parameter names. > > Alex > > On 12/10/2012 2:53 PM, Paul Benedict wrote: >> Eamonn, it's interesting. However, since Alex doesn't want a flag to >> tell whether they were synthesized, the $ could provide a leak in that >> information wall. >> >> Paul >> >> On Mon, Dec 10, 2012 at 4:51 PM, Eamonn McManus >> wrote: >>> Perhaps the synthesized names should have $ in them (e.g. arg$0 or >>> $0), as >>> is done for synthesized names elsewhere. >>> >>> ?amonn >>> >>> >>> >>> 2012/12/10 Alex Buckley >>> >>>> Thanks all for comments. We're going to proceed on the basis of the >>>> current spec. (Executable.getParameters() always returns Parameter >>>> objects, >>>> synthesizing them if necessary, and no flag method to tell whether they >>>> were synthesized.) >>>> >>>> Alex >>>> >>>> >>>> On 12/8/2012 4:52 AM, Remi Forax wrote: >>>> >>>>> On 12/08/2012 02:19 AM, Joseph Darcy wrote: >>>>> >>>>>> I agree; I think the API would be quite inconvenient to use if the >>>>>> client had to test the result for null and then make up their own >>>>>> parameter name. >>>>>> >>>>>> -Joe >>>>>> >>>>> >>>>> for what it worth, I agree too. >>>>> >>>>> R?mi >>>>> >>>>> >>>>>> On 12/7/2012 5:11 PM, Mike Duigou wrote: >>>>>> >>>>>>> There's slightly less value informationally to arg0, arg1 etc but >>>>>>> it's still useful. I'd rather refer to arg0 than "the third int >>>>>>> parameter". If I imagine I was looking at System.arrayCopy prototype >>>>>>> I'd prefer to see arg0, etc than just the type names. Seeing the >>>>>>> real >>>>>>> names would, of course, be even better because methods like >>>>>>> arrayCopy >>>>>>> are inscrutable without knowing the parameter names. Just looking at >>>>>>> the types doesn't tell you enough. >>>>>>> >>>>>>> So, synthesized flag yes, non-null name yes please. >>>>>>> >>>>>>> Mike >>>>>>> >>>>>>> On Dec 7 2012, at 16:13 , Paul Benedict wrote: >>>>>>> >>>>>>> Always returning Parameter objects seems like a good idea to me -- >>>>>>>> whether the information is available or not. However, if it's being >>>>>>>> manufactured (as the parameter names are absent), I question the >>>>>>>> utility of coming up with make-believe names. >>>>>>>> >>>>>>>> I would opt to have a Parameter object have a null name and a flag >>>>>>>> that says it's being synthesized. >>>>>>>> >>>>>>>> Paul >>>>>>>> >>>>>>>> On Fri, Dec 7, 2012 at 6:06 PM, Alex Buckley >>>>>>>> wrote: >>>>>>>> >>>>>>>>> On 12/6/2012 5:32 PM, Joseph Darcy wrote: >>>>>>>>> >>>>>>>>>> Alternatively, I think it is friendlier for the user for the >>>>>>>>>> implementation of Executable.getParameters() to manufacture >>>>>>>>>> placeholder >>>>>>>>>> names if none are available, "arg0", "arg1", etc. >>>>>>>>>> >>>>>>>>> >>>>>>>>> I concede that Executable.getParameters() can _always_ return >>>>>>>>> somewhat >>>>>>>>> useful results, namely Parameter objects which expose >>>>>>>>> annotations (if >>>>>>>>> present) and class/type info. Along with placeholder names/values, >>>>>>>>> this is a >>>>>>>>> good argument for always getting non-null Parameter values from >>>>>>>>> getParameters(). >>>>>>>>> >>>>>>>>> At the same time, a reflective client might want to know if the >>>>>>>>> Parameter >>>>>>>>> objects it's getting are made of placeholders or made from a real >>>>>>>>> MethodParameters attribute. Executable.**hasEnhancedMetadata() >>>>>>>>> is a >>>>>>>>> possibility, but it goes toward "quality of service" (i.e. are >>>>>>>>> names >>>>>>>>> normative?) which is out of scope for SE 8. >>>>>>>>> >>>>>>>>> So for now, let's always return Parameter objects and synthesize >>>>>>>>> placeholders as you suggest. I've updated the spec (section 2.2). >>>>>>>>> >>>>>>>>> Alex >>>>>>>>> >>>>>>>> >>>>>> >>>>> From michael.keith at oracle.com Fri Dec 14 13:59:03 2012 From: michael.keith at oracle.com (michael keith) Date: Fri, 14 Dec 2012 16:59:03 -0500 Subject: repeating annotations comments Message-ID: <50CBA127.9070002@oracle.com> Here are some observations from looking at the current state of the repeating annotation spec. If I got something wrong, here, I trust you'll let me know :-) 1. The getAnnotation(Class) method is being changed to look through container annotations. This method returns an Annotation, i.e. a single instance, so applying it to repeated ones is necessarily going to have to return only one. But having it look through container annotation ends up not being very productive, and may be causing it to be counter-productive. Look-through for this method is not productive because the call is being made precisely in the legacy cases when only one annotation was expected, but a container annotation will only be synthesized when multiples are present. So look-through does not really help get "the" expected annotation. The only case when it would be useful is in the unlikely case when the container annotation is used explicitly and contains a single contained annotation. It may be counter-productive for three reasons. The first is because getting a random single annotation in the presence of multiples is potentially dangerous since the calling code will continue without knowing that multiples are present, so legacy code is essentially broken, but will not actually fail. It will just be semantically incorrect. The second is because I didn't see (and I may just have missed it) where it was defined that if both T and TC were present that T would be guaranteed to be returned and not some instance within TC. Example 1.2-3 shows this to be the case but I didn't see that it was specified behavior rather than just because the T occurred before the TC. If the example had been TC and then T would the instance of T be returned? This could be important because existing code to handle this case checks for the container annotation TC and then checks for the single annotation T. However, if checking for T happens to look through TC and return one of the contained annotations in TC instead of the lone T annotation then the lone annotation would not get found. The third is because all of the code that is currently out there that needs to check for the previous case, i.e. both T and TC occurring, will get a false positive in the simpler case of multiple instances of T annotations (as per the second part of example 1.2-1 in the doc). The getAnnotation(TC) will return the synthesized TC containing all of the instances of T, and then getAnnotation(T) will return one of those same instances again. Legacy code will assume that the result of getAnnotation(T) is disjoint from the contained annotations of the TC returned by getAnnotation(TC). Note: The same argument applies to the isAnnotationPresent(T) method since it is defined in terms of getAnnotation(T). 2. Given that get[Declared]Annotations() is going to change and return multiple instances of the same annotation (rather than a single instance of a container annotation) existing implementations are going to have to be fixed since there is no backwards compatibility there at all. 3. In general, it appears that once an annotation is made repeatable the annotation processing code is inevitably going to have to change in order to handle the repeatability. We were willing to take that hit, particularly since the new behavior requires opting in, and that means that specs could do so at their own discretion. However, the code to handle both the new and the old (i.e. be able to process both new repeatable annotations as well as the older idiomatic container annotations) is a little less intuitive to write than I had hoped it would be. The easiest way might just be to create a Set of instances to avoid duplicates. Not rocket science, just not what I would have expected. Thanks, -Mike From alex.buckley at oracle.com Fri Dec 14 17:41:09 2012 From: alex.buckley at oracle.com (Alex Buckley) Date: Fri, 14 Dec 2012 17:41:09 -0800 Subject: repeating annotations comments In-Reply-To: <50CBA127.9070002@oracle.com> References: <50CBA127.9070002@oracle.com> Message-ID: <50CBD535.3040401@oracle.com> Hi Mike, Thanks for the quick feedback. (I know you've been playing with the JDK8 b68 binary.) On 12/14/2012 1:59 PM, michael keith wrote: > 1. The getAnnotation(Class) method is being changed to look through > container annotations. This method returns an Annotation, i.e. a single > instance, so applying it to repeated ones is necessarily going to have > to return only one. But having it look through container annotation ends > up not being very productive, and may be causing it to be > counter-productive. > > Look-through for this method is not productive because the call is being > made precisely in the legacy cases when only one annotation was > expected, but a container annotation will only be synthesized when > multiples are present. So look-through does not really help get "the" > expected annotation. The only case when it would be useful is in the > unlikely case when the container annotation is used explicitly and > contains a single contained annotation. I feel the author of the repeatable annotation type (who "opted in") and the author of the multiple annotations (@Foo @Foo class C ...) bear some responsibility when a legacy caller of getAnnotation(Class) sees one-out-of-many annotations. Someone decided there is no more of "'the' expected annotation". > It may be counter-productive for three reasons. > The first is because getting a random single annotation in the presence > of multiples is potentially dangerous since the calling code will > continue without knowing that multiples are present, so legacy code is > essentially broken, but will not actually fail. It will just be > semantically incorrect. Acknowledged. > The second is because I didn't see (and I may just have missed it) where > it was defined that if both T and TC were present that T would be > guaranteed to be returned and not some instance within TC. Example 1.2-3 > shows this to be the case but I didn't see that it was specified > behavior rather than just because the T occurred before the TC. If the > example had been TC and then T would the instance of T be returned? If both @T and @TC are present, we have not yet specified [1] whether get[Declared]Annotation(Class) returns always the lone @T v. always a containerized @T v. something different every time. That's what your feedback is for :-) [1] http://download.java.net/jdk8/docs/api/java/lang/reflect/AnnotatedElement.html#getAnnotation%28java.lang.Class%29 > This could be important because existing code to handle this case > checks for the container annotation TC and then checks for the single > annotation T. However, if checking for T happens to look through TC > and return one of the contained annotations in TC instead of the lone > T annotation then the lone annotation would not get found. The implementation currently "prefers" a lone @T over a @T inside @TC. If you have a declaration @TC(...) @T class C {} then C.class.getAnnotation(T.class) will return the standalone @T. So existing code to handle this case will still work. > The third is because all of the code that is currently out there that > needs to check for the previous case, i.e. both T and TC occurring, will > get a false positive in the simpler case of multiple instances of T > annotations (as per the second part of example 1.2-1 in the doc). The > getAnnotation(TC) will return the synthesized TC containing all of the > instances of T, and then getAnnotation(T) will return one of those same > instances again. Legacy code will assume that the result of > getAnnotation(T) is disjoint from the contained annotations of the TC > returned by getAnnotation(TC). Acknowledged. > 2. Given that get[Declared]Annotations() is going to change and return > multiple instances of the same annotation (rather than a single instance > of a container annotation) existing implementations are going to have to > be fixed since there is no backwards compatibility there at all. Acknowledged. The category of existing implementations which assume there will never be more than one annotation of a given type in the returned array is in for a surprise. But there is a category of existing implementations which will continue to work fine. Suppose code calls get[Declared]Annotations() and looks first for @T in the array; only if @T is not found does the code look for @TC in the array. This seems like rational behavior for a non-repeating world, as it means one call to get annotations rather than getAnnotation(T.class) plus getAnnotation(TC.class). Now, run the code on SE 8 to get the new behavior of get[Declared]Annotations(). The code will find an @T in the array (the first of many, perhaps) and there will be no search for @TC and everything will be fine. (Assume a top-level @T is returned before containerized @T's.) > 3. In general, it appears that once an annotation is made repeatable the > annotation processing code is inevitably going to have to change in > order to handle the repeatability. We were willing to take that hit, > particularly since the new behavior requires opting in, and that means > that specs could do so at their own discretion. However, the code to > handle both the new and the old (i.e. be able to process both new > repeatable annotations as well as the older idiomatic container > annotations) is a little less intuitive to write than I had hoped it > would be. The easiest way might just be to create a Set of instances to > avoid duplicates. Not rocket science, just not what I would have expected. I'm not sure if you are proposing that AnnotatedElement should return Set instances or your framework code should create Set instances. By policy, core reflection does not depend on the rest of the Java SE API, so uses array types as aggregates. So, where are we? Joe and I have always recognized that changing getAnnotation(Class) and get[Declared]Annotations() to look through official containers would affect legacy callers who assume there is at most one @T. A legacy caller which allows for both @T and @TC is perhaps hit harder than the rest - we weren't sure how many legacy callers were this careful, but you imply it's non-trivial. Here's an idea. We pondered having the "existing" methods - get[Declared]Annotation(Class) and get[Declared]Annotations() - be unaware of official containers, so they would return exactly what's in the class file. Essentially this is perfect behavioral compatibility. Meanwhile, the new get[Declared]Annotations(Class) methods would look through official containers if present. How does that grab you? Alex From pbenedict at apache.org Sat Dec 15 20:07:44 2012 From: pbenedict at apache.org (Paul Benedict) Date: Sat, 15 Dec 2012 22:07:44 -0600 Subject: repeating annotations comments In-Reply-To: <50CBD535.3040401@oracle.com> References: <50CBA127.9070002@oracle.com> <50CBD535.3040401@oracle.com> Message-ID: I think there is an argument to say that since container annotations are mandatory for repeating annotations, there shouldn't be any looking through. The container annotation should be the thing always returned. I think repeating annotations should be looked at merely as syntactic compiler sugar. Then all these complex rules can go away. Paul On Fri, Dec 14, 2012 at 7:41 PM, Alex Buckley wrote: > Hi Mike, > > Thanks for the quick feedback. (I know you've been playing with the JDK8 b68 > binary.) > > > On 12/14/2012 1:59 PM, michael keith wrote: >> >> 1. The getAnnotation(Class) method is being changed to look through >> container annotations. This method returns an Annotation, i.e. a single >> instance, so applying it to repeated ones is necessarily going to have >> to return only one. But having it look through container annotation ends >> up not being very productive, and may be causing it to be >> counter-productive. >> >> Look-through for this method is not productive because the call is being >> made precisely in the legacy cases when only one annotation was >> expected, but a container annotation will only be synthesized when >> multiples are present. So look-through does not really help get "the" >> expected annotation. The only case when it would be useful is in the >> unlikely case when the container annotation is used explicitly and >> contains a single contained annotation. > > > I feel the author of the repeatable annotation type (who "opted in") and the > author of the multiple annotations (@Foo @Foo class C ...) bear some > responsibility when a legacy caller of getAnnotation(Class) sees > one-out-of-many annotations. Someone decided there is no more of "'the' > expected annotation". > > >> It may be counter-productive for three reasons. >> The first is because getting a random single annotation in the presence >> of multiples is potentially dangerous since the calling code will >> continue without knowing that multiples are present, so legacy code is >> essentially broken, but will not actually fail. It will just be >> semantically incorrect. > > > Acknowledged. > > >> The second is because I didn't see (and I may just have missed it) where >> it was defined that if both T and TC were present that T would be >> guaranteed to be returned and not some instance within TC. Example 1.2-3 >> shows this to be the case but I didn't see that it was specified >> behavior rather than just because the T occurred before the TC. If the >> example had been TC and then T would the instance of T be returned? > > > If both @T and @TC are present, we have not yet specified [1] whether > get[Declared]Annotation(Class) returns always the lone @T v. always a > containerized @T v. something different every time. That's what your > feedback is for :-) > > [1] > http://download.java.net/jdk8/docs/api/java/lang/reflect/AnnotatedElement.html#getAnnotation%28java.lang.Class%29 > > >> This could be important because existing code to handle this case >> checks for the container annotation TC and then checks for the single >> annotation T. However, if checking for T happens to look through TC >> and return one of the contained annotations in TC instead of the lone >> T annotation then the lone annotation would not get found. > > > The implementation currently "prefers" a lone @T over a @T inside @TC. If > you have a declaration @TC(...) @T class C {} then > C.class.getAnnotation(T.class) will return the standalone @T. So existing > code to handle this case will still work. > > >> The third is because all of the code that is currently out there that >> needs to check for the previous case, i.e. both T and TC occurring, will >> get a false positive in the simpler case of multiple instances of T >> annotations (as per the second part of example 1.2-1 in the doc). The >> getAnnotation(TC) will return the synthesized TC containing all of the >> instances of T, and then getAnnotation(T) will return one of those same >> instances again. Legacy code will assume that the result of >> getAnnotation(T) is disjoint from the contained annotations of the TC >> returned by getAnnotation(TC). > > > Acknowledged. > > >> 2. Given that get[Declared]Annotations() is going to change and return >> multiple instances of the same annotation (rather than a single instance >> of a container annotation) existing implementations are going to have to >> be fixed since there is no backwards compatibility there at all. > > > Acknowledged. The category of existing implementations which assume there > will never be more than one annotation of a given type in the returned array > is in for a surprise. > > But there is a category of existing implementations which will continue to > work fine. Suppose code calls get[Declared]Annotations() and looks first for > @T in the array; only if @T is not found does the code look for @TC in the > array. This seems like rational behavior for a non-repeating world, as it > means one call to get annotations rather than getAnnotation(T.class) plus > getAnnotation(TC.class). Now, run the code on SE 8 to get the new behavior > of get[Declared]Annotations(). The code will find an @T in the array (the > first of many, perhaps) and there will be no search for @TC and everything > will be fine. (Assume a top-level @T is returned before containerized @T's.) > > >> 3. In general, it appears that once an annotation is made repeatable the >> annotation processing code is inevitably going to have to change in >> order to handle the repeatability. We were willing to take that hit, >> particularly since the new behavior requires opting in, and that means >> that specs could do so at their own discretion. However, the code to >> handle both the new and the old (i.e. be able to process both new >> repeatable annotations as well as the older idiomatic container >> annotations) is a little less intuitive to write than I had hoped it >> would be. The easiest way might just be to create a Set of instances to >> avoid duplicates. Not rocket science, just not what I would have expected. > > > I'm not sure if you are proposing that AnnotatedElement should return Set > instances or your framework code should create Set instances. By policy, > core reflection does not depend on the rest of the Java SE API, so uses > array types as aggregates. > > So, where are we? Joe and I have always recognized that changing > getAnnotation(Class) and get[Declared]Annotations() to look through > official containers would affect legacy callers who assume there is at most > one @T. A legacy caller which allows for both @T and @TC is perhaps hit > harder than the rest - we weren't sure how many legacy callers were this > careful, but you imply it's non-trivial. > > Here's an idea. We pondered having the "existing" methods - > get[Declared]Annotation(Class) and get[Declared]Annotations() - be > unaware of official containers, so they would return exactly what's in the > class file. Essentially this is perfect behavioral compatibility. Meanwhile, > the new get[Declared]Annotations(Class) methods would look through > official containers if present. How does that grab you? > > Alex From forax at univ-mlv.fr Sun Dec 16 02:40:10 2012 From: forax at univ-mlv.fr (Remi Forax) Date: Sun, 16 Dec 2012 11:40:10 +0100 Subject: repeating annotations comments In-Reply-To: References: <50CBA127.9070002@oracle.com> <50CBD535.3040401@oracle.com> Message-ID: <50CDA50A.20408@univ-mlv.fr> On 12/16/2012 05:07 AM, Paul Benedict wrote: > I think there is an argument to say that since container annotations > are mandatory for repeating annotations, there shouldn't be any > looking through. The container annotation should be the thing always > returned. I think repeating annotations should be looked at merely as > syntactic compiler sugar. Then all these complex rules can go away. yes, no magic is a good argument. > > Paul R?mi > > On Fri, Dec 14, 2012 at 7:41 PM, Alex Buckley wrote: >> Hi Mike, >> >> Thanks for the quick feedback. (I know you've been playing with the JDK8 b68 >> binary.) >> >> >> On 12/14/2012 1:59 PM, michael keith wrote: >>> 1. The getAnnotation(Class) method is being changed to look through >>> container annotations. This method returns an Annotation, i.e. a single >>> instance, so applying it to repeated ones is necessarily going to have >>> to return only one. But having it look through container annotation ends >>> up not being very productive, and may be causing it to be >>> counter-productive. >>> >>> Look-through for this method is not productive because the call is being >>> made precisely in the legacy cases when only one annotation was >>> expected, but a container annotation will only be synthesized when >>> multiples are present. So look-through does not really help get "the" >>> expected annotation. The only case when it would be useful is in the >>> unlikely case when the container annotation is used explicitly and >>> contains a single contained annotation. >> >> I feel the author of the repeatable annotation type (who "opted in") and the >> author of the multiple annotations (@Foo @Foo class C ...) bear some >> responsibility when a legacy caller of getAnnotation(Class) sees >> one-out-of-many annotations. Someone decided there is no more of "'the' >> expected annotation". >> >> >>> It may be counter-productive for three reasons. >>> The first is because getting a random single annotation in the presence >>> of multiples is potentially dangerous since the calling code will >>> continue without knowing that multiples are present, so legacy code is >>> essentially broken, but will not actually fail. It will just be >>> semantically incorrect. >> >> Acknowledged. >> >> >>> The second is because I didn't see (and I may just have missed it) where >>> it was defined that if both T and TC were present that T would be >>> guaranteed to be returned and not some instance within TC. Example 1.2-3 >>> shows this to be the case but I didn't see that it was specified >>> behavior rather than just because the T occurred before the TC. If the >>> example had been TC and then T would the instance of T be returned? >> >> If both @T and @TC are present, we have not yet specified [1] whether >> get[Declared]Annotation(Class) returns always the lone @T v. always a >> containerized @T v. something different every time. That's what your >> feedback is for :-) >> >> [1] >> http://download.java.net/jdk8/docs/api/java/lang/reflect/AnnotatedElement.html#getAnnotation%28java.lang.Class%29 >> >> >>> This could be important because existing code to handle this case >>> checks for the container annotation TC and then checks for the single >>> annotation T. However, if checking for T happens to look through TC >>> and return one of the contained annotations in TC instead of the lone >>> T annotation then the lone annotation would not get found. >> >> The implementation currently "prefers" a lone @T over a @T inside @TC. If >> you have a declaration @TC(...) @T class C {} then >> C.class.getAnnotation(T.class) will return the standalone @T. So existing >> code to handle this case will still work. >> >> >>> The third is because all of the code that is currently out there that >>> needs to check for the previous case, i.e. both T and TC occurring, will >>> get a false positive in the simpler case of multiple instances of T >>> annotations (as per the second part of example 1.2-1 in the doc). The >>> getAnnotation(TC) will return the synthesized TC containing all of the >>> instances of T, and then getAnnotation(T) will return one of those same >>> instances again. Legacy code will assume that the result of >>> getAnnotation(T) is disjoint from the contained annotations of the TC >>> returned by getAnnotation(TC). >> >> Acknowledged. >> >> >>> 2. Given that get[Declared]Annotations() is going to change and return >>> multiple instances of the same annotation (rather than a single instance >>> of a container annotation) existing implementations are going to have to >>> be fixed since there is no backwards compatibility there at all. >> >> Acknowledged. The category of existing implementations which assume there >> will never be more than one annotation of a given type in the returned array >> is in for a surprise. >> >> But there is a category of existing implementations which will continue to >> work fine. Suppose code calls get[Declared]Annotations() and looks first for >> @T in the array; only if @T is not found does the code look for @TC in the >> array. This seems like rational behavior for a non-repeating world, as it >> means one call to get annotations rather than getAnnotation(T.class) plus >> getAnnotation(TC.class). Now, run the code on SE 8 to get the new behavior >> of get[Declared]Annotations(). The code will find an @T in the array (the >> first of many, perhaps) and there will be no search for @TC and everything >> will be fine. (Assume a top-level @T is returned before containerized @T's.) >> >> >>> 3. In general, it appears that once an annotation is made repeatable the >>> annotation processing code is inevitably going to have to change in >>> order to handle the repeatability. We were willing to take that hit, >>> particularly since the new behavior requires opting in, and that means >>> that specs could do so at their own discretion. However, the code to >>> handle both the new and the old (i.e. be able to process both new >>> repeatable annotations as well as the older idiomatic container >>> annotations) is a little less intuitive to write than I had hoped it >>> would be. The easiest way might just be to create a Set of instances to >>> avoid duplicates. Not rocket science, just not what I would have expected. >> >> I'm not sure if you are proposing that AnnotatedElement should return Set >> instances or your framework code should create Set instances. By policy, >> core reflection does not depend on the rest of the Java SE API, so uses >> array types as aggregates. >> >> So, where are we? Joe and I have always recognized that changing >> getAnnotation(Class) and get[Declared]Annotations() to look through >> official containers would affect legacy callers who assume there is at most >> one @T. A legacy caller which allows for both @T and @TC is perhaps hit >> harder than the rest - we weren't sure how many legacy callers were this >> careful, but you imply it's non-trivial. >> >> Here's an idea. We pondered having the "existing" methods - >> get[Declared]Annotation(Class) and get[Declared]Annotations() - be >> unaware of official containers, so they would return exactly what's in the >> class file. Essentially this is perfect behavioral compatibility. Meanwhile, >> the new get[Declared]Annotations(Class) methods would look through >> official containers if present. How does that grab you? >> >> Alex From michael.keith at oracle.com Sun Dec 16 19:33:47 2012 From: michael.keith at oracle.com (Mike Keith) Date: Sun, 16 Dec 2012 22:33:47 -0500 Subject: repeating annotations comments In-Reply-To: <50CBD535.3040401@oracle.com> References: <50CBA127.9070002@oracle.com> <50CBD535.3040401@oracle.com> Message-ID: <7767D3E2-53AB-45A9-A4E9-DAFADC22D6AB@oracle.com> On 2012-12-14, at 8:41 PM, Alex Buckley wrote: > Hi Mike, > > Thanks for the quick feedback. (I know you've been playing with the JDK8 b68 binary.) > > On 12/14/2012 1:59 PM, michael keith wrote: >> 1. The getAnnotation(Class) method is being changed to look through >> container annotations. This method returns an Annotation, i.e. a single >> instance, so applying it to repeated ones is necessarily going to have >> to return only one. But having it look through container annotation ends >> up not being very productive, and may be causing it to be >> counter-productive. >> >> Look-through for this method is not productive because the call is being >> made precisely in the legacy cases when only one annotation was >> expected, but a container annotation will only be synthesized when >> multiples are present. So look-through does not really help get "the" >> expected annotation. The only case when it would be useful is in the >> unlikely case when the container annotation is used explicitly and >> contains a single contained annotation. > > I feel the author of the repeatable annotation type (who "opted in") and the author of the multiple annotations (@Foo @Foo class C ...) bear some responsibility when a legacy caller of getAnnotation(Class) sees one-out-of-many annotations. Someone decided there is no more of "'the' expected annotation". Sure, there is some responsibility to be shared by both of those parties.The problem is that the call succeeds at all. It should probably fail (eg return null) if there are multiples >> It may be counter-productive for three reasons. >> The first is because getting a random single annotation in the presence >> of multiples is potentially dangerous since the calling code will >> continue without knowing that multiples are present, so legacy code is >> essentially broken, but will not actually fail. It will just be >> semantically incorrect. > > Acknowledged. > >> The second is because I didn't see (and I may just have missed it) where >> it was defined that if both T and TC were present that T would be >> guaranteed to be returned and not some instance within TC. Example 1.2-3 >> shows this to be the case but I didn't see that it was specified >> behavior rather than just because the T occurred before the TC. If the >> example had been TC and then T would the instance of T be returned? > > If both @T and @TC are present, we have not yet specified [1] whether get[Declared]Annotation(Class) returns always the lone @T v. always a containerized @T v. something different every time. That's what your feedback is for :-) > > [1] http://download.java.net/jdk8/docs/api/java/lang/reflect/AnnotatedElement.html#getAnnotation%28java.lang.Class%29 > >> This could be important because existing code to handle this case >> checks for the container annotation TC and then checks for the single >> annotation T. However, if checking for T happens to look through TC >> and return one of the contained annotations in TC instead of the lone >> T annotation then the lone annotation would not get found. > > The implementation currently "prefers" a lone @T over a @T inside @TC. If you have a declaration @TC(...) @T class C {} then C.class.getAnnotation(T.class) will return the standalone @T. So existing code to handle this case will still work. > >> The third is because all of the code that is currently out there that >> needs to check for the previous case, i.e. both T and TC occurring, will >> get a false positive in the simpler case of multiple instances of T >> annotations (as per the second part of example 1.2-1 in the doc). The >> getAnnotation(TC) will return the synthesized TC containing all of the >> instances of T, and then getAnnotation(T) will return one of those same >> instances again. Legacy code will assume that the result of >> getAnnotation(T) is disjoint from the contained annotations of the TC >> returned by getAnnotation(TC). > > Acknowledged. > >> 2. Given that get[Declared]Annotations() is going to change and return >> multiple instances of the same annotation (rather than a single instance >> of a container annotation) existing implementations are going to have to >> be fixed since there is no backwards compatibility there at all. > > Acknowledged. The category of existing implementations which assume there will never be more than one annotation of a given type in the returned array is in for a surprise. > > But there is a category of existing implementations which will continue to work fine. Suppose code calls get[Declared]Annotations() and looks first for @T in the array; only if @T is not found does the code look for @TC in the array. This seems like rational behavior for a non-repeating world, as it means one call to get annotations rather than getAnnotation(T.class) plus getAnnotation(TC.class). Now, run the code on SE 8 to get the new behavior of get[Declared]Annotations(). The code will find an @T in the array (the first of many, perhaps) and there will be no search for @TC and everything will be fine. (Assume a top-level @T is returned before containerized @T's.) > >> 3. In general, it appears that once an annotation is made repeatable the >> annotation processing code is inevitably going to have to change in >> order to handle the repeatability. We were willing to take that hit, >> particularly since the new behavior requires opting in, and that means >> that specs could do so at their own discretion. However, the code to >> handle both the new and the old (i.e. be able to process both new >> repeatable annotations as well as the older idiomatic container >> annotations) is a little less intuitive to write than I had hoped it >> would be. The easiest way might just be to create a Set of instances to >> avoid duplicates. Not rocket science, just not what I would have expected. > > I'm not sure if you are proposing that AnnotatedElement should return Set instances or your framework code should create Set instances. By policy, core reflection does not depend on the rest of the Java SE API, so uses array types as aggregates. > > So, where are we? Joe and I have always recognized that changing getAnnotation(Class) and get[Declared]Annotations() to look through official containers would affect legacy callers who assume there is at most one @T. A legacy caller which allows for both @T and @TC is perhaps hit harder than the rest - we weren't sure how many legacy callers were this careful, but you imply it's non-trivial. > > Here's an idea. We pondered having the "existing" methods - get[Declared]Annotation(Class) and get[Declared]Annotations() - be unaware of official containers, so they would return exactly what's in the class file. Essentially this is perfect behavioral compatibility. Meanwhile, the new get[Declared]Annotations(Class) methods would look through official containers if present. How does that grab you? > > Alex From michael.keith at oracle.com Mon Dec 17 06:44:01 2012 From: michael.keith at oracle.com (Mike Keith) Date: Mon, 17 Dec 2012 09:44:01 -0500 Subject: repeating annotations comments In-Reply-To: <7767D3E2-53AB-45A9-A4E9-DAFADC22D6AB@oracle.com> References: <50CBA127.9070002@oracle.com> <50CBD535.3040401@oracle.com> <7767D3E2-53AB-45A9-A4E9-DAFADC22D6AB@oracle.com> Message-ID: <3B1C7369-471D-4285-B82E-976BD7C4019F@oracle.com> Thanks for your comments, ideas and suggestions, Alex. I had more answers but my draft got prematurely sent. More stuff below. -Mike On 2012-12-16, at 10:33 PM, Mike Keith wrote: > > On 2012-12-14, at 8:41 PM, Alex Buckley wrote: > >> Hi Mike, >> >> Thanks for the quick feedback. (I know you've been playing with the JDK8 b68 binary.) >> >> On 12/14/2012 1:59 PM, michael keith wrote: >>> 1. The getAnnotation(Class) method is being changed to look through >>> container annotations. This method returns an Annotation, i.e. a single >>> instance, so applying it to repeated ones is necessarily going to have >>> to return only one. But having it look through container annotation ends >>> up not being very productive, and may be causing it to be >>> counter-productive. >>> >>> Look-through for this method is not productive because the call is being >>> made precisely in the legacy cases when only one annotation was >>> expected, but a container annotation will only be synthesized when >>> multiples are present. So look-through does not really help get "the" >>> expected annotation. The only case when it would be useful is in the >>> unlikely case when the container annotation is used explicitly and >>> contains a single contained annotation. >> >> I feel the author of the repeatable annotation type (who "opted in") and the author of the multiple annotations (@Foo @Foo class C ...) bear some responsibility when a legacy caller of getAnnotation(Class) sees one-out-of-many annotations. Someone decided there is no more of "'the' expected annotation". > > Sure, there is some responsibility to be shared by both of those parties.The problem is that the call succeeds at all. It should probably fail (eg return null) if there are multiples > > >>> It may be counter-productive for three reasons. >>> The first is because getting a random single annotation in the presence >>> of multiples is potentially dangerous since the calling code will >>> continue without knowing that multiples are present, so legacy code is >>> essentially broken, but will not actually fail. It will just be >>> semantically incorrect. >> >> Acknowledged. >> >>> The second is because I didn't see (and I may just have missed it) where >>> it was defined that if both T and TC were present that T would be >>> guaranteed to be returned and not some instance within TC. Example 1.2-3 >>> shows this to be the case but I didn't see that it was specified >>> behavior rather than just because the T occurred before the TC. If the >>> example had been TC and then T would the instance of T be returned? >> >> If both @T and @TC are present, we have not yet specified [1] whether get[Declared]Annotation(Class) returns always the lone @T v. always a containerized @T v. something different every time. That's what your feedback is for :-) >> >> [1] http://download.java.net/jdk8/docs/api/java/lang/reflect/AnnotatedElement.html#getAnnotation%28java.lang.Class%29 >> >>> This could be important because existing code to handle this case >>> checks for the container annotation TC and then checks for the single >>> annotation T. However, if checking for T happens to look through TC >>> and return one of the contained annotations in TC instead of the lone >>> T annotation then the lone annotation would not get found. >> >> The implementation currently "prefers" a lone @T over a @T inside @TC. If you have a declaration @TC(...) @T class C {} then C.class.getAnnotation(T.class) will return the standalone @T. So existing code to handle this case will still work. >> >>> The third is because all of the code that is currently out there that >>> needs to check for the previous case, i.e. both T and TC occurring, will >>> get a false positive in the simpler case of multiple instances of T >>> annotations (as per the second part of example 1.2-1 in the doc). The >>> getAnnotation(TC) will return the synthesized TC containing all of the >>> instances of T, and then getAnnotation(T) will return one of those same >>> instances again. Legacy code will assume that the result of >>> getAnnotation(T) is disjoint from the contained annotations of the TC >>> returned by getAnnotation(TC). >> >> Acknowledged. >> >>> 2. Given that get[Declared]Annotations() is going to change and return >>> multiple instances of the same annotation (rather than a single instance >>> of a container annotation) existing implementations are going to have to >>> be fixed since there is no backwards compatibility there at all. >> >> Acknowledged. The category of existing implementations which assume there will never be more than one annotation of a given type in the returned array is in for a surprise. >> >> But there is a category of existing implementations which will continue to work fine. Suppose code calls get[Declared]Annotations() and looks first for @T in the array; only if @T is not found does the code look for @TC in the array. This seems like rational behavior for a non-repeating world, as it means one call to get annotations rather than getAnnotation(T.class) plus getAnnotation(TC.class). Now, run the code on SE 8 to get the new behavior of get[Declared]Annotations(). The code will find an @T in the array (the first of many, perhaps) and there will be no search for @TC and everything will be fine. (Assume a top-level @T is returned before containerized @T's.) I might be misunderstanding you, but I don't see how that category of legacy application would continue to work. It still won't be expecting multiples as it looks in the collection, so it will stop looking once it finds the first one. >> >>> 3. In general, it appears that once an annotation is made repeatable the >>> annotation processing code is inevitably going to have to change in >>> order to handle the repeatability. We were willing to take that hit, >>> particularly since the new behavior requires opting in, and that means >>> that specs could do so at their own discretion. However, the code to >>> handle both the new and the old (i.e. be able to process both new >>> repeatable annotations as well as the older idiomatic container >>> annotations) is a little less intuitive to write than I had hoped it >>> would be. The easiest way might just be to create a Set of instances to >>> avoid duplicates. Not rocket science, just not what I would have expected. >> >> I'm not sure if you are proposing that AnnotatedElement should return Set instances or your framework code should create Set instances. By policy, core reflection does not depend on the rest of the Java SE API, so uses array types as aggregates. No, sorry, I was just describing what the processor might have to do, not implying that a Set would be returned by any of the reflection calls. >> >> So, where are we? Joe and I have always recognized that changing getAnnotation(Class) and get[Declared]Annotations() to look through official containers would affect legacy callers who assume there is at most one @T. A legacy caller which allows for both @T and @TC is perhaps hit harder than the rest - we weren't sure how many legacy callers were this careful, but you imply it's non-trivial. Yes, and the number of users that would actually make use of this pattern is admittedly minuscule. Unfortunately, the processing code generally ends up having to handle it anyway, so the pattern for processing it is going to be widespread. >> Here's an idea. We pondered having the "existing" methods - get[Declared]Annotation(Class) and get[Declared]Annotations() - be unaware of official containers, so they would return exactly what's in the class file. Essentially this is perfect behavioral compatibility. Meanwhile, the new get[Declared]Annotations(Class) methods would look through official containers if present. How does that grab you? From a compatibility perspective that would be great. Existing code would be able to handle existing applications, and new code could easily handle both old and new applications. I would just like to mention, though, that while we in EE-land would like compatibility we are also sensitive to non-legacy users and don't want to impose changes that too severely hamper the API or render it unintuitive in the future. We are certainly willing to make changes to code if necessary, but I was kind of hoping that we wouldn't be in the situation of existing code apparently working, but not really. I would be interested in hearing how others view the idea of the typed version of get[Declared]Annotations behaving differently than the legacy untyped one. From pbenedict at apache.org Mon Dec 17 08:06:42 2012 From: pbenedict at apache.org (Paul Benedict) Date: Mon, 17 Dec 2012 10:06:42 -0600 Subject: repeating annotations comments In-Reply-To: <50CDA50A.20408@univ-mlv.fr> References: <50CBA127.9070002@oracle.com> <50CBD535.3040401@oracle.com> <50CDA50A.20408@univ-mlv.fr> Message-ID: If you look back in previous discussions, some have opined how they don't want incongruity between the reflection data and the developer's code. For example, if the code has @A @A, then two annotations should be returned (except for legacy reflection methods). I think this sentiment should fly out the window. Container annotations are mandatory forever. They aren't going away ever -- so why hide them? I definitely value all the work that has gone into this enhancement so far, but perhaps there can be some 20/20 hindsight and see the complexities getting a bit too deep. Is there any chance for the EG to consider this as syntactic sugar only? Paul On Sun, Dec 16, 2012 at 4:40 AM, Remi Forax wrote: > On 12/16/2012 05:07 AM, Paul Benedict wrote: >> >> I think there is an argument to say that since container annotations >> are mandatory for repeating annotations, there shouldn't be any >> looking through. The container annotation should be the thing always >> returned. I think repeating annotations should be looked at merely as >> syntactic compiler sugar. Then all these complex rules can go away. > > > yes, no magic is a good argument. > >> >> Paul > > > R?mi > > >> >> On Fri, Dec 14, 2012 at 7:41 PM, Alex Buckley >> wrote: >>> >>> Hi Mike, >>> >>> Thanks for the quick feedback. (I know you've been playing with the JDK8 >>> b68 >>> binary.) >>> >>> >>> On 12/14/2012 1:59 PM, michael keith wrote: >>>> >>>> 1. The getAnnotation(Class) method is being changed to look through >>>> container annotations. This method returns an Annotation, i.e. a single >>>> instance, so applying it to repeated ones is necessarily going to have >>>> to return only one. But having it look through container annotation ends >>>> up not being very productive, and may be causing it to be >>>> counter-productive. >>>> >>>> Look-through for this method is not productive because the call is being >>>> made precisely in the legacy cases when only one annotation was >>>> expected, but a container annotation will only be synthesized when >>>> multiples are present. So look-through does not really help get "the" >>>> expected annotation. The only case when it would be useful is in the >>>> unlikely case when the container annotation is used explicitly and >>>> contains a single contained annotation. >>> >>> >>> I feel the author of the repeatable annotation type (who "opted in") and >>> the >>> author of the multiple annotations (@Foo @Foo class C ...) bear some >>> responsibility when a legacy caller of getAnnotation(Class) sees >>> one-out-of-many annotations. Someone decided there is no more of "'the' >>> expected annotation". >>> >>> >>>> It may be counter-productive for three reasons. >>>> The first is because getting a random single annotation in the presence >>>> of multiples is potentially dangerous since the calling code will >>>> continue without knowing that multiples are present, so legacy code is >>>> essentially broken, but will not actually fail. It will just be >>>> semantically incorrect. >>> >>> >>> Acknowledged. >>> >>> >>>> The second is because I didn't see (and I may just have missed it) where >>>> it was defined that if both T and TC were present that T would be >>>> guaranteed to be returned and not some instance within TC. Example 1.2-3 >>>> shows this to be the case but I didn't see that it was specified >>>> behavior rather than just because the T occurred before the TC. If the >>>> example had been TC and then T would the instance of T be returned? >>> >>> >>> If both @T and @TC are present, we have not yet specified [1] whether >>> get[Declared]Annotation(Class) returns always the lone @T v. always a >>> containerized @T v. something different every time. That's what your >>> feedback is for :-) >>> >>> [1] >>> >>> http://download.java.net/jdk8/docs/api/java/lang/reflect/AnnotatedElement.html#getAnnotation%28java.lang.Class%29 >>> >>> >>>> This could be important because existing code to handle this case >>>> checks for the container annotation TC and then checks for the single >>>> annotation T. However, if checking for T happens to look through TC >>>> and return one of the contained annotations in TC instead of the lone >>>> T annotation then the lone annotation would not get found. >>> >>> >>> The implementation currently "prefers" a lone @T over a @T inside @TC. If >>> you have a declaration @TC(...) @T class C {} then >>> C.class.getAnnotation(T.class) will return the standalone @T. So existing >>> code to handle this case will still work. >>> >>> >>>> The third is because all of the code that is currently out there that >>>> needs to check for the previous case, i.e. both T and TC occurring, will >>>> get a false positive in the simpler case of multiple instances of T >>>> annotations (as per the second part of example 1.2-1 in the doc). The >>>> getAnnotation(TC) will return the synthesized TC containing all of the >>>> instances of T, and then getAnnotation(T) will return one of those same >>>> instances again. Legacy code will assume that the result of >>>> getAnnotation(T) is disjoint from the contained annotations of the TC >>>> returned by getAnnotation(TC). >>> >>> >>> Acknowledged. >>> >>> >>>> 2. Given that get[Declared]Annotations() is going to change and return >>>> multiple instances of the same annotation (rather than a single instance >>>> of a container annotation) existing implementations are going to have to >>>> be fixed since there is no backwards compatibility there at all. >>> >>> >>> Acknowledged. The category of existing implementations which assume there >>> will never be more than one annotation of a given type in the returned >>> array >>> is in for a surprise. >>> >>> But there is a category of existing implementations which will continue >>> to >>> work fine. Suppose code calls get[Declared]Annotations() and looks first >>> for >>> @T in the array; only if @T is not found does the code look for @TC in >>> the >>> array. This seems like rational behavior for a non-repeating world, as it >>> means one call to get annotations rather than getAnnotation(T.class) plus >>> getAnnotation(TC.class). Now, run the code on SE 8 to get the new >>> behavior >>> of get[Declared]Annotations(). The code will find an @T in the array (the >>> first of many, perhaps) and there will be no search for @TC and >>> everything >>> will be fine. (Assume a top-level @T is returned before containerized >>> @T's.) >>> >>> >>>> 3. In general, it appears that once an annotation is made repeatable the >>>> annotation processing code is inevitably going to have to change in >>>> order to handle the repeatability. We were willing to take that hit, >>>> particularly since the new behavior requires opting in, and that means >>>> that specs could do so at their own discretion. However, the code to >>>> handle both the new and the old (i.e. be able to process both new >>>> repeatable annotations as well as the older idiomatic container >>>> annotations) is a little less intuitive to write than I had hoped it >>>> would be. The easiest way might just be to create a Set of instances to >>>> avoid duplicates. Not rocket science, just not what I would have >>>> expected. >>> >>> >>> I'm not sure if you are proposing that AnnotatedElement should return Set >>> instances or your framework code should create Set instances. By policy, >>> core reflection does not depend on the rest of the Java SE API, so uses >>> array types as aggregates. >>> >>> So, where are we? Joe and I have always recognized that changing >>> getAnnotation(Class) and get[Declared]Annotations() to look through >>> official containers would affect legacy callers who assume there is at >>> most >>> one @T. A legacy caller which allows for both @T and @TC is perhaps hit >>> harder than the rest - we weren't sure how many legacy callers were this >>> careful, but you imply it's non-trivial. >>> >>> Here's an idea. We pondered having the "existing" methods - >>> get[Declared]Annotation(Class) and get[Declared]Annotations() - be >>> unaware of official containers, so they would return exactly what's in >>> the >>> class file. Essentially this is perfect behavioral compatibility. >>> Meanwhile, >>> the new get[Declared]Annotations(Class) methods would look through >>> official containers if present. How does that grab you? >>> >>> Alex > > From joel.franck at oracle.com Mon Dec 17 09:25:09 2012 From: joel.franck at oracle.com (=?iso-8859-1?Q?Joel_Borggr=E9n-Franck?=) Date: Mon, 17 Dec 2012 18:25:09 +0100 Subject: repeating annotations comments In-Reply-To: References: <50CBA127.9070002@oracle.com> <50CBD535.3040401@oracle.com> <50CDA50A.20408@univ-mlv.fr> Message-ID: <17A31276-7104-4E97-A9C0-A2C1023A0BE5@oracle.com> Hi, Paul and Remi, have you read the end of Alex' mail? When I read your mails I have a hard time figuring out if you noticed this idea and think even this is to much magic, if if you just missed it. On Dec 17, 2012, at 5:06 PM, Paul Benedict wrote: > If you look back in previous discussions, some have opined how they > don't want incongruity between the reflection data and the developer's > code. For example, if the code has @A @A, then two annotations should > be returned (except for legacy reflection methods). I think this > sentiment should fly out the window. Container annotations are > mandatory forever. They aren't going away ever -- so why hide them? I > definitely value all the work that has gone into this enhancement so > far, but perhaps there can be some 20/20 hindsight and see the > complexities getting a bit too deep. > > Is there any chance for the EG to consider this as syntactic sugar only? > >>>> >>>> Here's an idea. We pondered having the "existing" methods - >>>> get[Declared]Annotation(Class) and get[Declared]Annotations() - be >>>> unaware of official containers, so they would return exactly what's in >>>> the >>>> class file. Essentially this is perfect behavioral compatibility. >>>> Meanwhile, >>>> the new get[Declared]Annotations(Class) methods would look through >>>> official containers if present. How does that grab you? >>>> cheers /Joel From forax at univ-mlv.fr Mon Dec 17 09:50:27 2012 From: forax at univ-mlv.fr (Remi Forax) Date: Mon, 17 Dec 2012 18:50:27 +0100 Subject: repeating annotations comments In-Reply-To: <17A31276-7104-4E97-A9C0-A2C1023A0BE5@oracle.com> References: <50CBA127.9070002@oracle.com> <50CBD535.3040401@oracle.com> <50CDA50A.20408@univ-mlv.fr> <17A31276-7104-4E97-A9C0-A2C1023A0BE5@oracle.com> Message-ID: <50CF5B63.101@univ-mlv.fr> On 12/17/2012 06:25 PM, Joel Borggr?n-Franck wrote: > Hi, > > Paul and Remi, have you read the end of Alex' mail? When I read your mails I have a hard time figuring out if you noticed this idea and think even this is to much magic, if if you just missed it. Hi Joel, no, I've read the whole message :) I think that Alex's proposal goes is the right way but I also think that container annotations doesn't worth to have new calls like get[Declared]Annotations(Class), as I said, I prefer the non magical way. In my mind, container annotations are, as Paul said just syntactic sugar for framework users, and are seen by reflection as container annotations. cheers, R?mi > On Dec 17, 2012, at 5:06 PM, Paul Benedict wrote: > >> If you look back in previous discussions, some have opined how they >> don't want incongruity between the reflection data and the developer's >> code. For example, if the code has @A @A, then two annotations should >> be returned (except for legacy reflection methods). I think this >> sentiment should fly out the window. Container annotations are >> mandatory forever. They aren't going away ever -- so why hide them? I >> definitely value all the work that has gone into this enhancement so >> far, but perhaps there can be some 20/20 hindsight and see the >> complexities getting a bit too deep. >> >> Is there any chance for the EG to consider this as syntactic sugar only? >> >>>>> Here's an idea. We pondered having the "existing" methods - >>>>> get[Declared]Annotation(Class) and get[Declared]Annotations() - be >>>>> unaware of official containers, so they would return exactly what's in >>>>> the >>>>> class file. Essentially this is perfect behavioral compatibility. >>>>> Meanwhile, >>>>> the new get[Declared]Annotations(Class) methods would look through >>>>> official containers if present. How does that grab you? >>>>> > cheers > /Joel > From michael.keith at oracle.com Thu Dec 20 19:48:37 2012 From: michael.keith at oracle.com (michael keith) Date: Thu, 20 Dec 2012 22:48:37 -0500 Subject: repeating annotations comments In-Reply-To: <3B1C7369-471D-4285-B82E-976BD7C4019F@oracle.com> References: <50CBA127.9070002@oracle.com> <50CBD535.3040401@oracle.com> <7767D3E2-53AB-45A9-A4E9-DAFADC22D6AB@oracle.com> <3B1C7369-471D-4285-B82E-976BD7C4019F@oracle.com> Message-ID: <50D3DC15.9000205@oracle.com> Just to follow up on this, I did a quick survey and there are a number of EE 6 specs that make use of the idiomatic container pattern: EJB, JPA, JAXB, JAX-WS, JSF, Interceptors, Connectors, and Common Annotations. These are just the EE 6 specs, I didn't go through the ongoing EE 7 ones. This means that all of the implementations, IDE's, 3rd party tools and frameworks that process annotations from these specs will break, in many cases imperceptibly, if the semantics of the existing reflection methods get changed. As I mentioned earlier, while I was prepared to require that implementations change once we upgraded the specs to use repeatable annotations, I feel the fanout is too broad and the manner of breakage too subtle that the cost of abandoning compatibility is too high. If people feel there is confusion around the new methods acting differently from the old ones in the presence of repeatable annotations then perhaps we could go back to exploring the use of different names for the new ones. -Mike On 17/12/2012 9:44 AM, Mike Keith wrote: > Thanks for your comments, ideas and suggestions, Alex. I had more answers but my draft got prematurely sent. More stuff below. > > -Mike > > On 2012-12-16, at 10:33 PM, Mike Keith wrote: > >> On 2012-12-14, at 8:41 PM, Alex Buckley wrote: >> >>> Hi Mike, >>> >>> Thanks for the quick feedback. (I know you've been playing with the JDK8 b68 binary.) >>> >>> On 12/14/2012 1:59 PM, michael keith wrote: >>>> 1. The getAnnotation(Class) method is being changed to look through >>>> container annotations. This method returns an Annotation, i.e. a single >>>> instance, so applying it to repeated ones is necessarily going to have >>>> to return only one. But having it look through container annotation ends >>>> up not being very productive, and may be causing it to be >>>> counter-productive. >>>> >>>> Look-through for this method is not productive because the call is being >>>> made precisely in the legacy cases when only one annotation was >>>> expected, but a container annotation will only be synthesized when >>>> multiples are present. So look-through does not really help get "the" >>>> expected annotation. The only case when it would be useful is in the >>>> unlikely case when the container annotation is used explicitly and >>>> contains a single contained annotation. >>> I feel the author of the repeatable annotation type (who "opted in") and the author of the multiple annotations (@Foo @Foo class C ...) bear some responsibility when a legacy caller of getAnnotation(Class) sees one-out-of-many annotations. Someone decided there is no more of "'the' expected annotation". >> Sure, there is some responsibility to be shared by both of those parties.The problem is that the call succeeds at all. It should probably fail (eg return null) if there are multiples >> >> >>>> It may be counter-productive for three reasons. >>>> The first is because getting a random single annotation in the presence >>>> of multiples is potentially dangerous since the calling code will >>>> continue without knowing that multiples are present, so legacy code is >>>> essentially broken, but will not actually fail. It will just be >>>> semantically incorrect. >>> Acknowledged. >>> >>>> The second is because I didn't see (and I may just have missed it) where >>>> it was defined that if both T and TC were present that T would be >>>> guaranteed to be returned and not some instance within TC. Example 1.2-3 >>>> shows this to be the case but I didn't see that it was specified >>>> behavior rather than just because the T occurred before the TC. If the >>>> example had been TC and then T would the instance of T be returned? >>> If both @T and @TC are present, we have not yet specified [1] whether get[Declared]Annotation(Class) returns always the lone @T v. always a containerized @T v. something different every time. That's what your feedback is for :-) >>> >>> [1] http://download.java.net/jdk8/docs/api/java/lang/reflect/AnnotatedElement.html#getAnnotation%28java.lang.Class%29 >>> >>>> This could be important because existing code to handle this case >>>> checks for the container annotation TC and then checks for the single >>>> annotation T. However, if checking for T happens to look through TC >>>> and return one of the contained annotations in TC instead of the lone >>>> T annotation then the lone annotation would not get found. >>> The implementation currently "prefers" a lone @T over a @T inside @TC. If you have a declaration @TC(...) @T class C {} then C.class.getAnnotation(T.class) will return the standalone @T. So existing code to handle this case will still work. >>> >>>> The third is because all of the code that is currently out there that >>>> needs to check for the previous case, i.e. both T and TC occurring, will >>>> get a false positive in the simpler case of multiple instances of T >>>> annotations (as per the second part of example 1.2-1 in the doc). The >>>> getAnnotation(TC) will return the synthesized TC containing all of the >>>> instances of T, and then getAnnotation(T) will return one of those same >>>> instances again. Legacy code will assume that the result of >>>> getAnnotation(T) is disjoint from the contained annotations of the TC >>>> returned by getAnnotation(TC). >>> Acknowledged. >>> >>>> 2. Given that get[Declared]Annotations() is going to change and return >>>> multiple instances of the same annotation (rather than a single instance >>>> of a container annotation) existing implementations are going to have to >>>> be fixed since there is no backwards compatibility there at all. >>> Acknowledged. The category of existing implementations which assume there will never be more than one annotation of a given type in the returned array is in for a surprise. >>> >>> But there is a category of existing implementations which will continue to work fine. Suppose code calls get[Declared]Annotations() and looks first for @T in the array; only if @T is not found does the code look for @TC in the array. This seems like rational behavior for a non-repeating world, as it means one call to get annotations rather than getAnnotation(T.class) plus getAnnotation(TC.class). Now, run the code on SE 8 to get the new behavior of get[Declared]Annotations(). The code will find an @T in the array (the first of many, perhaps) and there will be no search for @TC and everything will be fine. (Assume a top-level @T is returned before containerized @T's.) > I might be misunderstanding you, but I don't see how that category of legacy application would continue to work. It still won't be expecting multiples as it looks in the collection, so it will stop looking once it finds the first one. > >>>> 3. In general, it appears that once an annotation is made repeatable the >>>> annotation processing code is inevitably going to have to change in >>>> order to handle the repeatability. We were willing to take that hit, >>>> particularly since the new behavior requires opting in, and that means >>>> that specs could do so at their own discretion. However, the code to >>>> handle both the new and the old (i.e. be able to process both new >>>> repeatable annotations as well as the older idiomatic container >>>> annotations) is a little less intuitive to write than I had hoped it >>>> would be. The easiest way might just be to create a Set of instances to >>>> avoid duplicates. Not rocket science, just not what I would have expected. >>> I'm not sure if you are proposing that AnnotatedElement should return Set instances or your framework code should create Set instances. By policy, core reflection does not depend on the rest of the Java SE API, so uses array types as aggregates. > No, sorry, I was just describing what the processor might have to do, not implying that a Set would be returned by any of the reflection calls. > >>> So, where are we? Joe and I have always recognized that changing getAnnotation(Class) and get[Declared]Annotations() to look through official containers would affect legacy callers who assume there is at most one @T. A legacy caller which allows for both @T and @TC is perhaps hit harder than the rest - we weren't sure how many legacy callers were this careful, but you imply it's non-trivial. > Yes, and the number of users that would actually make use of this pattern is admittedly minuscule. Unfortunately, the processing code generally ends up having to handle it anyway, so the pattern for processing it is going to be widespread. > >>> Here's an idea. We pondered having the "existing" methods - get[Declared]Annotation(Class) and get[Declared]Annotations() - be unaware of official containers, so they would return exactly what's in the class file. Essentially this is perfect behavioral compatibility. Meanwhile, the new get[Declared]Annotations(Class) methods would look through official containers if present. How does that grab you? > From a compatibility perspective that would be great. Existing code would be able to handle existing applications, and new code could easily handle both old and new applications. > > I would just like to mention, though, that while we in EE-land would like compatibility we are also sensitive to non-legacy users and don't want to impose changes that too severely hamper the API or render it unintuitive in the future. We are certainly willing to make changes to code if necessary, but I was kind of hoping that we wouldn't be in the situation of existing code apparently working, but not really. I would be interested in hearing how others view the idea of the typed version of get[Declared]Annotations behaving differently than the legacy untyped one. From joe.darcy at oracle.com Fri Dec 21 22:03:13 2012 From: joe.darcy at oracle.com (Joe Darcy) Date: Fri, 21 Dec 2012 22:03:13 -0800 Subject: repeating annotations comments In-Reply-To: <50D3DC15.9000205@oracle.com> References: <50CBA127.9070002@oracle.com> <50CBD535.3040401@oracle.com> <7767D3E2-53AB-45A9-A4E9-DAFADC22D6AB@oracle.com> <3B1C7369-471D-4285-B82E-976BD7C4019F@oracle.com> <50D3DC15.9000205@oracle.com> Message-ID: <50D54D21.5050900@oracle.com> Hi Mike, On 12/20/2012 7:48 PM, michael keith wrote: > Just to follow up on this, I did a quick survey and there are a number > of EE 6 specs that make use of the idiomatic container pattern: EJB, > JPA, JAXB, JAX-WS, JSF, Interceptors, Connectors, and Common > Annotations. These are just the EE 6 specs, I didn't go through the > ongoing EE 7 ones. This means that all of the implementations, IDE's, > 3rd party tools and frameworks that process annotations from these > specs will break, in many cases imperceptibly, if the semantics of the > existing reflection methods get changed. As I mentioned earlier, while > I was prepared to require that implementations change once we upgraded > the specs to use repeatable annotations, I feel the fanout is too > broad and the manner of breakage too subtle that the cost of > abandoning compatibility is too high. If people feel there is > confusion around the new methods acting differently from the old ones > in the presence of repeatable annotations then perhaps we could go > back to exploring the use of different names for the new ones. It would be very helpful for someone to verify that the idiomatic container pattern used in the various EE specs can be successfully retrofitted to use the formal container pattern in the current JDK 8 builds. Several adjustments were made to the initial formal container design to accommodate the actual usage patterns in EE. Thanks, -Joe > > -Mike > > On 17/12/2012 9:44 AM, Mike Keith wrote: >> Thanks for your comments, ideas and suggestions, Alex. I had more >> answers but my draft got prematurely sent. More stuff below. >> >> -Mike >> >> On 2012-12-16, at 10:33 PM, Mike Keith wrote: >> >>> On 2012-12-14, at 8:41 PM, Alex Buckley >>> wrote: >>> >>>> Hi Mike, >>>> >>>> Thanks for the quick feedback. (I know you've been playing with the >>>> JDK8 b68 binary.) >>>> >>>> On 12/14/2012 1:59 PM, michael keith wrote: >>>>> 1. The getAnnotation(Class) method is being changed to look >>>>> through >>>>> container annotations. This method returns an Annotation, i.e. a >>>>> single >>>>> instance, so applying it to repeated ones is necessarily going to >>>>> have >>>>> to return only one. But having it look through container >>>>> annotation ends >>>>> up not being very productive, and may be causing it to be >>>>> counter-productive. >>>>> >>>>> Look-through for this method is not productive because the call is >>>>> being >>>>> made precisely in the legacy cases when only one annotation was >>>>> expected, but a container annotation will only be synthesized when >>>>> multiples are present. So look-through does not really help get "the" >>>>> expected annotation. The only case when it would be useful is in the >>>>> unlikely case when the container annotation is used explicitly and >>>>> contains a single contained annotation. >>>> I feel the author of the repeatable annotation type (who "opted >>>> in") and the author of the multiple annotations (@Foo @Foo class C >>>> ...) bear some responsibility when a legacy caller of >>>> getAnnotation(Class) sees one-out-of-many annotations. Someone >>>> decided there is no more of "'the' expected annotation". >>> Sure, there is some responsibility to be shared by both of those >>> parties.The problem is that the call succeeds at all. It should >>> probably fail (eg return null) if there are multiples >>> >>> >>>>> It may be counter-productive for three reasons. >>>>> The first is because getting a random single annotation in the >>>>> presence >>>>> of multiples is potentially dangerous since the calling code will >>>>> continue without knowing that multiples are present, so legacy >>>>> code is >>>>> essentially broken, but will not actually fail. It will just be >>>>> semantically incorrect. >>>> Acknowledged. >>>> >>>>> The second is because I didn't see (and I may just have missed it) >>>>> where >>>>> it was defined that if both T and TC were present that T would be >>>>> guaranteed to be returned and not some instance within TC. Example >>>>> 1.2-3 >>>>> shows this to be the case but I didn't see that it was specified >>>>> behavior rather than just because the T occurred before the TC. If >>>>> the >>>>> example had been TC and then T would the instance of T be returned? >>>> If both @T and @TC are present, we have not yet specified [1] >>>> whether get[Declared]Annotation(Class) returns always the lone >>>> @T v. always a containerized @T v. something different every time. >>>> That's what your feedback is for :-) >>>> >>>> [1] >>>> http://download.java.net/jdk8/docs/api/java/lang/reflect/AnnotatedElement.html#getAnnotation%28java.lang.Class%29 >>>> >>>>> This could be important because existing code to handle this case >>>>> checks for the container annotation TC and then checks for the single >>>>> annotation T. However, if checking for T happens to look through TC >>>>> and return one of the contained annotations in TC instead of the lone >>>>> T annotation then the lone annotation would not get found. >>>> The implementation currently "prefers" a lone @T over a @T inside >>>> @TC. If you have a declaration @TC(...) @T class C {} then >>>> C.class.getAnnotation(T.class) will return the standalone @T. So >>>> existing code to handle this case will still work. >>>> >>>>> The third is because all of the code that is currently out there that >>>>> needs to check for the previous case, i.e. both T and TC >>>>> occurring, will >>>>> get a false positive in the simpler case of multiple instances of T >>>>> annotations (as per the second part of example 1.2-1 in the doc). The >>>>> getAnnotation(TC) will return the synthesized TC containing all of >>>>> the >>>>> instances of T, and then getAnnotation(T) will return one of those >>>>> same >>>>> instances again. Legacy code will assume that the result of >>>>> getAnnotation(T) is disjoint from the contained annotations of the TC >>>>> returned by getAnnotation(TC). >>>> Acknowledged. >>>> >>>>> 2. Given that get[Declared]Annotations() is going to change and >>>>> return >>>>> multiple instances of the same annotation (rather than a single >>>>> instance >>>>> of a container annotation) existing implementations are going to >>>>> have to >>>>> be fixed since there is no backwards compatibility there at all. >>>> Acknowledged. The category of existing implementations which assume >>>> there will never be more than one annotation of a given type in the >>>> returned array is in for a surprise. >>>> >>>> But there is a category of existing implementations which will >>>> continue to work fine. Suppose code calls >>>> get[Declared]Annotations() and looks first for @T in the array; >>>> only if @T is not found does the code look for @TC in the array. >>>> This seems like rational behavior for a non-repeating world, as it >>>> means one call to get annotations rather than >>>> getAnnotation(T.class) plus getAnnotation(TC.class). Now, run the >>>> code on SE 8 to get the new behavior of get[Declared]Annotations(). >>>> The code will find an @T in the array (the first of many, perhaps) >>>> and there will be no search for @TC and everything will be fine. >>>> (Assume a top-level @T is returned before containerized @T's.) >> I might be misunderstanding you, but I don't see how that category of >> legacy application would continue to work. It still won't be >> expecting multiples as it looks in the collection, so it will stop >> looking once it finds the first one. >> >>>>> 3. In general, it appears that once an annotation is made >>>>> repeatable the >>>>> annotation processing code is inevitably going to have to change in >>>>> order to handle the repeatability. We were willing to take that hit, >>>>> particularly since the new behavior requires opting in, and that >>>>> means >>>>> that specs could do so at their own discretion. However, the code to >>>>> handle both the new and the old (i.e. be able to process both new >>>>> repeatable annotations as well as the older idiomatic container >>>>> annotations) is a little less intuitive to write than I had hoped it >>>>> would be. The easiest way might just be to create a Set of >>>>> instances to >>>>> avoid duplicates. Not rocket science, just not what I would have >>>>> expected. >>>> I'm not sure if you are proposing that AnnotatedElement should >>>> return Set instances or your framework code should create Set >>>> instances. By policy, core reflection does not depend on the rest >>>> of the Java SE API, so uses array types as aggregates. >> No, sorry, I was just describing what the processor might have to do, >> not implying that a Set would be returned by any of the reflection >> calls. >> >>>> So, where are we? Joe and I have always recognized that changing >>>> getAnnotation(Class) and get[Declared]Annotations() to look >>>> through official containers would affect legacy callers who assume >>>> there is at most one @T. A legacy caller which allows for both @T >>>> and @TC is perhaps hit harder than the rest - we weren't sure how >>>> many legacy callers were this careful, but you imply it's non-trivial. >> Yes, and the number of users that would actually make use of this >> pattern is admittedly minuscule. Unfortunately, the processing code >> generally ends up having to handle it anyway, so the pattern for >> processing it is going to be widespread. >> >>>> Here's an idea. We pondered having the "existing" methods - >>>> get[Declared]Annotation(Class) and get[Declared]Annotations() - >>>> be unaware of official containers, so they would return exactly >>>> what's in the class file. Essentially this is perfect behavioral >>>> compatibility. Meanwhile, the new >>>> get[Declared]Annotations(Class) methods would look through >>>> official containers if present. How does that grab you? >> From a compatibility perspective that would be great. Existing code >> would be able to handle existing applications, and new code could >> easily handle both old and new applications. >> >> I would just like to mention, though, that while we in EE-land would >> like compatibility we are also sensitive to non-legacy users and >> don't want to impose changes that too severely hamper the API or >> render it unintuitive in the future. We are certainly willing to make >> changes to code if necessary, but I was kind of hoping that we >> wouldn't be in the situation of existing code apparently working, but >> not really. I would be interested in hearing how others view the idea >> of the typed version of get[Declared]Annotations behaving differently >> than the legacy untyped one. From michael.keith at oracle.com Sat Dec 22 08:50:01 2012 From: michael.keith at oracle.com (michael keith) Date: Sat, 22 Dec 2012 11:50:01 -0500 Subject: repeating annotations comments In-Reply-To: <50D54D21.5050900@oracle.com> References: <50CBA127.9070002@oracle.com> <50CBD535.3040401@oracle.com> <7767D3E2-53AB-45A9-A4E9-DAFADC22D6AB@oracle.com> <3B1C7369-471D-4285-B82E-976BD7C4019F@oracle.com> <50D3DC15.9000205@oracle.com> <50D54D21.5050900@oracle.com> Message-ID: <50D5E4B9.4010102@oracle.com> Okay. I'll give it a go and let you know. -Mike On 22/12/2012 1:03 AM, Joe Darcy wrote: > Hi Mike, > On 12/20/2012 7:48 PM, michael keith wrote: >> Just to follow up on this, I did a quick survey and there are a >> number of EE 6 specs that make use of the idiomatic container >> pattern: EJB, JPA, JAXB, JAX-WS, JSF, Interceptors, Connectors, and >> Common Annotations. These are just the EE 6 specs, I didn't go >> through the ongoing EE 7 ones. This means that all of the >> implementations, IDE's, 3rd party tools and frameworks that process >> annotations from these specs will break, in many cases imperceptibly, >> if the semantics of the existing reflection methods get changed. As I >> mentioned earlier, while I was prepared to require that >> implementations change once we upgraded the specs to use repeatable >> annotations, I feel the fanout is too broad and the manner of >> breakage too subtle that the cost of abandoning compatibility is too >> high. If people feel there is confusion around the new methods acting >> differently from the old ones in the presence of repeatable >> annotations then perhaps we could go back to exploring the use of >> different names for the new ones. > > It would be very helpful for someone to verify that the idiomatic > container pattern used in the various EE specs can be successfully > retrofitted to use the formal container pattern in the current JDK 8 > builds. Several adjustments were made to the initial formal container > design to accommodate the actual usage patterns in EE. > > Thanks, > > -Joe > >> >> -Mike >> >> On 17/12/2012 9:44 AM, Mike Keith wrote: >>> Thanks for your comments, ideas and suggestions, Alex. I had more >>> answers but my draft got prematurely sent. More stuff below. >>> >>> -Mike >>> >>> On 2012-12-16, at 10:33 PM, Mike Keith >>> wrote: >>> >>>> On 2012-12-14, at 8:41 PM, Alex Buckley >>>> wrote: >>>> >>>>> Hi Mike, >>>>> >>>>> Thanks for the quick feedback. (I know you've been playing with >>>>> the JDK8 b68 binary.) >>>>> >>>>> On 12/14/2012 1:59 PM, michael keith wrote: >>>>>> 1. The getAnnotation(Class) method is being changed to look >>>>>> through >>>>>> container annotations. This method returns an Annotation, i.e. a >>>>>> single >>>>>> instance, so applying it to repeated ones is necessarily going to >>>>>> have >>>>>> to return only one. But having it look through container >>>>>> annotation ends >>>>>> up not being very productive, and may be causing it to be >>>>>> counter-productive. >>>>>> >>>>>> Look-through for this method is not productive because the call >>>>>> is being >>>>>> made precisely in the legacy cases when only one annotation was >>>>>> expected, but a container annotation will only be synthesized when >>>>>> multiples are present. So look-through does not really help get >>>>>> "the" >>>>>> expected annotation. The only case when it would be useful is in the >>>>>> unlikely case when the container annotation is used explicitly and >>>>>> contains a single contained annotation. >>>>> I feel the author of the repeatable annotation type (who "opted >>>>> in") and the author of the multiple annotations (@Foo @Foo class C >>>>> ...) bear some responsibility when a legacy caller of >>>>> getAnnotation(Class) sees one-out-of-many annotations. Someone >>>>> decided there is no more of "'the' expected annotation". >>>> Sure, there is some responsibility to be shared by both of those >>>> parties.The problem is that the call succeeds at all. It should >>>> probably fail (eg return null) if there are multiples >>>> >>>> >>>>>> It may be counter-productive for three reasons. >>>>>> The first is because getting a random single annotation in the >>>>>> presence >>>>>> of multiples is potentially dangerous since the calling code will >>>>>> continue without knowing that multiples are present, so legacy >>>>>> code is >>>>>> essentially broken, but will not actually fail. It will just be >>>>>> semantically incorrect. >>>>> Acknowledged. >>>>> >>>>>> The second is because I didn't see (and I may just have missed >>>>>> it) where >>>>>> it was defined that if both T and TC were present that T would be >>>>>> guaranteed to be returned and not some instance within TC. >>>>>> Example 1.2-3 >>>>>> shows this to be the case but I didn't see that it was specified >>>>>> behavior rather than just because the T occurred before the TC. >>>>>> If the >>>>>> example had been TC and then T would the instance of T be returned? >>>>> If both @T and @TC are present, we have not yet specified [1] >>>>> whether get[Declared]Annotation(Class) returns always the lone >>>>> @T v. always a containerized @T v. something different every time. >>>>> That's what your feedback is for :-) >>>>> >>>>> [1] >>>>> http://download.java.net/jdk8/docs/api/java/lang/reflect/AnnotatedElement.html#getAnnotation%28java.lang.Class%29 >>>>> >>>>>> This could be important because existing code to handle this case >>>>>> checks for the container annotation TC and then checks for the >>>>>> single >>>>>> annotation T. However, if checking for T happens to look through TC >>>>>> and return one of the contained annotations in TC instead of the >>>>>> lone >>>>>> T annotation then the lone annotation would not get found. >>>>> The implementation currently "prefers" a lone @T over a @T inside >>>>> @TC. If you have a declaration @TC(...) @T class C {} then >>>>> C.class.getAnnotation(T.class) will return the standalone @T. So >>>>> existing code to handle this case will still work. >>>>> >>>>>> The third is because all of the code that is currently out there >>>>>> that >>>>>> needs to check for the previous case, i.e. both T and TC >>>>>> occurring, will >>>>>> get a false positive in the simpler case of multiple instances of T >>>>>> annotations (as per the second part of example 1.2-1 in the doc). >>>>>> The >>>>>> getAnnotation(TC) will return the synthesized TC containing all >>>>>> of the >>>>>> instances of T, and then getAnnotation(T) will return one of >>>>>> those same >>>>>> instances again. Legacy code will assume that the result of >>>>>> getAnnotation(T) is disjoint from the contained annotations of >>>>>> the TC >>>>>> returned by getAnnotation(TC). >>>>> Acknowledged. >>>>> >>>>>> 2. Given that get[Declared]Annotations() is going to change and >>>>>> return >>>>>> multiple instances of the same annotation (rather than a single >>>>>> instance >>>>>> of a container annotation) existing implementations are going to >>>>>> have to >>>>>> be fixed since there is no backwards compatibility there at all. >>>>> Acknowledged. The category of existing implementations which >>>>> assume there will never be more than one annotation of a given >>>>> type in the returned array is in for a surprise. >>>>> >>>>> But there is a category of existing implementations which will >>>>> continue to work fine. Suppose code calls >>>>> get[Declared]Annotations() and looks first for @T in the array; >>>>> only if @T is not found does the code look for @TC in the array. >>>>> This seems like rational behavior for a non-repeating world, as it >>>>> means one call to get annotations rather than >>>>> getAnnotation(T.class) plus getAnnotation(TC.class). Now, run the >>>>> code on SE 8 to get the new behavior of >>>>> get[Declared]Annotations(). The code will find an @T in the array >>>>> (the first of many, perhaps) and there will be no search for @TC >>>>> and everything will be fine. (Assume a top-level @T is returned >>>>> before containerized @T's.) >>> I might be misunderstanding you, but I don't see how that category >>> of legacy application would continue to work. It still won't be >>> expecting multiples as it looks in the collection, so it will stop >>> looking once it finds the first one. >>> >>>>>> 3. In general, it appears that once an annotation is made >>>>>> repeatable the >>>>>> annotation processing code is inevitably going to have to change in >>>>>> order to handle the repeatability. We were willing to take that hit, >>>>>> particularly since the new behavior requires opting in, and that >>>>>> means >>>>>> that specs could do so at their own discretion. However, the code to >>>>>> handle both the new and the old (i.e. be able to process both new >>>>>> repeatable annotations as well as the older idiomatic container >>>>>> annotations) is a little less intuitive to write than I had hoped it >>>>>> would be. The easiest way might just be to create a Set of >>>>>> instances to >>>>>> avoid duplicates. Not rocket science, just not what I would have >>>>>> expected. >>>>> I'm not sure if you are proposing that AnnotatedElement should >>>>> return Set instances or your framework code should create Set >>>>> instances. By policy, core reflection does not depend on the rest >>>>> of the Java SE API, so uses array types as aggregates. >>> No, sorry, I was just describing what the processor might have to >>> do, not implying that a Set would be returned by any of the >>> reflection calls. >>> >>>>> So, where are we? Joe and I have always recognized that changing >>>>> getAnnotation(Class) and get[Declared]Annotations() to look >>>>> through official containers would affect legacy callers who assume >>>>> there is at most one @T. A legacy caller which allows for both @T >>>>> and @TC is perhaps hit harder than the rest - we weren't sure how >>>>> many legacy callers were this careful, but you imply it's >>>>> non-trivial. >>> Yes, and the number of users that would actually make use of this >>> pattern is admittedly minuscule. Unfortunately, the processing code >>> generally ends up having to handle it anyway, so the pattern for >>> processing it is going to be widespread. >>> >>>>> Here's an idea. We pondered having the "existing" methods - >>>>> get[Declared]Annotation(Class) and get[Declared]Annotations() - >>>>> be unaware of official containers, so they would return exactly >>>>> what's in the class file. Essentially this is perfect behavioral >>>>> compatibility. Meanwhile, the new >>>>> get[Declared]Annotations(Class) methods would look through >>>>> official containers if present. How does that grab you? >>> From a compatibility perspective that would be great. Existing code >>> would be able to handle existing applications, and new code could >>> easily handle both old and new applications. >>> >>> I would just like to mention, though, that while we in EE-land would >>> like compatibility we are also sensitive to non-legacy users and >>> don't want to impose changes that too severely hamper the API or >>> render it unintuitive in the future. We are certainly willing to >>> make changes to code if necessary, but I was kind of hoping that we >>> wouldn't be in the situation of existing code apparently working, >>> but not really. I would be interested in hearing how others view the >>> idea of the typed version of get[Declared]Annotations behaving >>> differently than the legacy untyped one. > From alex.buckley at oracle.com Fri Dec 28 12:17:10 2012 From: alex.buckley at oracle.com (Alex Buckley) Date: Fri, 28 Dec 2012 12:17:10 -0800 Subject: A simpler model for repeating annotations Message-ID: <50DDFE46.6010106@oracle.com> Feedback from Java EE architects indicates a strong preference for 100% behavioral compatibility for legacy core reflection methods. Summarizing Mike Keith's comments: 1) getAnnotation(Class) must not return one @Foo annotation if multiple @Foo annotations were present in source, and 2) getAnnotations() must not return multiple @Foo annotations if they present in source. These requirements imply keeping containment at the heart of repeatability. Why? Assume there were no containers, and you could simply write: @Repeatable @interface Foo {} such that @Foo @Foo on class A is compiled directly into A.class. This scheme would impose high complexity on legacy core reflection methods. getAnnotation(Foo.class) would have to read _all_ annotations (declared and inherited) to detect multiple @Foo annotations then return null or throw an exception. (Remember, returning one of the multiple annotations is "wrong".) getAnnotations() would have similar trouble deciding what to return if multiple @Foo annotations are found. In essence, the legacy core reflection methods are morally incompatible with uncontained multiple annotations. The solution is to compile multiple annotations with containers, and have the legacy core reflection methods behave identically to Java SE 7 (no look through). To support new reflective clients who understand repeating annotations, we can keep the previously-proposed getAnnotations(Class) which looks through containers. That is, getAnnotations(Foo.class) returns @Foo @Foo because it a) detects that Foo.class is a repeatable annotation type with a containing annotation type of FooContainer, then b) looks through any @FooContainer present. It is clear that a repeatable annotation type must still nominate its containing annotation type, but the reverse is no longer true. That is, the declaration of FooContainer no longer needs to say @ContainerFor(Foo.class). This is a direct consequence of dropping look through for the legacy core reflection methods. Also, the difficult question about calling getAnnotations() on a subclass - should it look through an inherited container, or return it? - goes away, as normal overriding policy gives good answers. Here's a simple model that Joe, Joel, and I are happy with: - @Repeatable(FooContainer.class) on @interface Foo {} causes @Foo @Foo in source to be containerized in the class file. (Rename @ContainedBy to @Repeatable.) - The rules for a well-formed relationship between Foo and FooContainer remain. - Core reflection's legacy methods return what's in the class file: - get[Declared]Annotation(Foo.class) returns nothing, like today. - get[Declared]Annotations() returns @FooContainer, like today. - Core reflection's new typed methods look through containers: - get[Declared]Annotations(Foo.class) returns @Foo @Foo. - An annotation writer may manually rewrite @FooContainer(...) as @Foo @Foo, and it will be containerized with perfect compatibility. - Language model's legacy methods follow core reflection: - Element.getAnnotation(Foo.class) returns nothing, like today. - Element[s].get[All]AnnotationMirrors() returns @FooContainer, like today - Language model's new typed method looks through: - Element.getAnnotations(Foo.class) returns @Foo @Foo. - We may add Element.getAnnotationMirrors(TypeElement) in future. I think the reduced semantic burden for an annotation type owner (no more @ContainedFor) and the stronger compatibility story for an annotation reader (no look through for legacy methods) are real improvements. We will specify and implement the model over the next month. Alex From alex.buckley at oracle.com Fri Dec 28 12:19:54 2012 From: alex.buckley at oracle.com (Alex Buckley) Date: Fri, 28 Dec 2012 12:19:54 -0800 Subject: A simpler model for repeating annotations In-Reply-To: <50DDFE46.6010106@oracle.com> References: <50DDFE46.6010106@oracle.com> Message-ID: <50DDFEEA.9070000@oracle.com> On 12/28/2012 12:17 PM, Alex Buckley wrote: > I think the reduced semantic burden for an annotation type owner (no > more @ContainedFor) Typo; should be: (no more @ContainerFor) From forax at univ-mlv.fr Fri Dec 28 14:45:18 2012 From: forax at univ-mlv.fr (Remi Forax) Date: Fri, 28 Dec 2012 23:45:18 +0100 Subject: A simpler model for repeating annotations In-Reply-To: <50DDFE46.6010106@oracle.com> References: <50DDFE46.6010106@oracle.com> Message-ID: <50DE20FE.2010708@univ-mlv.fr> On 12/28/2012 09:17 PM, Alex Buckley wrote: > Feedback from Java EE architects indicates a strong preference for > 100% behavioral compatibility for legacy core reflection methods. > > Summarizing Mike Keith's comments: 1) getAnnotation(Class) must not > return one @Foo annotation if multiple @Foo annotations were present > in source, and 2) getAnnotations() must not return multiple @Foo > annotations if they present in source. > > These requirements imply keeping containment at the heart of > repeatability. Why? Assume there were no containers, and you could > simply write: > > @Repeatable @interface Foo {} > > such that @Foo @Foo on class A is compiled directly into A.class. This > scheme would impose high complexity on legacy core reflection methods. > getAnnotation(Foo.class) would have to read _all_ annotations > (declared and inherited) to detect multiple @Foo annotations then > return null or throw an exception. (Remember, returning one of the > multiple annotations is "wrong".) getAnnotations() would have similar > trouble deciding what to return if multiple @Foo annotations are > found. In essence, the legacy core reflection methods are morally > incompatible with uncontained multiple annotations. The solution is to > compile multiple annotations with containers, and have the legacy core > reflection methods behave identically to Java SE 7 (no look through). > > To support new reflective clients who understand repeating > annotations, we can keep the previously-proposed getAnnotations(Class) > which looks through containers. That is, getAnnotations(Foo.class) > returns @Foo @Foo because it a) detects that Foo.class is a repeatable > annotation type with a containing annotation type of FooContainer, > then b) looks through any @FooContainer present. > > It is clear that a repeatable annotation type must still nominate its > containing annotation type, but the reverse is no longer true. That > is, the declaration of FooContainer no longer needs to say > @ContainerFor(Foo.class). This is a direct consequence of dropping > look through for the legacy core reflection methods. Also, the > difficult question about calling getAnnotations() on a subclass - > should it look through an inherited container, or return it? - goes > away, as normal overriding policy gives good answers. > > Here's a simple model that Joe, Joel, and I are happy with: > > - @Repeatable(FooContainer.class) on @interface Foo {} causes > @Foo @Foo in source to be containerized in the class file. > (Rename @ContainedBy to @Repeatable.) > > - The rules for a well-formed relationship between Foo and > FooContainer remain. > > - Core reflection's legacy methods return what's in the class file: > - get[Declared]Annotation(Foo.class) returns nothing, like today. > - get[Declared]Annotations() returns @FooContainer, like today. > > - Core reflection's new typed methods look through containers: > - get[Declared]Annotations(Foo.class) returns @Foo @Foo. > > - An annotation writer may manually rewrite @FooContainer(...) as > @Foo @Foo, and it will be containerized with perfect compatibility. > > - Language model's legacy methods follow core reflection: > - Element.getAnnotation(Foo.class) returns nothing, like today. > - Element[s].get[All]AnnotationMirrors() returns @FooContainer, like > today > > - Language model's new typed method looks through: > - Element.getAnnotations(Foo.class) returns @Foo @Foo. > - We may add Element.getAnnotationMirrors(TypeElement) in future. > > I think the reduced semantic burden for an annotation type owner (no > more @ContainedFor) and the stronger compatibility story for an > annotation reader (no look through for legacy methods) are real > improvements. We will specify and implement the model over the next > month. > > Alex This spec is way better, to be sure, do you agree that getDeclaredAnnotations can be written like this: A[] getDeclaredAnnotations(Class annotationClass) { Repeatable repeatable = annotationClass.getDeclaredAnnotation(Repetable.class); if (repeatable != null) { Annotation container = getDeclaredAnnotation(repeatable.value()); if (container != null) { // if there is a container annotation, no single annotation can be present ? return (A[])callValuesByReflection(container); } } A annotation = getDeclaredAnnotation(annotationClass); if (annotation == null) return (A[])Arrays.newInstance(annotationClass, 0) A[] annotations = (A[])Arrays.newInstance(annotationClass, 1); annotations[0] = annotation; return annotations; } cheers, R?mi From alex.buckley at oracle.com Fri Dec 28 15:56:10 2012 From: alex.buckley at oracle.com (Alex Buckley) Date: Fri, 28 Dec 2012 15:56:10 -0800 (PST) Subject: A simpler model for repeating annotations Message-ID: <82606b04-52e8-4eb4-a500-cf8673d7a4af@default> Broadly speaking, all the rules in 8misc.pdf section 9.7 - about combinations of base and container annotations - still apply. In particular, it's perfectly legal to have @Foo @FooContainer(...) together. Mike Keith's comments revealed that EE frameworks that read annotations take considerable care over this case. So, I would expect get[Declared]Annotations(Class) to return contained annotations along with any singular base annotation present. See 8misc.pdf example 1.2-3: @Foo(0) @FooContainer({@Foo(1), at Foo(2)}) class A {} A.class.get[Declared]Annotations(Foo.class) = [ @Foo(0), @Foo(1), @Foo(2) ] A.class.get[Declared]Annotations(FooContainer.class) = [ @FooContainer(...) ] Alex ----- Original Message ----- This spec is way better, to be sure, do you agree that getDeclaredAnnotations can be written like this: A[] getDeclaredAnnotations(Class annotationClass) { Repeatable repeatable = annotationClass.getDeclaredAnnotation(Repetable.class); if (repeatable != null) { Annotation container = getDeclaredAnnotation(repeatable.value()); if (container != null) { // if there is a container annotation, no single annotation can be present ? return (A[])callValuesByReflection(container); } } A annotation = getDeclaredAnnotation(annotationClass); if (annotation == null) return (A[])Arrays.newInstance(annotationClass, 0) A[] annotations = (A[])Arrays.newInstance(annotationClass, 1); annotations[0] = annotation; return annotations; } cheers, R?mi