Libraries
A library is a bundle without internal state and should therefore have no components or Bundle Activator. A good library provides an API to do certain tasks but all observable state is maintained in instance variables and never in statics. Libraries should be started like all bundles but will not act differently whether they are started or not because they lack state. Libraries never register or use services.
The purpose of a library is to provide convenience functions for a specific area. Libraries do not provide substitution.
The second technique to reduce dependency hell is to separate an Application Programmer Interfaces (API) from the implementation, even if there will only be a single implementation for this API ever.
The bnd tool contains a nifty feature that it inherited from old school C. In those days, the link phase searched for missing symbols in libraries and automatically included those functions from the library in your code. This was called static linking. Neil Bartlett wrote a blog about the subject.
The -conditionalpackage instruction performs a similar function for packages.
--
You received this message because you are subscribed to the Google Groups "bndtools-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to bndtools-user...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
On 6 Mar 2017, at 10:32, i...@openfokus.org wrote:So this implies, if I undertand correctly that, for the Library type of "component" , as described on the osgi enroute website,
1) wrap the entire library as explained for Dom4j
2) write an api project that exposes what you need from this library ( as little as possible ). compile-only
3) write a provider project that implements this api and that has the wrapped lib from step 1) on the buildpath. The provider package exports the api from step 2) and nothing else.
4) if this library is also useful to test implementation code of other bundles , that is as part of junit code, write a mock implementation for the api in step 2) so that it can be used outside a framework
Hmm, I think I still don't get it. In step 4 , I need a _production_ version of the wrapped lib, not a mock. Its like using something from the jdk, or apache commons or whatever in the traditional way. Only that I want to use my osgi-wrapped version with its tightly controlled api.
class JunitTest {
private Framework fw = ....
ILibraryApi lib = fw.getService(ILibraryApi.class);
@Test public void test() {
lib.function() ;
.....
On 8 Mar 2017, at 14:20, i...@openfokus.org wrote:Hm, that's weird, are there restrictions on what can be posted ( hyperlinks, source code ) ?.
Anyway, many thanks for the code example. When I run it on my test bundle, I get:
extras:
1) org.jdom2,org.jdom2.input,org.jdom2.output,
2) softbrix.lib.type.common;version=1.0.0,
softbrix.lib.type.fs;version=1.0.0,
softbrix.lib.h;version=1.0.0,
3) softbrix.xml.lib.api;version=null,
4) softbrix.xml.lib.impl
1) (org.jdom2) is the external lib I want to wrap and it is referenced only in the private package section.
It should , I think, not be part of the extras, because it will never be used from outside of the bundle.
2) softbrix contains classes that I use to wrap other libraries. Has no dependencies.
3) this is the api of the new library that wraps 1). The "api" package is in the export package section.
4) this is the impl of the new library and is in the private package section. It should not be part of the extras.
So it seems that this extra package list is not exactly what I want. Only 2) and 3) should be part of it.
In the sample you sent, you use the "Import" section ( in getExtras()) .
In my current test implementation, I use the export section.
For the above bundle this is:
Export-Package: softbrix.xml.lib.api;version="1.0.0";
uses:=“softbrix.lib.type.common,softbrix.lib.type.fs,softbrix.lib.type.io,softbrix.lib.type.list,softbrix.lib.type.result"
From this I computed the extras:
softbrix.xml.lib.api;version="1.0.0", softbrix.lib.type.common;version="1.0.0", softbrix.lib.type.fs;version="1.0.0", softbrix.lib.type.io;version="1.0.0", softbrix.lib.type.list;version="1.0.0", softbrix.lib.type.result;version="1.0.0"
This works sometimes. The problem seems to be that if I instantiate a type
in the private section, that is not part of the export section, I get errors like these :
java.lang.LinkageError: loader constraint violation:
when resolving method "softbrix.lib.fpj.result.R.map(Lsoftbrix/lib/fpj/common/F;)Lsoftbrix/lib/fpj/result/R;"
the class loader (instance of org/apache/felix/framework/BundleWiringImpl$BundleClassLoaderJava5) of the current class,
robobrix/template/lib/impl/SimpleTemplate,
and the class loader (instance of sun/misc/Launcher$AppClassLoader) for the method’s defining class,
While I think that I understand what the error means, I don't know if there exists a necessary and sufficient condition that garantees that this error
never occurs - other than using the import super set which seems to be too large.
I can then fix this error by manually adding the missing types to the exports. But this is not satisfying because I only
discover this at runtime.
So as it stands, it seems to me, that using the imports - as you do in your sample - results in too many extras, but is this a problem ?
On the other hand, relying on the exports may result in LinkageErrors which is certainly a problem.
So using the imports is the way to go ?
On 9 Mar 2017, at 11:00, i...@openfokus.org wrote:Ok, many thanks, I think I got it. I'll continue to work based on the code you posted.
I try to familarize myself with the bnd java api, in particular the Analyzer class.