bndtools / bnd

Bnd/Bndtools. Tooling to build OSGi bundles including Eclipse, Maven, and Gradle plugins.
https://bndtools.org
Other
528 stars 306 forks source link

Bundle Activator MyDominoActivator does not implement BundleActivator #1005

Closed frgomes closed 8 years ago

frgomes commented 9 years ago

Seems like bnd does not like when a class extends BundleActivator indirectly.

MyDominoActivator (services.internal)
+-- DominoActivator (domino)
    +-- OsgiContext (domino)
        +-- EmptyBundleActivator (domino)
            +-- BundleActivator (org.osgi.framework)

Please find a project which shows this happening: https://github.com/frgomes/domino-osgi-sample

More details here: https://github.com/frgomes/domino-osgi-sample/issues/1

bjhargrave commented 9 years ago

Is the full type hierarchy visible to bnd via the -buildpath? If bnd cannot see the full hierarchy, then it cannot know if the subclass actually implements BundleActivator.

pkriens commented 9 years ago

a) You should stay away from bundle activators since they are singletons b) You get an error in the build process and in runtime, aren't they related? c) BJ is probably right that bnd cannot see all the super classes?

Can you provide a pointer to where the Domino jar can be found?

frgomes commented 9 years ago

Thanks @bjhargrave for your pointers. I'm sorry for my inability... but I'm trying to figure out what -buildpath means and how it should appear in MANIFEST.MF. I'm using sbt-osgi, so (I guess) I will have to make sbt-osgi support -buildpath.

Well, the page on Wrapping makes me think that -buildpath is just a -classpath. But the page on Testing suggests that -buildpath can be present in the manifest file.

I'm really confused about the details involved. And the devil lives in the details! So, could you provide an example of a MANIFEST.MF which has -buildpath in it (or maybe a -classpath), please?

Thanks a lot.

frgomes commented 9 years ago

Hi Peter,

The jar is in Maven Central but I guess it's easier to ask SBT to retrieve it for you. These are the directions:

$ git clone https://github.com/frgomes/domino-osgi-sample
$ cd domino-osgi-sample
$ ./sbt update  # this will download the Internet
$ find $HOME/.ivy2 -type d -name domino

In my computer, I can find it at

$HOME/.ivy2/cache/com.github.domino-osgi/domino_2.11/bundles/domino_2.11-1.1.0.jar
lefou commented 9 years ago

Domino can be found here: https://github.com/domino-osgi/domino#download The JARs are released to Maven Central.

The issue is only a build-time issue with sbt. The produced JAR is a valid and working bundle.

@pkriens In which way are bundled XML files (DS or BluePrint) less of a singleton nature than bundle activators? After all, the only difference is, that bundle activators need to be compiled and are less transparent for readers without access to the source code. Aren't all current mechanisms (activator, DS, Blueprint) controlled via manifest headers?

djencks commented 9 years ago

I wouldn’t wish blueprint on my worst enemy….

DS components can (depending on their configuration-policy) be configured through config admin, and by using factory configurations you can create multiple (differently-configured) instances. By using bundle or prototype scope you get one instance per using bundle or one instance per service request. In any case due to dependencies or the behavior of the default “delayed” status a DS component instance may come and go many times while the bundle is in the started state. These behaviors are all not available to bundle activators.

thanks david jencks

On Aug 5, 2015, at 7:41 AM, Tobias Roeser notifications@github.com wrote:

Domino can be found here: https://github.com/domino-osgi/domino#domino https://github.com/domino-osgi/domino#domino The JARs are released to Maven Central.

The issue is only a build-time issue with sbt. The produced JAR is a valid and working bundle.

@pkriens https://github.com/pkriens In which way are bundled XML files (DS or BluePrint) less of a singleton nature than bundle activators? After all, the only difference is, that bundle activators need to be compiled and are less transparent for readers without access to the source code. Aren't all current mechanisms (activator, DS, Blueprint) controlled via manifest headers?

— Reply to this email directly or view it on GitHub https://github.com/bndtools/bnd/issues/1005#issuecomment-127968100.

lefou commented 9 years ago

@djencks Thanks for your comment. I have to strongly agree with your opinion about blueprint.

If you will have a look at Domino, than you can see, that all the features you are talking about (maybe exept the "delayed" thing) are also possible with an activator. After all, DS just makes possible what is specified in the spec. And all this is also possible from an activator. Of course, if you talk about a pure dependency-free BundleActivator class, you have to do a lot of coding to get there. Fortunately, if you use the Domino DSL you get very concise activators, which are type safe, compile time validated, and IMHO even easier to read than an equivalent DS XML file. E.g. a config admin driven service factory can look as easy as this: https://github.com/domino-osgi/domino/blob/master/UserGuide.adoc#listen-to-factory-configuration-changes

