Pax Exam 4 和多个 Maven 存储库不工作
Pax Exam 4 and multiple Maven repositories not working
我正在尝试 运行 一个非常基本的 Pax Exam 4 单元测试,但需要访问多个 Maven 存储库(不是 Maven Central)。这是代码:
@RunWith(PaxExam.class)
public class ExamTest {
@Inject
private BundleContext bundleContext;
@Configuration
public Option[] config() {
return options(
repositories(
repository("http://maven.wso2.org/nexus/content/groups/wso2-public").id("wso2"),
repository("http://nexus.codehaus.org/snapshots").id("nexus.public.repo").allowSnapshots(),
),
mavenBundle("commons-httpclient.wso2", "commons-httpclient").version("3.1.0.wso2v2"),
mavenBundle("org.codehaus.woodstox", "stax2-api").version("3.0.1-SNAPSHOT"),
cleanCaches(),
junitBundles()
);
}
@Test
public void testInjection() {
Assert.assertNotNull(bundleContext);
Bundle[] bundles = bundleContext.getBundles();
for (Bundle bundle : bundles) {
System.out.println(bundle.getSymbolicName() + ", state = " + bundle.getState());
}
}
}
实际测试是微不足道的,但只是为了测试目的,所以不要介意(回购协议和库也只是为了测试目的而选择的)。问题是上述方法不起作用,Pax Exam 抱怨存储库 URLs 无效。 运行ning这个测试时输出如下:
[main] ERROR org.ops4j.pax.url.mvn.internal.AetherBasedResolver - invalid repository URLs
java.net.MalformedURLException: no protocol: +http://nexus.codehaus.org/snapshots/
at java.net.URL.<init>(URL.java:585)
at java.net.URL.<init>(URL.java:482)
at java.net.URL.<init>(URL.java:431)
at org.ops4j.pax.url.mvn.internal.config.MavenRepositoryURL.<init>(MavenRepositoryURL.java:191)
at org.ops4j.pax.url.mvn.internal.config.MavenConfigurationImpl.getRepositories(MavenConfigurationImpl.java:303)
at org.ops4j.pax.url.mvn.internal.AetherBasedResolver.selectRepositories(AetherBasedResolver.java:254)
...
如您所见,出于某种原因,在第二个 URL 之前添加了一个“+”,这会导致 MavenConfigurationImpl 中出现异常。奇怪的是,当我调试代码时,第一个 URL 也有一个“+”,但那个被 Pax 代码剥离了。然而,第二个没有被剥离,然后在将字符串传递给 MavenRepositoryURL 构造函数时导致 MalformedURLException:
if (repositoriesProp != null && repositoriesProp.trim().length() > 0) {
String[] repositories = repositoriesProp.split(REPOSITORIES_SEPARATOR);
for (String repositoryURL : repositories) {
repositoriesProperty.add(new MavenRepositoryURL(repositoryURL.trim()));
}
}
现在这对我来说看起来像是一个错误,但我真的不敢相信这样一个基本选项(能够处理多个 Maven 存储库)不起作用,所以我可能做错了什么。所以,我的问题是:如何让 Pax Exam 从多个 Maven 存储库下载 Maven 包?
此外:如果您只添加 1 个存储库,则一切正常,是否使用 repositories() 方法都没有关系。如果像这样多次使用 repository() 方法,结果是一样的:
@Configuration
public Option[] config() {
return options(
repository("http://maven.wso2.org/nexus/content/groups/wso2-public").id("wso2"),
repository("http://nexus.codehaus.org/snapshots").id("nexus.public.repo").allowSnapshots(),
mavenBundle("commons-httpclient.wso2", "commons-httpclient").version("3.1.0.wso2v2"),
mavenBundle("org.codehaus.woodstox", "stax2-api").version("3.0.1-SNAPSHOT"),
cleanCaches(),
junitBundles()
);
}
在显示我正在使用的依赖项(和版本)的 POM 片段下方:
<dependencies>
<dependency>
<groupId>org.osgi</groupId>
<artifactId>org.osgi.core</artifactId>
<version>4.3.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>1.7.10</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.ops4j.pax.exam</groupId>
<artifactId>pax-exam-container-native</artifactId>
<version>4.4.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.ops4j.pax.url</groupId>
<artifactId>pax-url-aether</artifactId>
<version>2.3.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.ops4j.pax.url</groupId>
<artifactId>pax-url-link</artifactId>
<version>2.3.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.ops4j.pax.url</groupId>
<artifactId>pax-url-classpath</artifactId>
<version>2.3.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.ops4j.pax.exam</groupId>
<artifactId>pax-exam-junit4</artifactId>
<version>4.4.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.geronimo.specs</groupId>
<artifactId>geronimo-atinject_1.0_spec</artifactId>
<version>1.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.ops4j.pax.exam</groupId>
<artifactId>pax-exam-link-assembly</artifactId>
<version>4.4.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.eclipse.tycho</groupId>
<artifactId>org.eclipse.osgi</artifactId>
<version>3.7.0.v20110613</version>
<scope>test</scope>
</dependency>
</dependencies>
这只是一个错误。
repository()
选项的 Pax 考试 regression tests 目前不使用多个存储库,显然没有其他人使用过。 (事实上,处理多个外部存储库的首选方法是使用设置为镜像的存储库管理器,这就解释了为什么这个功能可能根本不是那么基本。)
Pax URL mvn: protocol handler 的文档对系统 属性 org.ops4j.pax.url.mvn.repositories
的语法有点太模糊了。它提到了一个前导加号,表示除了来自 Maven settings.xml
的存储库之外,还应使用给定的存储库。
Pax 考试目前为每个存储库添加一个加号,但 Pax URL 预计整个列表最多加一个。
作为解决方法,您可以用系统 属性 选项替换存储库选项,如下所示:
systemProperty("org.ops4j.pax.url.mvn.repositories").value("+repo1,repo2")
注意:"repo1" 和 "repo2" 是您存储库的实际 URL。
这个问题还有另一种解决方案。不是让 Pax 直接与 Maven 存储库交互,而是可以设置构建和单元测试,以便 Maven 构建获取工件。在大多数情况下,单元测试中配置的存储库无论如何也会在 POM 中配置(例如,因为在编译期间也需要工件),因此这也将消除重复配置。
这里描述了解决方案:
我正在尝试 运行 一个非常基本的 Pax Exam 4 单元测试,但需要访问多个 Maven 存储库(不是 Maven Central)。这是代码:
@RunWith(PaxExam.class)
public class ExamTest {
@Inject
private BundleContext bundleContext;
@Configuration
public Option[] config() {
return options(
repositories(
repository("http://maven.wso2.org/nexus/content/groups/wso2-public").id("wso2"),
repository("http://nexus.codehaus.org/snapshots").id("nexus.public.repo").allowSnapshots(),
),
mavenBundle("commons-httpclient.wso2", "commons-httpclient").version("3.1.0.wso2v2"),
mavenBundle("org.codehaus.woodstox", "stax2-api").version("3.0.1-SNAPSHOT"),
cleanCaches(),
junitBundles()
);
}
@Test
public void testInjection() {
Assert.assertNotNull(bundleContext);
Bundle[] bundles = bundleContext.getBundles();
for (Bundle bundle : bundles) {
System.out.println(bundle.getSymbolicName() + ", state = " + bundle.getState());
}
}
}
实际测试是微不足道的,但只是为了测试目的,所以不要介意(回购协议和库也只是为了测试目的而选择的)。问题是上述方法不起作用,Pax Exam 抱怨存储库 URLs 无效。 运行ning这个测试时输出如下:
[main] ERROR org.ops4j.pax.url.mvn.internal.AetherBasedResolver - invalid repository URLs
java.net.MalformedURLException: no protocol: +http://nexus.codehaus.org/snapshots/
at java.net.URL.<init>(URL.java:585)
at java.net.URL.<init>(URL.java:482)
at java.net.URL.<init>(URL.java:431)
at org.ops4j.pax.url.mvn.internal.config.MavenRepositoryURL.<init>(MavenRepositoryURL.java:191)
at org.ops4j.pax.url.mvn.internal.config.MavenConfigurationImpl.getRepositories(MavenConfigurationImpl.java:303)
at org.ops4j.pax.url.mvn.internal.AetherBasedResolver.selectRepositories(AetherBasedResolver.java:254)
...
如您所见,出于某种原因,在第二个 URL 之前添加了一个“+”,这会导致 MavenConfigurationImpl 中出现异常。奇怪的是,当我调试代码时,第一个 URL 也有一个“+”,但那个被 Pax 代码剥离了。然而,第二个没有被剥离,然后在将字符串传递给 MavenRepositoryURL 构造函数时导致 MalformedURLException:
if (repositoriesProp != null && repositoriesProp.trim().length() > 0) {
String[] repositories = repositoriesProp.split(REPOSITORIES_SEPARATOR);
for (String repositoryURL : repositories) {
repositoriesProperty.add(new MavenRepositoryURL(repositoryURL.trim()));
}
}
现在这对我来说看起来像是一个错误,但我真的不敢相信这样一个基本选项(能够处理多个 Maven 存储库)不起作用,所以我可能做错了什么。所以,我的问题是:如何让 Pax Exam 从多个 Maven 存储库下载 Maven 包?
此外:如果您只添加 1 个存储库,则一切正常,是否使用 repositories() 方法都没有关系。如果像这样多次使用 repository() 方法,结果是一样的:
@Configuration
public Option[] config() {
return options(
repository("http://maven.wso2.org/nexus/content/groups/wso2-public").id("wso2"),
repository("http://nexus.codehaus.org/snapshots").id("nexus.public.repo").allowSnapshots(),
mavenBundle("commons-httpclient.wso2", "commons-httpclient").version("3.1.0.wso2v2"),
mavenBundle("org.codehaus.woodstox", "stax2-api").version("3.0.1-SNAPSHOT"),
cleanCaches(),
junitBundles()
);
}
在显示我正在使用的依赖项(和版本)的 POM 片段下方:
<dependencies>
<dependency>
<groupId>org.osgi</groupId>
<artifactId>org.osgi.core</artifactId>
<version>4.3.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>1.7.10</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.ops4j.pax.exam</groupId>
<artifactId>pax-exam-container-native</artifactId>
<version>4.4.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.ops4j.pax.url</groupId>
<artifactId>pax-url-aether</artifactId>
<version>2.3.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.ops4j.pax.url</groupId>
<artifactId>pax-url-link</artifactId>
<version>2.3.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.ops4j.pax.url</groupId>
<artifactId>pax-url-classpath</artifactId>
<version>2.3.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.ops4j.pax.exam</groupId>
<artifactId>pax-exam-junit4</artifactId>
<version>4.4.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.geronimo.specs</groupId>
<artifactId>geronimo-atinject_1.0_spec</artifactId>
<version>1.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.ops4j.pax.exam</groupId>
<artifactId>pax-exam-link-assembly</artifactId>
<version>4.4.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.eclipse.tycho</groupId>
<artifactId>org.eclipse.osgi</artifactId>
<version>3.7.0.v20110613</version>
<scope>test</scope>
</dependency>
</dependencies>
这只是一个错误。
repository()
选项的 Pax 考试 regression tests 目前不使用多个存储库,显然没有其他人使用过。 (事实上,处理多个外部存储库的首选方法是使用设置为镜像的存储库管理器,这就解释了为什么这个功能可能根本不是那么基本。)
Pax URL mvn: protocol handler 的文档对系统 属性 org.ops4j.pax.url.mvn.repositories
的语法有点太模糊了。它提到了一个前导加号,表示除了来自 Maven settings.xml
的存储库之外,还应使用给定的存储库。
Pax 考试目前为每个存储库添加一个加号,但 Pax URL 预计整个列表最多加一个。
作为解决方法,您可以用系统 属性 选项替换存储库选项,如下所示:
systemProperty("org.ops4j.pax.url.mvn.repositories").value("+repo1,repo2")
注意:"repo1" 和 "repo2" 是您存储库的实际 URL。
这个问题还有另一种解决方案。不是让 Pax 直接与 Maven 存储库交互,而是可以设置构建和单元测试,以便 Maven 构建获取工件。在大多数情况下,单元测试中配置的存储库无论如何也会在 POM 中配置(例如,因为在编译期间也需要工件),因此这也将消除重复配置。
这里描述了解决方案: