| Bundler Overview |
|
|
|
Bundle Generation is the process of generating bundles from OSGi-incompliant JAR archives. Bundler is an Automatic Bundle Generation utility that is capable of generating bundles at runtime and off-time, it provides an API and a primitive Command Line Interface plus features such as Caching to optimize the Bundle Generation process, and is runnable in OSGi and none-OSGi Environments. The API is simple to use and requires only 3-10 lines of code to generate bundles for a group of JAR archives. Bundler is well tested, stable and proved to work for hundreds of modules including modules for frameworks such as JAX-WS RI, JAXB RI, Axis2, Apache CXF, Toplink, OpenJPA, Hibernate, JAX-RS RI, H2, HSQLDB, MySQL Connector, Drools, etc. and none of the tested frameworks required any custom settings to be bundled and have metadata that allow the generated bundles function correctly in Java Environments JRE and JDK versions 1.5 and 1.6 with the three main OSGi Frameworks, i.e, Equinox, Felix and Knopflerfish. Bundler is very extensible and it contains no single functionality which requires source code modification to be customized, so developers who are interested in building Automatic Bundle Generation Utilities with specific/custom requirements can build their solutions on top of Bundler. While the algorithm used by Bundler handles unlimited number of libraries and frameworks, for those whom it doesn't generate needed metadata developers can apply custom bundle generation settings to help Bundler generate proper bundles. Complex Case ExampleThe archive dynamic-ws-bundler-example.zip contains an example which demonstrates a complex case of an OSGi-based application that consists of 13 bundles and 18 OSGi-incompliant archives to run a Web Service on JAX-WS RI in an OSGi Environment, both bundles and OSGi-incompliant archives depend on each other (use each others packages). The application is run using DA-Launcher to make it simple for you to run it, of course all the Bundle Generation process is handled by Bundler. The example was made so developers could confirm that without a single custom configuration, the application runs in Java Environments JRE and JDK versions 1.5 and 1.6 with the three main OSGi Frameworks, i.e, Equinox, Felix and Knopflerfish. Alhtough I have more than 6 such example applications, each integrates a completely different framework, I choose this one since the specifics of the application represent one of the most complex OSGi-integration scenarios that a developer would have. Bundler compared to other solutionsThe main advantage of the Automatic Bundle Generation approach is that it requires no developer interference to generate functioning bundles, by functioning bundles I mean bundles that are ready to function corretly in OSGi Environments. If you generate bundles on your own using some utility or consume bundled versions of the JAR archives you want from a Bundle Repository you will end up having bundles, but will you have usable bundles? For example, are you sure that they wouldn't cause Package Wiring conflicts or any other metadata related problems? From my own experience, if you want to bundle more than 10 JAR archives then you will mostly run into Package Wiring conflicts. Bundler is all about solving such conflicts, at its first release Bundler applies more than 20 rules only to determine the packages to be exported, imported, shadowed and package versions, many of the rules are rules of thumb that were learned from previous experiences of generating bundles for different kinds of frameworks. The other major advantage of Bundler is that it analyzes the OSGi Environment where the bundles will be used before generating them. The OSGi Environment analysis are required for generating accurate metadata, as you may know, a bundle which doesn't cause package wiring conflicts in a certain OSGi environment can cause them in another depending on the bundles that the other environment contains. Since Bundler is the only solution for dealing with OSGi-incompliant JAR archives that analyzes the OSGi Environment before generating bundles, you can rest assured that no other solution/utility/repository will take into account the specifics of your OSGi Environment to provide you with bundled versions of the needed JAR archives. Unlike Bundle Repositories, when using Bundler you don't have to wait for the latest version of the libraries you need to get supported since you can generate bundled versions of them on the fly without requiring any development or searching efforts from you. How to Use?You can use Bundler either through the API or the Command Line Interface (CLI), just remember that if you use the CLI Bundler will not be able to analyze your OSGi Environment. If you want to run an OSGi Application which contains OSGi-incompliant JAR archives but don't want to waste much time and resources on running it and generating the bundles you can consider using DA-Launcher which allows you to launch OSGi Applications within seconds and uses Bundler to generate the bundles for OSGi-incompliant JAR archives, so running your application would be as simple as copying your files to a certain directory.Bundler APIThe generate method of the BundleGenerator interface accepts BundleGenerationParams and BundleCollectionGenerationParams as parameters for generating bundles. Using BundleGenerationParams you can pass JAR archives by their File references, URLs or their input streams, it's also up to you to set the output to a file or any other output stream. On the other hand BundleCollectionGenerationParams constraints you in the sense that you can only pass JAR archives as file references and the resultive bundles are placed in a directory that you specify, but the main advantage of BundleCollectionGenerationParams is that it supports Caching, so always consider using this option first. The code below demonstrates an example which generates a bundle by passing the BundleGenerationParams object.
import org.dynamicjava.osgi.bundler.BundleGenerator;
import org.dynamicjava.osgi.bundler.BundleGeneratorFactory;
import org.dynamicjava.osgi.bundler.support.BundleGenerationParams;
import ...;
public void test() {
BundleGenerator bundleGenerator =
BundleGeneratorFactory.getDefaultFactory().create(getBundleContext());
BundleGenerationParams params = new BundleGenerationParams(
new File("./input/hello-world.jar") /* input file */,
new File("./output/hello-world-bundle.jar") /* output file */);
/// Some custom settings
params.settings().setGenerateMainMethodInvocationActivator(true);
bundleGenerator.generate(params);
}
protected BundleContext getBundleContext() {
/// Return your Bundle Context here
}
The code below demonstrates an example which generates a bundle by passing the BundleCollectionGenerationParams object.
import org.dynamicjava.osgi.bundler.BundleGenerator;
import org.dynamicjava.osgi.bundler.BundleGeneratorFactory;
import org.dynamicjava.osgi.bundler.support.BundleGenerationParams;
import ...;
public void test() {
BundleGenerator bundleGenerator =
BundleGeneratorFactory.getDefaultFactory().create(getBundleContext());
BundleCollectionGenerationParams params = new BundleCollectionGenerationParams(
new File("./input/") /* input dir */,
new File("./output/") /* output dir */,
true /* enable caching */);
bundleGenerator.generate(params);
}
protected BundleContext getBundleContext() {
/// Return your Bundle Context here
}
The API is clear and simple so you can learn it by simply trying it but if you prefer to check code examples first, you can check the file "src/test/java/org/dynamicjava/osgi/bundler/BundleGeneratorTest.java" which contains tests on all of the functionalities provided by Bundler except of the BundleCollectionGenerationParams case.
If you use Bundler from your bundle (inside the OSGi Environment), don't forget to import these packages:org.dynamicjava.osgi.bundler org.dynamicjava.osgi.bundler.support org.dynamicjava.osgi.bundler.exceptions Bundler CLIBundle CLI accepts only two parameters as system properties: input.dir and output.dir. The input.dir parameter must point to the directory which contains your JAR archives and output.dir the directory where generated bundles will be placed. Below is an example command which runs Bundler CLI: > java -jar -Dinput.dir=./input -Doutput.dir=./output bundler-1.0.0.jar Bundler CLI with an example can be downloaded from here.Bundle Generation SettingsYou can customize the Bundle Generation process by providing Bundler with custom settings. Below are available settings.
You also can customize the generation process by setting your own values for manifest headers. The way you customize the settings and manifest headers depends on whether you are using the API or CLI. If you pass the BundleGenerationParams as an argument to the generate then you can set the settings using the setSettings method of the BundleGenerationParams class and the headers using the setManifestHeaders method. If you pass the BundleCollectionGenerationParams to the generate method or you use the CLI then you need to provide a Properties file for any JAR archive you want to customize, the Properties file must have the same name of the JAR archive but with .properties extension instead of .jar, e.g., the custom settings file for ./input/hello-world.jar must have this path ./input/hello-world.properties. The property names of settings values must be prefixed with settings. and manifest headers with header., e.g., settings.importAllPackages and header.Bundle-Activator. The CLI application contains an example where a Properties file is used. What if it does not work?Bundler was tested against different complex integration scenarios to make sure that it handles any possible case, but needless to say that there will always be some rare cases that it can't handle completely, for such cases you can use either custom settings or setting your own values for manifest headers which will surely work though it will require some additional effort from you. If you would have such cases, whether you solve them or not, please let us know of them so we could update the rule base to handle your case also, for that we will need a detailed info of your OSGi Environment, the bundles it contains and the packages they export. |