-
Notifications
You must be signed in to change notification settings - Fork 1.7k
WIP: AVRO-4223 Gradle plugin for generating Java code #3614
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
Fix Intellij not finding generated sources Add generating BigDecimal property
Add dynamic output directory
…ugin # Conflicts: # doc/package-lock.json
| fun compileSchema() { | ||
| project.logger.info("Generating Java files from Avro schemas...") | ||
|
|
||
| if (!source.isEmpty) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If something like DirectoryProperty is used in conjunction with @SkipWhenEmpty , a task state of NO_SOURCE should be used when no sources are available.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How can we log some useful message when we use @SkipWhenEmpty and no sources are available? Now we have the else branch where we log.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we need to? Other Gradle tasks (compileJava, compileTestJava etc) don't warn when no sources are available.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
From a code point of view, if @SkipWhenEmpty is more idiomatic Gradle, I understand. But we should care about user experience. It will improve UX If the user directly sees why no code was generated because e.g. a wrong directory was provided.
lang/java/gradle-plugin/src/main/kotlin/eu/eventloopsoftware/avro/gradle/plugin/GradlePlugin.kt
Outdated
Show resolved
Hide resolved
lang/java/gradle-plugin/README.md
Outdated
| For Intellij to recognize the newly generated Java files add this to `build.gradle.kts`: | ||
|
|
||
| ```kotlin | ||
| tasks.named("compileKotlin") { dependsOn(tasks.named("avroGenerateJavaClasses")) } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is the jank that can be avoided by setting the srcDir using the task to avoid requiring dependsOn fixes https://github.com/apache/avro/pull/3614/changes#r2662114325
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Compilation fails if we don't use that line. Unresolved reference 'SomeGeneratedClass.
I've used your method of adding sources: https://github.com/apache/avro/pull/3614/files#diff-02e299025197282b1f1fec4a0fe89c1fb47606fcd9a2b0fc55206ca1ae8f511dR75
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This works: 3853d9a#diff-6f6c17b901d3a280371d65a7c7907afd0275f06f4dd28682c65343c4a92a97ebR40
No need to add tasks.named("compileKotlin") { dependsOn(tasks.named("avroGenerateJavaClasses")) } any more. Thanks for pointing it out 🙏
|
|
||
| #### How can I benefit from Kotlin's null safety? | ||
| Use `createNullSafeAnnotations = true` and Java getters will be annotated with | ||
| `@org.jetbrains.annotations.NotNull`/ `@org.jetbrains.annotations.Nullable`. This way |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Gradle has finished migrating to jspecify, Kotlin 2.+ also supports jspecify annotations. Perhaps those should be used by default instead of jetbrains'?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Although JSpecify seems to become the new standard, I'd be hesitant to make this change yet for the Maven plugin.
Here though, as both Gradle and Kotlin are moving in this direction and this plugin is new, I think the JSpecify annotations are a good default to use.
| Kotlin will recognize which value is nullable. | ||
|
|
||
| #### When I update my schemas and generate code, the Java classes stay the same | ||
| Yes, for now you have to `./gradlew clean` every time you update your Avro schemas. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should clear controlled output directories (outputDir/testOutputDir) instead of requiring the user to do so.
lang/java/gradle-plugin/src/main/resources/META-INF/eu.eventloopsoftware.properties
Outdated
Show resolved
Hide resolved
| import org.gradle.api.tasks.Input | ||
| import org.gradle.api.tasks.SourceTask | ||
|
|
||
| abstract class AbstractCompileTask : SourceTask() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Gradle's SourceTask is probably not the preferred superclass for this task, that's usually used for things like compilation, analysis. I'd recommend DefaultTask.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
DefaultTask is being deprecated. Why is SourceTask not preferred? From the docs: A {@code SourceTask} performs some operation on source files, which is kind of what we're doing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've not seen anything that would indicate DefaultTask being deprecated, and I can't imagine they could considering how many tasks already inherit directly from DefaultTask.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's an error on my side, DefaultTask is indeed not being deprecated.
Anyway, with DefaultTask we don't have source, setIncludes(..) and setExcludes(..)which are very useful in filtering for specific Avro file extension like "**/*.avsc". Then we have to manually filter the FileTree for Avro file extensions. Do you still recommend it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think I'm starting to understand why SourceTask is maybe not the right fit. We now use source and sourceDirectory, which are used for the same things. If we use DefaultTask we don't have the issue of this ambiguity, and only use sourceDirectory
...n/src/main/kotlin/eu/eventloopsoftware/avro/gradle/plugin/extension/GradlePluginExtension.kt
Outdated
Show resolved
Hide resolved
|
|
||
| @TaskAction | ||
| fun compileSchema() { | ||
| project.logger.info("Generating Java files from Avro schemas...") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should be using the task's logger, not the project's logger. I also don't think these logs provide any useful information.
|
|
||
|
|
||
| private fun getSourceDirectoryFullPath(directoryProperty: Property<String>): File = | ||
| project.layout.projectDirectory.dir(directoryProperty.get()).asFile |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Calling project at runtime is soft-deprecated in Gradle 8, deprecated in Gradle 9 and will be unsupported in Gradle 10. https://docs.gradle.org/8.12.1/userguide/configuration_cache.html#config_cache:requirements:use_project_during_execution
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This would be avoided by using DirectoryPropertys, which would already be project-relative.
lang/java/gradle-plugin/src/main/kotlin/eu/eventloopsoftware/avro/gradle/plugin/GradlePlugin.kt
Outdated
Show resolved
Hide resolved
| name = "Avro Gradle Plugin" | ||
| description = "Generate Java code from Avro files" | ||
| inceptionYear = "2025" | ||
| url = "https://github.com/frevib/avro/" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| url = "https://github.com/frevib/avro/" | |
| url = "https://github.com/apache/avro/" |
For the non-beta release (and below)
| * at schema compiling time. All files can therefore be referenced as classpath | ||
| * resources following the directory structure under the source directory. | ||
| * | ||
| * @parameter property="sourceDirectory" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we use the Maven annotations instead? IMHO they're easier to read (less likely to be missed when reading the code).
opwvhk
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking good so far!
|
New BETA |
What is the purpose of the change
Gradle plugin to generate Java code from Avro files
Verifying this change
This change added tests and can be verified as follows:
cd to
avro/lang/java/gradle-plugin./gradlew testDocumentation
Release
BETA
0.0.2is released and fully works with AVSC files: https://central.sonatype.com/artifact/eu.eventloopsoftware.avro-gradle-plugin/eu.eventloopsoftware.avro-gradle-plugin.gradle.plugin/versions - read docs (above) how to useBETA
0.0.5https://plugins.gradle.org/plugin/eu.eventloopsoftware.avro-gradle-pluginAn official release will be done in the coming month