Steven E. Harris wrote:
It took me a day or so to realize that if one starts up Felix with no felix.auto.install or felix.auto.start property specified, no bundles can ever be added, as the only (other) way to install a bundle is with a BundleContext, and the only way to get a BundleContext is with an Activator's start() method. If we agree on that, then at least one bundle must be added at startup for Felix to do anything useful.
This is not entirely accurate. The Felix.start() method accepts a list of BundleActivator instances. These passed in activator instances effectively become part of the system bundle and their start()/stop() methods will be given the system bundle's context so that they can install bundles, register services, etc.
I started experimenting with creating a "root" bundle that's the sole thing specified in felix.auto.start, with this "root" bundle's job being to capture a BundleContext and start up the rest of the application. Several questions arose. Using the felix.auto.(install|start) property causes a bundle to be /installed/ from some URL into the cache. This means that each time the application starts, some files are inspected and copied. If we're talking about an application that will be run over and over, is it sound to think of the cache as durable, meaning that once a bundle is installed, it will be there the next time the program starts up? If so, there's a difference between "seeding" a new cache and starting up a program that's using an already-populated cache. The first mode -- seeding a new cache, or re-seeding an existing cache -- is what's shown in the sample Felix programs. It's easy to understand, but it has a few problems. First, it keeps doing the same inspecting and copying operations every time the program starts. It requires that the startup bundles be sitting somewhere accessible -- either taking up space on the disk, or causing a network connection to reach a remote resource -- even though the program has already installed these bundles in its cache. Finally, it makes the program keep on trying to install bundles with fixed names (including their version number in the examples).
I don't think this explanation (as I understand it) is completely accurate either. The installBundle() operation does not do any extra work (or at least not much) if a bundle is already installed. Installed bundles are indexed by their location, so on startup if the bundles in the autostart property are installed again, the only thing that happens is that the existing bundle object is discovered and returned.
The copying, etc. only happens when you create a new profile.
To avoid these problems, would it make sense to deliver a Felix-based application with pre-populated cache? The set of bundles normally specified in the felix.auto.(install|start) properties would be in the cache, perhaps along with the their dependencies.
Yes, I think it makes sense to deliver Felix-based applications with a pre-populated cache. However, this just depends. For some applications, you the user may be able to select different configurations when they start. The launcher in that case may select a set of bundles to autostart based on the selected configuration, etc. But both approaches could make sense depending on your application.
Maybe the best approach would be if the program could behave differently depending on whether it's being started up with no cache (creating one afresh) versus an existing cache. In the first case, it would seed the cache with a few bundles, while in the second case it wouldn't bother trying, assuming the necessary bundles are already installed.
This pretty much happens already, since nothing is done if you try to install a bundle a second time.
This could work if most of the bundles normally specified in the felix.auto.(install|start) property were available on the disk as a repository. The "root" bundle could start up and attempt to resolve some initial requirements with a RepositoryAdmin and a Resolver, deploying resources to satisfy any unmet requirements. Well, but in order to even have a RepositoryAdmin, we'd need to have the OBR bundle installed. Chicken-and-egg problem.
In the end, you cannot get around the issue that something has to be installed in the framework. It can either be bundles using the autostart properties or it can be a custom launcher that uses some other mechanism to load bundles, such as the system bundle activator approach mentioned above.
-> richard