Open MZimmermann opened 1 year ago
I see the exact same issue. We are currently workarounding the issue by not using groups
altogether in favor of creating completely separate xjc-Task
instances:
tasks.register("xjc-a", XjcTask::class) { ... }
tasks.register("xjc-b", XjcTask::class) { ... }
I wonder if this makes the groups
-mechanism of this plugin completely redundant.
Sorry, my workaround doesn't work. I accidentally tested against version 1.8.0.
The issue seems to be that the bindingFiles
of the singleton XjcExtension are shared between all groups/tasks. See:
Since the FileCollection is a constant (cannot be replaced like a Property
) and there is no API to clear the collection, I don't even see a workaround for this issue.
As it stands, this seems to be fundamentally broken and unfortunately we cannot upgrade from 1.8.0.
The cause of this issue is the wrong order of configuration actions. You can easily workaround it:
xjc {
groups {
create("group1") {
includes.add("my-schema.xsd")
afterEvaluate {
bindingFiles.setFrom("src/main/resources/xjb/my-binding.xjb")
}
}
}
}
or
xjc {
groups {
register("group1") {
includes.add("my-schema.xsd")
}
matching { name == "group1" }.configureEach {
bindingFiles.setFrom("src/main/resources/xjb/my-binding.xjb")
}
}
}
For others reading this: We've decided that this plugin doesn't carry its weight. We've replaced it by this piece of code:
val xjcDeps: Configuration by configurations.creating {
extendsFrom(configurations.implementation.get())
}
dependencies {
xjcDeps("org.glassfish.jaxb:jaxb-xjc:4.0.3")
}
fun addXjcTask(baseName: String, packageName: String): TaskProvider<JavaExec> {
val outputDir = "src-gen/xjc-${baseName}/java"
sourceSets["main"].java.srcDir(outputDir)
val xjcTask = tasks.register("xjc-${baseName}", JavaExec::class) {
doFirst {
project.delete(outputDir)
project.mkdir(outputDir)
}
val xsdDir = "xsd-templates/${baseName}"
val schemaFile = "$xsdDir/schema.xsd"
val bindingsFile = "$xsdDir/bindings.xjb"
inputs.files(schemaFile, bindingsFile)
outputs.dir(outputDir)
classpath = xjcDeps
mainClass.set("com.sun.tools.xjc.XJCFacade")
args("-extension")
args("-d", outputDir)
args("-p", packageName)
args(schemaFile)
args("-b", bindingsFile)
}
tasks.withType<JavaCompile>().configureEach {
dependsOn(xjcTask)
}
return xjcTask
}
This works just as well for us.
Also affected by this, the workaround doesn't work for me :(
Affecting me as well
Spent a day with this problem in my project and fortunately finally encountered this Issue item. Solved by downgrading the plugin to 1.8.0 and configuring bindingFiles by assignment rather than "setFrom()".
Affecting me as well.
The problem exists in v1.8.2 also.
I think the problem lies in the XjcTask. Each task is initialized with the bindingFiles
of the extension and therefore share the same FileCollection
instance. See
https://github.com/bjornvester/xjc-gradle-plugin/blob/v1.8.2/src/main/kotlin/com/github/bjornvester/xjc/XjcTask.kt#L58
It is
val bindingFiles = getXjcExtension().bindingFiles
but should be
val bindingFiles = objectFactory.fileCollection()
You can work around the problem with reflection:
xjc {
groups {
register("A") {
bindingFilesSetFrom("A.xjb")
}
register("B") {
bindingFilesSetFrom("B.xjb")
}
}
}
fun XjcExtensionGroup.bindingFilesSetFrom(vararg paths: Any) {
val bindingFilesField = XjcTask::class.java.getDeclaredField("bindingFiles")
bindingFilesField.isAccessible = true
// see: https://github.com/bjornvester/xjc-gradle-plugin/blob/v1.8.2/src/main/kotlin/com/github/bjornvester/xjc/XjcPlugin.kt#L66
val taskName = com.github.bjornvester.xjc.XjcPlugin.Companion.XJC_TASK_NAME + name.replaceFirstChar(Char::titlecase)
bindingFilesField.set( //
project.tasks.getByName(taskName), //
project.objects.fileCollection().from(*paths) //
)
}
Hey,
I'm having trouble with release 1.8.1, because of inconsistent bindings when there is more than one xjc-task involved (which will be the case, when multiple groups are configured). I attached a minimal example-project:
XjcTest.zip
Each group is supposed to generate a single class (
A
andB
).A
has anxsd:dateTime
-attribute, which is supposed to be handled via a custom-converter, which is specified in the bindings-filexsd-templates/a/bindings_a.xjb
.B
has anxsd:duration
-attribute, which is supposed to be handled via another converter, which is specified in the bindings-filexsd-templates/b/bindings_b.xjb
.This example compiles, because it's using the plugin at version 1.8.0. But if you change it to 1.8.1, and replace the lines
bindingFiles = project.files(xsdDir.file("bindings_a.xjb"))
with
bindingFiles.setFrom(project.files(xsdDir.file("bindings_a.xjb")))
,(the same for the
B
-task respectively)it will fail.
If we're attempting to run
./gradlew xjcA xjcB --rerun-tasks --info
, we see the problem in the output:Note, that the task xjcA now loads the binding-file
/home/mz/git/private/XjcTest/xsd-templates/b/bindings_b.xjb
, which means that the code fromMain.java
will lead to compile errors. Eithera.setMyDateTime(OffsetDateTime.MAX);
orb.setMyDuration(Duration.ofSeconds(4));
will produce an error, because one of the task will have worked with mismatched binding-file.I'm guessing, that replacing the
FileCollection
withConfigurableFileCollection
and making them final has something to do with the problem, but I'm not well versed in the intricacies of gradle. I would appreciate it, if you could have a look.