You can use the bnd discourse site mail list or mail me.
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:
In the likely case the import is real but unwanted, look at Unwanted Imports.
This usually indicates that:
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.
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.
Many people are surprised that bnd does not automatically calculate the Bundle-Activator. Basically, there are the following issues:
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.
@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
.
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 :-)
Annotations are not inherited from the component’s super classes by default. The problem is that super classes from imported packages may be different at runtime than they were at build time. So it is always best to declare your annotations on the actual component class. Alternatively you can use the instruction -dsannotations-options: inherit
. Then bnd will use DS annotations found in the class hierarchy of the component class. This will not work for the @Component
annotation itself; it will not be inherited from super classes causing a subclass to suddenly be a component.
If no explicit export version is specified in the bnd file then bnd will look in the following places.
The use of the bundle version is a rather bad idea, packages should be versioned independently. It is possible to not use the bundle version for a package with:
-nodefaultversion true
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.
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
The Best Practices section 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.