ebean-orm-tools / ebean-gradle-plugin

Plugin that performs Enhancement (entity, transactional, query bean) and can generate query beans from entity beans written in Kotlin via kapt
Apache License 2.0
10 stars 12 forks source link

Enhancement breaks in gradle multiproject setups #31

Closed fraenkelc closed 3 years ago

fraenkelc commented 3 years ago

I've recently run into this issue which took some time to debug: When running querybean enhancement on a gradle multiproject where the generated query beans are in a different project from the consumer the consumer project will not be properly enhanced. The cause of this isssue is that gradle does not put the resources of the domain project on the consumer compile classpath. The ebean enhancer can then in turn not find the ebean.mf file and will not perform any querybean enhancement. Here's a project that reproduces the issue (https://github.com/fraenkelc/annotationProcessor-reproducer) and a corresponding gradle build scan (https://scans.gradle.com/s/ywyzllxg5d67g/console-log#L12-L17)

I do have a workaround that uses the gradle variant system to require jars instead of folders on the classpath (see https://github.com/fraenkelc/annotationProcessor-reproducer/blob/master/workaround/build.gradle.kts#L6-L12).

Something that gave me a hard time and feels like bad UX is that it all works in a single project. It only breaks (and in a hard to debug way) once the domain model is extracted to a separate project.

Is there something that ebean can do to fix this? If not it would be great to add some documentation on how to deal with such issues.

rbygrave commented 3 years ago

I think it might be good to also describe this to the ebean@googlegroups.com https://groups.google.com/forum/#!forum/ebean

Getting a wider audience might be a good idea for this issue - get more input/thoughts.

Cheers, Rob.

rbygrave commented 3 years ago

> The ebean enhancer can then in turn not find the ebean.mf file

More accurately the META-INF/ebean-generated-info.mf resource right? (There is no ebean.mf resource by default now)

> gradle does not put the resources of the domain project on the consumer compile classpath

Is there any Gradle documentation as to why this is the case? Why is this not treated as a Gradle bug? Does this apply to all resources of the domain project? (As in, I wonder if Gradle is giving resources under META-INF/services special treatment, otherwise Gradle multi-module builds will be breaking a lot of things that use ServiceLoader - unless this issue is related to the fact that META-INF/ebean-generated-info.mf is a generated resource (not a static resource in src/main/resources).

> I do have a workaround that uses the gradle variant system to require jars instead of folders on the classpath

Is there documentation related to this workaround? What is the intention of the workaround / why does it fix the issue?

On Mon, 28 Sep 2020 at 21:30, fraenkelc notifications@github.com wrote:

I've recently run into this issue which took some time to debug: When running querybean enhancement on a gradle multiproject where the generated query beans are in a different project from the consumer the consumer project will not be properly enhanced. The cause of this isssue is that gradle does not put the resources of the domain project on the consumer compile classpath. The ebean enhancer can then in turn not find the ebean.mf file and will not perform any querybean enhancement. Here's a project that reproduces the issue ( https://github.com/fraenkelc/annotationProcessor-reproducer) and a corresponding gradle build scan ( https://scans.gradle.com/s/ywyzllxg5d67g/console-log#L12-L17)

I do have a workaround that uses the gradle variant system to require jars instead of folders on the classpath (see https://github.com/fraenkelc/annotationProcessor-reproducer/blob/master/workaround/build.gradle.kts#L6-L12 ).

Something that gave me a hard time and feels like bad UX is that it all works in a single project. It only breaks (and in a hard to debug way) once the domain model is extracted to a separate project.

Is there something that ebean can do to fix this? If not it would be great to add some documentation on how to deal with such issues.

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/ebean-orm-tools/ebean-gradle-plugin/issues/31, or unsubscribe https://github.com/notifications/unsubscribe-auth/AABTATLULWVC5YBPJETUY4TSIBCTFANCNFSM4R4GYZ3Q .

rbygrave commented 3 years ago

thoughts:

With model dependencies of:

dependencies { api("io.ebean:ebean:12.4.1") api("io.ebean:ebean-querybean:12.4.1")

annotationProcessor("io.ebean:querybean-generator:12.4.1")

}

the workaround module dependencies can be simplified to:

dependencies { implementation(project(":model")) }

Note: In the model module the querybean-generator generates: build/classes/java/main/META-INF/ebean-generated-info.mf (as expected, the enhancement is looking for all the META-INF/ebean-generated-info.mf resources in the classpath)

... it does this so that in theory we don't need to manually define a ebean.mf ... however, gradle is not including this in the classpath for me regardless of the workaround - it is not seen by the ebean plugin running enhancement for workaround (or broken). So the workaround is a "double workaround" where we need to 1) manually add ebean.mf and 2) have the additional compileClasspath / attributes config.

On Tue, 29 Sep 2020 at 12:36, Rob Bygrave robin.bygrave@gmail.com wrote:

> The ebean enhancer can then in turn not find the ebean.mf file

More accurately the META-INF/ebean-generated-info.mf resource right? (There is no ebean.mf resource by default now)

> gradle does not put the resources of the domain project on the consumer compile classpath

Is there any Gradle documentation as to why this is the case? Why is this not treated as a Gradle bug? Does this apply to all resources of the domain project? (As in, I wonder if Gradle is giving resources under META-INF/services special treatment, otherwise Gradle multi-module builds will be breaking a lot of things that use ServiceLoader - unless this issue is related to the fact that META-INF/ebean-generated-info.mf is a generated resource (not a static resource in src/main/resources).

> I do have a workaround that uses the gradle variant system to require jars instead of folders on the classpath

Is there documentation related to this workaround? What is the intention of the workaround / why does it fix the issue?

On Mon, 28 Sep 2020 at 21:30, fraenkelc notifications@github.com wrote:

I've recently run into this issue which took some time to debug: When running querybean enhancement on a gradle multiproject where the generated query beans are in a different project from the consumer the consumer project will not be properly enhanced. The cause of this isssue is that gradle does not put the resources of the domain project on the consumer compile classpath. The ebean enhancer can then in turn not find the ebean.mf file and will not perform any querybean enhancement. Here's a project that reproduces the issue ( https://github.com/fraenkelc/annotationProcessor-reproducer) and a corresponding gradle build scan ( https://scans.gradle.com/s/ywyzllxg5d67g/console-log#L12-L17)

I do have a workaround that uses the gradle variant system to require jars instead of folders on the classpath (see https://github.com/fraenkelc/annotationProcessor-reproducer/blob/master/workaround/build.gradle.kts#L6-L12 ).

Something that gave me a hard time and feels like bad UX is that it all works in a single project. It only breaks (and in a hard to debug way) once the domain model is extracted to a separate project.

Is there something that ebean can do to fix this? If not it would be great to add some documentation on how to deal with such issues.

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/ebean-orm-tools/ebean-gradle-plugin/issues/31, or unsubscribe https://github.com/notifications/unsubscribe-auth/AABTATLULWVC5YBPJETUY4TSIBCTFANCNFSM4R4GYZ3Q .

rbygrave commented 3 years ago

Q: Why are the "resources" writing to the "class output directory" ?

To date there hasn't been a location for annotation processors to use to write resources. Refer https://docs.oracle.com/en/java/javase/11/docs/api/java.compiler/javax/tools/StandardLocation.html So as a workaround the querybean-generator annotation processor writes the META-INF/ebean-generated-info.mf using

FileObject createMetaInfWriter(String target) throws IOException { return filer.createResource(StandardLocation.CLASS_OUTPUT, "", target); }

That is, both META-INF/ebean-generated-info.mf and META-INF/services/io.ebean.config.ModuleInfoLoader ... are written this way (to class output).

On Tue, 29 Sep 2020 at 14:05, Rob Bygrave robin.bygrave@gmail.com wrote:

thoughts:

With model dependencies of:

dependencies { api("io.ebean:ebean:12.4.1") api("io.ebean:ebean-querybean:12.4.1")

annotationProcessor("io.ebean:querybean-generator:12.4.1")

}

the workaround module dependencies can be simplified to:

dependencies { implementation(project(":model")) }

Note: In the model module the querybean-generator generates: build/classes/java/main/META-INF/ebean-generated-info.mf (as expected, the enhancement is looking for all the META-INF/ebean-generated-info.mf resources in the classpath)

... it does this so that in theory we don't need to manually define a ebean.mf ... however, gradle is not including this in the classpath for me regardless of the workaround - it is not seen by the ebean plugin running enhancement for workaround (or broken). So the workaround is a "double workaround" where we need to 1) manually add ebean.mf and 2) have the additional compileClasspath / attributes config.

On Tue, 29 Sep 2020 at 12:36, Rob Bygrave robin.bygrave@gmail.com wrote:

> The ebean enhancer can then in turn not find the ebean.mf file

More accurately the META-INF/ebean-generated-info.mf resource right? (There is no ebean.mf resource by default now)

> gradle does not put the resources of the domain project on the consumer compile classpath

Is there any Gradle documentation as to why this is the case? Why is this not treated as a Gradle bug? Does this apply to all resources of the domain project? (As in, I wonder if Gradle is giving resources under META-INF/services special treatment, otherwise Gradle multi-module builds will be breaking a lot of things that use ServiceLoader - unless this issue is related to the fact that META-INF/ebean-generated-info.mf is a generated resource (not a static resource in src/main/resources).

> I do have a workaround that uses the gradle variant system to require jars instead of folders on the classpath

Is there documentation related to this workaround? What is the intention of the workaround / why does it fix the issue?

On Mon, 28 Sep 2020 at 21:30, fraenkelc notifications@github.com wrote:

I've recently run into this issue which took some time to debug: When running querybean enhancement on a gradle multiproject where the generated query beans are in a different project from the consumer the consumer project will not be properly enhanced. The cause of this isssue is that gradle does not put the resources of the domain project on the consumer compile classpath. The ebean enhancer can then in turn not find the ebean.mf file and will not perform any querybean enhancement. Here's a project that reproduces the issue ( https://github.com/fraenkelc/annotationProcessor-reproducer) and a corresponding gradle build scan ( https://scans.gradle.com/s/ywyzllxg5d67g/console-log#L12-L17)

I do have a workaround that uses the gradle variant system to require jars instead of folders on the classpath (see https://github.com/fraenkelc/annotationProcessor-reproducer/blob/master/workaround/build.gradle.kts#L6-L12 ).

Something that gave me a hard time and feels like bad UX is that it all works in a single project. It only breaks (and in a hard to debug way) once the domain model is extracted to a separate project.

Is there something that ebean can do to fix this? If not it would be great to add some documentation on how to deal with such issues.

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/ebean-orm-tools/ebean-gradle-plugin/issues/31, or unsubscribe https://github.com/notifications/unsubscribe-auth/AABTATLULWVC5YBPJETUY4TSIBCTFANCNFSM4R4GYZ3Q .

rbygrave commented 3 years ago

Oh, I'm overthinking it ... https://github.com/fraenkelc/annotationProcessor-reproducer/blob/master/settings.gradle.kts#L3

Change the plugin version from 11.42.2 to 12.4.1 ... and it works as expected.

Note: We have only been releasing the gradle plugin to plugins.gradle and no longer additionally releasing to maven central.

On Tue, 29 Sep 2020 at 14:24, Rob Bygrave robin.bygrave@gmail.com wrote:

Q: Why are the "resources" writing to the "class output directory" ?

To date there hasn't been a location for annotation processors to use to write resources. Refer https://docs.oracle.com/en/java/javase/11/docs/api/java.compiler/javax/tools/StandardLocation.html So as a workaround the querybean-generator annotation processor writes the META-INF/ebean-generated-info.mf using

FileObject createMetaInfWriter(String target) throws IOException { return filer.createResource(StandardLocation.CLASS_OUTPUT, "", target); }

That is, both META-INF/ebean-generated-info.mf and META-INF/services/io.ebean.config.ModuleInfoLoader ... are written this way (to class output).

On Tue, 29 Sep 2020 at 14:05, Rob Bygrave robin.bygrave@gmail.com wrote:

thoughts:

With model dependencies of:

dependencies { api("io.ebean:ebean:12.4.1") api("io.ebean:ebean-querybean:12.4.1")

annotationProcessor("io.ebean:querybean-generator:12.4.1")

}

the workaround module dependencies can be simplified to:

dependencies { implementation(project(":model")) }

Note: In the model module the querybean-generator generates: build/classes/java/main/META-INF/ebean-generated-info.mf (as expected, the enhancement is looking for all the META-INF/ebean-generated-info.mf resources in the classpath)

... it does this so that in theory we don't need to manually define a ebean.mf ... however, gradle is not including this in the classpath for me regardless of the workaround - it is not seen by the ebean plugin running enhancement for workaround (or broken). So the workaround is a "double workaround" where we need to 1) manually add ebean.mf and 2) have the additional compileClasspath / attributes config.

On Tue, 29 Sep 2020 at 12:36, Rob Bygrave robin.bygrave@gmail.com wrote:

> The ebean enhancer can then in turn not find the ebean.mf file

More accurately the META-INF/ebean-generated-info.mf resource right? (There is no ebean.mf resource by default now)

> gradle does not put the resources of the domain project on the consumer compile classpath

Is there any Gradle documentation as to why this is the case? Why is this not treated as a Gradle bug? Does this apply to all resources of the domain project? (As in, I wonder if Gradle is giving resources under META-INF/services special treatment, otherwise Gradle multi-module builds will be breaking a lot of things that use ServiceLoader - unless this issue is related to the fact that META-INF/ebean-generated-info.mf is a generated resource (not a static resource in src/main/resources).

> I do have a workaround that uses the gradle variant system to require jars instead of folders on the classpath

Is there documentation related to this workaround? What is the intention of the workaround / why does it fix the issue?

On Mon, 28 Sep 2020 at 21:30, fraenkelc notifications@github.com wrote:

I've recently run into this issue which took some time to debug: When running querybean enhancement on a gradle multiproject where the generated query beans are in a different project from the consumer the consumer project will not be properly enhanced. The cause of this isssue is that gradle does not put the resources of the domain project on the consumer compile classpath. The ebean enhancer can then in turn not find the ebean.mf file and will not perform any querybean enhancement. Here's a project that reproduces the issue ( https://github.com/fraenkelc/annotationProcessor-reproducer) and a corresponding gradle build scan ( https://scans.gradle.com/s/ywyzllxg5d67g/console-log#L12-L17)

I do have a workaround that uses the gradle variant system to require jars instead of folders on the classpath (see https://github.com/fraenkelc/annotationProcessor-reproducer/blob/master/workaround/build.gradle.kts#L6-L12 ).

Something that gave me a hard time and feels like bad UX is that it all works in a single project. It only breaks (and in a hard to debug way) once the domain model is extracted to a separate project.

Is there something that ebean can do to fix this? If not it would be great to add some documentation on how to deal with such issues.

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/ebean-orm-tools/ebean-gradle-plugin/issues/31, or unsubscribe https://github.com/notifications/unsubscribe-auth/AABTATLULWVC5YBPJETUY4TSIBCTFANCNFSM4R4GYZ3Q .

fraenkelc commented 3 years ago

thanks for taking a look at it. I can confirm that after upgrading the plugin no workaround is necessary anymore. Sorry about the hassle. I'm not 100% sure where I picked up the old plugin version from but I think it was from the github releases link: image

rbygrave commented 3 years ago

Yeah all good.

We were publishing the plugin additionally to maven central but then stopped, so I think it can be confusing as to what the latest version is.

Cheers, Rob.

On Tue, 29 Sep 2020, 9:23 pm fraenkelc, notifications@github.com wrote:

Closed #31 https://github.com/ebean-orm-tools/ebean-gradle-plugin/issues/31.

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/ebean-orm-tools/ebean-gradle-plugin/issues/31#event-3818151104, or unsubscribe https://github.com/notifications/unsubscribe-auth/AABTATL5XNXPM5TKB67R35TSIGKONANCNFSM4R4GYZ3Q .