简体   繁体   中英

JAXB class generation for Amazon Product.xsd not working

When generating Java classes from the Products.xsd using JAXB and it's maven plugin I get the following warnings and errors

org.xml.sax.SAXParseException; systemId: https://images-na.ssl-images-amazon.com/images/G/01/rainier/help/xsd/release_1_9/amzn-base.xsd; lineNumber: 956; columnNumber: 45; Simple type "ProcessorTypeValues" was not mapped to Enum due to EnumMemberSizeCap limit. Facets count: 744, current limit: 256. You can use customization attribute "typesafeEnumMaxMembers" to extend the limit.
  at com.sun.tools.xjc.reader.xmlschema.ErrorReporter.warning(ErrorReporter.java:88)
...
Error while generating code.Location [ https://images-na.ssl-images-amazon.com/images/G/01/rainier/help/xsd/release_1_9/SWVG.xsd{300,40}].
  org.xml.sax.SAXParseException; systemId: https://images-na.ssl-images-amazon.com/images/G/01/rainier/help/xsd/release_1_9/SWVG.xsd; lineNumber: 300; columnNumber: 40; A class/interface with the same name "generated.BBFCRatingType" is already in use. Use a class customization to resolve this conflict.

After I was able to fix this, I got errors like:

.../target/generated-sources/xjc/generated/Home.java:[2737,45] cannot find symbol
  symbol:   class Home
  location: class generated.Home.ProductType
.../target/generated-sources/xjc/generated/Home.java:[2929,23] class generated.Home is already defined in package generated

I've seen many questions concerning this while googling, but no one proposed a proper solution.

After a day of analyzing the problems and solving them step by step I got it to work.

To my opinion the XSDs are not very consistent, they contain for example multiple element declarations that could be summarized in a common XSD and some elements have a hierachy which contain elements with the same name.

The XSDs are not invalid but do not comply to Java conventions in some ways, when using JAXBs default settings.

One solution is, to keep the XSDs locally and to just comment out the conflicting parts an then generate classes. But I wanted to generate the classes using the provided URLs, so this did not work for me.

So I'll post my solution here, perhaps it helps somebody:

The generation is done via maven-jaxb2-plugin in the pom.xml , so this part reads (my target package is defined as com.amazon.product , you can change it to what you like):

<plugins>
...
 <plugin>
    <groupId>org.jvnet.jaxb2.maven2</groupId>
    <artifactId>maven-jaxb2-plugin</artifactId>
    <version>0.8.1</version>
    <executions>
      <execution>
        <goals>
          <goal>generate</goal>
        </goals>
        <configuration>
          <schemas>
            <schema>
              <url>https://images-na.ssl-images-amazon.com/images/G/01/rainier/help/xsd/release_1_9/Product.xsd</url>
            </schema>
          </schemas>
        </configuration>
        <id>jaxb-generate-amazon</id>
      </execution>
    </executions>
    <configuration>
      <catalogResolver>org.jvnet.jaxb2.maven2.resolver.tools.ClasspathCatalogResolver</catalogResolver>
      <generatePackage>com.amazon.product</generatePackage>
      <generateDirectory>${project.build.directory}/generated-sources/xjc</generateDirectory>
      <verbose>true</verbose>
      <removeOldOutput>false</removeOldOutput>
      <clearOutputDir>false</clearOutputDir>
      <forceRegenerate>true</forceRegenerate>
    </configuration>
 </plugin>
...
<plugins>

My bindig.xjb in the resource folder reads:

  <bindings
    xmlns="http://java.sun.com/xml/ns/jaxb" 
    xmlns:xsi="http://www.w3.org/2000/10/XMLSchema-instance"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    version="2.1">

  <globalBindings underscoreBinding="asCharInWord" typesafeEnumMaxMembers="9000" typesafeEnumMemberName="generateName"/>

  <bindings schemaLocation="https://images-na.ssl-images-amazon.com/images/G/01/rainier/help/xsd/release_1_9/FoodServiceAndJanSan.xsd" node="//xsd:element[@name='ProductType']/xsd:complexType/xsd:choice/xsd:element[@name='FoodServiceAndJanSan']/xsd:complexType">
    <class name="FoodServiceAndJanSanSub"/>
  </bindings>
  <bindings schemaLocation="https://images-na.ssl-images-amazon.com/images/G/01/rainier/help/xsd/release_1_9/Home.xsd" node="//xsd:element[@name='ProductType']/xsd:complexType/xsd:choice/xsd:element[@name='Home']/xsd:complexType">
    <class name="HomeSub"/>
  </bindings>
  <bindings schemaLocation="https://images-na.ssl-images-amazon.com/images/G/01/rainier/help/xsd/release_1_9/GiftCards.xsd" node="//xsd:element[@name='ProductType']/xsd:complexType/xsd:choice/xsd:element[@name='GiftCard']/xsd:complexType">
    <class name="GiftCardSub"/>
  </bindings>
  <bindings schemaLocation="https://images-na.ssl-images-amazon.com/images/G/01/rainier/help/xsd/release_1_9/MechanicalFasteners.xsd" node="//xsd:element[@name='ProductType']/xsd:complexType/xsd:choice/xsd:element[@name='MechanicalFasteners']/xsd:complexType">
    <class name="MechanicalFastenersSub"/>
  </bindings>
</bindings>

Why do we need this bindings? I'll tell you:

Long enum types result in a WARNING

This is just a warning but it annoyed me. Enums such as ´ProcessorTypeValues` have more entries than the default valid number of 256. You can configure this in the globalBindings:

<globalBindings ... typesafeEnumMaxMembers="1000" .../>

A class/interface with the same name "generated.BBFCRatingType" is already in use.

Amazon for example defines the element types like BBFCRatingType and BBFC_Rating_Type . Unforunately the default config will generate for both a Java class named BBFCRatingType . But two classes in a Java package cannot have the same name. The solution is to tell JAXB to include the underscores:

<globalBindings ... underscoreBinding="asCharInWord" .../>

class generated.Home is already defined in package generated

For example the Home.xsd defines an element called Home as a subelement of ProductType which itself is located in another element, also called Home . The problem is the same as in the previous errors: Two classes with the same name in one package.

We have to give the second class a different name:

<bindings schemaLocation="https://images-na.ssl-images-amazon.com/images/G/01/rainier/help/xsd/release_1_9/Home.xsd" node="//xsd:element[@name='ProductType']/xsd:complexType/xsd:choice/xsd:element[@name='Home']/xsd:complexType">
  <class name="HomeSub"/>
</bindings>

Additional thoughts/improvements

If you want some enums, that cannot be generated automatically, to be real Java enums, you have to force this manually for each one. For example for ProductClothing:

<bindings schemaLocation="xsd/ProductClothing.xsd">
  <bindings node="//xsd:element[@name='VariationData']/xsd:complexType/xsd:sequence">
    <bindings node="./xsd:element[@name='Parentage']/xsd:simpleType">
      <typesafeEnumClass name="Parentage" />
    </bindings>
    <bindings node="./xsd:element[@name='VariationTheme']/xsd:simpleType">
      <typesafeEnumClass name="VariationTheme" />
    </bindings>
  </bindings>
  <bindings node="//xsd:element[@name='ClassificationData']/xsd:complexType/xsd:sequence">
    <bindings node="./xsd:element[@name='ClothingType']/xsd:simpleType">
      <typesafeEnumClass name="ClothingType" />
    </bindings>
    <bindings node="./xsd:element[@name='PerformanceRating']/xsd:simpleType">
      <typesafeEnumClass name="PerformanceRating" />
    </bindings>
    <bindings node="./xsd:element[@name='CupSize']/xsd:simpleType">
      <typesafeEnumClass name="CupSize" />
    </bindings>
    <bindings node="./xsd:element[@name='TargetGender']/xsd:simpleType">
      <typesafeEnumClass name="TargetGender" />
    </bindings>
    <bindings node="./xsd:element[@name='WaterResistanceLevel']/xsd:simpleType">
      <typesafeEnumClass name="WaterResistanceLevel" />
    </bindings>
  </bindings>
</bindings>

Update 22.12.2017

I've created a repository on GitHub containing all necessary binding to get the XSD working with Java.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM