我有一个由多个模块组成的Eclipse Maven项目,其中一些模块包含我想为(使用Jaxb)生成类的Xml模式。我的项目布局如下:
schemas\core (pom)
schemas\core\types (jar)
schemas\vehicle (pom)
schemas\vehicle\automobile (jar)
schemas\vehicle\civic (jar)
包含架构的项目是:
schemas\core\types (xsd\types.xsd)
schemas\vehicle\automobile (xsd\automobile.xsd)
schemas\vehicle\civic (xsd\civic.xsd)
某些模块包含从其他模块导入模式的模式:
automobile.xsd imports types.xsd
civic.xsd imports types.xsd, automobile.xsd
由于模式位于不同的项目中,因此我使用类路径目录解析器和目录文件来解析模式的位置。
cars 项目依赖于 types 项目中的模式。以下是其目录文件( catalog.xml )中的条目:
<rewriteSystem systemIdStartString="http://schemas/core/types/" rewritePrefix="classpath:xsd/" />
请注意使用 classpath:xsd / 告诉目录解析程序在类路径中查找模式。
我还使用剧集来防止在 cars 项目中重新生成 types 中的类。这是来自 pom.xml 的snippit:
<plugin>
<groupId>org.jvnet.jaxb2.maven2</groupId>
<artifactId>maven-jaxb2-plugin</artifactId>
<version>0.8.3</version>
<configuration>
<episodes>
<episode>
<groupId>schemas.core</groupId>
<artifactId>types</artifactId>
<version>1.0-SNAPSHOT</version>
</episode>
<episodes>
<catalog>src/main/resources/catalog.xml</catalog>
<catalogResolver>org.jvnet.jaxb2.maven2.resolver.tools.ClasspathCatalogResolver</catalogResolver>
<extension>true</extension>
....
当我在汽车项目上运行 mvn clean install 时,一切正常。在类路径上解析模式 types.xsd ,最终生成类。
我遇到问题的地方是尝试编译项目 civic 。
civic 项目取决于 types.xsd 和 automobile.xsd 。我使用目录文件( catalog.xml )来定义模式的位置:
<rewriteSystem systemIdStartString="http://schemas/core/types/" rewritePrefix="classpath:xsd/" />
<rewriteSystem systemIdStartString="http://schemas/vehicle/automobile/" rewritePrefix="classpath:xsd/" />
我使用剧集来防止重新生成类。以下是来自 pom.xml 的 civic 的snippit:
<plugin>
<groupId>org.jvnet.jaxb2.maven2</groupId>
<artifactId>maven-jaxb2-plugin</artifactId>
<version>0.8.3</version>
<configuration>
<episodes>
<episode>
<groupId>schemas.core</groupId>
<artifactId>types</artifactId>
<version>1.0-SNAPSHOT</version>
</episode>
<episode>
<groupId>schemas.vehicle</groupId>
<artifactId>automobile</artifactId>
<version>1.0-SNAPSHOT</version>
</episode>
</episodes>
<catalog>src/main/resources/catalog.xml</catalog>
<catalogResolver>org.jvnet.jaxb2.maven2.resolver.tools.ClasspathCatalogResolver</catalogResolver>
<extension>true</extension>
...
当我尝试在 civic 项目上运行 mvn clean install 时,我遇到了问题。它抱怨无法解决公共/系统ID。以下是我收到的一些错误消息:
Could not resolve publicId [null], systemId [jar:file:/_m2repository/schemas/vehicle/automobile/1.0-SNAPSHOT/automobile-1.0-SNAPSHOT.jar!http://schemas/core/types/types.xsd]
[ERROR] Error while parsing schema(s).Location [].
com.sun.istack.SAXParseException2;
IOException thrown when processing "jar:file:/_m2repository/schemas/vehicle/automobile/1.0-SNAPSHOT/automobile-1.0-SNAPSHOT.jar!http://schemas/core/types/types.xsd".
Exception: java.net.MalformedURLException: no !/ in spec.
....
由于某些原因,在尝试从汽车项目中解析jar文件时,找不到 types.xsd 。
有谁知道为什么会这样?
谢谢。
注意 - 我正在尝试打算让事情发挥作用,我确实找到了一种方法。如果我从 pom.xml 文件中删除剧集我不再收到错误,但是,项目 civic 最终会使用依赖模块中的所有类型(这是我想通过使用剧集来避免的事情。
如果您想查看每个项目的完整 catalog.xml 和 pom.xml 文件,请参阅以下链接:
类型:http://pastebin.com/Uym3DY6X
答案 0 :(得分:2)
此处maven-jaxb2-plugin
的作者。
我只有0.10.0
版maven-jaxb2-plugin
maven-jaxb2-plugin
版。此版本修复了与报告的问题相关的released问题。
这实际上不是maven-jaxb2-plugin
中的错误,而是XJC本身的一个问题(或者更好地说几个问题):
当目录和绑定文件一起使用时,这些问题会导致问题。这也是Maven工件解决在某些情况下无法正常工作的原因。
在0.10.0版本中,我已经为JAXB-1044和JAXB-1045实现了变通方法。我会尝试通过拉取请求将补丁发送到XJC,但是你知道,我不确定,Oracle的人是否会接受我的PR。
在REWRITE_SYSTEM "http://www.ab.org" "maven:org.jvnet.jaxb2.maven2:maven-jaxb2-plugin-tests-MAVEN_JAXB2_PLUGIN-82-a:jar::!"
我现在已经实施了非常可靠的解决方法。请在此处查看此测试项目:
https://java.net/jira/browse/JAXB-1046
这正是您想要的:通过目录和Maven解析器将模式解析为来自另一个工件的资源。基本上,这改写:
mvn -X
现在工作正常。
如果出现问题 <schemas>
<schema>
<url>http://www.w3.org/1999/xlink.xsd</url>
</schema>
</schemas>
<schemaIncludes/>
<bindings>
<binding>
<dependencyResource>
<groupId>${project.groupId}</groupId>
<artifactId>w3c-schemas</artifactId>
<resource>globalBindings.xjb</resource>
<version>${project.version}</version>
</dependencyResource>
</binding>
</bindings>
<catalogs>
<catalog>
<dependencyResource>
<groupId>${project.groupId}</groupId>
<artifactId>w3c-schemas</artifactId>
<resource>catalog.cat</resource>
<version>${project.version}</version>
</dependencyResource>
</catalog>
</catalogs>
并检查输出,您还会在日志中看到目录解析器的语句。这可能会给你提示,什么不起作用。
这是另一个项目,它使用模式,绑定和目录本身来自一个中心工件:
https://github.com/highsource/maven-jaxb2-plugin/tree/master/tests/MAVEN_JAXB2_PLUGIN-82
来自POM的片段:
REWRITE_SYSTEM "http://www.w3.org" "maven:org.hisrc.w3c:w3c-schemas:jar::!/w3c"
目录:
<jaxb:bindings schemaLocation="http://www.w3.org/1999/xlink.xsd" node="/xs:schema">
<jaxb:schemaBindings>
<jaxb:package name="org.hisrc.w3c.xlink.v_1_0"/>
</jaxb:schemaBindings>
</jaxb:bindings>
结合:
w3c-schemas
所以这一切是如何运作的:
http://www.w3.org/1999/xlink.xsd
中。maven:org.hisrc.w3c:w3c-schemas:jar::!/w3c/1999/xlink.xsd
。/w3c/1999/xlink.xsd
。 (w3c-schemas
jar中有maven-jaxb2-plugin
个资源。jar:...
传递到)“真实”网址,该网址将是w3c-schemas
指向dependencyResource
内资源的{{1}}网址本地存储库中的工件JAR。答案 1 :(得分:0)
我有同样的问题。模式C导入B和A,B导入A.为A,works,B生成源也很好,对于C,弹出MalformedUrlException。
我仍在调查错误,但解决方法是使用systemIdSuffix(Oasis规范1.1)来匹配systemId并重写它。您需要执行以下操作:
从poms中的插件配置中删除'catalogResolver'元素。
使用以下内容替换“汽车”项目的目录文件的内容:
<systemSuffix systemIdSuffix="types.xsd" uri="maven:schemas.core:types!/types.xsd"/>
使用以下内容替换'civic'项目的目录文件的内容:
<systemSuffix systemIdSuffix="types.xsd" uri="maven:schemas.core:types!/types.xsd"/>
<systemSuffix systemIdSuffix="automobile.xsd" uri="maven:schemas.vehicle:automobile!/automobile.xsd"/>
请告诉我这是否适合您。
答案 2 :(得分:0)
我遇到了类似的问题。我使用了here找到的示例项目。
我以两种方式修改了这些项目:
1)拥有一个包含2个命名空间和本地目录文件的A项目。根据此项目B使用B中的A集。
2)拥有A项目,B项目和C项目。 B依赖A和C依赖B。
在这两种情况下,我都得到了与你相同的例外情况。但我开始意识到情况2发生了什么。
这是例外: com.sun.istack.SAXParseException2;处理“jar:file:/Users/sjaak/.m2/repository/org/tst/b-working/1.0/b-working-1.0.jar!http://www.a1.org/a1/a1.xsd”时抛出IOException。例外:java.net.MalformedURLException:no!/ in spec。
因此,它在构建项目C时尝试解析相对于项目B的名称空间http://www.a1.org/a1/a1.xsd。我将问题追溯到com.sun.tools.xjc.reader.internalizerAbstractReferenceFinderImpl,方法startElement。
我使用的解决方案是调整org.jvnet.jaxb2.maven2:maven-jaxb2-plugin。我使用了他们的MavenCatalogResolver(如上所述的默认值)并进行了一些小改动,根本没有提供整个systemId:jar:file:/Users/sjaak/.m2/repository/org/tst/b-working/1.0/ b-working-1.0.jar!http://www.a1.org/a1/a1.xsd,但不要使用只提供感叹号后部分的模式进行解析。
以下是代码:
package org.jvnet.jaxb2.maven2.resolver.tools;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.text.MessageFormat;
import org.jvnet.jaxb2.maven2.DependencyResource;
import org.jvnet.jaxb2.maven2.DependencyResourceResolver;
import com.sun.org.apache.xml.internal.resolver.CatalogManager;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class MavenCatalogResolver extends
com.sun.org.apache.xml.internal.resolver.tools.CatalogResolver {
private final static Pattern PTRN = Pattern.compile("^jar:file:(.*).jar!(.*)$");
public static final String URI_SCHEME_MAVEN = "maven";
private final DependencyResourceResolver dependencyResourceResolver;
private final CatalogManager catalogManager;
public MavenCatalogResolver(CatalogManager catalogManager,
DependencyResourceResolver dependencyResourceResolver) {
super(catalogManager);
this.catalogManager = catalogManager;
if (dependencyResourceResolver == null) {
throw new IllegalArgumentException(
"Dependency resource resolver must not be null.");
}
this.dependencyResourceResolver = dependencyResourceResolver;
}
@Override
public String getResolvedEntity(String publicId, String systemId)
{
String result;
Matcher matcher = PTRN.matcher(systemId);
if (matcher.matches())
{
result = super.getResolvedEntity(publicId, matcher.group(2));
}
else
{
result = super.getResolvedEntity(publicId, systemId);
}
if (result == null) {
return null;
}
try {
final URI uri = new URI(result);
if (URI_SCHEME_MAVEN.equals(uri.getScheme())) {
final String schemeSpecificPart = uri.getSchemeSpecificPart();
try {
final DependencyResource dependencyResource = DependencyResource
.valueOf(schemeSpecificPart);
try {
final URL url = dependencyResourceResolver
.resolveDependencyResource(dependencyResource);
String resolved = url.toString();
return resolved;
} catch (Exception ex) {
catalogManager.debug.message(1, MessageFormat.format(
"Error resolving dependency resource [{0}].",
dependencyResource));
}
} catch (IllegalArgumentException iaex) {
catalogManager.debug.message(1, MessageFormat.format(
"Error parsing dependency descriptor [{0}].",
schemeSpecificPart));
}
return null;
} else {
return result;
}
} catch (URISyntaxException urisex) {
return result;
}
}
}
这实际上解决了我的问题。我会调查一下。我觉得可能会有一些我可以使用的XJC arg,或者目录XML格式提供了更多的可能性。
希望它有所帮助。