我有一个 Maven 存储库,可以在其中加载 Jena TDB 0.9.3(取决于 Jena ARQ 2.9.3)、Jersey 1.8 和 RMOnto 1.0 。正如您所期望的,重点是对语义数据集进行一些分析。
看起来 RMOnto 内置了 ARQ 2.8.7,如“硬连线”中所示。其 pom 文件中没有任何显式依赖项,但 jar 文件包含 ARQ.class
。这非常棘手,因为您不会通过 Maven Enforcer Plugin 等注意到它。
看起来这会导致 Jersey 使用 RMOnto 的 ARQ 版本,而不是 pom.xml 中定义的版本。这是minimal example 。当您运行测试时(检查 ARQ.VERSION 是否等于 2.9.3),它会成功。当您构建项目并将其部署在 Tomcat 7 上时,您应该会看到 2.8.7 作为输出。
- 这种行为是否符合预期?原因是什么?
- 如何强制 Jersey 使用 ARQ 2.9.3?
- 万一不可能,能否隔离 RMOnto 使用 2.8.7,而其余源则使用 2.9.3?
提前致谢!
最佳答案
您应该首先在依赖项列表中定义 ARQ 2.9.3。通过这样做,您可以强制您的构建使用该特定版本。在选择要使用的 Artifact 时,依赖顺序是相关的。
更新
好的,我明白问题所在了。
- RMOnto jar 根据 pom 明显有阴影:http://semantic.cs.put.poznan.pl/maven/put/semantic/RMOnto/1.0/RMOnto-1.0.pom .
- Tomcat 7 以未定义的顺序加载
WEB-INF/lib
中的 jar。这意味着,即使您将 ARQ 2.9.3 定义为依赖项中的第一个,当应用程序在 Tomcat 中运行时,情况也不会如此。 http://tomcat.apache.org/tomcat-7.0-doc/class-loader-howto.html - 好的一点是,Tomcat 总是在
WEB-INF/lib
之前先在WEB-INF/classes
中查找依赖项。
因此,您可以采取的解决方法是确保将 ARQ 2.9.3 版本添加到 WEB-INF/classes
文件夹中。这可以使用 maven-dependency-plugin
来完成:
<build>
<plugins>
<plugin>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<phase>prepare-package</phase>
<goals>
<goal>unpack</goal>
</goals>
<configuration>
<artifactItems>
<artifactItem>
<groupId>org.apache.jena</groupId>
<artifactId>jena-arq</artifactId>
<version>2.9.3</version>
<outputDirectory>${project.build.directory}/classes</outputDirectory>
<excludes>**/META-INF/</excludes>
</artifactItem>
</artifactItems>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
您的 war 以及爆发的 war 现在将包含 WEB-INF/classes
文件夹中 ARQ 2.9.3 中的所有类。它们将在 WEB-INF/lib
文件夹中的任何 jar 文件之前加载。
注意:我还没有在 Tomcat 上测试过这个,但我看不出它不起作用。
NB2:这是一个黑客行为。最好的办法是从 RMOnto jar 中删除 ARQ 包。
关于Maven:强制 Jersey 使用特定的 Artifact 版本,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13237405/