You are viewing a plain text version of this content. The canonical link for it is here.
Posted to user@karaf.apache.org by Steinar Bang <sb...@dod.no> on 2017/05/20 18:25:22 UTC

How do karaf feature dependencies resolve transitive dependencies?

Hi,

I have introduced a new feature into my project https://github.com/steinarb/ukelonn
(the changes haven't been pushed to any branch yet)


The new feature is:
    <feature name="ukelonn-db-liquibase" description="Ukelonn webapp Liquibase change list OSGi bundle" version="1.0.0.SNAPSHOT">
        <bundle start-level="80">mvn:org.yaml/snakeyaml/1.17</bundle>
        <bundle start-level="80">mvn:org.liquibase/liquibase-core/3.5.3</bundle>
        <bundle start-level="80">mvn:no.priv.bang.ukelonn/ukelonn.bundle.db.liquibase/1.0.0-SNAPSHOT</bundle>
    </feature>

The existing feature that has been changed to depend on this feature,
is:
    <feature name="ukelonn-db-derby-test" description="Ukelonn webapp derby test database OSGi bundle" version="1.0.0.SNAPSHOT">
        <feature prerequisite="false" dependency="false">pax-jdbc</feature>
        <feature prerequisite="false" dependency="false">pax-jdbc-derby</feature>
        <feature version="1.0.0.SNAPSHOT" prerequisite="false" dependency="false">ukelonn-api</feature>
        <feature version="1.0.0.SNAPSHOT" prerequisite="false" dependency="false">ukelonn-db-liquibase</feature>
        <bundle start-level="80">mvn:no.priv.bang.ukelonn/ukelonn.bundle.db.test/1.0.0-SNAPSHOT</bundle>
    </feature>

The bundle mvn:no.priv.bang.ukelonn/ukelonn.bundle.db.test/1.0.0-SNAPSHOT
in the second feature uses code from the bundle
mvn:no.priv.bang.ukelonn/ukelonn.bundle.db.liquibase/1.0.0-SNAPSHOT

However it also uses code in the bundle directly mvn:org.liquibase/liquibase-core/3.5.3

Is the above feature dependency enough to ensure that
mvn:no.priv.bang.ukelonn/ukelonn.bundle.db.test/1.0.0-SNAPSHOT can use
mvn:org.liquibase/liquibase-core/3.5.3?

Or do I need to require the bundle
mvn:org.liquibase/liquibase-core/3.5.3 directly in the
ukelonn-db-derby-test feature?

Or do I need to create a third feature that only loads the
mvn:org.liquibase/liquibase-core/3.5.3 and the
mvn:org.yaml/snakeyaml/1.17 bundles and make both of my features depend
on it?

The reason I'm asking is that the above dependency seemed to work at
first, when I test loaded it in karaf, but my karaf based pax exam test
refused to start.

And when I started uninstalling and installing features in various
orders (I usually do that a little to test the robustness of my
features), I ended up with ukelonn-db-derby-test not being able to
start, and the following stack trace in karaf.log:
2017-05-20T19:43:50,156 | ERROR | Karaf local console user karaf | ShellUtil                        | 42 - org.apache.karaf.shell.core - 4.1.1 | Exception caught while executing command
org.apache.karaf.features.internal.util.MultiException: Error restarting bundles
	at org.apache.karaf.features.internal.service.Deployer.deploy(Deployer.java:898) ~[?:?]
	at org.apache.karaf.features.internal.service.FeaturesServiceImpl.doProvision(FeaturesServiceImpl.java:1170) ~[?:?]
	at org.apache.karaf.features.internal.service.FeaturesServiceImpl.lambda$doProvisionInThread$0(FeaturesServiceImpl.java:1069) ~[?:?]
	at java.util.concurrent.FutureTask.run(FutureTask.java:266) [?:?]
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [?:?]
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [?:?]
	at java.lang.Thread.run(Thread.java:748) [?:?]
	Suppressed: org.osgi.framework.BundleException: Activator start error in bundle no.priv.bang.ukelonn.test.db [80].
		at org.apache.felix.framework.Felix.activateBundle(Felix.java:2288) ~[?:?]
		at org.apache.felix.framework.Felix.startBundle(Felix.java:2144) ~[?:?]
		at org.apache.felix.framework.BundleImpl.start(BundleImpl.java:998) ~[?:?]
		at org.apache.felix.framework.BundleImpl.start(BundleImpl.java:984) ~[?:?]
		at org.apache.karaf.features.internal.service.FeaturesServiceImpl.startBundle(FeaturesServiceImpl.java:1281) ~[?:?]
		at org.apache.karaf.features.internal.service.Deployer.deploy(Deployer.java:890) ~[?:?]
		at org.apache.karaf.features.internal.service.FeaturesServiceImpl.doProvision(FeaturesServiceImpl.java:1170) ~[?:?]
		at org.apache.karaf.features.internal.service.FeaturesServiceImpl.lambda$doProvisionInThread$0(FeaturesServiceImpl.java:1069) ~[?:?]
		at java.util.concurrent.FutureTask.run(FutureTask.java:266) [?:?]
		at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [?:?]
		at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [?:?]
		at java.lang.Thread.run(Thread.java:748) [?:?]
	Caused by: java.lang.NoClassDefFoundError: liquibase/exception/DatabaseException
		at java.lang.Class.getDeclaredMethods0(Native Method) ~[?:?]
		at java.lang.Class.privateGetDeclaredMethods(Class.java:2701) ~[?:?]
		at java.lang.Class.getDeclaredMethods(Class.java:1975) ~[?:?]
		at no.steria.osgi.jsr330activator.implementation.ProviderAdapter.findInjections(ProviderAdapter.java:65) ~[?:?]
		at no.steria.osgi.jsr330activator.implementation.ProviderAdapter.<init>(ProviderAdapter.java:39) ~[?:?]
		at no.steria.osgi.jsr330activator.Jsr330Activator.createProviderAdapterList(Jsr330Activator.java:110) ~[?:?]
		at no.steria.osgi.jsr330activator.Jsr330Activator.start(Jsr330Activator.java:51) ~[?:?]
		at org.apache.felix.framework.util.SecureAction.startActivator(SecureAction.java:697) ~[?:?]
		at org.apache.felix.framework.Felix.activateBundle(Felix.java:2238) ~[?:?]
		... 11 more
	Caused by: java.lang.ClassNotFoundException: liquibase.exception.DatabaseException not found by no.priv.bang.ukelonn.test.db [80]
		at org.apache.felix.framework.BundleWiringImpl.findClassOrResourceByDelegation(BundleWiringImpl.java:1550) ~[?:?]
		at org.apache.felix.framework.BundleWiringImpl.access$200(BundleWiringImpl.java:79) ~[?:?]
		at org.apache.felix.framework.BundleWiringImpl$BundleClassLoader.loadClass(BundleWiringImpl.java:1958) ~[?:?]
		at java.lang.ClassLoader.loadClass(ClassLoader.java:357) ~[?:?]
		at java.lang.Class.getDeclaredMethods0(Native Method) ~[?:?]
		at java.lang.Class.privateGetDeclaredMethods(Class.java:2701) ~[?:?]
		at java.lang.Class.getDeclaredMethods(Class.java:1975) ~[?:?]
		at no.steria.osgi.jsr330activator.implementation.ProviderAdapter.findInjections(ProviderAdapter.java:65) ~[?:?]
		at no.steria.osgi.jsr330activator.implementation.ProviderAdapter.<init>(ProviderAdapter.java:39) ~[?:?]
		at no.steria.osgi.jsr330activator.Jsr330Activator.createProviderAdapterList(Jsr330Activator.java:110) ~[?:?]
		at no.steria.osgi.jsr330activator.Jsr330Activator.start(Jsr330Activator.java:51) ~[?:?]
		at org.apache.felix.framework.util.SecureAction.startActivator(SecureAction.java:697) ~[?:?]
		at org.apache.felix.framework.Felix.activateBundle(Felix.java:2238) ~[?:?]
		... 11 more

The bundle containing the missing class liquibase.exception.DatabaseException
is Liquibase core, and that is "Active":
 karaf@root()> bundle:list
 START LEVEL 100 , List Threshold: 50
 ID | State    | Lvl | Version               | Name
 ---+----------+-----+-----------------------+----------------------------------------------------
 28 | Active   |  80 | 4.1.1                 | Apache Karaf :: OSGi Services :: Event
 52 | Resolved |  80 | 10.11.1000001.1616546 | Apache Derby 10.11
 78 | Active   |  80 | 1.0.0.SNAPSHOT        | Ukelonn webapp OSGi service definitions OSGi bundle
 79 | Active   |  80 | 1.0.0.SNAPSHOT        | Ukelonn webapp Liquibase change list OSGi bundle
 80 | Resolved |  80 | 1.0.0.SNAPSHOT        | Ukelonn webapp derby test database OSGi bundle
 81 | Active   |  80 | 3.5.3                 | Liquibase Core
 82 | Active   |  80 | 1.5.0                 | OPS4J Base - Service Provider Access
 83 | Active   |  80 | 1.0.1                 | OPS4J Pax JDBC Generic Driver Extender
 84 | Active   |  80 | 1.0.1                 | OPS4J Pax JDBC Apache Derby Driver Adapter
 85 | Active   |  80 | 1.0.0.201505202023    | org.osgi:org.osgi.service.jdbc
 86 | Active   |  80 | 1.17.0                | SnakeYAML
 karaf@root()>

There's also something strange about Derby here... it wasn't uninstalled
when I uninstalled the feature ukelonn-db-derby-test that has pulled it
in.  However was marked Resolved, and it has stayed Resolved even after
the feature ukelonn-db-derby-test has been reinstalled.


Re: How do karaf feature dependencies resolve transitive dependencies?

Posted by Jean-Baptiste Onofré <jb...@nanthrax.net>.
OK ;)

Thanks for the update.

Regards
JB

On 05/21/2017 10:12 AM, Steinar Bang wrote:
>>>>>> Jean-Baptiste Onofré <jb...@nanthrax.net>:
> 
>> you don't need dependency or prerequisite in that case. Instead you
>> can use just inner feature dependency (transitive) or req/cap.
> 
>> Can I have access to your bundle headers as well ?
> 
> Hi, I just figured out: this wasn't anything related to feature
> dependencies at all.  Sorry about the noise.
> 
> And thanks for responding!
> 
> This was my own home-brewed mini dependency injection system failing
>   https://github.com/sbang/jsr330activator/issues/8
> 
> For now I'm working around this issue by removing the offending
> "throw liquibase.exception.DatabaseException" from the method
> declaration (it wasn't even from an API method.  Just a package private
> method intended for a unit test), and wrapping the code in a try/catch
> retrowing everything wrapped into a RunTime exception.
> 
> (As for why I wrote https://github.com/sbang/jsr330activator in the first
> place:
> 
>   1. Writing activators is boring and rewriting the same code again and
>      again, I wanted annotation based dependency injections (like we had
>      where I worked back in 2006-2008)
>   2. The existing dependency injection implementations (eg. spring DI,
>      eclipse4 DI) had too many dependencies that were mutually exclusive
> 
> According to google nobody else was writing what I wanted so I wrote it
> myself.  And what I wrote was an embeddable Activator implementation
> that uses reflection to find OSGi service dependencies and start and
> register OSGi services.  I tried to make it as small as possible and I
> tried to have as few dependencies as possible.
> 
> And when I find bugs... I get to fix them myself...:-) )
>      
> 

