71

Using JAXB to generate XML binding classes.

The schema is based on a set of legacy XML files, and includes this snippet:

<xs:complexType name="MetaType">
    <xs:simpleContent>
        <xs:extension base="xs:string">
            <xs:attribute type="xs:string" name="Name" />
            <xs:attribute type="xs:string" name="Scheme" />
            <xs:attribute type="xs:string" name="Value" />
        </xs:extension>
    </xs:simpleContent>
</xs:complexType>

The 'Value' attribute conflicts with the 'value' property of xs:string, and the code generation fails with the error:

com.sun.istack.SAXParseException2: Property "Value" is already defined. Use &lt;jaxb:property> to resolve this conflict. 
brasskazoo
  • 76,030
  • 23
  • 64
  • 76

7 Answers7

74

The answer lies in making use of JAXB bindings (site-template.xjb):

<bindings xmlns="http://java.sun.com/xml/ns/jaxb"
          xmlns:xsi="http://www.w3.org/2000/10/XMLSchema-instance"
          xmlns:xs="http://www.w3.org/2001/XMLSchema"
          version="2.1">
    <bindings schemaLocation="site-template.xsd" version="1.0">
        <!-- Customise the package name -->
        <schemaBindings>
            <package name="com.example.schema"/>
        </schemaBindings>

        <!-- rename the value element -->
        <bindings node="//xs:complexType[@name='MetaType']">
            <bindings node=".//xs:attribute[@name='Value']">
                <property name="ValueAttribute"/>
            </bindings>
        </bindings>
    </bindings>
</bindings>

The XPath expressions locate the nodes and renames it, thereby avoiding the naming conflict.

Using this bindings XML file, the generated Java class ends up having the desired getValueAttribute() (as well as the getValue()).

brasskazoo
  • 76,030
  • 23
  • 64
  • 76
  • 3
    I had this problem too and this answer solved it, thanks! Would like to add that if you do the Java class generation with Maven jaxb plugin, you can put the xjb file in the same resources directory as the actual XSD file. – Kaitsu Jan 05 '12 at 14:27
  • 1
    Can this solution be used for remote XSDs somehow? I'm getting "is not a part of this compilation." error. Thanks. – tomasb Jul 17 '12 at 12:20
  • 4
    Where should I place this `site-template.xjb` file? – Andremoniy May 27 '15 at 07:14
  • 1
    @Andremoniy put the file anywhere you like then specify it as a command line argument. See the `-b` argument in @rrayasam answer – HairOfTheDog Jan 30 '18 at 22:15
  • What would help here, is some explanation of the binding of the .xjb file to the .xsd – theRiley Mar 10 '21 at 16:24
35

If you want to avoid creating/changing a JAXB bindings file, and you don't mind annotating your XSD, you can add the jxb:property annotation to your attribute's definition, e.g.:

<xs:complexType name="MetaType">
    <xs:simpleContent>
        <xs:extension base="xs:string">
            <xs:attribute type="xs:string" name="Name" />
            <xs:attribute type="xs:string" name="Scheme" />
            <xs:attribute type="xs:string" name="Value">
                <!-- rename property generated by JAXB (avoiding "Value" name conflict) -->
                <xs:annotation>
                    <xs:appinfo>
                        <jxb:property name="valueAttribute"/>
                    </xs:appinfo>
                </xs:annotation>
            </xs:attribute>
        </xs:extension>
    </xs:simpleContent>
</xs:complexType>

with suitable additions to the xs:schema tag:

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
           xmlns:jxb="http://java.sun.com/xml/ns/jaxb"
           jxb:version="2.1">
Gary
  • 4,426
  • 1
  • 22
  • 19
7

Once after xxxx.xjb file is created for duplicate attribute name "value" (duplicate is default 'value' provided by JAXB) as below, run XJC command to create JAXB objects

xjc -p "com.track.doc" -d "C:\JAXBDocuments\prasam\Desktop\JAXB_me\DealerTrace" appSamp.xsd -b xxxx.xjb

appSmp.xsd:-

<xsd:complexType name="range">
    <xsd:simpleContent>
        <xsd:extension base="xsd:string">
             <xsd:attribute name="value" type="xsd:string"/> 
        </xsd:extension>
    </xsd:simpleContent>        
</xsd:complexType>

xxxx.xjb:-