djencks commented 9 years ago

Hi,

II quickly scanned through the user manual…. ’m not that familiar with scala, unfortunately. It looks to me like you may have produced something more similar to felix dependency manager than DS, although I’m also pretty unfamiliar with DM so this comparison may be totally misguided.

My basic problem with your approach is that instead of an annotated DS component class being pretty much self-documenting and standalone, you’ve put the configuration information into a singleton class in the bundle. It’s really easy to move a DS component to a different bundle. It’s not at all clear to me how you would do that with domino. It’s also pretty easy to understand the dependencies and behavior of an annotated DS component just by looking at the class. While I’m very limited by my limited knowledge of scala, it looks to me like it’s a lot trickier to understand how a domino component relates to its OSGI environment, and not just because the DSL code is in a different class.

Can you come up with a way to at least put the DSL stuff related to a class in that class and not need to write a bundle activator?

You might also want to think about implementing some of the DS R6 capabilities such as configuration through annotations and multiple pid support.

thanks david jencks

On Aug 5, 2015, at 11:10 AM, Tobias Roeser notifications@github.com wrote:

@djencks https://github.com/djencks Thanks for your comment. I have to strongly agree with your opinion about blueprint.

If you will have a look at Domino, than you can see, that all the features you are talking about (maybe exept the "delayed" thing) are also possible with an activator. After all, DS just makes possible what is specified in the spec. And all this is also possible from an activator. Of course, if you talk about a pure dependency-free BundleActivator class, you have to do a lot of coding to get there. Fortunately, if you use the Domino DSL you get very concise activators, which are type safe, compile time validated, and IMHO even easier to read than an equivalent DS XML file. E.g. a config admin driven service factory can look as easy as this: https://github.com/domino-osgi/domino/blob/master/UserGuide.adoc#listen-to-factory-configuration-changes https://github.com/domino-osgi/domino/blob/master/UserGuide.adoc#listen-to-factory-configuration-changes — Reply to this email directly or view it on GitHub https://github.com/bndtools/bnd/issues/1005#issuecomment-128032063.

lefou commented 9 years ago

@djencks Thank you very much for your valuable feedback. It was not my intention to hijack this ticket to discus Domino, though. So here are some final comments. If you are interested in a deeper discussion, I invite you to join the Gitter chat: https://gitter.im/domino-osgi/domino

Of course you have the full power of the prorgamming language and the "capsule" concept in Domino to modularize the bundle setup further, but maybe you also want to split your bundle into parts in such a case.

I most cases I try to keep my domain and business logic free of any OSGi API. Domino (which was not invented by me, btw) fits this approach very well. And because it's code, it's very easy to navigate and refactor the code and bundle configuration.

Regards, Tobias

frgomes commented 9 years ago

sbt-osgi seems to be pretty simple: it just passes strings from the user's build.sbt to bnd. So, I guess the issue is in my build.sbt. But i have pretty scarse knowledge on bnd. @bjhargrave mentioned that "-buildpath" is probably needed, which @pkriens agrees. But my request for more clarification was forgotten along the way. Could someone clarify how "-buildpath" should be passed to bnd? Thanks

frgomes commented 9 years ago

You can see below the MANIFEST.MF produced. Does anyone see something missing? I mean: where -buildpath (or -classpath???) should be specified? Thanks :)

Manifest-Version: 1.0
Bnd-LastModified: 1438863932801
Bundle-Activator: moduleB.internal.MyDominoActivator
Bundle-Description: moduleB
Bundle-ManifestVersion: 2
Bundle-Name: moduleB
Bundle-SymbolicName: com.github.frgomes.domino.moduleb
Bundle-Vendor: com.github.frgomes.domino
Bundle-Version: 0.1.0.SNAPSHOT
Created-By: 1.8.0_45 (Oracle Corporation)
Export-Package: moduleB.api;version="0.1.0.SNAPSHOT"
Import-Package: domino;version="[1.1,2)",scala;version="[2.11,3)",scala.
 reflect;version="[2.11,3)",scala.runtime;version="[2.11,3)",sun.misc;re
 solution:=optional
Private-Package: moduleB.internal
Require-Capability: osgi.ee;filter:="(&(osgi.ee=JavaSE)(version=1.8))"
Tool: Bnd-2.4.0.201411031534
lefou commented 9 years ago

Specifying -classpath in the bnd file is an alternative to specifying it via it's API, e.g. when run as standalone tool. So, it should not be necessary at all. Also, the fact that there is a proper version range for domino package in generated Import-Package is an evidence that the domino jar is seen by bnd.

As an aside, you should restrict the Scala import further to only accept the same minor version, as the Scala bundles do not follow OSGi semantic versioning and treat it as: "epoch.major.minor" instead of "major.minor.micro".

Could you post the full transitive classpath used by sbt?

