Closed dsuchy closed 2 years ago
Can you share your Gradle configuration?
plugins {
id "io.mateo.cxf-codegen" version "1.0.1"
}
...
cxfCodegen {
wsdl2java {
service1 {
wsdl = file("src/main/resources/soap-ws-service1.wsdl")
outputDir = file("src/main/java")
bindingFiles = ["src/main/resources/binding.xjb"]
extraArgs = ["-client", "-verbose"]
}
service2 {
wsdl = file("src/main/resources/soap-ws-service2.wsdl")
outputDir = file("src/main/java")
bindingFiles = ["src/main/resources/binding.xjb"]
extraArgs = ["-client", "-verbose"]
}
...
}
wsdl2java.configureEach {
markGenerated = true
extraArgs = ["-frontend", "jaxws21"]
}
}
dependencies {
cxfCodegen (
'jakarta.xml.ws:jakarta.xml.ws-api:2.3.3',
'jakarta.annotation:jakarta.annotation-api:1.3.5'
)
...
}
Couple issues with that setup.
To further expand on (2), when service1
finishes generating, then service2
generates its code which will overwrite what was previously generated; vice versa. This is why the default output directory is unique for each task to avoid such situations and allow Gradle to cache outputs effectively.
The wsdl2java
plugin by Nil's 'hooks' in to the code generation process. This plugin does no such thing and instead leaves all code generation to the wsdl2java
tool itself. As such, modification of the code generated is out of scope for this plugin. This plugins goal is to provide an API over the wsdl2java
CLI tool provided by the Apache CXF project.
Furthermore, the issue you are facing seems to be CXF-1340. From the issue comments:
This issue is very closely related to https://issues.apache.org/jira/browse/CXF-1662 and is a JAXB limitation/design that we have no control over. We just call off to JAXB to generate these files. Thus, we cannot do anything about it.
Basically, JAXB is pretty much COMPLETELY designed around the idea of namespace:package is a 1:1 mapping. If you try to map multiple schemas into the same package, it's very likely NOT to work.
Along with the ObjectFactory issue, the package-info.java file that is generated is also very specific to the schema that was being processed when generated. If you have multiple schemas generating into the package, the resulting XML is likely to have the wrong namespaces, wrong qualification, etc... set. Basically, invalid XML according to the schema.
My understanding of that is that this behavior is expected. Further more, from the comments in the issue you linked, a workaround for the limitations of JAXB is specifying the package for each service. So:
cxfCodegen {
wsdl2java {
register("service1") {
packageNames.set(listOf("com.example.service1"))
}
register("service2") {
packageNames.set(listOf("com.example.service2"))
}
}
}
But since the extension configuration is deprecated, the preferred way using the task:
tasks.register("service1", io.mateo.cxf.codegen.wsdl2java.Wsdl2Java::class) {
toolOptions {
wsdl.set(file("src/main/resources/soap-ws-service1.wsdl"))
bindingFiles.set(listOf("src/main/resources/binding.xjb"))
extraArgs.set(listOf("-client"))
verbose.set(true)
}
}
tasks.register("service2", io.mateo.cxf.codegen.wsdl2java.Wsdl2Java::class) {
toolOptions {
wsdl.set(file("src/main/resources/soap-ws-service2.wsdl"))
bindingFiles.set(listOf("src/main/resources/binding.xjb"))
extraArgs.set(listOf("-client"))
verbose.set(true)
}
}
tasks.withType(io.mateo.cxf.codegen.wsdl2java.Wsdl2Java::class).configureEach {
toolOptions {
markGenerated.set(true)
frontend.set("jaxws21")
}
}
The output directory by default is build/${taskName}-wsdl2java-generated-sources
which is added to the main
source set by default, so no need to generate to src/main
either.
Thank you for your detailed answer.
I probably should have worded my question more precisely – I tried to avoid generating into multiple packages, because many classes are shared and therefore would get multiplicated. Some of them aren't identical between services though, that is the reason why I was searching for a way to recreate stabilizeAndMergeObjectFactory property with non-deprecated plugin despite Apache CFX tool limitations.
The wsdl2java plugin by Nil's 'hooks' in to the code generation process. This plugin does no such thing and instead leaves all code generation to the wsdl2java tool itself. As such, modification of the code generated is out of scope for this plugin. This plugins goal is to provide an API over the wsdl2java CLI tool provided by the Apache CXF project.
I understand that the goal of the project is to port the CLI tool, not to extend its functionality. Thanks again for your quick and thorough help.
many classes are shared and therefore would get multiplicated
The implication of that is, unfortunately, that generating to the default build/${taskName}-wsdl2java-generated-sources
directory will result in several error: duplicate class
compile errors
searching for a way to recreate stabilizeAndMergeObjectFactory property with non-deprecated plugin despite Apache CFX tool limitations.
One idea, although it will be a bit of trail/error, is to generate the Java code to its default output directory, but exclude them from the main
source and then use the output in combination with logic from ObjectFactoryMerger
val sevice1 = tasks.register("service1", io.mateo.cxf.codegen.wsdl2java.Wsdl2Java::class) {
addToMainSourceSet.set(false)
toolOptions {
wsdl.set(file("src/main/resources/soap-ws-service1.wsdl"))
}
}
val service2 = tasks.register("service2", io.mateo.cxf.codegen.wsdl2java.Wsdl2Java::class) {
addToMainSourceSet.set(false)
toolOptions {
wsdl.set(file("src/main/resources/soap-ws-service2.wsdl"))
}
}
val copyCode = tasks.register("copyCode", Copy::class) {
from(service1, service2)
into(layout.buildDirectory.dir("merged-wsdl2java"))
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
// Rest of code
doLast {
}
}
sourceSets {
main {
java {
srcDir(copyCode)
}
}
}
Closing as nothing to do here.
For future lost souls that go down the path of creating separate packages in Spring. Make sure your JaxB2Marshaller configuration does not scan all packages at once or you will still get an error on startup.
The following config will not work if you have com.mypackage.soapservicea
, com.mypackage.soapserviceb
with duplicated types. They may be separate packages, but it still fails because you are scanning all of them.
@Configuration
public class BaseConfiguration {
@Bean
public Jaxb2Marshaller xmlMarshaller() {
Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
marshaller.setPackagesToScan("com.mypackage");
return marshaller;
}
}
I had to do the following to get it to work.
@Configuration
public class BaseConfiguration {
@Bean
public Jaxb2Marshaller soapServiceAXmlMarshaller() {
Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
marshaller.setPackagesToScan("com.mypackage.soapservicea");
return marshaller;
}
@Bean
public Jaxb2Marshaller soapServiceBXmlMarshaller() {
Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
marshaller.setPackagesToScan("com.mypackage.soapserviceb");
return marshaller;
}
}
Not pretty, but it works.
Sample case: few services (each defined by different WSDL) are using common model files. ObjectFactory for the common package will get overwritten after every iteration and, in the end, will consist of bindings for the last imported WSDL only.
The deprecated nils wsdl2java utility seems to have had a property for merging those files in that case: https://github.com/nilsmagnus/wsdl2java/issues/39
Does this plugin support ObjectFactory merging?