1

I have a dynamic application that uses OSGi to load modular functionality at runtime. OSGi bundles contain the modular functionality and the application loads the bundles when they are needed. This approach works okay, but I would like a more granular solution. The bundles contain components controlled through Declarative Services. I'd like to be able to load a bundle, and only enable the components that are needed within the bundle. I've done research in this area, but cannot find a solution that I'm satisfied with. One approach was to create a "gatekeeper" component that is always enabled in the bundle and through the ComponentContext let it call enable and disable component. It's a viable solution, but I could not figure out a way for the "gatekeeper" to "know about" the other components in the bundle without hard coding the component names as properties in the "gatekeepers" SCR xml descriptor.

What I prefer is a way to load bundles and "know about" all components within the loaded bundles. Be able to determine what bundle the components are located in and what state they are currently in (similar to the equinox console command 'ls' that lists out all components). I would like to enable and disable the components when needed.

How does the console do this and how could I do this in an application?

Update: @Neil Bartlett: Sorry for the delay. I had to move on to something else. Now I'm back on this issue. Really would appreciate any further assistance. My application is role based. I need to enable components based on the functionality they provide. The goal is for all role based components to initially be disabled. Upon role change, a role manager polls each component for its provided functionality and determines whether to load it. Each component will broadcast what functionality it provides (through a common service interface). ScrService will not allow me to enable an initially disabled service component. Having the components initially enabled and let ScrService disable them as soon as possible during application startup does not fit my needs.

Toolshed
  • 21
  • 6
  • Yes the gatekeeper needs to know the IDs of the components it wishes to enable/disable. Bear in mind that you can also pass `null` to enable/disable *all* other components in the bundle. Also as you probably know, the gatekeeper can only access the other components in the same bundle, not any other bundle. The suggestion from "forty-two" to use the ScrService is a good one. – Neil Bartlett Nov 12 '11 at 17:03
  • @Toolshed Did you finally solve this? I have the same issue with ScrService. – Pablo García Feb 05 '14 at 16:19
  • @PabloGarcía Ended up with a very messy implementation that required a custom scr xml parser. It worked okay, but was far from ideal and worked for my custom needs. – Toolshed Dec 17 '14 at 15:20

3 Answers3

1

Have a look at ScrService. Bothe equinox and felix has it.

However, components can be made to load lazily, i.e. only when needed by other components/bundles; but that is perhaps not what you want.

forty-two
  • 12,204
  • 2
  • 26
  • 36
  • ScrService is exactly what I need. This will allow me to dynamically enable and disable components as needed. – Toolshed Nov 13 '11 at 06:23
  • After using the ScrService, I've found an issue that I can't get past. I can enable and disable components externally (not within the same bundle) only if the component is initially enabled. I have the need for components to be initially disabled and then enabled when needed. This will not work. If a component is initially disabled it displays (from debug) an unsatisfied state. If the component is unsatisfied it cannot be enabled. Is this a bug? Surely that's not the intent. – Toolshed Nov 15 '11 at 21:21
  • Example output: osgi> ls -c 21 Components in bundle Test: ID Component details 37 Component[ name = test.TestImpl activate = activate deactivate = deactivate modified = configuration-policy = ignore factory = null autoenable = false immediate = true implementation = test.TestImpl **state = Unsatisfied** properties = serviceFactory = false serviceInterface = [java.util.Comparator] references = null located in bundle = Test_1.0.0 [21] ] Dynamic information : **The component is satisfied** All component references are satisfied Component configurations : – Toolshed Nov 15 '11 at 21:37
  • @Toolshed: I hadn't considered that implication but now you describe it, it makes sense. A component that is disabled should not be "forced" from the outside into an enabled state; only a component internal to the bundle (i.e. the "gatekeeper") can know whether it's possible to enable it. I think it would be useful at this point to step back and describe at a higher level what you're trying to achieve, it may be that there is an alternative and more elegant solution. – Neil Bartlett Nov 16 '11 at 02:29
0

I have a similar issue, but for a different purpose: - I have apache file install and configuration admin service to configure my components externally with property files. - I needed to make sure that some components get the config from the outer file and the only way I've found so far is that I mark my components with ConfigurationPolicy.REQUIRED. - But that way my plugin projects doesn't run in eclipse (where there are no config files). - The component.xml also contains a default development configuration so I'm okay with that, just my component doesn't start until there is a config data avalilable with configadmin. My components ar unsatisfied this way, until someone creates a configadmin entry. - I figured out that if I create a osgi command line extender that sends empty configurations to service pid's they would start up with default values in component.xml files. - I just came here to find a way to list all bundles

But I think this solution I use can also work with your setup and that's why I write this. Just mark all your components with the configurtationpolicy.require and you can selectively start and stop them with adding and removing configurations with configadmin. This could be hard if you already use the configadmin for other purposes too, but it may be managable as a last resort.

prenex
  • 24
  • 3
0

In your service description, mark the components as enabled, but requiring configuration information provided by the Configuration Management service. you then can write a CM plugin service (can't remember the exact term) that can publish and modify the configuration of your components. Services by default are identified by their name, which by default is their implementation class name. Configuration data is passed as a map, and it can be empty. DS will make the service available as soon as the CM provides a configuration.

Tassos Bassoukos
  • 16,017
  • 2
  • 36
  • 40
  • I need to communicate with the components before they are active. That's why the ScrService is more attractive. I've updated my original to clarify. – Toolshed Feb 19 '12 at 20:53