Using Pax Exam in Maven builds
The recommended approach (see also here) to run OSGi unit tests with Pax Exam in a Maven build relies on the
pax-url-aether
library. This library allows to resolve Maven artifacts and to provision them as bundles to the OSGi
runtime started by Pax Exam. Assuming that the bundles to be provisioned are declared as Maven dependencies in the
project, a typical Pax Exam configuration would look as follows (Note that asInProject()
relies on the execution of
the org.apache.servicemix.tooling:depends-maven-plugin
during the build):
@Configuration
public static Option[] configuration() {
return options(
mavenBundle().groupId("org.example").artifactId("mybundle").version(asInProject()),
junitBundles());
}
While at first glance this looks straightforward and natural, there are a couple of issues with this approach. The
problem is that pax-url-aether
creates its own Maven session to resolve artifacts, thereby bypassing the underlying
Maven build. This means that the resolution performed by Pax Exam doesn’t necessarily use the same configuration as the
Maven build. There are several known circumstances where this causes problems:
-
Repositories configured in the POM. Some have argued that declaring repositories in POMs is discouraged. That argument is correct for repositories containing release artifacts, but not for snapshot repositories: all release dependencies should indeed be available from the central repository, but dependencies on snapshot versions from upstream projects necessarily require configuration of additional repositories. The right place to configure these repositories is in the POM, not in
settings.xml
. -
The location of the local Maven repository (normally specified in
settings.xml
) can be overridden using themaven.repo.local
system property. However, Pax Exam only looks atsettings.xml
. While overriding the local Maven repository on the command line is rarely done when running Maven manually, it is quite common for builds executed by a CI tool. E.g. Jenkins has a “Use private Maven repository” option that does exactly that (with a local repository in the Jenkins workspace). This problem is described in PAXEXAM-543. -
Offline mode. This mode is enabled using the
-o
switch on themvn
command, but Pax Exam has no way to detect this and will continue trying to access remote Maven repositories.
Probably this list is not exhaustive and there are other POM settings that will cause similar problems.
Actually the whole approach of having Pax Exam resolve Maven dependencies on its own is questionable. This is certainly a very useful feature when used outside of a Maven build (e.g. to provision bundles directly from a Maven repository to a stand-alone OSGi container), but in a Maven build, it should be Maven’s responsibility to download artifacts, and Pax Exam’s role should be limited to provisioning them to the embedded OSGi container.
It is indeed possible to set up a project so that artifact downloading is handled exclusively by the Maven build, but this requires the help of a custom Maven plugin to generate a set of link files. Some time ago I developed a plugin that (among other things) is able to generate these files. This plugin is now available in Maven central and I’m using it in several project, e.g. in Apache Axiom. Usage instructions can be found here. Feel free to experiment with it and provide feedback.
Note: A previous version of this article mentioned org.apache.ws.commons.axiom:paxexam-maven-plugin
. That plugin
no longer exists. Please use the plugin described above.