Question for Mike re: changing containers

michael keith michael.keith at oracle.com
Thu Mar 7 23:47:38 PST 2013


On 07/03/2013 8:05 PM, Alex Buckley wrote:
> If you change:
>
>   @Repeatable(FooContainer.class)
>   @interface Foo {...}
>
> to:
>
>   @Repeatable(OtherContainer.class)
>   @interface Foo {...}
>
> then getAnnotationsByType(Foo.class) will seek out @OtherContainer. 
> Any @FooContainer (generated by a compiler to wrap @Foo @Foo prior to 
> the change) will be ignored. So, switching Foo's containing annotation 
> type is behaviorally incompatible for reflective clients.

My point was only that the processing client code does not and should 
not change regardless of the container type when using the look-through 
methods. Clearly, processing a precompiled annotated class is not going 
to find the contained annotation if the container annotation has been 
changed in the interim. However, I think one would have to accept that 
after changing the container annotation one would have to recompile the 
annotated classes with the updated annotations.

>
> There is no way around that, but actually, it wasn't what I meant to 
> ask you!
>
> Suppose FooContainer is intended to be the containing annotation type 
> for Foo forever. Do you ever tweak FooContainer's declaration, for 
> example, expanding its applicability (adding entries to @Target) ?

The elements of the annotation do not ever change for us from one 
release to another (we only ever have a single value() element that 
consists of an array of the contained annotation type) but modifying the 
meta-annotations of the containing annotation is something that can 
happen occasionally as they may get expanded on the contained 
annotation. Adding an entry to @Target is a good example, where an 
annotation is being extended to be allowed to be present on additional 
code elements.

>
> I ask because Joel and I are wondering how strict to be in 
> getAnnotationsByType(Class) if FooContainer diverges slightly from 
> Foo's expectations. No doubt FooContainer will be a proper "containing 
> annotation type" for Foo almost all the time, since you can't compile 
> @Foo @Foo otherwise - but maybe someone makes a mistake, where 
> @Inherited is removed from FooContainer but not Foo, and then @Foo 
> @Foo isn't inherited because @FooContainer isn't inherited - this 
> would cause a subtle change in client behavior. I think we're heading 
> towards saying this is just "OK", rather than raising an 
> AnnotationFormatError.

As I think I mentioned in the past, I think the real annotation 
development happens on Foo, and the container annotation must get 
changed to match. In other words it is far more likely that I would 
change @Inherited on @Foo but forget to do so on @FooContainer. Anyway, 
that isn't really your question either ;-)

My experience is that the meta-annotations on the container annotation 
should match exactly what is on the contained annotation (with the 
possible exception that I might only want @Documented to be on @Foo and 
not on @FooContainer, if that worked :-). In all other cases I would 
expect to be told at compile-time since it is likely an oversight if 
they don't match. I don't know that it is that important to catch at 
runtime, though, and I would likely opt out of the extra checking if it 
cost me some performance.

> tl;dr There are many rules tying FooContainer to Foo, and maybe they 
> just don't matter much at run-time.
>
> Alex
>
> On 3/6/2013 11:10 PM, michael keith wrote:
>> Our usage of the container annotation has fairly consistently been a
>> trivial mapping from the singular contained annotation to its pluralized
>> containing form. We have, during development, changed the name of the
>> singular annotation and then had to go and rename the container
>> annotation to the plural form of the newly named singular one, but it
>> would not be common at all to decide to rename the container one
>> independent of the singular one, and I am talking about development,
>> before clients exist.
>>
>> Existing clients of the current getAnnotation(Class) and
>> getAnnotations() methods are written to reference both the repeatable
>> and the container annotations directly, so renaming either one of them
>> would be a breaking change that we would not generally undertake after
>> the annotations have been created/released.
>>
>> I would not have expected a precompiled client of
>> getAnnotationsByType(Foo.class) to be affected by such a change, though.
>> The container annotation is meant to be transparent to them, isn't it?
>>
>> -Mike
>>
>> On 06/03/2013 8:22 PM, Alex Buckley wrote:
>>> Mike, we're pondering whether the new methods in core reflection
>>> should be strict about the relationship of containing type to
>>> repeatable type.
>>>
>>> Have you ever written @FooContainer({@Foo(1),...}) on a declartion,
>>> and later changed it to @OtherContainer({@Foo(1),...}) ? The effect on
>>> clients using getAnnotation(Class) and getAnnotations() would be
>>> significant.
>>>
>>> Effectively we are wondering if a client using
>>> getAnnotationsByType(Foo.class) should be affected by such a change.
>>>
>>> Alex
>>




More information about the enhanced-metadata-spec-discuss mailing list