JAXB2 Basics Plugins - Issue with schemaLocation in my External binding customization file - maven

I am using JAXB to generate classes from my XSD file. I would like to have the classes that are generated implement a common interface. So I am trying out the JAXB2 Basics plugin with the external binding file approach to do this. This is my custom binding file:
customBindingFile.xjb
<?xml version="1.0"?>
<jxb:bindings version="1.0"
xmlns:jxb="http://java.sun.com/xml/ns/jaxb"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc"
xmlns:inheritance="http://jaxb2-commons.dev.java.net/basic/inheritance"
jxb:extensionBindingPrefixes="xjc">
<jxb:bindings schemaLocation="abc-api.xsd">
<jxb:bindings node="//xs:complexType[#name='MyClass']">
<inheritance:implements>com.kuldeep.CommonInterface</inheritance:implements>
</jxb:bindings>
</jxb:bindings>
</jxb:bindings>
Following is my maven plugin in pom file for source generation:
Note the comment added by me is the change I made to this existing plugin entry.
pom.xml
<plugin>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-codegen-plugin</artifactId>
<version>${cxf.plugin.version}</version>
<executions>
<execution>
<id>generate-sources</id>
<phase>generate-sources</phase>
<configuration>
<!-- **extensions and args added by me** -->
<extensions>
<extension>org.jvnet.jaxb2_commons:jaxb2-basics:0.9.2</extension>
</extensions>
<args>
<arg>-Xinheritance</arg>
</args>
<sourceRoot>${project.build.directory}/generated/cxf</sourceRoot>
<defaultOptions>
<bindingFiles>
<bindingFile>src/main/resources/jaxws_binding.xml</bindingFile>
<bindingFile>src/main/resources/jaxb_binding.xml</bindingFile>
</bindingFiles>
</defaultOptions>
<wsdlOptions>
......
<wsdlOption>
<wsdl>${project.build.directory}/generated/framework/cxf/abc-api-inline.wsdl</wsdl>
<!-- **bindingFile added by me** -->
<bindingFile>src/main/resources/customBindingFile.xjb</bindingFile>
</wsdlOption>
</wsdlOptions>
</configuration>
<goals>
<goal>wsdl2java</goal>
</goals>
</execution>
</executions>
<!-- **dependency added by me** -->
<dependencies>
<dependency>
<groupId>org.jvnet.jaxb2_commons</groupId>
<artifactId>jaxb2-basics</artifactId>
<version>0.9.2</version>
</dependency>
</dependencies>
</plugin>
The issue that I have is my schema file abc-api.xsd resides in some other project, so when I try to do maven install to generate my classes, I get error saying abc-api.xsd is not a part of this compilation.
[ERROR] Failed to execute goal
org.apache.cxf:cxf-codegen-plugin:3.0.3:wsdl2java (generate-sources)
on project : Execution generate-sources of goal
org.apache.cxf:cxf-codegen-plugin:3.0.3:wsdl2java failed:
file:/I:/project/src/main/resources/customBindingFile.xjb [9,56]:
"file:/I:/project/src/main/resources/abc-api.xsd" is not a part of
this compilation. Is this a mistake for
"file:/I:/project/src/main/resources/jaxb_binding.xml"? -> [Help 1]
And if I remove the schemaLocation attribute from customBindingFile.xjb it does not work and gives error:
XPath evaluation of "//xs:complexType[#name='MyClass']" results in
empty target node
So my question is how can I avoid providing the specific schema file name/location in customBindingFile.xjb and just have it applied to whatever xsd it's using to generate the classes.

