Generating JAXB classes with multiple prefixes using an external binding - java

I have a group of XSD files, as follows:
http://www.iana.org/assignments/xml-registry/schema/contact-1.0.xsd
http://www.iana.org/assignments/xml-registry/schema/domain-1.0.xsd
http://www.iana.org/assignments/xml-registry/schema/epp-1.0.xsd
http://www.iana.org/assignments/xml-registry/schema/eppcom-1.0.xsd
http://www.iana.org/assignments/xml-registry/schema/host-1.0.xsd
Most of them are dependent on each other, so I created the following catalog file to allow the JAXB compiler (XJC) to generate the classes.
<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog">
<public publicId="urn:ietf:params:xml:ns:contact-1.0" uri="contact-1.0.xsd"/>
<public publicId="urn:ietf:params:xml:ns:domain-1.0" uri="domain-1.0.xsd"/>
<public publicId="urn:ietf:params:xml:ns:epp-1.0" uri="epp-1.0.xsd"/>
<public publicId="urn:ietf:params:xml:ns:eppcom-1.0" uri="eppcom-1.0.xsd"/>
<public publicId="urn:ietf:params:xml:ns:host-1.0" uri="host-1.0.xsd"/>
<public publicId="urn:ietf:params:xml:ns:rgp-1.0" uri="rgp-1.0.xsd"/>
</catalog>
Unfortunately, there are some collisions between some of the generated class names, which I must resolve - according to some research I need to create an external bindings file.
I would like to prefix all classes that are directly generated from each XSD.
Imported XSDs should be ignored (e.g. epp-1.0 imports eppcom-1.0.xsd), since they will already be generated if I repeat the process for each XSD. (i.e. prefix by XSD namespace if possible)
Does anyone know how I can solve this issue?
Since the XSD files are maintained by a 3rd party, I do not have the option of modifying the XSDs directly. I have tried the following external binding, but it does not work:
<jxb:bindings version="2.0"
xmlns:jxb="http://java.sun.com/xml/ns/jaxb"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<jxb:bindings scd="x-schema:epp" node="/xs:schema">
<jxb:schemaBindings>
<jxb:nameXmlTransform>
<jxb:typeName prefix="Epp" />
<jxb:elementName prefix="Epp" />
<jxb:modelGroupName prefix="Epp" />
<jxb:anonymousTypeName prefix="Epp" />
</jxb:nameXmlTransform>
</jxb:schemaBindings>
</jxb:bindings>
<jxb:bindings scd="x-schema:eppcom" node="/xs:schema">
<jxb:schemaBindings>
<jxb:nameXmlTransform>
<jxb:typeName prefix="EppCom" />
<jxb:elementName prefix="EppCom" />
<jxb:modelGroupName prefix="EppCom" />
<jxb:anonymousTypeName prefix="EppCom" />
</jxb:nameXmlTransform>
</jxb:schemaBindings>
</jxb:bindings>
</jxb:bindings>
Output:
parsing a schema...
[ERROR] XPath evaluation of "/xs:schema" results in empty target node
line 4 of file:/C:/Users/Jin%20Kim/workspace/registry/server/src/main/resources/xsd/bindings.xjb
[ERROR] XPath evaluation of "/xs:schema" results in empty target node
line 14 of file:/C:/Users/Jin%20Kim/workspace/registry/server/src/main/resources/xsd/bindings.xjb
Failed to parse a schema.

Related

JAXB Generating Classes Issue