-- 
Jean-Baptiste Onofré
jbonofre@apache.org
http://blog.nanthrax.net
Talend - http://www.talend.com

Re: How do karaf feature dependencies resolve transitive dependencies?

Posted by Steinar Bang <sb...@dod.no>.
>>>>> Jean-Baptiste Onofré <jb...@nanthrax.net>:

> you don't need dependency or prerequisite in that case. Instead you
> can use just inner feature dependency (transitive) or req/cap.

> Can I have access to your bundle headers as well ?

Hi, I just figured out: this wasn't anything related to feature
dependencies at all.  Sorry about the noise.

And thanks for responding!

This was my own home-brewed mini dependency injection system failing
 https://github.com/sbang/jsr330activator/issues/8

For now I'm working around this issue by removing the offending
"throw liquibase.exception.DatabaseException" from the method
declaration (it wasn't even from an API method.  Just a package private
method intended for a unit test), and wrapping the code in a try/catch
retrowing everything wrapped into a RunTime exception.

(As for why I wrote https://github.com/sbang/jsr330activator in the first
place:

 1. Writing activators is boring and rewriting the same code again and
    again, I wanted annotation based dependency injections (like we had
    where I worked back in 2006-2008)
 2. The existing dependency injection implementations (eg. spring DI,
    eclipse4 DI) had too many dependencies that were mutually exclusive

According to google nobody else was writing what I wanted so I wrote it
myself.  And what I wrote was an embeddable Activator implementation
that uses reflection to find OSGi service dependencies and start and
register OSGi services.  I tried to make it as small as possible and I
tried to have as few dependencies as possible.

And when I find bugs... I get to fix them myself...:-) )
    