frgomes commented 9 years ago

These are the dependencies of moduleB (the one which is related to the MANIFEST.MF I've shown before):

[info] com.github.frgomes.domino:moduleb_2.11:0.1-SNAPSHOT [S] [info] +-ch.qos.logback:logback-classic:1.1.3 [info] | +-ch.qos.logback:logback-core:1.1.3 [info] | +-org.slf4j:slf4j-api:1.7.7 [info] | [info] +-com.github.domino-osgi:domino_2.11:1.1.0 [S] [info] | +-org.osgi:org.osgi.compendium:4.3.0 [info] | +-org.osgi:org.osgi.core:4.3.0 [info] | +-org.scala-lang:scala-reflect:2.11.6 [S] [info] | [info] +-com.typesafe.scala-logging:scala-logging_2.11:3.1.0 [S] [info] | +-org.scala-lang:scala-reflect:2.11.1 (evicted by: 2.11.6) [info] | +-org.scala-lang:scala-reflect:2.11.6 [S] [info] | +-org.slf4j:slf4j-api:1.7.7 [info] | [info] +-org.ops4j.pax.logging:pax-logging-api:1.8.3 [info] +-org.osgi:org.osgi.compendium:4.3.0 [info] +-org.osgi:org.osgi.core:4.3.0 [info] +-org.slf4j:log4j-over-slf4j:1.7.7 [info] | +-org.slf4j:slf4j-api:1.7.7 [info] | [info] +-org.slf4j:slf4j-api:1.7.7

rotty3000 commented 8 years ago

I wonder if the recent changes @djencks made to aQute.bnd.component.AnnotationReader.assignable(String, String) could be applied to the BundleActivator check in aQute.bnd.osgi.Verifier.verifyActivator()?

bnd had somewhat weak class hierarchy checking before the change so this issue may potentially be solvable using the same impl.

See https://github.com/rotty3000/bnd/blob/master/biz.aQute.bndlib/src/aQute/bnd/osgi/Verifier.java#L353-L357 Perhaps this block could use a derivation of assignable from aQute.bnd.component.AnnotationReader. https://github.com/rotty3000/bnd/blob/master/biz.aQute.bndlib/src/aQute/bnd/component/AnnotationReader.java#L781-L793

@frgomes would you be capable of testing this? It would be a quick hack to get a bndlib which does this. Not sure how hard it would then be to get sbt-osgi to use that.

pkriens commented 8 years ago

I guess that could should be in Analyzer ...

frgomes commented 8 years ago

@rotty3000 :: Hello, I'm sorry for the long delay.

I've tried to upgrade things like described below:

  1. I've cloned to my workspace the master of sbt-osgi
  2. I've made my local copy of sbt-osgi depend on "biz.aQute.bnd" % "biz.aQute.bndlib" % "3.1.0" from Cloudbees "https://bndtools.ci.cloudbees.com/job/bnd.master/lastSuccessfulBuild/artifact/maven/target/m2"
  3. I've made my sample project depend on this modified version of sbt-osgi.

The same error still persists.

Thanks a lot,

-- Richard

frgomes commented 8 years ago

@pkriens I've upgraded http://github.com/frgomes/sbt-osgi so that it now employs bndlib 3.2.0 Nothing else changed.

Then I've made my sample project employ this modified version of sbt-osgi. https://github.com/frgomes/domino-osgi-sample Nothing else changed.

Now it fails like this below. Seems like it's not able to find SLF4J anymore, despite that it was able to find it before and despite nothing else changed between the two scenarios.

Any idea?

$ sbt clean package osgiBundle
[info] Loading global plugins from /home/richard/.sbt/0.13/plugins
[info] Loading project definition from /home/richard/.sbt/0.13/staging/32961ba36a0bf2582801/sbt-osgi/project
[info] Loading project definition from /home/richard/workspace/domino-osgi-sample/project
[info] Set current project to root (in build file:/home/richard/workspace/domino-osgi-sample/)
java.lang.NoClassDefFoundError: org/slf4j/LoggerFactory
        at aQute.bnd.osgi.Processor.(Processor.java:97)
        at aQute.bnd.osgi.Analyzer.(Analyzer.java:128)
        at aQute.bnd.osgi.Builder.(Builder.java:74)
        at com.typesafe.sbt.osgi.Osgi$.bundleTask(Osgi.scala:38)
        at com.typesafe.sbt.osgi.SbtOsgi$$anonfun$defaultOsgiSettings$1.apply(SbtOsgi.scala:54)
        at com.typesafe.sbt.osgi.SbtOsgi$$anonfun$defaultOsgiSettings$1.apply(SbtOsgi.scala:54)
        at scala.Function8$$anonfun$tupled$1.apply(Function8.scala:35)
        at scala.Function8$$anonfun$tupled$1.apply(Function8.scala:34)
        at scala.Function1$$anonfun$compose$1.apply(Function1.scala:47)
        at sbt.$tilde$greater$$anonfun$$u2219$1.apply(TypeFunctions.scala:40)
        at sbt.std.Transform$$anon$4.work(System.scala:63)
        at sbt.Execute$$anonfun$submit$1$$anonfun$apply$1.apply(Execute.scala:226)
        at sbt.Execute$$anonfun$submit$1$$anonfun$apply$1.apply(Execute.scala:226)
        at sbt.ErrorHandling$.wideConvert(ErrorHandling.scala:17)
        at sbt.Execute.work(Execute.scala:235)
        at sbt.Execute$$anonfun$submit$1.apply(Execute.scala:226)
        at sbt.Execute$$anonfun$submit$1.apply(Execute.scala:226)
        at sbt.ConcurrentRestrictions$$anon$4$$anonfun$1.apply(ConcurrentRestrictions.scala:159)
        at sbt.CompletionService$$anon$2.call(CompletionService.scala:28)
        at java.util.concurrent.FutureTask.run(FutureTask.java:266)
        at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
        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:745)