I am trying to use Eclipse to generate a few Java Classes. But somehow I am running into issues. When I try to do it, I get this error:
parsing a schema...
compiling a schema...
[ERROR] A class/interface with the same name "com.xml.apis.schemas.MPLSVPNListItem" is already in use. Use a class customization to resolve this conflict.
line 9 of file:/C:/Workspace/MyFiles/WebContent/WEB-INF/XSDFiles/jaxb_binding.xml
[ERROR] (Relevant to above error) another "MPLSVPNListItem" is generated from here.
line 3122 of file:/C:/Workspace/MyFiles/WebContent/WEB-INF/XSDFiles/APIcTypes.xsd
[ERROR] Two declarations cause a collision in the ObjectFactory class.
line 9 of file:/C:/Workspace/MyFiles/WebContent/WEB-INF/XSDFiles/jaxb_binding.xml
[ERROR] (Related to above error) This is the other declaration.
line 3122 of file:/C:/Workspace/MyFiles/WebContent/WEB-INF/XSDFiles/APIcTypes.xsd
Failed to produce code.
I am using the JAXB Binding file (jaxb_binding.xml):
<?xml version="1.0" encoding="UTF-8"?>
<jxb:bindings xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:jxb="http://java.sun.com/xml/ns/jaxb" version="2.1">
<jxb:bindings
schemaLocation="APIcTypes.xsd">
<jxb:bindings
node="//xs:complexType[#name='MPLS-VPNListItem']">
<jxb:class name="MPLS_VPNListItem" />
</jxb:bindings>
</jxb:bindings>
<jxb:bindings
schemaLocation="APIcTypes.xsd">
<jxb:bindings
node="//xs:complexType[#name='MPLSVPNListItem']">
<jxb:class name="MPLSVPNListItem" />
</jxb:bindings>
</jxb:bindings>
</jxb:bindings>
Because I think these two tags are causing the problem.
I have to say that APIcTypes.xsd is actually an import in the XSD that I am trying to generate the classes for.
The includes structure is like:
API.xsd --> APIRequests.xsd --> APIcTypes.xsd --> APIsTypes.xsd.
I hope this is understandable. If you need any more info, please do let me know. Just cant get it to work!

Multiple <schemaBindings> are defined for the target namespace when defining package

I have 3 XSD's in my project. Two in the namespace "A" and one in namespace "B".
I want to generate XSD-1, XSD-2 (same namespace) into one package.
Then generate XSD-3 in to an different package.
I am trying to do this via the bindings.xjb file.
If I declare
<jxb:bindings schemaLocation="xsd1-namespaceA.xsd">
<jxb:schemaBindings>
<jxb:package name="com.xsdPrimary" />
</jxb:schemaBindings>
</jxb:bindings>
<jxb:bindings schemaLocation="xsd2-namespaceA.xsd">
<jxb:schemaBindings>
<jxb:package name="com.xsdPrimary" />
</jxb:schemaBindings>
</jxb:bindings>
<jxb:bindings schemaLocation="xsd3-namespaceB.xsd">
<jxb:schemaBindings>
<jxb:package name="com.xsdSecondary" />
</jxb:schemaBindings>
</jxb:bindings>
Then I get the error:
com.sun.istack.SAXParseException2: Multiple <schemaBindings> are defined for the target
namespace "http://www.jeff-test.org/namespaceA/"
If I remove the first two entries in the bindings file, then the generation works, but it puts all my classes in a package called "jeff-test.namespaceA" for namespaceA and all those from namespaceB in the package "com.xsdSecondary".
I want all the classes from namespace-A into one package and all those from namespace-B into another package.
Is this possible?
Multiple are defined for the target namespace "http://www.jeff-test.org/namespaceA/"
If I remove the first two entries in the bindings file, then the generation works, but it puts all my classes in a package called "jeff-test.namespaceA" for namespaceA...
Just remove just one of the entries for namespaceA. What's the logic behind removing both?
<jxb:bindings schemaLocation="xsd1-namespaceA.xsd">
<jxb:schemaBindings>
<jxb:package name="com.xsdPrimary" />
</jxb:schemaBindings>
</jxb:bindings>
<jxb:bindings schemaLocation="xsd3-namespaceB.xsd">
<jxb:schemaBindings>
<jxb:package name="com.xsdSecondary" />
</jxb:schemaBindings>
</jxb:bindings>
schemaBindings is considered once per namespace, it does not matter which schema file is it bound to (as long as this file is a part of the compilation).