Re: How do karaf feature dependencies resolve transitive dependencies?

Posted by Jean-Baptiste Onofré <jb...@nanthrax.net>.
Hi Steinar,

you don't need dependency or prerequisite in that case. Instead you can use just 
inner feature dependency (transitive) or req/cap.

Can I have access to your bundle headers as well ?

Regards
JB

On 05/20/2017 08:25 PM, Steinar Bang wrote:
> Hi,
> 
> I have introduced a new feature into my project https://github.com/steinarb/ukelonn
> (the changes haven't been pushed to any branch yet)
> 
> 
> The new feature is:
>      <feature name="ukelonn-db-liquibase" description="Ukelonn webapp Liquibase change list OSGi bundle" version="1.0.0.SNAPSHOT">
>          <bundle start-level="80">mvn:org.yaml/snakeyaml/1.17</bundle>
>          <bundle start-level="80">mvn:org.liquibase/liquibase-core/3.5.3</bundle>
>          <bundle start-level="80">mvn:no.priv.bang.ukelonn/ukelonn.bundle.db.liquibase/1.0.0-SNAPSHOT</bundle>
>      </feature>
> 
> The existing feature that has been changed to depend on this feature,
> is:
>      <feature name="ukelonn-db-derby-test" description="Ukelonn webapp derby test database OSGi bundle" version="1.0.0.SNAPSHOT">
>          <feature prerequisite="false" dependency="false">pax-jdbc</feature>
>          <feature prerequisite="false" dependency="false">pax-jdbc-derby</feature>
>          <feature version="1.0.0.SNAPSHOT" prerequisite="false" dependency="false">ukelonn-api</feature>
>          <feature version="1.0.0.SNAPSHOT" prerequisite="false" dependency="false">ukelonn-db-liquibase</feature>
>          <bundle start-level="80">mvn:no.priv.bang.ukelonn/ukelonn.bundle.db.test/1.0.0-SNAPSHOT</bundle>
>      </feature>
> 
> The bundle mvn:no.priv.bang.ukelonn/ukelonn.bundle.db.test/1.0.0-SNAPSHOT
> in the second feature uses code from the bundle
> mvn:no.priv.bang.ukelonn/ukelonn.bundle.db.liquibase/1.0.0-SNAPSHOT
> 
> However it also uses code in the bundle directly mvn:org.liquibase/liquibase-core/3.5.3
> 
> Is the above feature dependency enough to ensure that
> mvn:no.priv.bang.ukelonn/ukelonn.bundle.db.test/1.0.0-SNAPSHOT can use
> mvn:org.liquibase/liquibase-core/3.5.3?
> 
> Or do I need to require the bundle
> mvn:org.liquibase/liquibase-core/3.5.3 directly in the
> ukelonn-db-derby-test feature?
> 
> Or do I need to create a third feature that only loads the
> mvn:org.liquibase/liquibase-core/3.5.3 and the
> mvn:org.yaml/snakeyaml/1.17 bundles and make both of my features depend
> on it?
> 
> The reason I'm asking is that the above dependency seemed to work at
> first, when I test loaded it in karaf, but my karaf based pax exam test
> refused to start.
> 
> And when I started uninstalling and installing features in various
> orders (I usually do that a little to test the robustness of my
> features), I ended up with ukelonn-db-derby-test not being able to
> start, and the following stack trace in karaf.log:
> 2017-05-20T19:43:50,156 | ERROR | Karaf local console user karaf | ShellUtil                        | 42 - org.apache.karaf.shell.core - 4.1.1 | Exception caught while executing command
> org.apache.karaf.features.internal.util.MultiException: Error restarting bundles
> 	at org.apache.karaf.features.internal.service.Deployer.deploy(Deployer.java:898) ~[?:?]
> 	at org.apache.karaf.features.internal.service.FeaturesServiceImpl.doProvision(FeaturesServiceImpl.java:1170) ~[?:?]
> 	at org.apache.karaf.features.internal.service.FeaturesServiceImpl.lambda$doProvisionInThread$0(FeaturesServiceImpl.java:1069) ~[?:?]
> 	at java.util.concurrent.FutureTask.run(FutureTask.java:266) [?:?]
> 	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [?:?]
> 	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [?:?]
> 	at java.lang.Thread.run(Thread.java:748) [?:?]
> 	Suppressed: org.osgi.framework.BundleException: Activator start error in bundle no.priv.bang.ukelonn.test.db [80].
> 		at org.apache.felix.framework.Felix.activateBundle(Felix.java:2288) ~[?:?]
> 		at org.apache.felix.framework.Felix.startBundle(Felix.java:2144) ~[?:?]
> 		at org.apache.felix.framework.BundleImpl.start(BundleImpl.java:998) ~[?:?]
> 		at org.apache.felix.framework.BundleImpl.start(BundleImpl.java:984) ~[?:?]
> 		at org.apache.karaf.features.internal.service.FeaturesServiceImpl.startBundle(FeaturesServiceImpl.java:1281) ~[?:?]
> 		at org.apache.karaf.features.internal.service.Deployer.deploy(Deployer.java:890) ~[?:?]
> 		at org.apache.karaf.features.internal.service.FeaturesServiceImpl.doProvision(FeaturesServiceImpl.java:1170) ~[?:?]
> 		at org.apache.karaf.features.internal.service.FeaturesServiceImpl.lambda$doProvisionInThread$0(FeaturesServiceImpl.java:1069) ~[?:?]
> 		at java.util.concurrent.FutureTask.run(FutureTask.java:266) [?:?]
> 		at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [?:?]
> 		at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [?:?]
> 		at java.lang.Thread.run(Thread.java:748) [?:?]
> 	Caused by: java.lang.NoClassDefFoundError: liquibase/exception/DatabaseException
> 		at java.lang.Class.getDeclaredMethods0(Native Method) ~[?:?]
> 		at java.lang.Class.privateGetDeclaredMethods(Class.java:2701) ~[?:?]
> 		at java.lang.Class.getDeclaredMethods(Class.java:1975) ~[?:?]
> 		at no.steria.osgi.jsr330activator.implementation.ProviderAdapter.findInjections(ProviderAdapter.java:65) ~[?:?]
> 		at no.steria.osgi.jsr330activator.implementation.ProviderAdapter.<init>(ProviderAdapter.java:39) ~[?:?]
> 		at no.steria.osgi.jsr330activator.Jsr330Activator.createProviderAdapterList(Jsr330Activator.java:110) ~[?:?]
> 		at no.steria.osgi.jsr330activator.Jsr330Activator.start(Jsr330Activator.java:51) ~[?:?]
> 		at org.apache.felix.framework.util.SecureAction.startActivator(SecureAction.java:697) ~[?:?]
> 		at org.apache.felix.framework.Felix.activateBundle(Felix.java:2238) ~[?:?]
> 		... 11 more
> 	Caused by: java.lang.ClassNotFoundException: liquibase.exception.DatabaseException not found by no.priv.bang.ukelonn.test.db [80]
> 		at org.apache.felix.framework.BundleWiringImpl.findClassOrResourceByDelegation(BundleWiringImpl.java:1550) ~[?:?]
> 		at org.apache.felix.framework.BundleWiringImpl.access$200(BundleWiringImpl.java:79) ~[?:?]
> 		at org.apache.felix.framework.BundleWiringImpl$BundleClassLoader.loadClass(BundleWiringImpl.java:1958) ~[?:?]
> 		at java.lang.ClassLoader.loadClass(ClassLoader.java:357) ~[?:?]
> 		at java.lang.Class.getDeclaredMethods0(Native Method) ~[?:?]
> 		at java.lang.Class.privateGetDeclaredMethods(Class.java:2701) ~[?:?]
> 		at java.lang.Class.getDeclaredMethods(Class.java:1975) ~[?:?]
> 		at no.steria.osgi.jsr330activator.implementation.ProviderAdapter.findInjections(ProviderAdapter.java:65) ~[?:?]
> 		at no.steria.osgi.jsr330activator.implementation.ProviderAdapter.<init>(ProviderAdapter.java:39) ~[?:?]
> 		at no.steria.osgi.jsr330activator.Jsr330Activator.createProviderAdapterList(Jsr330Activator.java:110) ~[?:?]
> 		at no.steria.osgi.jsr330activator.Jsr330Activator.start(Jsr330Activator.java:51) ~[?:?]
> 		at org.apache.felix.framework.util.SecureAction.startActivator(SecureAction.java:697) ~[?:?]
> 		at org.apache.felix.framework.Felix.activateBundle(Felix.java:2238) ~[?:?]
> 		... 11 more
> 
> The bundle containing the missing class liquibase.exception.DatabaseException
> is Liquibase core, and that is "Active":
>   karaf@root()> bundle:list
>   START LEVEL 100 , List Threshold: 50
>   ID | State    | Lvl | Version               | Name
>   ---+----------+-----+-----------------------+----------------------------------------------------
>   28 | Active   |  80 | 4.1.1                 | Apache Karaf :: OSGi Services :: Event
>   52 | Resolved |  80 | 10.11.1000001.1616546 | Apache Derby 10.11
>   78 | Active   |  80 | 1.0.0.SNAPSHOT        | Ukelonn webapp OSGi service definitions OSGi bundle
>   79 | Active   |  80 | 1.0.0.SNAPSHOT        | Ukelonn webapp Liquibase change list OSGi bundle
>   80 | Resolved |  80 | 1.0.0.SNAPSHOT        | Ukelonn webapp derby test database OSGi bundle
>   81 | Active   |  80 | 3.5.3                 | Liquibase Core
>   82 | Active   |  80 | 1.5.0                 | OPS4J Base - Service Provider Access
>   83 | Active   |  80 | 1.0.1                 | OPS4J Pax JDBC Generic Driver Extender
>   84 | Active   |  80 | 1.0.1                 | OPS4J Pax JDBC Apache Derby Driver Adapter
>   85 | Active   |  80 | 1.0.0.201505202023    | org.osgi:org.osgi.service.jdbc
>   86 | Active   |  80 | 1.17.0                | SnakeYAML
>   karaf@root()>
> 
> There's also something strange about Derby here... it wasn't uninstalled
> when I uninstalled the feature ukelonn-db-derby-test that has pulled it
> in.  However was marked Resolved, and it has stayed Resolved even after
> the feature ukelonn-db-derby-test has been reinstalled.
> 

-- 
Jean-Baptiste Onofré
jbonofre@apache.org
http://blog.nanthrax.net
Talend - http://www.talend.com