I'm not able to extends an xsd schema from another project.
I've a basemodel.xsd in a jar project (ModelBase:jar), which also contains generated classes via maven-jaxb2-plugin. I'm trying to extends that model in another project (test), using basemodel.xsd as dependency
Here the setup:
basemodel.xsd in ModelBase:jar
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:tnsBaseModel="h-spamfilter-p://it.test.base.model" xmlns:xs="h-spamfilter-p://www.w3.org/2001/XMLSchema" xmlns:jaxb="h-spamfilter-p://java.sun.com/xml/ns/jaxb" targetNamespace="h-spamfilter-p://it.test.base.model" version="1.0" jaxb:version="2.1">
<xs:complexType name="requestBase">
<xs:sequence>
<xs:element name="errorMSG" type="xs:string" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
</xs:schema>
model2.xsd in test:jar
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:tns="h-spamfilter-p://it.test.newmodel" xmlns:tnsBaseModel="h-spamfilter-p://it.test.base.model" xmlns:xs="h-spamfilter-p://www.w3.org/2001/XMLSchema" xmlns:jaxb="h-spamfilter-p://java.sun.com/xml/ns/jaxb"
xmlns:annox="h-spamfilter-p://annox.dev.java.net" targetNamespace="h-spamfilter-p://it.test.newmodel" version="1.0" jaxb:version="2.1"
jaxb:extensionBindingPrefixes="annox">
<xs:import namespace="h-spamfilter-p://it.test.base.model"/>
<xs:complexType name="testInfo">
<xs:complexContent>
<xs:extension base="tnsBaseModel:requestBase">
<xs:sequence>
<xs:element name="body" type="tns:other"/>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
Please note the import without explicit schemaLocation.
test:jar pom:
<plugin>
<groupId>org.jvnet.jaxb2.maven2</groupId>
<artifactId>maven-jaxb2-plugin</artifactId>
<version>0.14.0</version>
<executions>
<execution>
<goals>
<goal>generate</goal>
</goals>
<phase>generate-sources</phase>
</execution>
</executions>
<configuration>
<generateDirectory>${project.build.directory}/generated-sources/annotations/</generateDirectory>
<cleanPackageDirectories>true</cleanPackageDirectories>
<forceRegenerate>true</forceRegenerate>
<schemas>
<schema>
<fileset>
<directory>${project.basedir}/src/main/resources</directory>
<includes>
<include>model2.xsd</include>
</includes>
</fileset>
</schema>
<schema>
<dependencyResource>
<groupId>it.test</groupId>
<artifactId>ModelBase</artifactId>
<version>${modelbase.version}</version>
<resource>basemodel.xsd</resource>
</dependencyResource>
</schema>
</schemas>
</configuration>
</plugin>
mvn -X output:
...
[INFO] dependsURIs (resolved):[file:/Users/computer/Documents/eclipse-workspace/test/src/main/resource/catalog.cat, file:/Users/computer/Documents/eclipse-workspace/test/src/main/resources/model2.xsd, file:/Users/computer/Documents/eclipse-workspace/test/src/main/resources/model2.xsd, jar:file:/Users/computer/.m2/repository/it/test/ModelBase/trunk-SNAPSHOT/ModelBase-trunk-SNAPSHOT.jar!/basemodel.xsd, file:/Users/computer/Documents/eclipse-workspace/test/pom.xml]
[INFO] optionsConfiguration:OptionsConfiguration [specVersion=2.2
generateDirectory=/Users/computer/Documents/eclipse-workspace/test/target/generated-sources/annotations
generatePackage=null
schemaLanguage=null
grammars.systemIds=[file:/Users/computer/Documents/eclipse-workspace/test/src/main/resources/model2.xsd, file:/Users/computer/Documents/eclipse-workspace/test/src/main/resources/model2.xsd, maven:it.test:ModelBase:jar::trunk-SNAPSHOT!/basemodel.xsd]
bindFiles.systemIds=[]
plugins=[]
readOnly=false
packageLevelAnnotations=true
noFileHeader=false
enableIntrospection=false
disableXmlSecurity=true
accessExternalSchema=all
accessExternalDTD=all
contentForWildcard=false
extension=true
strict=true
verbose=true
debugMode=false
arguments=[-episode, /Users/computer/Documents/eclipse-workspace/test/target/generated-sources/annotations/META-INF/sun-jaxb.episode]]
[INFO] The [forceRegenerate] switch is turned on, XJC will be executed.
[INFO] Parsing input schema(s)...
[DEBUG] Resolving publicId [null], systemId [maven:it.test:ModelBase:jar::trunk-SNAPSHOT!/basemodel.xsd].
resolveSystem(maven:it.test:ModelBase:jar::trunk-SNAPSHOT!/basemodel.xsd)
[DEBUG] Parent resolver has resolved publicId [null], systemId [maven:it.test:ModelBase:jar::trunk-SNAPSHOT!/basemodel.xsd] to [null].
[DEBUG] Resolving systemId [maven:it.test:ModelBase:jar::trunk-SNAPSHOT!/basemodel.xsd] as Maven dependency resource.
[DEBUG] Resolved dependency resource [Dependency {groupId=it.test, artifactId=ModelBase, version=trunk-SNAPSHOT, type=jar, classifier=null, resource=basemodel.xsd}] to resource URL [jar:file:/Users/computer/.m2/repository/it/test/ModelBase/trunk-SNAPSHOT/ModelBase-trunk-SNAPSHOT.jar!/basemodel.xsd].
[DEBUG] Resolved systemId [maven:it.test:ModelBase:jar::trunk-SNAPSHOT!/basemodel.xsd] to [jar:file:/Users/computer/.m2/repository/it/test/ModelBase/trunk-SNAPSHOT/ModelBase-trunk-SNAPSHOT.jar!/basemodel.xsd].
[DEBUG] Resolving publicId [h-spamfilter-p://it.test.base.model], systemId [null].
resolvePublic(h-spamfilter-p://it.test.base.model,null)
[DEBUG] Parent resolver has resolved publicId [h-spamfilter-p://it.test.base.model], systemId [null] to [null].
[ERROR] Error while parsing schema(s).Location [ file:/Users/computer/Documents/eclipse-workspace/test/src/main/resources/model2.xsd{1007,50}].
org.xml.sax.SAXParseException: src-resolve: Cannot resolve the name 'tnsBaseModel:requestBase' to a(n) 'type definition' component.
at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.createSAXParseException (ErrorHandlerWrapper.java:203)
at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.error (ErrorHandlerWrapper.java:134)
at com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError (XMLErrorReporter.java:396)
at com.sun.org.apache.xerces.internal.impl.xs.traversers.XSDHandler.reportSchemaErr (XSDHandler.java:4154)
at com.sun.org.apache.xerces.internal.impl.xs.traversers.XSDHandler.reportSchemaError (XSDHandler.java:4137)
at com.sun.org.apache.xerces.internal.impl.xs.traversers.XSDHandler.getGlobalDecl (XSDHandler.java:1684)
at
[DEBUG] Resolving publicId [null], systemId [maven:it.test:ModelBase:jar::trunk-SNAPSHOT!/basemodel.xsd].
resolveSystem(maven:it.test:ModelBase:jar::trunk-SNAPSHOT!/basemodel.xsd)
[DEBUG] Parent resolver has resolved publicId [null], systemId [maven:it.test:ModelBase:jar::trunk-SNAPSHOT!/basemodel.xsd] to [null].
[DEBUG] Resolving systemId [maven:it.test:ModelBase:jar::trunk-SNAPSHOT!/basemodel.xsd] as Maven dependency resource.
[DEBUG] Resolved dependency resource [Dependency {groupId=it.test, artifactId=ModelBase, version=trunk-SNAPSHOT, type=jar, classifier=null, resource=basemodel.xsd}] to resource URL [jar:file:/Users/computer/.m2/repository/it/test/ModelBase/trunk-SNAPSHOT/ModelBase-trunk-SNAPSHOT.jar!/basemodel.xsd].
[DEBUG] Resolved systemId [maven:it.test:ModelBase:jar::trunk-SNAPSHOT!/basemodel.xsd] to [jar:file:/Users/computer/.m2/repository/it/test/ModelBase/trunk-SNAPSHOT/ModelBase-trunk-SNAPSHOT.jar!/basemodel.xsd].
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 3.076 s
[INFO] Finished at: 2023-03-29T10:21:00+02:00
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal org.jvnet.jaxb2.maven2:maven-jaxb2-plugin:0.14.0:generate (default) on project test: Unable to parse input schema(s). Error messages should have been provided. -> [Help 1]
org.apache.maven.lifecycle.LifecycleExecutionException: Failed to execute goal org.jvnet.jaxb2.maven2:maven-jaxb2-plugin:0.14.0:generate (default) on project test: Unable to parse input schema(s). Error messages should have been provided.
at org.apache.maven.lifecycle.internal.MojoExecutor.doExecute2 (MojoExecutor.java:375)
at org.apache.maven.lifecycle.internal.MojoExecutor.doExecute (MojoExecutor.java:351)
at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:215)
at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:171)
at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:163)
at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject (LifecycleModuleBuilder.java:117)
at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject (LifecycleModuleBuilder.java:81)
at org.apache.maven.lifecycle.internal.builder.singlethreaded.SingleThreadedBuilder.build (SingleThreadedBuilder.java:56)
at org.apache.maven.lifecycle.internal.LifecycleStarter.execute (LifecycleStarter.java:128)
at org.apache.maven.DefaultMaven.doExecute (DefaultMaven.java:294)
at org.apache.maven.DefaultMaven.doExecute (DefaultMaven.java:192)
[ERROR]
[ERROR]
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] h-spamfilter-p://cwiki.apache.org/confluence/display/MAVEN/MojoExecutionException
I get Cannot resolve the name 'tnsBaseModel:requestBase' to a(n) 'type definition' component.
,
adding schemaLocation="basemodel.xsd" cause to get [WARNING] Error while parsing schema(s).Location [ file:/Users/computer/Documents/eclipse-workspace/test/src/main/resources/model2.xsd{5,94}]. org.xml.sax.SAXParseException: schema_reference.4: Failed to read schema document 'basemodel.xsd', because 1) could not find the document; 2) the document could not be read; 3) the root element of the document is not <xsd:schema>.
The HiSrc HigherJAXB Maven Plugin is a fork of maven-jaxb2-plugin that can be used to demonstrate this solution (zip). The solution includes a catalog and an episode configuration to generate JAXB classes from basemodel.xsd and model2.xsd where the second schema imports the first schema to extend a complex type named requestBase
and defines an element/type named testInfo
.
A catalog is a logical structure that contains "mapping" information. In order to make optimal use of the information about an XML external resource, there needs to be some interoperable way to map the information in an XML external identifier into a URI reference for the desired resource.
and
An episode file, typically
*META-INF/sun-jaxb.episode*
, is generated by the XJC (XML Schema to Java) compiler. It is a schema bindings file that associates schema types with existing classes. It is useful when you have one XML schema that is imported by other schemas, as it prevents the model from being regenerated. XJC will scan JARs for*.episode files
, then use them as binding files automatically.
This solution (zip) is a stand-alone, multi-module Maven project. You can run the test(s) using:
mvn -Pall,test clean test
mvn -Ptest clean install
cd extend
mvn -Ptest clean test
mvn -Pexec clean compile exec:java
Only the first execution is necessary to demonstrate the solution and this output shows the test results. The other executions provide more insight, as follows:
mvn -Pall,test clean test
This solution contains a top-level POM project with two sub-modules:
base
andextend
. The goal of this first execution is toclean
,compile
andtest
all three projects using the Maven reactor. Note: The reactor keeps all modules on the classpath; thus, theextend
module is able to resolve thebase
module, cleverly.
mvn -Ptest clean install
To resolve the
base
artifact outside of the reactor, you need to install the artifact into your local repository. Note: A profile namedtest
is used to add the SLF4J implementation into the build for its test phase, only.
cd extend
Change to the
extend
sub-module for testing and execution outside of the multi-module reactor.
mvn -Ptest clean test
Perform a clean test using the
test
profile for unit testing.
mvn -Pexec clean compile exec:java
Execute a simple Java application to demonstrate the unmarshalling of this sample TestInfo.xml. Note: The
exec
profile adds the simplelogger.properties and SLF4J implementation into the classpath for this execution only.
Because model2.xsd imports the namespace defined in basemodel.xsd, a catalog.xml is required to resolve the physical location using MavenCatalogResolver.
model2.xsd
...
<xs:import namespace="h-spamfilter-p://it.test.base.model"/>
...
In this case, the namespace
is the public identifier for the catalog's publicId
.
catalog.xml
...
<public
publicId="h-spamfilter-p://it.test.base.model"
uri="maven:org.patrodyne.jvnet:hisrc-higherjaxb-sample-base-extend-base!/basemodel.xsd"
/>
...
The catalog resolves the publicId
to a uri
, the physical location. In this case, the physical location is inside of the base
jar.
Because the base module generates and provides the RequestBase
class, you need to configure the extend module to use the *META-INF/sun-jaxb.episode*
bindings from the base module.
extend/pom.xml
...
<plugin>
<groupId>org.patrodyne.jvnet</groupId>
<artifactId>hisrc-higherjaxb-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>generate</goal>
</goals>
<configuration>
<episodes>
<episode>
<groupId>org.patrodyne.jvnet</groupId>
<artifactId>hisrc-higherjaxb-sample-base-extend-base</artifactId>
</episode>
</episodes>
<!-- Using catalogs to resolve schema URIs in strict mode is known to be problematic and may fail. -->
<strict>false</strict>
<catalog>src/main/resources/catalog.xml</catalog>
</configuration>
</execution>
</executions>
</plugin>
...
Important: You must configure the plugin to use your catalog.xml file!
The multi-module Maven project generates these JAXB classes, where TestInfo.java
extends RequestBase.java
:
base/target/generated-sources/xjc
├── h_spamfilter_p
│ └── it_test_base
│ ├── ObjectFactory.java
│ ├── package-info.java
│ └── RequestBase.java
└── META-INF
└── sun-jaxb.episode
extend/target/generated-sources/xjc
├── h_spamfilter_p
│ └── it_test
│ ├── ObjectFactory.java
│ ├── package-info.java
│ └── TestInfo.java
└── META-INF
└── sun-jaxb.episode
The JUnit test classes, RequestBaseTest and TestInfoTest, scan for the sample file(s) and invoke the method checkSample(File sample)
to provide each file to the tester. For this project, a JAXBContext
is created and each file in the samples path is unmarshaled to a base-extend
object. When successful, the base-extend
object is marshaled for logging and your review.
Disclaimer: I am the maintainer for the forked HiSrc projects.