With help from our Architect, I was able to resolve this issue. I added a jaxws binding file and used prefix-less xpath query in there to match my request elements.
This way I don't need to provide schema location anywhere and it will be applied to the specific WSDL based on the XPath query.
jaxws_binding_inheritance.xml
<jaxws:bindings version="2.0" xmlns:jaxws="http://java.sun.com/xml/ns/jaxws" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc"
xmlns:inheritance="http://jaxb2-commons.dev.java.net/basic/inheritance" jaxb:extensionBindingPrefixes="inheritance xjc"
xmlns:jxb="http://java.sun.com/xml/ns/jaxb" jaxb:version="2.1">
<jaxws:enableWrapperStyle>false</jaxws:enableWrapperStyle>
<jaxws:bindings
node="*[local-name()='definitions']/*[local-name()='types']/*[local-name()='schema' and
(#targetNamespace='urn:net:mycompany:api:abc')]">
<jaxb:bindings
node="//*[local-name()='element' and
not(#name = 'ExcludeThisRequest' or #name = 'AlsoExcludeThisRequest') and
(substring(#name, string-length(#name) - string-length('Request') +1) = 'Request')]/*[local-name()='complexType']">
<inheritance:implements>com.kuldeep.CommonRequest</inheritance:implements>
</jaxb:bindings>
</jaxws:bindings>
</jaxws:bindings>
And added that jaxws binding file (jaxws_binding_inheritance.xml) under wsdloption for the wsdl where I wanted to apply that.
pom.xml
<wsdlOption>
<wsdl>${project.build.directory}/generated/framework/cxf/abc-api-inline.wsdl</wsdl>
<bindingFiles>
<bindingFile>src/main/resources/jaxws_binding_inheritance.xml</bindingFile>
</bindingFiles>
</wsdlOption>

Related

Modify package names of generated java classes for wsdl and xsd in gradle application

I am working on an app using Gradle kotlin dsl, ie build.gradle is in Kotlin. I have a WSDL file that imports multiple XSDs. while compiling, Java classes are getting generated in the default location(which is mentioned in the XSDs). My requirement is that Java classes of each XSD should be generated in the custom location.
I am referring an another maven project for this. The following plugin is used to achieve my requirement.
<plugin>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-codegen-plugin</artifactId>
<version>3.1.5</version>
<executions>
<execution>
<id>generate-sources-sample</id>
<phase>generate-sources</phase>
<configuration>
<sourceRoot>${project.build.directory}/generated-sources</sourceRoot>
<wsdlOptions>
<wsdlOption>
<wsdl>${basedir}/src/main/resources/wsdl_file_name.wsdl</wsdl>
<extraargs>
<extraarg>-client</extraarg>
<extraarg>-p</extraarg>
<extraarg>urn:namespace:of:xsd:one=com.first.xsd.from.wsdl</extraarg>
<extraarg>-p</extraarg>
<extraarg>urn:namespace:of:xsd:one=com.second.xsd.from.wsdl</extraarg>
</extraargs>
</wsdlOption>
</wsdlOptions>
</configuration>
<goals>
<goal>wsdl2java</goal>
</goals>
</execution>
</executions>
</plugin>
I have tried using wsdl2Java task to assign a custom location. I could not use the task as it needs CXF. It may lead to jar conflicts in my application.
extra["cxfVersion"] = "3.1.5"
project.wsdl2javaExt {
cxfVersion = "${property("cxfVersion")}"
}
tasks.getByName<no.nils.wsdl2java.Wsdl2JavaTask>("wsdl2java") {
wsdlDir = file("$projectDir/src/main/resources/xsd/trip") // wslds location
generatedWsdlDir = file("$projectDir/src/main/generated-sources/xjc/newpackage") // store generates java classes to
wsdlsToGenerate = arrayListOf(
arrayListOf("$wsdlDir/wsdl_file_name.wsdl"),
arrayListOf("-xjc", "-autoNameResolution",
"$wsdlDir/wsdl_file_name.wsdl")
)
}
Please guide me to get the same behavior in Gradle.
I have resolved it by adding the custom location in binding.xjb file in my application. The following changes worked for me.
<jaxb:bindings xmlns:tns="urn:namespace:of:xsd:one" scd="x-schema::tns">
<jaxb:schemaBindings>
<jaxb:package name="com.first.xsd.from.wsdl"/>
</jaxb:schemaBindings>
</jaxb:bindings>
<jaxb:bindings xmlns:tns="urn:namespace:of:xsd:two" scd="x-schema::tns">
<jaxb:schemaBindings>
<jaxb:package name="com.second.xsd.from.wsdl"/>
</jaxb:schemaBindings>
</jaxb:bindings>

Properties defined in the properties section of the POM are not seen in external ant build file

I'm using maven-antrun-plugin in my pom.xml with external ant file.
It's said in plugin's document:
All of the properties available to Maven are also available in the
target configuration. However, you may want to call an external Ant
build script using the ant task. To avoid name conflicts, only a
subset of the properties are passed to the external Ant build. These
include all properties defined in the properties section of the POM.
It also includes prefixed versions of some of the commonly used Maven
properties.
So here's my pom, where I define "test.prop" property:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>testant</groupId>
<artifactId>testant</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<test.prop>TestPropValue</test.prop>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<dependencies>
<dependency>
<groupId>ant</groupId>
<artifactId>optional</artifactId>
<version>1.5.4</version>
</dependency>
</dependencies>
<executions>
<execution>
<id>generate-index-properties</id>
<phase>install</phase>
<configuration>
<tasks>
<!--<property name="test.prop" value="${test.prop}"/>-->
<ant antfile="build.xml">
<target name="echo-prop"/>
</ant>
</tasks>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
And just trying to echo this property in build.xml:
<project default="test">
<target name="echo-prop">
<echo>${test.prop}</echo>
</target>
</project>
This is what I get:
echo-prop:
[echo] ${test.prop}
So property is not resolved as it should, according to the doc.
And it works fine only in case if I uncomment line with explicit property declaration under "tasks" tag.
Could you please help me in understanding, what am I doing wrong?
Thank you!
You should specify a version for the antrun-plugin:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.8</version><!--$NO-MVN-MAN-VER$-->
(...)
</plugin>
ant by default passes all properties of the parent to an underlying "ant"-call. Unless you define inheritAll=false, all properties are passed.
In this case, you should have a look at the effective pom. There a very ancient version of the antrun-plugin is defined.
As soon as you switch to a recent one, the example code works.

JAXBElement generated even with generateElementProperty to false

I generate types in a WSDL using xjc maven plugin. Following my configuration :
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>jaxb2-maven-plugin</artifactId>
<version>1.5</version>
<executions>
<execution>
<id>auth-service-type-generation</id>
<goals>
<goal>xjc</goal>
</goals>
<phase>generate-sources</phase>
<configuration>
<encoding>UTF8</encoding>
<schemaDirectory>${wsdl.location}</schemaDirectory>
<schemaFiles>${wsdl.auth.srv.file.name}</schemaFiles>
<xmlschema>false</xmlschema>
<wsdl>true</wsdl>
<nv>false</nv>
<bindingDirectory>${project.basedir}/src/main/resources/jaxb/</bindingDirectory>
<bindingFiles>jaxb_bindings.xjb</bindingFiles>
</configuration>
</execution>
</executions>
</plugin>
Content of jaxb_bindings.xjb :
<jaxb:bindings version="2.0"
xmlns:jaxb="http://java.sun.com/xml/ns/jaxb">
<jaxb:bindings>
<jaxb:globalBindings generateElementProperty="false"/>
</jaxb:bindings>
</jaxb:bindings>
I used this binding to get rid of JAXBElement but it is still generated. What's wrong in my settings or is there another way to generate types in my WSDLs without JAXBElement ?
It looks like there is missing properties in your config: schemaLocation and node.
<jaxb:bindings version="2.0"
xmlns:jaxb="http://java.sun.com/xml/ns/jaxb">
<jaxb:bindings schemaLocation="../path/your.xsd" node="/xs:schema">
<jaxb:globalBindings generateElementProperty="false"/>
</jaxb:bindings>
</jaxb:bindings>

JAXB2 Basic Annotate plugin not working with maven cxf-codegen-plugin

I'm using the cxf-codegen-plugin to generate Java classes from wsdl files. I want to add annotations to once of the classes and I specify a Binding File and use the jaxb2-basics-annotate plugin to do so. The generated files don't contain the the annotation specified in the binding file.
Here is the configuration in the pom file
<plugins>
<plugin>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-codegen-plugin</artifactId>
<version>2.7.4</version>
<executions>
<execution>
<id>generate-sources</id>
<phase>generate-sources</phase>
<configuration>
<wsdlOptions>
<wsdlOption>
<wsdl>src/main/resources/wsdl/QueryJobService.wsdl</wsdl>
<wsdlLocation>classpath:wsdl/QueryJobService.wsdl</wsdlLocation>
<extraargs>
<extraarg>-xjc-Xannotate</extraarg>
</extraargs>
<bindingFiles>
<bindingFile>src/main/resources/wsdl/xsd/job-bindings.xjb</bindingFile>
</bindingFiles>
</wsdlOption>
</wsdlOptions>
</configuration>
<goals>
<goal>wsdl2java</goal>
</goals>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>org.jvnet.jaxb2_commons</groupId>
<artifactId>jaxb2-basics-annotate</artifactId>
<version>1.0.1</version>
</dependency>
</dependencies>
</plugin>
</plugins>
and here is the binding file
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<jaxb:bindings
xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:annox="http://annox.dev.java.net"
xsi:schemaLocation="http://java.sun.com/xml/ns/jaxb http://java.sun.com/xml/ns/jaxb/bindingschema_2_0.xsd"
version="2.1">
<jaxb:bindings schemaLocation="data.xsd" node="/xs:schema">
<jaxb:bindings node="//xs:complexType[#name='resource']">
<annox:annotate target="class">
<annox:annotate annox:class="javax.xml.bind.annotation.XmlSeeAlso" value="model.common.sm.dcp.com.data._1.SimOrder"/>
</annox:annotate>
</jaxb:bindings>
</jaxb:bindings>
running maven in debug mode doesn't show anything strange. Is it so that cxf-codegen-plugin and jaxb2-basics-annotate don't work together ? Or is there something wrong with my configurations ?
It should work with CXF.
Please make sure that bindings are applied at all. Try to replace annox:annotate with something like <jaxb:class name="FooBar"/> - does it get generated as FooBar?
Also try the new Java Syntax: https://github.com/highsource/jaxb2-annotate-plugin instead of XML.
Finally, I guess you might be missing this attribute on your root jaxb:bindings element:
jaxb:extensionBindingPrefixes="annox"
See this example.
If nothing helps, send me a PR on github.
SO disclaimer: I'm the author of jaxb2-annotate-plugin.

Change the execution directory of a cxf-codegen-plugin

I'm building some tooling to (automatically) convert a large ANT project to a Maven structure. The project contains webservices. Therefore, I'm not able to change the input wsdl / xsd files. This is my input wsdl file. It contains a reference to a types definition from the poject base dir.
<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" targetNamespace="http://schemas.test.com/test" name="Test">
<wsdl:import namespace="http://schemas.test.com/test" location="./src/wsdl/Test.xsd"/>
<wsdl:types>
</wsdl:types>
</wsdl:definitions>
This is my maven plugin configuration:
<plugin>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-codegen-plugin</artifactId>
<executions>
<execution>
<id>generate-sources</id>
<phase>generate-sources</phase>
<goals>
<goal>wsdl2java</goal>
</goals>
<configuration>
<sourceRoot>${project.build.directory}/generated-sources/cxf</sourceRoot>
<wsdlRoot>${project.build.directory}/../src/wsdl/</wsdlRoot>
<includes>
<include>**/*.wsdl</include>
</includes>
</configuration>
</execution>
</executions>
</plugin>
Building the submodule works fine, since the cfx-codegen-plugin seems to take the ${project.basedir} as execution root directory.
However, when I try to build the complete multimodule project, the cfx-codegen-plugin seems to revert to the project.parent.basedir. I get the following build error:
Caused by : WSDLException (at /wsdl:definitions/wsdl:import): faultCode=PARSER_ERROR: Problem parsing './src/wsdl/Test.xsd'.: java.io.FileNotFoundException: C:\Users\test\Desktop\multimod\src\wsdl\Test.xsd (The system cannot find the path specified)
Does anyone know how to:
Change the execution root dir of a plugin in a specific maven phase?
Or force the cfx-codegen-plugin to use an alternative execution root?
Thanks,
sjaak

Resources