I have three XSD files: a.xsd, b.xsd and c.xsd
Each of them contains an xs:element called MyHeader
I try to use xjc to generate java classes from these three XSD file
Error when generating the java file
Here is the common part in all three XSDs:
<xs:element name="MyHeader">
<xs:complexType>
<xs:attribute name="Username" type="xs:string" />
<xs:attribute name="Password" type="xs:string" />
</xs:complexType>
</xs:element>
The error message is [xjc] [ERROR] 'MyHeader' is already defined
Then I try to use external bindings to solve the problem, because I really want MyHeader can be ONE java class.
My external binding is like
<bindings xmlns="http://java.sun.com/xml/ns/jaxb" xmlns:xsi="http://www.w3.org/2000/10/XMLSchema-instance"
xsi:schemaLocation=" http://java.sun.com/xml/ns/jaxb http://java.sun.com/xml/ns/jaxb/bindingschema_2_0.xsd"
version="2.1">
<bindings schemaLocation="./a.xsd" node="/xs:schema">
<bindings node="//xs:element[#name='MyHeader']">
<class name="MyHeader" />
</bindings>
</bindings>
<bindings schemaLocation="./b.xsd" node="/xs:schema">
<bindings node="//xs:element[#name='MyHeader']">
<class name="MyHeader" />
</bindings>
</bindings>
<bindings schemaLocation="./c.xsd" node="/xs:schema">
<bindings node="//xs:element[#name='MyHeader']">
<class name="MyHeader" />
</bindings>
</bindings>
</bindings>
Then it complains xpath error...
Can someone help me get rid of this issue. Thanks.
Your binding file needs the definition of the namespace prefix xs:. After adding this, a rename for MyHeader in one of the three xsd files works.
But you won't be able to rename three clashing element names in three different XML schema files.
One way around this would be to use different namespaces: then the elements wouldn't clash.
Removing the definition of this element from two schema files is another option.
Clearly, the entire schema design is flawed and should be reconsidered using an approach where common types or elements are defined in one file, with other files including this common base file.
Related
I'm trying to generate the java files from XSD with use of jaxb2-maven-plugin. This works without any issues and I can see generated classes in target directory.
Now I decided to let all generated classes implement some interface. So I set up bindings.xjb file where I'm defining the interface. The issue is the plugin can not recognize correct namespace which defines inheritance.
Unsupported binding namespace "http://jaxb2-commons.dev.java.net/basic/inheritance". Perhaps you meant "http://jaxb.dev.java.net/plugin/code-injector"?
I think code-injector is not what I'm looking for, since this allow to define custom pieces of code to add to generated file.
I'm trying to use latest maven plugin:
<groupId>org.codehaus.mojo</groupId>
<artifactId>jaxb2-maven-plugin</artifactId>
<version>3.1.0</version>
The bindings.xjb file contains following content:
<?xml version="1.0" encoding="UTF-8"?>
<jaxb:bindings xmlns:jaxb="https://jakarta.ee/xml/ns/jaxb"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:inheritance="http://jaxb2-commons.dev.java.net/basic/inheritance"
jaxb:extensionBindingPrefixes="inheritance"
version="3.0">
<jaxb:bindings schemaLocation="application.xsd" node="/xs:schema">
<jaxb:bindings node="//xs:complexType[#name='applicationType']">
<inheritance:implements>com.example.SomeInterface</inheritance:implements>
<jaxb:property name="inheritance"/>
</jaxb:bindings>
</jaxb:bindings>
</jaxb:bindings>
And the application.xsd file:
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="application" type="applicationType"/>
<xs:complexType name="applicationType">
<xs:sequence>
<xs:element type="xs:string" name="language"/>
</xs:sequence>
</xs:complexType>
</xs:schema>
I have found this namespace xmlns:inheritance="http://jaxb2-commons.dev.java.net/basic/inheritance" on the internet.
Also notice plugin requires version 3.0 of bindings.xjb file.
What is the correct definition of namespace to let plugin generate classes with interface?
My wsdl specification contains imported XSD schema.
wsdl file looks like below
<wsdl:definitions xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" ....>
<wsdl:types>
<xsd:schema targetNamespace="http://tempuri.org/Imports">
<xsd:import schemaLocation="https://abcserver.com/v2/two-way-ssl/MyService.svc?xsd=xsd2" namespace="http://tempuri.org/"/>
<xsd:import schemaLocation="https://abcserver.com/v2/two-way-ssl/MyService.svcc?xsd=xsd4" namespace="http://schemas.datacontract.org/2004/07/System.Web.Services.Protocols"/>
<xsd:import schemaLocation="https://abcserver.com/v2/two-way-ssl/MyService.svc?xsd=xsd0" namespace="http://schemas.microsoft.com/2003/10/Serialization/"/>
<xsd:import schemaLocation="https://abcserver.com/v2/two-way-ssl/MyService.svc?xsd=xsd1" namespace="http://schemas.datacontract.org/2004/07/ABCUser.Web.Services"/>
<xsd:import schemaLocation="https://abcserver.com/v2/two-way-ssl/MyService.svc?xsd=xsd3" namespace="http://schemas.datacontract.org/2004/07/ABCUser.Web.ServiceModels"/>
<xsd:import schemaLocation="https://abcserver.com/v2/two-way-ssl/MyService.svc?xsd=xsd5" namespace="http://schemas.datacontract.org/2004/07/System"/>
<xsd:import schemaLocation="https://abcserver.com/v2/two-way-ssl/MyService.svc?xsd=xsd6" namespace="http://schemas.microsoft.com/2003/10/Serialization/Arrays"/>
<xsd:import schemaLocation="https://abcserver.com/v2/two-way-ssl/MyService.svc?xsd=xsd7" namespace="http://schemas.datacontract.org/2004/07/System.Collections.Generic"/>
<xsd:import schemaLocation="https://abcserver.com/v2/two-way-ssl/MyService.svc?xsd=xsd8" namespace="http://schemas.datacontract.org/2004/07/ABC.Fs.UIEntities"/>
<xsd:import schemaLocation="https://abcserver.com/v2/two-way-ssl/MyService.svc?xsd=xsd9"/>
</xsd:schema>
</wsdl:types>
.......
</wsdl:definitions>
My jaxb bindings file look like below:
<jaxws:bindings xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:jaxws="http://java.sun.com/xml/ns/jaxws"
xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" jaxb:version="2.1"
wsdlLocation="https://abcserver.com/v2/two-way-ssl/MyService.svc?wsdl">
<enableWrapperStyle>true</enableWrapperStyle>
<enableAsyncMapping>false</enableAsyncMapping>
<jaxws:bindings node="wsdl:definitions/wsdl:types/xs:schema/xs:complexType[#name='Node']/xs:sequence/xs:element[#name='Type']">
<jaxb:class name="NodeTypeString"/>
</jaxws:bindings>
</jaxws:bindings>
If I don't use bindings.xml, I get following error while generating java classes through wsimport
[ERROR] Two declarations cause a collision in the ObjectFactory class.
line 1 of https://abcserver.com/v2/two-way-ssl/MyService.svc?xsd=xsd3
[ERROR] (Related to above error) This is the other declaration.
line 1 of https://abcserver.com/v2/two-way-ssl/MyService.svc?xsd=xsd3
Schema it is complaining about looks like below
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:tns="http://schemas.datacontract.org/2004/07/ABCUser.Web.ServiceModels" elementFormDefault="qualified" targetNamespace="http://schemas.datacontract.org/2004/07/ABCUser.Web.ServiceModels">
<xs:import schemaLocation="https://abcserver.com/v2/two-way-ssl/MyService.svc?xsd=xsd6" namespace="http://schemas.microsoft.com/2003/10/Serialization/Arrays"/>
.......
<xs:complexType name="Node">
<xs:sequence>
<xs:element minOccurs="0" name="Description" nillable="true" type="xs:string"/>
<xs:element minOccurs="0" name="Name" nillable="true" type="xs:string"/>
<xs:element minOccurs="0" name="Type" nillable="true" type="xs:string"/>
<xs:element minOccurs="0" name="Users" nillable="true" type="tns:ArrayOfUser"/>
</xs:sequence>
</xs:complexType>
<xs:element name="Node" nillable="true" type="tns:Node"/>
......
But now when I use bindings.xml, I get the following error
[ERROR] XPath evaluation of "wsdl:definitions/wsdl:types/xs:schema/xs:complexType[#name='Node']/xs:sequence/xs:element[#name='Type']" results in an empty target node
line 8 of file:/E:/projects/codegeneration/bindings.xml
What am I missing? I am using wsimport to generate the classes.
<xsd:import> does not actually change the WSDL file’s XML document tree. You have elements matching wsdl:definitions/wsdl:types/xs:schema/xs:import, not wsdl:definitions/wsdl:types/xs:schema/xs:complexType/xs:sequence/xs:element.
The JAX-WS specification’s “Customizations” chapter says:
Additionally, jaxb:bindings MAY appear inside a JAX-WS external binding file as a child of a jaxws:bindings element whose node attribute points to a xs:schema element inside a WSDL document. When the schema is processed, the outcome MUST be as if the jaxb:bindings element was inlined inside the schema document as an annotation on the schema component.
While processing a JAXB binding declaration (i.e. a jaxb:bindings element) for a schema document embedded inside a WSDL document, all XPath expressions that appear inside it MUST be interpreted as if the containing xs:schema element was the root of a standalone schema document.
So, your inner jaxws:bindings element must contain the XPath of the xs:schema element, not any of its descendants:
<jaxws:bindings node="wsdl:definitions/wsdl:types/xs:schema">
<jaxb:bindings node="xs:complexType[#name='Node']/xs:sequence/xs:element[#name='Type']">
<jaxb:class name="NodeTypeString"/>
</jaxb:bindings>
</jaxws:bindings>
I’m not sure if the above will actually work with a schema that uses <xsd:import>. You may have to refer to the imported schema explicitly:
<jaxws:bindings node="wsdl:definitions/wsdl:types/xs:schema">
<jaxb:bindings schemaLocation="https://abcserver.com/v2/two-way-ssl/MyService.svc?xsd=xsd2">
<jaxb:bindings node="xs:complexType[#name='Node']/xs:sequence/xs:element[#name='Type']">
<jaxb:class name="NodeTypeString"/>
</jaxb:bindings>
</jaxb:bindings>
</jaxws:bindings>
I got two solutions for this issue I was facing.
I streamlined the wsdl schema by adding imported schema in it and removing import statements.
First build an episode using xjc for imported schema
xjc -episode myschema.episode myschema.xsd
And then use that episode as a binding in java classes generation through wsimport
wsimport mywsdl.wsdl -b myschema.episode
More about 2nd solution here
When generating Java classes from a XSD, how can I specify that for some specific node, a specific and already existent Java class should be used instead of trying to generate one?
Thank you very much.
You can use episode file to reference the existing classes. .episode files are just jaxb bindings file and has mappings between elements and java classes.
a) if those existing classes are also generated from (another) xsd. use below option to first create .episode file.
xjc -episode a.episode a.xsd
then use this a.episode that contains the mappings as input to the next xjc generation.
xjc b.xsd -extension -b a.episode
b) If you want to refer some random classes, then you may have to write your own episode file providing mapping between element and class reference like below.
sample.episode
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<jaxb:bindings xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" if-exists="true" version="2.1">
<jaxb:bindings scd="x-schema::">
<jaxb:bindings scd="employee">
<jaxb:class ref="www1.example.Employee"/>
<jaxb:package name="www1.example" />
</jaxb:bindings>
</jaxb:bindings>
and use xjc b.xsd -extension -b sample.episode
You should use following binding customization
<bindings version="2.0" xmlns="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:annox="http://annox.dev.java.net" xmlns:namespace="http://jaxb2-commons.dev.java.net/namespace-prefix">
<bindings schemaLocation="../schema/yourSchema.xsd">
<bindings node="//xs:complexType[#name='Foo']">
<class ref="com.FooImpl"/>
</bindings>
</bindings>
</bindings>
This is my general problem: I want everything to be automated as much as it can be.
This is my specific problem: I want to marshal/unmarshal CDATA. I know that I can specify my own adapter as here. For building process I use Maven and its maven-jaxb2-plugin. Is there some option how to annotate elements in .xsd so they will be automatically annotated by my custom adapter? I really don't want to manually change those after each build.
Any other ways how to solve my problem are more than welcome. :)
EDIT: I've ran to a subproblem and it is described there: JAXB binding - "unable to honor this conversion customization".
try this configuration
<bindings version="2.0" xmlns="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:annox="http://annox.dev.java.net"
xmlns:namespace="http://jaxb2-commons.dev.java.net/namespace-prefix">
<bindings schemaLocation="yourXSD.xsd">
<bindings node="//xsd:complexType[#name='Certificate']//xsd:sequence//xsd:element[#name='certificate']">
<xjc:javaType name="java.security.cert.X509Certificate" adapter="adapters.X509CertificateAdapter" />
</bindings>
<bindings node="//xsd:complexType[#name='User']//xsd:sequence//xsd:element[#name='certificate']">
<xjc:javaType name="java.security.cert.X509Certificate" adapter="adapters.X509CertificateAdapter" />
</bindings>
</bindings>
</bindings>
i solved this issue on this link
this configuration work fine if is an xmltype like xs:string, xs:date, etc.
Try this configuration to solve your problem, using XmlJavaTypeAdapter.
I want to generate the POJOs using the xml-binding with a different hierarchy that I have right now.
Now I have an xsd like this one:
<?xml version="1.0" encoding="UTF-8"?>
<schema xmlns="http://www.w3.org/2001/XMLSchema" targetNamespace="http://manueldoncel.com" xmlns:tns="http://manueldoncel.com" elementFormDefault="qualified">
<!-- Base element that any element uses / extends -->
<complexType name="baseElement" abstract="true">
<sequence>
<element name="attributes" type="anyType" minOccurs="0" />
</sequence>
<attribute name="id" type="string" />
</complexType>
<complexType name="Square">
<complexContent><extension base="tns:baseElement" /></complexContent>
</complexType>
<complexType name="Triangle">
<complexContent><extension base="tns:baseElement" /></complexContent>
</complexType>
</schema>
An a xjb like this;
<?xml version="1.0"?>
<jxb:bindings version="1.0" xmlns:jxb="http://java.sun.com/xml/ns/jaxb" xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc" jxb:extensionBindingPrefixes="xjc" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<jxb:bindings schemaLocation="figures.xsd" node="/xs:schema">
<jxb:globalBindings>
<xjc:simple />
<xjc:superClass name="org.manuel.metadata.Figure"/>
</jxb:globalBindings>
</jxb:bindings>
</jxb:bindings>
But, I would like to have a better hierarchy with this approach
public abstract class Figure {
// some methods for all the figures
}
public abstract class ThreeSideFigure extends Figure {
.... // some methods for only the Three side Figures
}
So, the Triangle POJO generated from the XSD should extend from ThreeSideFigure rather than from Figure.
In this particular xsd I only put 2 figures, but I can have much more. I would like to be able to specify in the xjb that all the complexType should extends from Figure but only a few of them, should extends from ThreeSideFigure.
Do you know how the xjb should look like?
I don't think the Metro JAXB RI extensions will let you do that.
From the 2.2.7 documentation:
3.1.3. Extending a Common Super Class
The <xjc:superClass> customization allows you to specify the fully
qualified name of the Java class that is to be used as the super class
of all the generated implementation classes. The <xjc:superClass>
customization can only occur within your <jaxb:globalBindings>
customization on the <xs:schema> element
That said, the answer to XJC superinterface and superclass only for all classes? suggests that you may be able to do it with 3rd party extensions. There are some details about plugins in the documentation.