julaudo julaudo - 1 month ago 19
Java Question

JAXB type is already defined

I'd like to call ISAN Restful API from my Java project, so I'm trying to generate java beans from xsd files using maven-jaxb2-plugin.
Here are the xsds:



I downloaded theses files and copied them into my src/main/resources folder.
Here is my plugin configuration from pom.xml:

<plugins>
<plugin>
<groupId>org.jvnet.jaxb2.maven2</groupId>
<artifactId>maven-jaxb2-plugin</artifactId>
<version>0.12.3</version>
<configuration>
<schemaDirectory>src/main/resources</schemaDirectory>
</configuration>

<executions>
<execution>
<id>isan</id>
<goals>
<goal>generate</goal>
</goals>
<configuration>
<generatePackage>org.isan</generatePackage>
<generateDirectory>${project.build.directory}/generated-sources/isan</generateDirectory>
</configuration>
</execution>
</executions>
</plugin>


Now the plugin is telling me that some types are defined multiple times. For example :


03/11/2016 16:42:53 UTC+1: [ERROR] Error while parsing schema(s).Location [ file:/D:/isan/isan/src/main/resources/common.xsd{51,37}]. 'DurationType' is already defined
03/11/2016 16:42:53 UTC+1: [ERROR] Error while parsing schema(s).Location [ http://www.isan.org/schema/v1.11/common/common.xsd{46,38}]. (related to above error) the first definition appears here


I understand this is because each type is defined in my local file and in the remote file. One solution seem to be using catalogs (https://github.com/highsource/maven-jaxb2-plugin/wiki/Using-Catalogs), but it doesn't seem to work.

I added this catalog in "src/main/resources:"

PUBLIC "http://www.isan.org/schema/v1.11/common/common.xsd" "./common.xsd"
PUBLIC "http://www.isan.org/schema/v1.11/common/country.xsd" "./country.xsd"
PUBLIC "http://www.isan.org/schema/v1.11/common/externalid.xsd" "./externalid.xsd"
PUBLIC "http://www.isan.org/schema/v1.11/common/isan.xsd" "./isan.xsd"
PUBLIC "http://www.isan.org/schema/v1.11/common/language.xsd" "./language.xsd"
PUBLIC "http://www.isan.org/schema/v1.11/common/participant.xsd" "./participant.xsd"
PUBLIC "http://www.isan.org/schema/v1.11/common/serial.xsd" "./serial.xsd"
PUBLIC "http://www.isan.org/schema/v1.11/common/title.xsd" "./title.xsd"
PUBLIC "http://www.isan.org/schema/v1.11/common/version.xsd" "./version.xsd"

REWRITE_SYSTEM "http://www.isan.org" "isan"


and modified the plugin configuration:

<configuration>
<strict>false</strict>
<catalog>src/main/resources/catalog.cat</catalog>
<generatePackage>org.isan</generatePackage>
<generateDirectory>${project.build.directory}/generated-sources/isan</generateDirectory>
</configuration>


I'm still getting the same errors

Answer

You're hitting this bug:

https://java.net/jira/browse/JAXB-1045

The problem is that when XJC uses a catalog file it ultimately associates resolved URLs with namespaces, not original ones. This leads to this weird error that the same type is reported to be defined several times.

The solution is to use the catalog (as you do) but compile absolute URLs instead of local files. In this case all your schemas will have original URLs.

So this is how you do it:

Create a local copy of schema files. I've found it better to duplicate the directory structure on the server. So you'll have something like:

isan
  schema
    v1.11
      common
        common.xsd
        version.xsd
        title.xsd
        externalid.xsd
        participant.xsd
        language.xsd
        country.xsd
    v1.21
      common
        serial.xsd
  ISAN
    isan.xsd

Write a catalog file to rewrite the absolute URL:

REWRITE_SYSTEM "http://www.isan.org" "isan"

Use this catalog and compile your schemas from absolute URLs like:

<strict>false</strict>
<catalog>src/main/resources/catalog.cat</catalog>
<schemas>
    <schema>
        <url>http://www.isan.org/schema/v1.11/common/common.xsd</url>
    </schema>
    <schema>
        <url>http://www.isan.org/schema/v1.21/common/serial.xsd</url>
    </schema>
    <!-- ... -->
</schemas>

You probably only need only a few URLs as schemas probably import one another.

One problem which you may encounter is when schema use both relative URLs and absolute URLs in xs:import. Relative URLs will be resolved into local URLs, so you get the same problem. In this case I had to patch schemas to make all of them only use absolute URLs.

Here's a couple of projects you can check for this kind of setup:

Check schemas module for patched/prepared schemas. Other modules compiles schemas from absolute URLs but using a catalog which rewrites absolute URLs into resources in this schemas module.

Here's the catalog file:

REWRITE_SYSTEM "http://www.w3.org" "maven:org.hisrc.w3c:w3c-schemas:jar::!/w3c"

Here's a snippet from pom.xml of one of the modules:

<schemas>
    <schema>
        <url>http://www.w3.org/2007/06/wsdl/wsdl20.xsd</url>
    </schema>
    <schema>
        <url>http://www.w3.org/2007/06/wsdl/http.xsd</url>
    </schema>
    <schema>
        <url>http://www.w3.org/2007/06/wsdl/rpc.xsd</url>
    </schema>
    <schema>
        <url>http://www.w3.org/2007/06/wsdl/soap.xsd</url>
    </schema>
    <schema>
        <url>http://www.w3.org/2007/06/wsdl/wsdl20-extensions.xsd</url>
    </schema>
    <schema>
        <url>http://www.w3.org/2007/06/wsdl/wsdl20-instance.xsd</url>
    </schema>
</schemas>