[Records] Component annotations not propagated when explicit canonical constructor is given
Gunnar Morling
gunnar at hibernate.org
Tue Jan 21 16:44:01 UTC 2020
Vincente,
Just tried with build 15-ea+6-123 and can confirm the issue is fixed
there. Thanks!
--Gunnar
Am Di., 21. Jan. 2020 um 00:08 Uhr schrieb Vicente Romero
<vicente.romero at oracle.com>:
>
> Hi Gunnar
>
> On 1/20/20 12:18 PM, Gunnar Morling wrote:
> > Ah, yes, indeed! I'll track this issue then, thanks! Perhaps it would
> > even make sense to have it fixed for JDK 14?
>
> the issue has already being fixed in 15. Could you please try with 15 to
> see double check that you can't reproduce the issue with jdk15?
>
> >
> > --Gunnar
>
> Vicente
>
> >
> > Am Mo., 20. Jan. 2020 um 17:35 Uhr schrieb Jorn Vernee <jorn.vernee at oracle.com>:
> >> Hi,
> >>
> >> I remember this issue coming up before. Looks like there was a fix
> >> targeted at JDK 15: https://bugs.openjdk.java.net/browse/JDK-8236597
> >>
> >> Jorn
> >>
> >> On 20/01/2020 09:36, Gunnar Morling wrote:
> >>> Thanks for your reply!
> >>>
> >>>> If a canonical ctor / accessor is explicitly specified, the annos on the declaration are used instead.
> >>> That's where things are still unclear for me, it seems contradictory
> >>> to "sounds like incorrect behavior to me" above. To make things more
> >>> concrete, here's an example:
> >>>
> >>> public class RecordAnnos {
> >>> public static void main(String... args) {
> >>> System.out.println(Arrays.toString(Foo.class.getConstructors()[0].getParameters()[0].getAnnotations()));
> >>> System.out.println(Arrays.toString(Bar.class.getConstructors()[0].getParameters()[0].getAnnotations()));
> >>> }
> >>>
> >>> public static record Foo (@Deprecated String foo) {}
> >>>
> >>> public static record Bar (@Deprecated String bar) {
> >>> public Bar {}
> >>> }
> >>> }
> >>>
> >>> Running this prints:
> >>>
> >>> java --enable-preview --source 14 RecordAnnos.java
> >>> [@java.lang.Deprecated(forRemoval=false, since="")]
> >>> []
> >>>
> >>> Whereas I hoped it'd print this:
> >>>
> >>> [@java.lang.Deprecated(forRemoval=false, since="")]
> >>> [@java.lang.Deprecated(forRemoval=false, since="")]
> >>>
> >>> In case an explicit canonical constructor is declared without the
> >>> formal parameter list, there's no way to specify any annotations on
> >>> the parameters. So shouldn't those from the components be applied?
> >>> With the current behaviour, if I want to declare any annotation for
> >>> the constructor itself, I need to repeat all annotations from the
> >>> components on the annotations of a fully manually implemented
> >>> constructor:
> >>>
> >>> public static record Bar (@Deprecated String bar) {
> >>> @Deprecated
> >>> public Bar(@Deprecated String bar) {
> >>> this.bar = bar;
> >>> }
> >>> }
> >>>
> >>> Note that @Deprecated is just used here to make the example
> >>> self-contained; my actual use case is about Bean Validation constraint
> >>> annotations.
> >>>
> >>> Thanks,
> >>>
> >>> --Gunnar
> >>>
> >>> Am Mo., 20. Jan. 2020 um 01:32 Uhr schrieb Brian Goetz <brian.goetz at oracle.com>:
> >>>> This sounds like incorrect behavior to me. The way it should work is:
> >>>>
> >>>> - A declaration annotation is applicable to a record component if it has no @Target meta-anno, or its target includes one or more of PARAMETER, FIELD, METHOD, RECORD_COMPONENT.
> >>>> - For _each_ of the applicable types present, the anno is pushed down to the corresponding _implicit_ { ctor parameter, field, accessor method, record component }.
> >>>> - If multiple applicable types are present, it is pushed down to all of them.
> >>>> - If a canonical ctor / accessor is explicitly specified, the annos on the declaration are used instead.
> >>>>
> >>>>
> >>>>
> >>>>
> >>>> On 1/19/2020 4:14 PM, Gunnar Morling wrote:
> >>>>
> >>>> Hi,
> >>>>
> >>>> I'm observing the following behaviour around annotations on record
> >>>> components, using JDK 14 b32. I'm putting an annotation to a record
> >>>> component:
> >>>>
> >>>> public record Person(@NotNull String name) {}
> >>>>
> >>>> In this case the @NotNull annotation is propagated to the
> >>>> corresponding parameter of the generated constructor, from where I can
> >>>> obtain it using reflection. This is not the case though when I
> >>>> explicitly declare the canonical constructor:
> >>>>
> >>>> public record Person(@NotNull String name) {
> >>>> public Person {
> >>>> // ...
> >>>> }
> >>>> }
> >>>>
> >>>> In this case the annotation isn't propagated, and it won't be
> >>>> retrievable from that constructor's parameter via reflection.
> >>>>
> >>>> Is this behaviour intended or is it a bug actually? I lean towards the
> >>>> latter, as I don't explicitly define the parameter in the constructor,
> >>>> so I'd expect the annotations given on the component to still be
> >>>> propagated.
> >>>>
> >>>> If it *is* intended, it'd make my use case a bit more complex, as I'd
> >>>> want to be able to put other annotations to the canonical constructor
> >>>> *itself*, while still getting all the component annotations propagated
> >>>> to its parameters.
> >>>>
> >>>> Thanks a lot,
> >>>>
> >>>> --Gunnar
> >>>>
> >>>>
>
More information about the amber-dev
mailing list