<?xml version="1.0" encoding="UTF-8"?>
<bindings xmlns="http://java.sun.com/xml/ns/jaxb"
          xmlns:xsi="http://www.w3.org/2000/10/XMLSchema-instance"
          xmlns:xs="http://www.w3.org/2001/XMLSchema"
          version="2.1">
    <bindings schemaLocation="appSmp.xsd" version="1.0">

        <schemaBindings>
            <package name="com.track.doc"/>
        </schemaBindings>    
        <bindings node="//xs:complexType[@name='range']">
            <bindings node=".//xs:attribute[@name='value']">
                <property name="valueAttribute"/>
            </bindings>
        </bindings>
    </bindings>
</bindings>
Jin Kwon
  • 20,295
  • 14
  • 115
  • 184
rrayasam
  • 71
  • 1
  • 2
  • Hi, Thanks for the answer. Actually, I am facing the issue so I found this answer and tried to follow the steps provided here: I placed the `appSmp.xsd` and 'xxxx.xjb' files in a directory along with the content provided in this answer. Changed file path and ran the following command: `xjc -p "com.track.doc" -d "path" appSamp.xsd -b xxxx.xjb` still I get the error : ` [ERROR] schema_reference.4: Failed to read schema document '´path/appSamp.xsd', because 1) could not find the document; 2) the document could not be read; 3) the root element of the document is not . unknown location` – BATMAN_2008 Apr 19 '21 at 14:39
1

I had a problem using the solution with Eclipse (tried both Helios SR1 and Juno SR1) and CXF 2.6.3. The solution was similar to what Kaitsu says. Namely the New > Web Service wizard of Eclipse copies the wsdl into the foldre WebContent/wsdl. I had to place the wsdl and the binding file there myself. Otherwise the binding file gave the "is not a part of this compilation" error.

I wasn't able to use an inline schema in the WSDL but it did work with an external schema like in answer #1.

I'm using the CXF Servlet endpoint config option. In my WSDL I have:

<wsdl:port binding="axis2:ConverterSOAP12Binding" name="ConverterSOAP12port_http">
  <soap12:address location="http://localhost/Converter/services/Converter"/>
</wsdl:port>

The wizard generated this into my web.xml, which works ok:

<servlet-mapping>
  <servlet-name>cxf</servlet-name>
  <url-pattern>/services/*</url-pattern>
</servlet-mapping>

But it put this into cxf-servlet.xml:

<jaxws:endpoint xmlns:tns="http://wtp" id="converterporttype"
implementor="wtp.ConverterPortTypeImpl" wsdlLocation="wsdl/Converter.wsdl"
endpointName="tns:ConverterSOAP12port_http" serviceName="tns:Converter"
address="/ConverterSOAP12port_http">
  <jaxws:features>
    <bean class="org.apache.cxf.feature.LoggingFeature" />
  </jaxws:features>
</jaxws:endpoint>

I had to change the address into the full URL, like this:

address="http://localhost:8080/Converter/services/Converter">
1

None of this bindings worked for me, i got this error:

[ERROR] La evaluación de XPath de ".//xs:attribute[@name='Value']" produce un nodo de destino vacío

It produced an empty target node... Then i realized (after 30 minutes of dispair) that my binding was aiming to a complexType instead of an element. The answer was in my xsd file.

Thank you

0

This bindings file mentioned in the other answer did not work for me with CXF 3.0.0. Notice that jaxb namespace has an element "bindings" and so do the namespace jaxws, so we need to declare them:

<?xml version="1.0" encoding="UTF-8"?>
<bindings xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
          xmlns="http://java.sun.com/xml/ns/jaxws"
          xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
          xmlns:xs="http://www.w3.org/2001/XMLSchema"
          wsdlLocation="mesh.wsdl" >
    <bindings node="wsdl:definitions/wsdl:types/xs:schema[...">
        <jaxb:bindings node="./xs:element[@name='Profiles']">
            <jaxb:property name="ProfilesElement"/>
        </jaxb:bindings>
    </bindings>
</bindings>

In my case the schema was already inside the WSDL so I did no have to specify the schemaLocation attribute.

  • This is the one answer here that includes `jaxb:property`, but I don't understand how the answer here relates to the rest of the file. For one thing, I see no `bindings` tag in the WSDL file I'm trying to fix. – JohnK May 26 '17 at 18:33
  • 1
    This XML goes in a .xjb file. This other question has an example: https://stackoverflow.com/questions/23961421 – Constantino Cronemberger May 26 '17 at 19:52
0

you can also use the parameter -XautoNameResolution in the command line and also in the pluggin to let jxc resolve the name if you don´t bother about the name on the classes.