pkriens commented 8 years ago

We started using SLF4J in the last release. The ‘environment’ like Gradle, Eclipse, SBT, etc. must provide this API. It is I think the ONLY dependency so far in bnd …

Kind regards,

Peter Kriens

On 6 jun. 2016, at 20:08, Richard Gomes notifications@github.com wrote:

I've upgraded http://github.com/frgomes/sbt-osgi https://github.com/frgomes/sbt-osgi so that it now employs bndlib 3.2.0 Nothing else changed.

Then I've made my sample project employ this modified version of sbt-osgi. Nothing else changed.

Now it fails like this below. Seems like it's not able to find SLF4J anymore, despite that it was able to find it before and despite nothing changed between the two scenarios.

Any idea?

$ sbt clean package osgiBundle [info] Loading global plugins from /home/richard/.sbt/0.13/plugins [info] Loading project definition from /home/richard/.sbt/0.13/staging/32961ba36a0bf2582801/sbt-osgi/project [info] Loading project definition from /home/richard/workspace/domino-osgi-sample/project [info] Set current project to root (in build file:/home/richard/workspace/domino-osgi-sample/) java.lang.NoClassDefFoundError: org/slf4j/LoggerFactory at aQute.bnd.osgi.Processor.(Processor.java:97) at aQute.bnd.osgi.Analyzer.(Analyzer.java:128) at aQute.bnd.osgi.Builder.(Builder.java:74) at com.typesafe.sbt.osgi.Osgi$.bundleTask(Osgi.scala:38) at com.typesafe.sbt.osgi.SbtOsgi$$anonfun$defaultOsgiSettings$1.apply(SbtOsgi.scala:54) at com.typesafe.sbt.osgi.SbtOsgi$$anonfun$defaultOsgiSettings$1.apply(SbtOsgi.scala:54) at scala.Function8$$anonfun$tupled$1.apply(Function8.scala:35) at scala.Function8$$anonfun$tupled$1.apply(Function8.scala:34) at scala.Function1$$anonfun$compose$1.apply(Function1.scala:47) at sbt.$tilde$greater$$anonfun$$u2219$1.apply(TypeFunctions.scala:40) at sbt.std.Transform$$anon$4.work(System.scala:63) at sbt.Execute$$anonfun$submit$1$$anonfun$apply$1.apply(Execute.scala:226) at sbt.Execute$$anonfun$submit$1$$anonfun$apply$1.apply(Execute.scala:226) at sbt.ErrorHandling$.wideConvert(ErrorHandling.scala:17) at sbt.Execute.work(Execute.scala:235) at sbt.Execute$$anonfun$submit$1.apply(Execute.scala:226) at sbt.Execute$$anonfun$submit$1.apply(Execute.scala:226) at sbt.ConcurrentRestrictions$$anon$4$$anonfun$1.apply(ConcurrentRestrictions.scala:159) at sbt.CompletionService$$anon$2.call(CompletionService.scala:28) at java.util.concurrent.FutureTask.run(FutureTask.java:266) at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) 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:745) — You are receiving this because you modified the open/close state. Reply to this email directly, view it on GitHub https://github.com/bndtools/bnd/issues/1005#issuecomment-224039927, or mute the thread https://github.com/notifications/unsubscribe/AAMPLtn7XFmj0wOZYeqaSMvZihzQ__ROks5qJGIGgaJpZM4Fep5_.

bjhargrave commented 8 years ago

This is a closed issue. You should open a new issue.

bndlib now uses SLF4J to log, so if you bundle bndlib in a tool, you need to make sure slf4j api is available to class load. This is mentioned in https://github.com/bndtools/bnd/wiki/Changes-in-3.2.0.