javamavenpackagingapache-karafkaraf

Can i place third party jars in karaf (any specific folder) to resolve transitive dependencies?


I have various self made projects that have third party libraries dependencies. I am bundling them for OSGI container but unable to resolve deep dependencies in my projects. Now i am looking for karaf folder where i can place my libraries so bundles can directly access them and not to install them.

More over i am using maven too.

EDIT: After following your 'feature' solution i am able to produce manifest containg transitive dependencies but problem is now it also look for very common java files: e.g: below is list of quite big dependencies:

bsh -- Cannot be resolved
com.fasterxml.jackson.annotation -- Cannot be resolved
com.fasterxml.jackson.core -- Cannot be resolved
com.fasterxml.jackson.databind -- Cannot be resolved
com.fasterxml.jackson.databind.annotation -- Cannot be resolved
com.fasterxml.jackson.databind.module -- Cannot be resolved
com.gargoylesoftware.htmlunit -- Cannot be resolved
com.gargoylesoftware.htmlunit.util -- Cannot be resolved
com.google.protobuf -- Cannot be resolved
com.ibm.uvm.tools -- Cannot be resolved
com.ibm.websphere.uow -- Cannot be resolved
com.ibm.wsspi.uow -- Cannot be resolved
com.jamonapi -- Cannot be resolved
com.jamonapi.utils -- Cannot be resolved
com.jayway.jsonpath -- Cannot be resolved
com.jcraft.jzlib -- Cannot be resolved
com.mysema.query.types -- Cannot be resolved
com.sun.javadoc -- Cannot be resolved and overwritten by Boot Delegation
com.sun.jdmk.comm -- Cannot be resolved and overwritten by Boot Delegation
com.sun.net.httpserver -- Cannot be resolved and overwritten by Boot Delegation
com.sun.tools.javadoc -- Cannot be resolved and overwritten by Boot Delegation
com.sun.xml.fastinfoset.sax -- Cannot be resolved and overwritten by Boot Delegation
com.sun.xml.fastinfoset.stax -- Cannot be resolved and overwritten by Boot Delegation
com.typesafe.config -- Cannot be resolved
groovy.lang -- Cannot be resolved
groovy.xml -- Cannot be resolved
javassist -- Cannot be resolved
javax.activation from org.apache.felix.framework (0)
javax.annotation from org.apache.felix.framework (0)
javax.crypto from org.apache.felix.framework (0)
javax.crypto.spec from org.apache.felix.framework (0)
javax.ejb -- Cannot be resolved
javax.el -- Cannot be resolved
javax.enterprise.concurrent -- Cannot be resolved
javax.enterprise.context -- Cannot be resolved
javax.enterprise.context.spi -- Cannot be resolved
javax.enterprise.event -- Cannot be resolved
javax.enterprise.inject -- Cannot be resolved
javax.enterprise.inject.spi -- Cannot be resolved
javax.enterprise.util -- Cannot be resolved

Solution

  • To answer your question: You could drop all your dependency bundles into the $KARAF_HOME/deploy folder and Karaf would deploy them for you.

    However, this is not very convenient as it is a manual process and not driven by Maven. Instead have a look at Karaf's concept of feature repositories. You can use the Karaf maven plugin to create a feature repository for your bundles and their (transitive) dependencies. If you need to ship your application as a single artifact, you can use the same plugin to create a KAR archive, which is zip file that contains both the feature repository and the required dependencies in a self-contained deployment unit.

    To get started put a template feature.xml file into src/main/feature:

    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <features xmlns="http://karaf.apache.org/xmlns/features/v1.3.0" 
            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
            xsi:schemaLocation="http://karaf.apache.org/xmlns/features/v1.3.0 http://karaf.apache.org/xmlns/features/v1.3.0"
            name="My feature">
        <feature name="${project.artifactId}" version="${project.version}" description="Describe feature here">
             <!-- Add "self" to the list of dependencies -->
             <bundle>mvn:${project.groupId}/${project.artifactId}/${project.version}</bundle>
        </feature>
    </features>
    

    Then set up the plugin to populate the feature template based on your maven dependencies:

    <plugin>
        <groupId>org.apache.karaf.tooling</groupId>
        <artifactId>karaf-maven-plugin</artifactId>
        <configuration>
            <includeTransitiveDependency>true</includeTransitiveDependency>
        </configuration>
        <executions>
            <execution>
                <id>generate-features-descriptor</id>
                <goals>
                    <goal>features-generate-descriptor</goal>
                </goals>
            </execution>
        </executions>
    </plugin>
    

    Building your project will create an additional maven artifact together with your bundle jar in your local maven repository: xxx-features.xml You can make a local Karaf aware of your feature repository with the feature:repo-add command. Then add your feature with the feature:install command. This will start your bundle and all its declared (transitive) Maven dependencies.

    EDIT:

    As you mentioned in the comments that some (all?) your dependencies are plain JARs, not OSGi bundles, possibly you are better off embedding those non-OSGi dependencies into your own bundle with the maven-bundle-plugin. This can be quite tedious though. Most non-OSGi JARs have package imports that are either not used during runtime at all, or not used in your specific usage scenario. To avoid blowing up your OSGi dependency list beyond your list of transitive maven dependencies, you then have to prevent those "inherited" packages from being added to the list of package imports in the MANIFEST of your own bundle. E.g., I have a bundle that uses the httl template library, which again depends on Javassist. Neither are OSGi bundles. So I embed both and suppress the import of the packages declared in either the httl or javassist code but not required at runtime:

    <plugin>
        <groupId>org.apache.felix</groupId>
        <artifactId>maven-bundle-plugin</artifactId>
        <extensions>true</extensions>
        <configuration>
            <instructions>
                <Embed-Dependency>*;scope=compile|runtime;inline=false;artifactId=httl|javassist</Embed-Dependency>
                <Embed-Transitive>false</Embed-Transitive>
                <Import-Package>
                    !com.alibaba.*,
                    !com.thoughtworks.*,
                    !javassist.*,
                    !net.htmlparser.*,
                    !org.apache.commons.logging.*,
                    !org.codehaus.jackson.*,
                    !org.joda.convert.*,
                    !com.sun.jdi.*,
                    !javax.servlet.*,
                    *
                </Import-Package>
            </instructions>
        </configuration>
    </plugin>