osgidependency-managementapache-karafkarafapache-servicemix

Retrieving every dependencies with Karaf Maven Plugin and create Karaf Archive


I'm using ServiceMix 6.1.0 (containing Karaf 3.0.5) and I have a Maven project. I want to create a Karaf Archive (.kar) using karaf-maven-plugin.

I understood the goal of using a Karaf Archive : retrieving every dependencies so that the .kar can be deployed in an offline environment. Well... I thought I had understood... After creating .kar and deploying it, I get an error :

Error executing command: Can't install feature karafMavenPlugin/0.0.0:
Could not start bundle mvn:org.testng/testng/6.8.8 in feature(s) karafMavenPlugin-0.0.1-SNAPSHOT: 
Unresolved constraint in bundle org.testng [371]: 
Unable to resolve 371.0: 
missing requirement [371.0] osgi.wiring.package; (osgi.wiring.package=org.junit)

Here is the pom.xml :

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>test</groupId>
  <artifactId>karafMavenPlugin</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>kar</packaging>
  <name>TestKarafMavenPlugin</name>

    <build>
        <plugins>
            <!-- Plugin to create .kar -->
            <plugin>
                <groupId>org.apache.karaf.tooling</groupId>
                <artifactId>karaf-maven-plugin</artifactId>
                <version>3.0.5</version>
                <extensions>true</extensions>
                <configuration>
                    <aggregateFeatures>true</aggregateFeatures>
                    <includeTransitiveDependency>true</includeTransitiveDependency>
                </configuration>
            </plugin>
        </plugins>
        <pluginManagement>
            <plugins>
                <!--This plugin's configuration is used to store Eclipse m2e settings 
                    only. It has no influence on the Maven build itself. -->
                <plugin>
                    <groupId>org.eclipse.m2e</groupId>
                    <artifactId>lifecycle-mapping</artifactId>
                    <version>1.0.0</version>
                    <configuration>
                        <lifecycleMappingMetadata>
                            <pluginExecutions>
                                <pluginExecution>
                                    <pluginExecutionFilter>
                                        <groupId>
                                            org.apache.karaf.tooling
                                        </groupId>
                                        <artifactId>
                                            karaf-maven-plugin
                                        </artifactId>
                                        <versionRange>
                                            [3.0.5,)
                                        </versionRange>
                                        <goals>
                                            <goal>
                                                features-generate-descriptor
                                            </goal>
                                        </goals>
                                    </pluginExecutionFilter>
                                    <action>
                                        <ignore></ignore>
                                    </action>
                                </pluginExecution>
                            </pluginExecutions>
                        </lifecycleMappingMetadata>
                    </configuration>
                </plugin>
            </plugins>
        </pluginManagement>
    </build>
    <dependencies>
        <dependency>
            <groupId>org.testng</groupId>
            <artifactId>testng</artifactId>
            <version>6.8.8</version>
        </dependency>
    </dependencies>
</project>

Here is the feature.xml generated :

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<features xmlns="http://karaf.apache.org/xmlns/features/v1.2.1" name="karafMavenPlugin">
    <feature name="karafMavenPlugin" version="0.0.1-SNAPSHOT" description="TestKarafMavenPlugin">
        <bundle>mvn:org.testng/testng/6.8.8</bundle>
        <bundle>wrap:mvn:org.beanshell/bsh/2.0b4</bundle>
        <bundle>mvn:com.beust/jcommander/1.27</bundle>
    </feature>
</features>

Why is the JUnit dependency not retrieved ?

My guess would be that karaf-maven-plugin does not retrieve dependencies in pom.xml which are <optional> or <provided>. Indeed, JUnit is a TestNG's dependency and here is the TestNG's pom.xml (only dependencies) :

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">

  <modelVersion>4.0.0</modelVersion>
  <groupId>org.testng</groupId>
  <artifactId>testng</artifactId>
  <packaging>jar</packaging>
  <name>TestNG</name>
  <version>6.8.8</version>
  <description>TestNG is a testing framework.</description>
  <url>http://testng.org</url>

  <dependencies>
    <dependency>
      <groupId>org.apache.ant</groupId>
      <artifactId>ant</artifactId>
      <version>1.7.0</version>
      <optional>true</optional>
    </dependency>

    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.10</version>
      <optional>true</optional>
    </dependency>

    <dependency>
      <groupId>org.beanshell</groupId>
      <artifactId>bsh</artifactId>
      <version>2.0b4</version>
<!--
      <scope>provided</scope>
-->
    </dependency>

    <dependency>
      <groupId>com.google.inject</groupId>
      <artifactId>guice</artifactId>
      <version>2.0</version>
      <scope>provided</scope>
    </dependency>
    <dependency>
      <groupId>com.beust</groupId>
      <artifactId>jcommander</artifactId>
      <version>1.27</version>
    </dependency>
      <dependency>
        <groupId>org.yaml</groupId>
        <artifactId>snakeyaml</artifactId>
        <version>1.12</version>
      <optional>true</optional>
      </dependency>
  </dependencies>    
</project>

We can see that every dependencies who are not <optional> and not <provided> are retrieved by karaf-maven-plugin.

So... Am I wrong ? Is it an expected behavior ? If it is the case, is there a way to indicate to the karaf-maven-plugin to download every dependencies ?


Solution

  • As described in the maven documentation about scope :

    provided

    This is much like compile, but indicates you expect the JDK or a container to provide the dependency at runtime. For example, when building a web application for the Java Enterprise Edition, you would set the dependency on the Servlet API and related Java EE APIs to scope provided because the web container provides those classes. This scope is only available on the compilation and test classpath, and is not transitive.

    'provided' is not transitive : when asking for maven dependencies through api, the provided dependencies are not retrieved.

    So, in order to work with karaf-maven-plugin, you have to explicitly add this dependency in the pom.