Given this scenario:
Bundle A: component 1A (enabled:false)
Bundle B: component 2B
How can i enable component 1A from Bundle B or Component 2B?
I've tried to do it by using componentContext,
dsContext.enableComponent("1A");
but it seems to work only with services in the same bundle.
Your using a mechanism that is intended for management and it seems you want to use it on application level. Declarative services should be enabled/disabled through their dependencies, or through a domain specific means. You should not let another actor that enables/disables a component. Using this route you likely get very complex systems since it is difficult to control the timing and order.
Technically, you should use the Apache Felix SCR Service to control the enable/disable of a DS, this is unfortunately not yet standardized and then requires Apache Felix SCR as implementation of DS.
If you explain why you want to enable/disable other components it might be possible to point you to better solutions.
Related
Rather than manually making configuration changes to OSGi components in Felix, it's good practice to create sling:OsgiConfig nodes in the JCR to make sure that the settings are version controlled, applied the same across environments, etc.
Similarly, I want to disable an out-of-the-box component on each environment. Is there any way to achieve this via configuration? Rather than going to system/console/components and disabling it there?
Anything I've read about this has mentioned making changes internally within the bundle, but since it's one that I don't own, I'd need some external configuration to do this.
You can do this with the ScrService, which is published by the SCR runtime bundle. API documentation is here.
Note that ScrService is not "standard", i.e. it doesn't come from the OSGi specification. However it is supported by Felix and Equinox and Knopflerfish, so it's pretty much a de facto standard. In fact this service is used by the Web Console when you go to system/console/components.
Try to use attribute policy=ConfigurationPolicy.REQUIRE on #Component.
Then you could prepare a set of packages with configurations for each environment as part of the build. This is also a good practice for having different OSGI configurations for each environment.
So for some of enironments you could just simply not provide a configuration for a particular component. Such component would not run - it would have unsatisfied status.
I believe I've seen this approach in AEM itself.
You can also create a filter to remove current configurations but it still would require to disable the Component at least once. And this solution will work only if this component has mentioned policy.
The other way around is to prepare a Service that would be responsible for disabling other components - it could be configurable. But it doesn't sound like a good solution to me.
I’m currently “struggling” with OSGi services, or to be more specific, with the wiring between the services. I’m aware of the basics of DS, SCR and the general strategies for a component instance to acquire services. Anyway, here is my problem:
Following DS, components declare e.g. their provided and consumed services in a XML-file. In my case, I’m interested in the “consumed/referenced” services of a particular component (which are declared by the “Reference” tag in the component’s XML-file).
E.g. consider a running OSGi-application: a bunch of bundles collaborating with each other based on services (DS). Now, I want to pick a particular bundle and query all its references to the services it (may) consume - no matter if these services are currently available or not.
Referring to Apache Felix GoGo shell commands, like inspect requirements *, I do get information about the imported packages etc. but not a complete overview about the consumed services (-> both currently consumed services and services the component is waiting for).
I’ve read about the Framework API which provides insight in the registration, modification and deregistration of service but apparently, it does not provide the information about what services bundles are waiting for. Following the OSGi core specification, this could be achieved by a Listener Hook.
Isn’t there a way, where I just can query e.g. the SCR to get all referenced services of a specific bundle? Obviously, the SCR is supposed to read the bundle’s Service-Component-XML-file and to “register” some kind of “Service Tracker” to track the consumed/referenced services – hence the information of a bundle’s consumed/referenced services should somehow be available, shouldn’t it?
It would be great if you could help me with this.
Thanks,
Don
Checkout xray, http://softwaresimplexity.blogspot.com/2012/07/xray-again.html, from Peter Kriens.
We run Restlet 2.1 in an OSGi environment (Equinox) as bundle (ie. not as library within a bundle). The problem is that the Restlet Engine does not detect helpers (like converters) that are provided by Restlet extensions. Specifically, the EngineClassLoader#getResources() call does not return any result. The extensions are also deployed as OSGi bundles in the target platform.
Is automatic converter registration actually supposed to work within OSGi environments?
In fact, Restlet supports such feature thanks to a dedicated activator (see the Activator class in the package org.restlet.engine.internal).
This activator introspects bundles to find out the following things:
servers corresponding to registered servers
servers corresponding to registered clients
authenticators corresponding to registered clients
converters
Be aware that to use this feature, we must use the OSGi edition of Restlet since it's the only that has the MANIFEST file of the org.restlet bundle with the activator class specified. Otherwise you don't have to care about the bundle loading order...
Hope it helps you.
Thierry
Unless the Restlet-bundle explicitly imports the packages that contain the extensions (and I doubt it does, and it shouldn't), it wouldn't be able to load them, because bundles have isolated class-spaces.
A possible solution would be to provide the extensions as fragments attached to the Restlet-bundle. Thus, if you make it use the bundle-classloader (the documentation says this can be done by setting the Engines classloader), it would be able to load classes from the fragments.
Indeed it doesn't quite work for OSGi, as it depends on the ability to see the entire class space.
The way to do this in OSGi would be to use the service registry for the extensions, but that only works for OSGi aware libraries.
There is some help on the way: In the recently released OSGi 5 (Service Loader Mediator) there will be support to 'bridge' META-INF/services (I don't know if Restlet uses those, though) onto OSGi services, so 'legacy' libraries should work well within OSGi.
There is an implementation in Apache Aries called Spi-Fly. I looked at it briefly a while back. It might do the trick for you, it might not.
Is it possible to add declarative services using some kind of api?
A little background:
I have a server application based on dynamic scripts (they can be added, edited or removed at any time).
Those scripts have dependencies to OSGi services and possibly each other. Whenever a script gets
edited, the script gets compiled to javascript, and its dependencies are detected.
At that point, I'd like to (re)register it as a declarative service, so it will be activated / deactivated when its
dependencies come and go.
Is this even possible? Or is there something major I'm missing?
If it isn't possible with an OSGi standard, is there a specific solution for Felix or Equinox?
Can you do that in the other frameworks, like iPojo or blueprint?
There is no API to imperatively add declarative services. You can use the normal OSGi api to register and use services. Perhaps that is what you want?
You may want to checkout the Dependency Manager which may provide an API model giving you the dependency support you want.
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.
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.
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.
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.