xjc handle duplicated elemements

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.

Web service code created by CXF is not legal because of XMLGregorianCalendar?

I have a WSDL and created a web service from it using CXF in Eclipse. The execution went fine: no output in the console, I don't know if there is a log somewhere but I could not find one. But in the service interface created, everywhere an XMLGregorianCalendar is used (as either parameter or return value), I get this error from Eclipse:
Abstract class javax.xml.datatype.XMLGregorianCalendar cannot be used as a runtime class because it is not extended by a non abstract class which is suitable as a runtime class
The use of XMLGregorialCalendar in the beans causes no problem, just in the interface. The WSDL was originally created by the same environment (so I am assuming is OK).
I have no idea what this error means! Is it a bug in CXF, a setting I set wrong, or some code I need to add now that the skeleton is created?
That happens because you are using defaults. You can specify what type you want in bindings file.
Here is an example exert (notice how I tell to use java.util.Date class for "xs:dateTime"):
<jaxws:globalBindings>
<jaxws:javaType name="java.util.Date" xmlType="xs:dateTime"
parseMethod="org.apache.cxf.tools.common.DataTypeAdapter.parseDateTime"
printMethod="org.apache.cxf.tools.common.DataTypeAdapter.printDateTime" />
<jaxws:javaType name="java.lang.Integer" xmlType="xs:gYear" />
<jaxws:javaType name="java.lang.Integer" xmlType="xs:positiveInteger" />
<jaxws:javaType name="java.lang.Integer" xmlType="xs:integer" />
<jaxws:javaType name="java.lang.Integer" xmlType="xs:int" />
<jaxws:javaType name="java.util.Locale" xmlType="xs:language" />
</jaxws:globalBindings>
You can read more about JAXWS Customization and Customizing JAXB Bindings
This is the actual binding file generated by CXF (if it helps anyone):
<jxb:bindings version="1.0" xmlns:jxb="http://java.sun.com/xml/ns/jaxb" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<jxb:bindings schemaLocation="example_schema1.xsd" node="/xs:schema">
<jxb:globalBindings xmlns:jxb="http://java.sun.com/xml/ns/jaxb" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<jxb:javaType name="java.util.Date" xmlType="xs:dateTime"
parseMethod="org.apache.cxf.xjc.runtime.DataTypeAdapter.parseDateTime"
printMethod="org.apache.cxf.xjc.runtime.DataTypeAdapter.printDateTime"/>
</jxb:globalBindings>
</jxb:bindings>
</jxb:bindings>

How to skip complexType in JAXB bindings

I use JAXB bindings to generate java class from an existing xml schema. But I want to skip class generation for types that endswith "Old" or declare an "obsolete" attribute or contains undescore.
I try, in vain, to modify my JAXB bindings file but I don't know what node write to declare these types skipped...
<!-- skip old types -->
<!-- with ie:obsolete attribute -->
<jaxb:bindings schemaLocation="external/insee/*.xsd">
<jaxb:bindings node="//*[#ie:obsolete='true']">
<!-- declare this type skipped -->
</jaxb:bindings>
</jaxb:bindings>
<!-- that endswith Old -->
<!-- that contains "_" underscore -->
Is there a solution?
Assuming none of the types you process reference these "skipped types", then you could use an external bindings file to specify that they correspond to an existing class so that a new one won't be generated. If these skipped types are referenced then references to this fake class will be brought into your model.
binding.xml
<jxb:bindings
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:jxb="http://java.sun.com/xml/ns/jaxb"
version="2.1">
<jxb:bindings schemaLocation="beta.xsd">
<jxb:bindings node="//xs:element[#name='person']/complexType">
<jxb:class ref="com.FakeClass"/>
</jxb:bindings>
</jxb:bindings>
</jxb:bindings>
Full Example
Shared class for child element in JAXB in different xmls/roots

Categories

Resources