Frequently Asked Questions
Description: How to Ask a Question Too Many Imports Remove unwanted imports Importing Default Package Why No Automatic Bundle-Activator How to set the unbind method with @Reference? packageinfo or package-info.java Why are super classes not inspected for annotations? Where do the exported package versions come from? Should I use the Bundle-ClassPath? What Should I use instead of the Bundle-ClassPath? Sharing CNF Folder and bnd Projects
Date: 2019-10-12T20:27:56-04:00

- Supported by OSGi enRoute

- # Frequently Asked Questions

  - How to Ask a Question
  - Too Many Imports
  - Remove unwanted imports
  - Importing Default Package
  - Why No Automatic Bundle-Activator
  - How to set the unbind method with @Reference?
  - packageinfo or package-info.java
  - Why are super classes not inspected for annotations?
  - Where do the exported package versions come from?
  - Should I use the Bundle-ClassPath?
  - What Should I use instead of the Bundle-ClassPath?

  - ## Sharing CNF Folder and bnd Projects

  ## How to ask a question

  You can send a mail to bndtools users or mail me.

  ## Too Many Imports

  Sometimes bnd reports imports that seem plain wrong. Believe me, they are almost always right. bnd does a thorough analysis of the byte codes in your class files and when it imports something it is almost sure to be a reference in your code. How can you find the culprit? Bndtools has tooling to drill down into your code. bnd also can print out the JAR and look at the `[USEDBY]` section to find the package(s) that cause the import.

  If there is no package using the imported package, then look at the following places for imports:

  - Spring/Blueprint XML
  - Bundle Activator
  - Component annotations or Service-Component headers

  In the likely case the import is real but unwanted, look at Unwanted Imports.

  ## Importing the default package error

  This usually indicates that:

  - You include classes that have compile errors. Some compilers still create class files on errors but they are invalid.
  - One of the imports caused by Spring, Blueprint, or Service Components are not proper.

  ## Remove unwanted imports

  If you have an unwanted import than you can remove it from the Import-Package manifest header with the ‘!’ operator:

      Import-Package: !com.unwanted.reference.*, *

  A usually better way is to make the imports optional:

      Import-Package: com.unwanted.reference.*;resolution:=optional, *

  Note the end at the Import-Package statement, that wildcard ‘*’ is crucial for remaining imports, see No Imports Show Up.

  ## No Imports Show Up

  The imports that show up in your Import-Package manifest header are controlled by the bnd file’s Import-Package instruction. In bnd, the list is a set of patterns that are sequentially applied to your imports as calculated by bnd from the classes, resources, and headers in the JAR.

  The default Import-Package bnd instruction is:

      Import-Package: *

  This imports all referred packages. The most common reasons imports do not appear in the manifest is that the default is overridden and the overrider forgot to add the wildcard ‘*’ at the end. For example, the following is wrong:

      Import-Package: com.example; version=1.2

  This will create an import for com.example but it ignores all other imports.

  Another reason is the exclude operator (‘!’) that will remove imports. If this is too wild, then no imports are left to insert in the manifest. So the following leads to no imports for any package starting with com.example.

      Import-Package: !com.example.*, *

  Last but not least, look at the `[USEDBY]` section of the JAR print out, make sure there are actually references.

  ## Why No Automatic Bundle-Activator

  Many people are surprised that bnd does not automatically calculate the Bundle-Activator. Basically, there are the following issues:

  - Not all bundles have a bundle activator
  - Detecting an activator in the code does not always mean you want one
  - Detecting means you can find more than one

  That said, it is possible to automate the Bundle-Activator:

      Bundle-Activator: \
         ${classes;IMPLEMENTS;org.osgi.framework.BundleActivator}

  However, if there are multiple Bundle-Activators you will get an error.

  ## How to assign an unbind method to a @Reference?

  `@Reference` automatically sets the bind method but how is the unbind method set? Simple, you use a method with a similar name:

  bind | unbind
  --- | ---
  setX | unsetX
  addX | removeX

  For example:

      @Reference
      protected void setFoo(LogService l) { ... }
      protected void unsetFoo(LogService l) { ... }

  If you want to override this, use

      @Reference(unbind="IRefuseToCallMyMethodUnFoo");
      protected void foo(LogService l) {}
      protected void IRefuseToCallMyMethodUnFoo(LogService l) {}

  Unfortunately Java has no method references so it is not type safe.A non existent `@UnReference` annotation is not very useful because that still requires linking it up symbolically to the associated `@Reference`.

  ## packageinfo or package-info.java?

  Inspired by the osgi-dev thread Why default version for Export-Package is 0.0.0, not bundle version? I’m just a little bit confused about the bnd approach with the file naming “packageinfo”. The JLS already defines “package-info.java” for package relevant infos. Wouldn’t it be simplier (less complex) to have only one file for package definitions? So, the bnd tool could manage the package version in “package-info.java”, too.

  You can use either file. The reason there are two options is that one constituency thinks annotations are the only solution and the other is running pre Java 5 … Basically if I would have to choose it would be packageinfo because that works anywhere but I expect that you probably would not like that :-)

  ## Why are superclass not inspected for Component annotations?

  Annotations are not inherited form the component’s super classes. The problem is that bnd cannot in all cases can see super classes (and interfaces) because the super class does not have to be available in the build. In runtime you are sure the super class is there, at build time you do not have that luxury. So to make sure, always define your annotations on the actual component class.

  ## Can’t find the source of the version on an Export-Package?

  If no explicit export version is specified in the bnd file then bnd will look in the following places.

  - packageinfo file in the package directory (recommended)
  - package-info.java, bnd’s Version annotation
  - Manifest of the exporting JAR

  There was a mis-feature in an older version of the maven plugin that appended the pom version to the exported packages. It looked professional but it was baloney. Versioning a bundle should not version a package automatically, try it and feel the pain. So if you can’t find the source of an exported package version you might have an old maven bundle plugin.

  ## Should I use the Bundle-ClassPath?

  No. It creates unnecessary complexity, it is slower, and it is not necessary. It will also not be compatible with techniques like PojoSR, something that the OSGi is looking into standardizing.

  ## What should I use instead of the Bundle-ClassPath?

  Just use Private-Package and Export-Package, know what goes into your JAR. If you really need to wrap one or more JARs, use the Include-Resource instruction, it has an option to unroll a JAR resource (see @ option. This will copy all its contents in the target JAR. The -exportcontents can then be used to export selected packages. Even better is of course to know

  ## Sharing CNF Folder and BNDTools Projects

  The [Best Practices section[1] provides some good tips about how you setup workspaces that share some information.

  If an entry is wrong, send a mail with the JAR that has the problem. Preferably as small as possible.