Re: Compiling several groovy files together

Saravanan Palanichamy <[email protected]>
Newsgroups gmane.comp.lang.groovy.user
Message-ID <CAG3fL7ncPDnYTfJnip3K-yNZkccV4iYkd0QuQC0kWT77M9zKeA@mail.gmail.com>
Thank you Jochen

I further narrowed this down to this behaviour

   - I have an annotation MyAnnotation. This is marked as SOURCE retention
   and is used as a repeatable annoation
   - I have another annotation MyGroupAnnotation. This is marked as RUNTIME
   retention
   - I have an AST transformation that removes all MyAnnotation on the type
   it is defined on and collates them into MyGroupAnnotation

@MustBeDocumented
@Retention(AnnotationRetention.SOURCE)
@Target(AnnotationTarget.FUNCTION)
annotation class MyAnnotation(...)

@MustBeDocumented
@Retention(AnnotationRetention.RUNTIME)
@Target(AnnotationTarget.FUNCTION)
annotation class MyGroupAnnotation(
    val all: Array<RemoteActivity> = []
)

This is how I use it

@MyAnnotation(...)
@MyAnnotation(...)
List<MyStuff> someMethod(List<MyStuff> blah)

And this is how it ends up after the AST

@MyGroupAnnotation(all = [MyAnnotation(...), MyAnnotation(...)])
List<MyStuff> someMethod(List<MyStuff> blah)


When I use someMethod, if it has already been loaded separately by the same
class loader, the MethodNode representing someMethod contains 1 annotation
(MyGroupAnnotation) with 1 member which is a list but that list has one
NULL value in it

This seems to be because it goes through
Java8::annotationValueToExpression(...) through the array section and then
back into annotationValueToExpression where it sees an instance of a proxy
object instead of a Class definition. So it returns NULL

Not sure if this rings any bells, I am lost though. This seems to work if I
load someMethod from a jar or class path. This only fails if I use the same
class loader that compiled someMethod

regards
Saravanan


On Fri, Mar 4, 2022 at 5:44 PM Jochen Theodorou <[email protected]> wrote:

> On 15.02.22 05:20, Saravanan Palanichamy wrote:
> > Hello Groovy users
> >
> > I am using Groovy 3.0.5
> >
> >   * I have a file A.groovy and B.groovy. B depends on A
> >   * I have ast transformations that add annotations to methods in A
> >     (specifically an annotation with a list expression that contains
> >     other annotations)
> >   * I compile A.groovy using the loadClass and then compile B.groovy
> >     again with load class. When I inspect a method call to A(using the
> >     method target field inside method call expression), I see only null
> >     values for the annotations I added
> >   * If I compiled B.groovy and have it automatically detect A.groovy, I
> >     see the right values for my annotations (no nulls)
> >
> > Any idea why this is happening?
>
> If the annotations are directly in the file, then the one way this makes
> sense to me is that you load a different A. That would mean your class
> loader you use for B finds a different A, then the one you loaded (given
> you loaded the right A of course). Without further details about the
> setup this is a bit difficult. I suggest you do the following style of
> test:
>
> * loadClass for A, and keep a reference to A: x=loadClass("A")
> * have B return the class A (something like "return A.class")
> * loadClass for B and execute the code that returns A:
> y=loadClass("B").getA()
> * now the first A and the second A must be fulfilling referential
> identity: assert x===y
>
> If the assert fails it is clear that you are doing something wrong with
> your class loaders. If the assert does not fail I suggest to stop after
> loading A and checking that the annotations are on it. If they are not,
> you load the wrong A - wherever A is coming from. If they are there, but
> later not... well then you created some very very strange case that
> violates classloader constraints, because that means A has been modified
> after the class has been loaded, without loading a new A. Not sure you
> can do that even with instrumentation to that extend.
>
> bye Jochen
>
>
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.