You are viewing a plain text version of this content. The canonical link for it is here.
Posted to user@aries.apache.org by Manuel Holzleitner <ma...@gmail.com> on 2015/03/06 10:34:43 UTC

Aries Subsystem & Extender

Hello,

I would like to understand how to use the subsystem in combination with
extenders but I couldn't find any details on how to do it in the right way.

Specifically, I have bundle in the root subsystem:
org.apache.camel.camel-core which uses a bundle tracker (on its own bundle
context) to extend camel component bundles (e.g. camel-ftp). I would like
to separate the camel components along with their dependencies into
isolated composite subsystems.

When now starting a camel component subsystem the extender does not get
notified with an event since they do not share the same scope. How can I
make sure that the camel-core extender should be notified with such events?

Is it enough to specify i.e. provide/require osgi.extender capabilities and
also specify them on the subsystem level? May another possible solution is
that the camel-core extender uses a bundle tracker on the system bundle,
since this should be notified with the events in all subsystems. Is this
correct? If yes, is this also the preferred way to do it?

I have seen that in the blueprint extender there is a property
("org.apache.aries.blueprint.use.system.context") also to specify that the
bundle tracker is using the system context. Was this property added for the
same reason?

I would appreciate any help, hints or pointers to detailed information on
this issue (i.e. osgi spec section)?

Kind Regards,
Manuel

Re: Aries Subsystem & Extender

Posted by David Jencks <da...@yahoo.com>.
I don't have a strong opinion on whether to add such a wiring constraint in the aries blueprint implementation.  Most likely the next blueprint spec revision will include such a constraint.   Until the format is set by the spec you run the risk of introducing something incompatible.  I suppose you could use the org.apache.aries namespace but that won't help with conflicts with the eclipse implementation.  I'd probably wait until it was specced.

My opinion on whether the default scope should be isolated or global is highly prejudiced by my belief that using blueprint is a mistake :-)  I therefore tend to think that if you insist on using it you should put the blueprint implementation in the isolated place your blueprint app is and that the default-isolated flag is better.  If I thought blueprint was the best thing since sliced bread I'd probably think the global default was better.

thanks
david jencks

On Mar 18, 2015, at 4:11 AM, Manuel Holzleitner <ma...@gmail.com> wrote:

> Do you think that the same "requires wiring" functionality should also be included in the Aries blueprint extender? The blueprint extender already provides a property to listen for bundle changes on the system bundle, but this property is disabled by default. Shouldn't that be changed to be enabled per default so that blueprint is always subsystem aware? I would assume that there is no difference between creating the bundle tracker on the system bundle or the extender bundle for containers that do not use the subsystem module. 
> 
> Kind Regards,
> Manuel
> 
> On Tue, Mar 10, 2015 at 3:05 PM, David Jencks <da...@yahoo.com> wrote:
> That's pretty much the same code as I just wrote for DS :-)
> 
> The only difference I see is that I used the BundleVersion rather than the bundle id for comparison of "wired to the same bundle".  It's unlikely but perhaps conceivable that the extender itself might be present in two versions perhaps during an upgrade.  Anyway I used
> 
> m_bundle.adapt(BundleRevision.class).equals(wire.getProvider())
> 
> which probably should factor out the adapt so it only happens once :-)
> 
> thanks!!
> david jencks
> 
> On Mar 10, 2015, at 9:54 AM, Manuel Holzleitner <ma...@gmail.com> wrote:
> 
>> With your help, I tried to quickly implement this approach according to your suggestions for the camel-core example (see source snippet below) and tested it in combination with the subsystem module and correct require/provide-capabilities headers. Maybe you could briefly look over the extenderCapabilityWired() method to check whether this is how the "requires wiring" part should be implemented or if there is an easier or better way to do it. 
>> 
>> In general, I prefer this second option since also no (optional) dependency to the subsystem API needs to be established by the extender (in this case camel-core) and it seems to be aligned to the OSGi spec, as well.
>> 
>>     ....
>>     public void start(BundleContext context) throws Exception {
>>         LOG.info("Camel activator starting");
>> 
>>         bundleId = context.getBundle().getBundleId();
>>         tracker = new BundleTracker(context.getBundle(Constants.SYSTEM_BUNDLE_LOCATION).getBundleContext(), Bundle.ACTIVE, this);
>>         tracker.open();
>> 
>>         LOG.info("Camel activator started");
>>     }
>> 
>>     public void stop(BundleContext context) throws Exception {
>>         LOG.info("Camel activator stopping");
>>         tracker.close();
>>         LOG.info("Camel activator stopped");
>>     }
>> 
>>     public Object addingBundle(Bundle bundle, BundleEvent event) {
>>         LOG.debug("Bundle started: {}", bundle.getSymbolicName());
>> 
>>         if (extenderCapabilityWired(bundle)) {
>>             List<BaseService> r = new ArrayList<BaseService>();
>>             registerComponents(bundle, r);
>>             registerLanguages(bundle, r);
>>             registerDataFormats(bundle, r);
>>             registerTypeConverterLoader(bundle, r);
>>             for (BaseService service : r) {
>>                 service.register();
>>             }
>>             resolvers.put(bundle.getBundleId(), r);
>>         }
>> 
>>         return bundle;
>>     }
>> 
>>     private boolean extenderCapabilityWired(Bundle bundle) {
>>         BundleWiring wiring = bundle.adapt(BundleWiring.class);
>>         List<BundleWire> requiredWires = wiring.getRequiredWires(ExtenderNamespace.EXTENDER_NAMESPACE);
>>         for (BundleWire requiredWire : requiredWires) {
>>             if ("org.apache.camel".equals(requiredWire.getCapability().getAttributes().get(ExtenderNamespace.EXTENDER_NAMESPACE))) {
>>                 if (this.bundleId == requiredWire.getProviderWiring().getBundle().getBundleId()) {
>>                     LOG.debug("Bundle {} extender capability wired to this extender implementation.", bundle.getBundleId());
>>                     return true;
>>                 } else {
>>                     LOG.info("Bundle {} ignored since extender capability is not wired to this extender implementation.", bundle.getBundleId());
>>                     return false;
>>                 }
>>             }
>>         }
>>         LOG.debug("Bundle {} does not require extender capability.", bundle.getBundleId());
>> 
>>         return true;
>>     }
>>     ...
>> 
>> On Fri, Mar 6, 2015 at 7:04 PM, David Jencks <da...@yahoo.com> wrote:
>> I really think dragging in any awareness of subsystems is going to make things disastrously more complicated than they need to be.  The upcoming R6 DS 1.3 spec mentions the approach I suggest of listening on the system bundle for DS implementations that want to work for bundles in isolated environments (such as subsystems).  The extender capability/requirement/wiring bit is part of the spec.  The (trunk, unreleased) Felix DS implementation has a configuration flag to choose whether to use its' own bundle or the system bundle for bundle tracking, and exposes an appropriate extender capability.  bnd trunk now adds an extender requirement for bundles that end up using the 1.3 DS namespace (or you request it using an option).  I don't think we implemented the "requires wiring" bit yet though. 
>> 
>> thanks
>> david jencks
>> 
>> On Mar 6, 2015, at 10:40 AM, Manuel Holzleitner <ma...@gmail.com> wrote:
>> 
>>> Hi, 
>>> 
>>> thanks for your information. I agree that case 2b should match in this case. It's a very good point that the camel extender within an subsystem needs to extend for the subsystem context and only in the root subsystem on the framework context. But how should the camel-core extender find out in which subsystem it resides?
>>> 
>>> I sketched the following solution according to what you proposed:
>>>     ...
>>>     public void start(BundleContext context) throws Exception {
>>>         LOG.info("Camel activator starting");
>>> 
>>>         BundleContext trackerContext = context;
>>>         ServiceReference serviceReference = context.getServiceReference("org.osgi.service.subsystem.Subsystem");
>>>         if (serviceReference != null) {
>>>             org.osgi.service.subsystem.Subsystem subsystem = (org.osgi.service.subsystem.Subsystem) context.getService(serviceReference);
>>>             if (subsystem != null) {
>>>                 LOG.debug("Camel activator starting in subsystem: {}", subsystem);
>>> 
>>>                 if (subsystem.getSymbolicName().equals(org.osgi.service.subsystem.SubsystemConstants.ROOT_SUBSYSTEM_SYMBOLICNAME)) {
>>>                     trackerContext = context.getBundle(Constants.SYSTEM_BUNDLE_LOCATION).getBundleContext();
>>>                 } else {
>>>                     trackerContext = subsystem.getBundleContext();
>>>                 }
>>>             }
>>>         }
>>> 
>>>         tracker = new BundleTracker(trackerContext, Bundle.ACTIVE, this);
>>>         tracker.open();
>>>         LOG.info("Camel activator started");
>>>     }
>>>     ...
>>> 
>>> I also needed to add an optional Import-Package to org.osgi.service.subsystem package and a optional dependency to osgi.enterprise 5.0.0 so that this mechanism is only active for containers with subsystem features.
>>> First tests showed that the bundle tracker events are received properly in the camel extender in the root subsystem also for subsystems. I would need to further test this on different subsystem levels and check the service registration for correct subsystem isolation. Do you think this should be the right way to do it?
>>> 
>>> The alternative proposal with the "global" extender pattern also sounds interesting but now I'm wondering which of those options should be preferred. Since you mentioned that this approach seems to be a common pattern could you point me to an actual extender implementation that uses this approach?
>>> 
>>> Thanks for your help!
>>> Manuel
>>> 
>>> On Fri, Mar 6, 2015 at 4:14 PM, David Bosschaert <da...@gmail.com> wrote:
>>> Hi David
>>> 
>>> On 6 March 2015 at 14:48, David Jencks <da...@yahoo.com> wrote:
>>> > I'm not sure what the "synthesized bundle" you are talking about is.  Subsystems run off resolver hooks.
>>> 
>>> AFAIK synthesized bundles appear for every isolated subsystem. If you
>>> want to see an example see bundle 20 in the following example:
>>> http://coderthoughts.blogspot.com/2014/01/osgi-subsytems-on-apache-felix.html
>>> 
>>> Best regards,
>>> 
>>> David
>>> 
>> 
>> 
> 
> 


Re: Aries Subsystem & Extender

Posted by Manuel Holzleitner <ma...@gmail.com>.
Do you think that the same "requires wiring" functionality should also be
included in the Aries blueprint extender? The blueprint extender already
provides a property to listen for bundle changes on the system bundle, but
this property is disabled by default. Shouldn't that be changed to be
enabled per default so that blueprint is always subsystem aware? I would
assume that there is no difference between creating the bundle tracker on
the system bundle or the extender bundle for containers that do not use the
subsystem module.

Kind Regards,
Manuel

On Tue, Mar 10, 2015 at 3:05 PM, David Jencks <da...@yahoo.com>
wrote:

> That's pretty much the same code as I just wrote for DS :-)
>
> The only difference I see is that I used the BundleVersion rather than the
> bundle id for comparison of "wired to the same bundle".  It's unlikely but
> perhaps conceivable that the extender itself might be present in two
> versions perhaps during an upgrade.  Anyway I used
>
> m_bundle.adapt(BundleRevision.class).equals(wire.getProvider())
>
> which probably should factor out the adapt so it only happens once :-)
>
> thanks!!
> david jencks
>
> On Mar 10, 2015, at 9:54 AM, Manuel Holzleitner <
> manuel.holzleitner@gmail.com> wrote:
>
> With your help, I tried to quickly implement this approach according to
> your suggestions for the camel-core example (see source snippet below) and
> tested it in combination with the subsystem module and correct
> require/provide-capabilities headers. Maybe you could briefly look over
> the extenderCapabilityWired() method to check whether this is how the
> "requires wiring" part should be implemented or if there is an easier or
> better way to do it.
>
> In general, I prefer this second option since also no (optional)
> dependency to the subsystem API needs to be established by the extender (in
> this case camel-core) and it seems to be aligned to the OSGi spec, as well.
>
>     ....
>     public void start(BundleContext context) throws Exception {
>         LOG.info("Camel activator starting");
>
>         bundleId = context.getBundle().getBundleId();
>         tracker = new
> BundleTracker(context.getBundle(Constants.SYSTEM_BUNDLE_LOCATION).getBundleContext(),
> Bundle.ACTIVE, this);
>         tracker.open();
>
>         LOG.info("Camel activator started");
>     }
>
>     public void stop(BundleContext context) throws Exception {
>         LOG.info("Camel activator stopping");
>         tracker.close();
>         LOG.info("Camel activator stopped");
>     }
>
>     public Object addingBundle(Bundle bundle, BundleEvent event) {
>         LOG.debug("Bundle started: {}", bundle.getSymbolicName());
>
>         if (extenderCapabilityWired(bundle)) {
>             List<BaseService> r = new ArrayList<BaseService>();
>             registerComponents(bundle, r);
>             registerLanguages(bundle, r);
>             registerDataFormats(bundle, r);
>             registerTypeConverterLoader(bundle, r);
>             for (BaseService service : r) {
>                 service.register();
>             }
>             resolvers.put(bundle.getBundleId(), r);
>         }
>
>         return bundle;
>     }
>
>     private boolean extenderCapabilityWired(Bundle bundle) {
>         BundleWiring wiring = bundle.adapt(BundleWiring.class);
>         List<BundleWire> requiredWires =
> wiring.getRequiredWires(ExtenderNamespace.EXTENDER_NAMESPACE);
>         for (BundleWire requiredWire : requiredWires) {
>             if
> ("org.apache.camel".equals(requiredWire.getCapability().getAttributes().get(ExtenderNamespace.EXTENDER_NAMESPACE)))
> {
>                 if (this.bundleId ==
> requiredWire.getProviderWiring().getBundle().getBundleId()) {
>                     LOG.debug("Bundle {} extender capability wired to this
> extender implementation.", bundle.getBundleId());
>                     return true;
>                 } else {
>                     LOG.info("Bundle {} ignored since extender capability
> is not wired to this extender implementation.", bundle.getBundleId());
>                     return false;
>                 }
>             }
>         }
>         LOG.debug("Bundle {} does not require extender capability.",
> bundle.getBundleId());
>
>         return true;
>     }
>     ...
>
> On Fri, Mar 6, 2015 at 7:04 PM, David Jencks <da...@yahoo.com>
> wrote:
>
>> I really think dragging in any awareness of subsystems is going to make
>> things disastrously more complicated than they need to be.  The upcoming R6
>> DS 1.3 spec mentions the approach I suggest of listening on the system
>> bundle for DS implementations that want to work for bundles in isolated
>> environments (such as subsystems).  The extender
>> capability/requirement/wiring bit is part of the spec.  The (trunk,
>> unreleased) Felix DS implementation has a configuration flag to choose
>> whether to use its' own bundle or the system bundle for bundle tracking,
>> and exposes an appropriate extender capability.  bnd trunk now adds an
>> extender requirement for bundles that end up using the 1.3 DS namespace (or
>> you request it using an option).  I don't think we implemented the
>> "requires wiring" bit yet though.
>>
>> thanks
>> david jencks
>>
>> On Mar 6, 2015, at 10:40 AM, Manuel Holzleitner <
>> manuel.holzleitner@gmail.com> wrote:
>>
>> Hi,
>>
>> thanks for your information. I agree that case 2b should match in this
>> case. It's a very good point that the camel extender within an subsystem
>> needs to extend for the subsystem context and only in the root subsystem on
>> the framework context. But how should the camel-core extender find out in
>> which subsystem it resides?
>>
>> I sketched the following solution according to what you proposed:
>>     ...
>>     public void start(BundleContext context) throws Exception {
>>         LOG.info("Camel activator starting");
>>
>>         BundleContext trackerContext = context;
>>         ServiceReference serviceReference =
>> context.getServiceReference("org.osgi.service.subsystem.Subsystem");
>>         if (serviceReference != null) {
>>             org.osgi.service.subsystem.Subsystem subsystem =
>> (org.osgi.service.subsystem.Subsystem) context.getService(serviceReference);
>>             if (subsystem != null) {
>>                 LOG.debug("Camel activator starting in subsystem: {}",
>> subsystem);
>>
>>                 if
>> (subsystem.getSymbolicName().equals(org.osgi.service.subsystem.SubsystemConstants.ROOT_SUBSYSTEM_SYMBOLICNAME))
>> {
>>                     trackerContext =
>> context.getBundle(Constants.SYSTEM_BUNDLE_LOCATION).getBundleContext();
>>                 } else {
>>                     trackerContext = subsystem.getBundleContext();
>>                 }
>>             }
>>         }
>>
>>         tracker = new BundleTracker(trackerContext, Bundle.ACTIVE, this);
>>         tracker.open();
>>         LOG.info("Camel activator started");
>>     }
>>     ...
>>
>> I also needed to add an optional Import-Package to
>> org.osgi.service.subsystem package and a optional dependency to
>> osgi.enterprise 5.0.0 so that this mechanism is only active for containers
>> with subsystem features.
>> First tests showed that the bundle tracker events are received properly
>> in the camel extender in the root subsystem also for subsystems. I would
>> need to further test this on different subsystem levels and check the
>> service registration for correct subsystem isolation. Do you think this
>> should be the right way to do it?
>>
>> The alternative proposal with the "global" extender pattern also sounds
>> interesting but now I'm wondering which of those options should be
>> preferred. Since you mentioned that this approach seems to be a common
>> pattern could you point me to an actual extender implementation that uses
>> this approach?
>>
>> Thanks for your help!
>> Manuel
>>
>> On Fri, Mar 6, 2015 at 4:14 PM, David Bosschaert <
>> david.bosschaert@gmail.com> wrote:
>>
>>> Hi David
>>>
>>> On 6 March 2015 at 14:48, David Jencks <da...@yahoo.com> wrote:
>>> > I'm not sure what the "synthesized bundle" you are talking about is.
>>> Subsystems run off resolver hooks.
>>>
>>> AFAIK synthesized bundles appear for every isolated subsystem. If you
>>> want to see an example see bundle 20 in the following example:
>>>
>>> http://coderthoughts.blogspot.com/2014/01/osgi-subsytems-on-apache-felix.html
>>>
>>> Best regards,
>>>
>>> David
>>>
>>
>>
>>
>
>

Re: Aries Subsystem & Extender

Posted by David Jencks <da...@yahoo.com>.
That's pretty much the same code as I just wrote for DS :-)

The only difference I see is that I used the BundleVersion rather than the bundle id for comparison of "wired to the same bundle".  It's unlikely but perhaps conceivable that the extender itself might be present in two versions perhaps during an upgrade.  Anyway I used

m_bundle.adapt(BundleRevision.class).equals(wire.getProvider())

which probably should factor out the adapt so it only happens once :-)

thanks!!
david jencks

On Mar 10, 2015, at 9:54 AM, Manuel Holzleitner <ma...@gmail.com> wrote:

> With your help, I tried to quickly implement this approach according to your suggestions for the camel-core example (see source snippet below) and tested it in combination with the subsystem module and correct require/provide-capabilities headers. Maybe you could briefly look over the extenderCapabilityWired() method to check whether this is how the "requires wiring" part should be implemented or if there is an easier or better way to do it. 
> 
> In general, I prefer this second option since also no (optional) dependency to the subsystem API needs to be established by the extender (in this case camel-core) and it seems to be aligned to the OSGi spec, as well.
> 
>     ....
>     public void start(BundleContext context) throws Exception {
>         LOG.info("Camel activator starting");
> 
>         bundleId = context.getBundle().getBundleId();
>         tracker = new BundleTracker(context.getBundle(Constants.SYSTEM_BUNDLE_LOCATION).getBundleContext(), Bundle.ACTIVE, this);
>         tracker.open();
> 
>         LOG.info("Camel activator started");
>     }
> 
>     public void stop(BundleContext context) throws Exception {
>         LOG.info("Camel activator stopping");
>         tracker.close();
>         LOG.info("Camel activator stopped");
>     }
> 
>     public Object addingBundle(Bundle bundle, BundleEvent event) {
>         LOG.debug("Bundle started: {}", bundle.getSymbolicName());
> 
>         if (extenderCapabilityWired(bundle)) {
>             List<BaseService> r = new ArrayList<BaseService>();
>             registerComponents(bundle, r);
>             registerLanguages(bundle, r);
>             registerDataFormats(bundle, r);
>             registerTypeConverterLoader(bundle, r);
>             for (BaseService service : r) {
>                 service.register();
>             }
>             resolvers.put(bundle.getBundleId(), r);
>         }
> 
>         return bundle;
>     }
> 
>     private boolean extenderCapabilityWired(Bundle bundle) {
>         BundleWiring wiring = bundle.adapt(BundleWiring.class);
>         List<BundleWire> requiredWires = wiring.getRequiredWires(ExtenderNamespace.EXTENDER_NAMESPACE);
>         for (BundleWire requiredWire : requiredWires) {
>             if ("org.apache.camel".equals(requiredWire.getCapability().getAttributes().get(ExtenderNamespace.EXTENDER_NAMESPACE))) {
>                 if (this.bundleId == requiredWire.getProviderWiring().getBundle().getBundleId()) {
>                     LOG.debug("Bundle {} extender capability wired to this extender implementation.", bundle.getBundleId());
>                     return true;
>                 } else {
>                     LOG.info("Bundle {} ignored since extender capability is not wired to this extender implementation.", bundle.getBundleId());
>                     return false;
>                 }
>             }
>         }
>         LOG.debug("Bundle {} does not require extender capability.", bundle.getBundleId());
> 
>         return true;
>     }
>     ...
> 
> On Fri, Mar 6, 2015 at 7:04 PM, David Jencks <da...@yahoo.com> wrote:
> I really think dragging in any awareness of subsystems is going to make things disastrously more complicated than they need to be.  The upcoming R6 DS 1.3 spec mentions the approach I suggest of listening on the system bundle for DS implementations that want to work for bundles in isolated environments (such as subsystems).  The extender capability/requirement/wiring bit is part of the spec.  The (trunk, unreleased) Felix DS implementation has a configuration flag to choose whether to use its' own bundle or the system bundle for bundle tracking, and exposes an appropriate extender capability.  bnd trunk now adds an extender requirement for bundles that end up using the 1.3 DS namespace (or you request it using an option).  I don't think we implemented the "requires wiring" bit yet though. 
> 
> thanks
> david jencks
> 
> On Mar 6, 2015, at 10:40 AM, Manuel Holzleitner <ma...@gmail.com> wrote:
> 
>> Hi, 
>> 
>> thanks for your information. I agree that case 2b should match in this case. It's a very good point that the camel extender within an subsystem needs to extend for the subsystem context and only in the root subsystem on the framework context. But how should the camel-core extender find out in which subsystem it resides?
>> 
>> I sketched the following solution according to what you proposed:
>>     ...
>>     public void start(BundleContext context) throws Exception {
>>         LOG.info("Camel activator starting");
>> 
>>         BundleContext trackerContext = context;
>>         ServiceReference serviceReference = context.getServiceReference("org.osgi.service.subsystem.Subsystem");
>>         if (serviceReference != null) {
>>             org.osgi.service.subsystem.Subsystem subsystem = (org.osgi.service.subsystem.Subsystem) context.getService(serviceReference);
>>             if (subsystem != null) {
>>                 LOG.debug("Camel activator starting in subsystem: {}", subsystem);
>> 
>>                 if (subsystem.getSymbolicName().equals(org.osgi.service.subsystem.SubsystemConstants.ROOT_SUBSYSTEM_SYMBOLICNAME)) {
>>                     trackerContext = context.getBundle(Constants.SYSTEM_BUNDLE_LOCATION).getBundleContext();
>>                 } else {
>>                     trackerContext = subsystem.getBundleContext();
>>                 }
>>             }
>>         }
>> 
>>         tracker = new BundleTracker(trackerContext, Bundle.ACTIVE, this);
>>         tracker.open();
>>         LOG.info("Camel activator started");
>>     }
>>     ...
>> 
>> I also needed to add an optional Import-Package to org.osgi.service.subsystem package and a optional dependency to osgi.enterprise 5.0.0 so that this mechanism is only active for containers with subsystem features.
>> First tests showed that the bundle tracker events are received properly in the camel extender in the root subsystem also for subsystems. I would need to further test this on different subsystem levels and check the service registration for correct subsystem isolation. Do you think this should be the right way to do it?
>> 
>> The alternative proposal with the "global" extender pattern also sounds interesting but now I'm wondering which of those options should be preferred. Since you mentioned that this approach seems to be a common pattern could you point me to an actual extender implementation that uses this approach?
>> 
>> Thanks for your help!
>> Manuel
>> 
>> On Fri, Mar 6, 2015 at 4:14 PM, David Bosschaert <da...@gmail.com> wrote:
>> Hi David
>> 
>> On 6 March 2015 at 14:48, David Jencks <da...@yahoo.com> wrote:
>> > I'm not sure what the "synthesized bundle" you are talking about is.  Subsystems run off resolver hooks.
>> 
>> AFAIK synthesized bundles appear for every isolated subsystem. If you
>> want to see an example see bundle 20 in the following example:
>> http://coderthoughts.blogspot.com/2014/01/osgi-subsytems-on-apache-felix.html
>> 
>> Best regards,
>> 
>> David
>> 
> 
> 


Re: Aries Subsystem & Extender

Posted by Manuel Holzleitner <ma...@gmail.com>.
With your help, I tried to quickly implement this approach according to
your suggestions for the camel-core example (see source snippet below) and
tested it in combination with the subsystem module and correct
require/provide-capabilities headers. Maybe you could briefly look over
the extenderCapabilityWired() method to check whether this is how the
"requires wiring" part should be implemented or if there is an easier or
better way to do it.

In general, I prefer this second option since also no (optional) dependency
to the subsystem API needs to be established by the extender (in this case
camel-core) and it seems to be aligned to the OSGi spec, as well.

    ....
    public void start(BundleContext context) throws Exception {
        LOG.info("Camel activator starting");

        bundleId = context.getBundle().getBundleId();
        tracker = new
BundleTracker(context.getBundle(Constants.SYSTEM_BUNDLE_LOCATION).getBundleContext(),
Bundle.ACTIVE, this);
        tracker.open();

        LOG.info("Camel activator started");
    }

    public void stop(BundleContext context) throws Exception {
        LOG.info("Camel activator stopping");
        tracker.close();
        LOG.info("Camel activator stopped");
    }

    public Object addingBundle(Bundle bundle, BundleEvent event) {
        LOG.debug("Bundle started: {}", bundle.getSymbolicName());

        if (extenderCapabilityWired(bundle)) {
            List<BaseService> r = new ArrayList<BaseService>();
            registerComponents(bundle, r);
            registerLanguages(bundle, r);
            registerDataFormats(bundle, r);
            registerTypeConverterLoader(bundle, r);
            for (BaseService service : r) {
                service.register();
            }
            resolvers.put(bundle.getBundleId(), r);
        }

        return bundle;
    }

    private boolean extenderCapabilityWired(Bundle bundle) {
        BundleWiring wiring = bundle.adapt(BundleWiring.class);
        List<BundleWire> requiredWires =
wiring.getRequiredWires(ExtenderNamespace.EXTENDER_NAMESPACE);
        for (BundleWire requiredWire : requiredWires) {
            if
("org.apache.camel".equals(requiredWire.getCapability().getAttributes().get(ExtenderNamespace.EXTENDER_NAMESPACE)))
{
                if (this.bundleId ==
requiredWire.getProviderWiring().getBundle().getBundleId()) {
                    LOG.debug("Bundle {} extender capability wired to this
extender implementation.", bundle.getBundleId());
                    return true;
                } else {
                    LOG.info("Bundle {} ignored since extender capability
is not wired to this extender implementation.", bundle.getBundleId());
                    return false;
                }
            }
        }
        LOG.debug("Bundle {} does not require extender capability.",
bundle.getBundleId());

        return true;
    }
    ...

On Fri, Mar 6, 2015 at 7:04 PM, David Jencks <da...@yahoo.com> wrote:

> I really think dragging in any awareness of subsystems is going to make
> things disastrously more complicated than they need to be.  The upcoming R6
> DS 1.3 spec mentions the approach I suggest of listening on the system
> bundle for DS implementations that want to work for bundles in isolated
> environments (such as subsystems).  The extender
> capability/requirement/wiring bit is part of the spec.  The (trunk,
> unreleased) Felix DS implementation has a configuration flag to choose
> whether to use its' own bundle or the system bundle for bundle tracking,
> and exposes an appropriate extender capability.  bnd trunk now adds an
> extender requirement for bundles that end up using the 1.3 DS namespace (or
> you request it using an option).  I don't think we implemented the
> "requires wiring" bit yet though.
>
> thanks
> david jencks
>
> On Mar 6, 2015, at 10:40 AM, Manuel Holzleitner <
> manuel.holzleitner@gmail.com> wrote:
>
> Hi,
>
> thanks for your information. I agree that case 2b should match in this
> case. It's a very good point that the camel extender within an subsystem
> needs to extend for the subsystem context and only in the root subsystem on
> the framework context. But how should the camel-core extender find out in
> which subsystem it resides?
>
> I sketched the following solution according to what you proposed:
>     ...
>     public void start(BundleContext context) throws Exception {
>         LOG.info("Camel activator starting");
>
>         BundleContext trackerContext = context;
>         ServiceReference serviceReference =
> context.getServiceReference("org.osgi.service.subsystem.Subsystem");
>         if (serviceReference != null) {
>             org.osgi.service.subsystem.Subsystem subsystem =
> (org.osgi.service.subsystem.Subsystem) context.getService(serviceReference);
>             if (subsystem != null) {
>                 LOG.debug("Camel activator starting in subsystem: {}",
> subsystem);
>
>                 if
> (subsystem.getSymbolicName().equals(org.osgi.service.subsystem.SubsystemConstants.ROOT_SUBSYSTEM_SYMBOLICNAME))
> {
>                     trackerContext =
> context.getBundle(Constants.SYSTEM_BUNDLE_LOCATION).getBundleContext();
>                 } else {
>                     trackerContext = subsystem.getBundleContext();
>                 }
>             }
>         }
>
>         tracker = new BundleTracker(trackerContext, Bundle.ACTIVE, this);
>         tracker.open();
>         LOG.info("Camel activator started");
>     }
>     ...
>
> I also needed to add an optional Import-Package to
> org.osgi.service.subsystem package and a optional dependency to
> osgi.enterprise 5.0.0 so that this mechanism is only active for containers
> with subsystem features.
> First tests showed that the bundle tracker events are received properly in
> the camel extender in the root subsystem also for subsystems. I would need
> to further test this on different subsystem levels and check the service
> registration for correct subsystem isolation. Do you think this should be
> the right way to do it?
>
> The alternative proposal with the "global" extender pattern also sounds
> interesting but now I'm wondering which of those options should be
> preferred. Since you mentioned that this approach seems to be a common
> pattern could you point me to an actual extender implementation that uses
> this approach?
>
> Thanks for your help!
> Manuel
>
> On Fri, Mar 6, 2015 at 4:14 PM, David Bosschaert <
> david.bosschaert@gmail.com> wrote:
>
>> Hi David
>>
>> On 6 March 2015 at 14:48, David Jencks <da...@yahoo.com> wrote:
>> > I'm not sure what the "synthesized bundle" you are talking about is.
>> Subsystems run off resolver hooks.
>>
>> AFAIK synthesized bundles appear for every isolated subsystem. If you
>> want to see an example see bundle 20 in the following example:
>>
>> http://coderthoughts.blogspot.com/2014/01/osgi-subsytems-on-apache-felix.html
>>
>> Best regards,
>>
>> David
>>
>
>
>

Re: Aries Subsystem & Extender

Posted by David Jencks <da...@yahoo.com>.
I really think dragging in any awareness of subsystems is going to make things disastrously more complicated than they need to be.  The upcoming R6 DS 1.3 spec mentions the approach I suggest of listening on the system bundle for DS implementations that want to work for bundles in isolated environments (such as subsystems).  The extender capability/requirement/wiring bit is part of the spec.  The (trunk, unreleased) Felix DS implementation has a configuration flag to choose whether to use its' own bundle or the system bundle for bundle tracking, and exposes an appropriate extender capability.  bnd trunk now adds an extender requirement for bundles that end up using the 1.3 DS namespace (or you request it using an option).  I don't think we implemented the "requires wiring" bit yet though. 

thanks
david jencks

On Mar 6, 2015, at 10:40 AM, Manuel Holzleitner <ma...@gmail.com> wrote:

> Hi, 
> 
> thanks for your information. I agree that case 2b should match in this case. It's a very good point that the camel extender within an subsystem needs to extend for the subsystem context and only in the root subsystem on the framework context. But how should the camel-core extender find out in which subsystem it resides?
> 
> I sketched the following solution according to what you proposed:
>     ...
>     public void start(BundleContext context) throws Exception {
>         LOG.info("Camel activator starting");
> 
>         BundleContext trackerContext = context;
>         ServiceReference serviceReference = context.getServiceReference("org.osgi.service.subsystem.Subsystem");
>         if (serviceReference != null) {
>             org.osgi.service.subsystem.Subsystem subsystem = (org.osgi.service.subsystem.Subsystem) context.getService(serviceReference);
>             if (subsystem != null) {
>                 LOG.debug("Camel activator starting in subsystem: {}", subsystem);
> 
>                 if (subsystem.getSymbolicName().equals(org.osgi.service.subsystem.SubsystemConstants.ROOT_SUBSYSTEM_SYMBOLICNAME)) {
>                     trackerContext = context.getBundle(Constants.SYSTEM_BUNDLE_LOCATION).getBundleContext();
>                 } else {
>                     trackerContext = subsystem.getBundleContext();
>                 }
>             }
>         }
> 
>         tracker = new BundleTracker(trackerContext, Bundle.ACTIVE, this);
>         tracker.open();
>         LOG.info("Camel activator started");
>     }
>     ...
> 
> I also needed to add an optional Import-Package to org.osgi.service.subsystem package and a optional dependency to osgi.enterprise 5.0.0 so that this mechanism is only active for containers with subsystem features.
> First tests showed that the bundle tracker events are received properly in the camel extender in the root subsystem also for subsystems. I would need to further test this on different subsystem levels and check the service registration for correct subsystem isolation. Do you think this should be the right way to do it?
> 
> The alternative proposal with the "global" extender pattern also sounds interesting but now I'm wondering which of those options should be preferred. Since you mentioned that this approach seems to be a common pattern could you point me to an actual extender implementation that uses this approach?
> 
> Thanks for your help!
> Manuel
> 
> On Fri, Mar 6, 2015 at 4:14 PM, David Bosschaert <da...@gmail.com> wrote:
> Hi David
> 
> On 6 March 2015 at 14:48, David Jencks <da...@yahoo.com> wrote:
> > I'm not sure what the "synthesized bundle" you are talking about is.  Subsystems run off resolver hooks.
> 
> AFAIK synthesized bundles appear for every isolated subsystem. If you
> want to see an example see bundle 20 in the following example:
> http://coderthoughts.blogspot.com/2014/01/osgi-subsytems-on-apache-felix.html
> 
> Best regards,
> 
> David
> 


Re: Aries Subsystem & Extender

Posted by Manuel Holzleitner <ma...@gmail.com>.
Hi,

thanks for your information. I agree that case 2b should match in this
case. It's a very good point that the camel extender within an subsystem
needs to extend for the subsystem context and only in the root subsystem on
the framework context. But how should the camel-core extender find out in
which subsystem it resides?

I sketched the following solution according to what you proposed:
    ...
    public void start(BundleContext context) throws Exception {
        LOG.info("Camel activator starting");

        BundleContext trackerContext = context;
        ServiceReference serviceReference =
context.getServiceReference("org.osgi.service.subsystem.Subsystem");
        if (serviceReference != null) {
            org.osgi.service.subsystem.Subsystem subsystem =
(org.osgi.service.subsystem.Subsystem) context.getService(serviceReference);
            if (subsystem != null) {
                LOG.debug("Camel activator starting in subsystem: {}",
subsystem);

                if
(subsystem.getSymbolicName().equals(org.osgi.service.subsystem.SubsystemConstants.ROOT_SUBSYSTEM_SYMBOLICNAME))
{
                    trackerContext =
context.getBundle(Constants.SYSTEM_BUNDLE_LOCATION).getBundleContext();
                } else {
                    trackerContext = subsystem.getBundleContext();
                }
            }
        }

        tracker = new BundleTracker(trackerContext, Bundle.ACTIVE, this);
        tracker.open();
        LOG.info("Camel activator started");
    }
    ...

I also needed to add an optional Import-Package to
org.osgi.service.subsystem package and a optional dependency to
osgi.enterprise 5.0.0 so that this mechanism is only active for containers
with subsystem features.
First tests showed that the bundle tracker events are received properly in
the camel extender in the root subsystem also for subsystems. I would need
to further test this on different subsystem levels and check the service
registration for correct subsystem isolation. Do you think this should be
the right way to do it?

The alternative proposal with the "global" extender pattern also sounds
interesting but now I'm wondering which of those options should be
preferred. Since you mentioned that this approach seems to be a common
pattern could you point me to an actual extender implementation that uses
this approach?

Thanks for your help!
Manuel

On Fri, Mar 6, 2015 at 4:14 PM, David Bosschaert <david.bosschaert@gmail.com
> wrote:

> Hi David
>
> On 6 March 2015 at 14:48, David Jencks <da...@yahoo.com> wrote:
> > I'm not sure what the "synthesized bundle" you are talking about is.
> Subsystems run off resolver hooks.
>
> AFAIK synthesized bundles appear for every isolated subsystem. If you
> want to see an example see bundle 20 in the following example:
>
> http://coderthoughts.blogspot.com/2014/01/osgi-subsytems-on-apache-felix.html
>
> Best regards,
>
> David
>

Re: Aries Subsystem & Extender

Posted by David Bosschaert <da...@gmail.com>.
Hi David

On 6 March 2015 at 14:48, David Jencks <da...@yahoo.com> wrote:
> I'm not sure what the "synthesized bundle" you are talking about is.  Subsystems run off resolver hooks.

AFAIK synthesized bundles appear for every isolated subsystem. If you
want to see an example see bundle 20 in the following example:
http://coderthoughts.blogspot.com/2014/01/osgi-subsytems-on-apache-felix.html

Best regards,

David

Re: Aries Subsystem & Extender

Posted by David Jencks <da...@yahoo.com>.
I'm not sure what the "synthesized bundle" you are talking about is.  Subsystems run off resolver hooks.

The pattern for "global" extenders seems to be:

- use the system bundle (bundle 0) to look for events of interest, so you see them for all bundles
- have the extender register an extender capability
- have bundles that need extension register a matching extender requirement
- the extender should only extend bundles with no extender requirement or ones with extender requirements wired to their own extender capability.

Then you can run multiple extenders of the same "kind" and each bundle needing extension should only get extended once.  If you're sure there will only ever be one extender of this kind you can leave out the extender capabilites/requirements/matching.

Generally once you have the bundle that needs extension, you want to use that bundle for everything the extender does, for instance access the service registry, config adimin, etc, so that the services, configs, etc, the extender uses are actually the ones visible to that bundle.

thanks
david jencks


On Mar 6, 2015, at 5:13 AM, David Bosschaert <da...@gmail.com> wrote:

> Hi Manuel,
> 
> There are really three possible situations if I'm not mistaken.
> 
> 1. The extender is in the same subsystem as the extendee(s). In this
> case things should just work as-is.
> 2. The extender is in a parent subsystem of the extendees. In this
> case there are two sub-situations:
> 2a. If all the child subsystems are feature subsystems (no isolation)
> things should still work as-is.
> 2b. If any of the child subsystems has isolation (application /
> composite subsystems) then something special needs to be done - the
> extender needs to be 'subsystem-aware'. This means that it needs to
> use the right bundle context to listen for bundle/service changes
> (such as the framework bundle context) and it needs to register any
> new services under the right bundle context so that the isolated child
> subsystem can see them but not others. The synthesized bundle
> associated with each isolated subsystem can be used for this. In the
> case of 'global' service registrations (e.g. something like the
> ConfigAdmin service) you most likely need separate instances or
> facades for each isolated child subsystem, in order to not leak any
> information from other isolated subsystem.
> 
> I think that your case is the 2b case. The camel extender needs to be
> made subsystem aware. What this means precisely is a little bit
> different from case to case but I can think of the camel extender
> using the bundle context associated with the subsystem that it's
> running in to watch for bundle events. So if you're running in the
> root subsystem, you use the framework bundle context. If you're
> running in a child subsystem, you'd use its associated bundle context.
> That way the camel extender will always see what's in child
> subsystems, but not in any parent subsystem, which I guess is what you
> really want. If the camel bundle registers OSGi services and/or other
> global components then you need to think about limiting the visibility
> for isolated subsystems...
> 
> Cheers,
> 
> David
> 
> On 6 March 2015 at 09:34, Manuel Holzleitner
> <ma...@gmail.com> wrote:
>> Hello,
>> 
>> I would like to understand how to use the subsystem in combination with
>> extenders but I couldn't find any details on how to do it in the right way.
>> 
>> Specifically, I have bundle in the root subsystem:
>> org.apache.camel.camel-core which uses a bundle tracker (on its own bundle
>> context) to extend camel component bundles (e.g. camel-ftp). I would like to
>> separate the camel components along with their dependencies into isolated
>> composite subsystems.
>> 
>> When now starting a camel component subsystem the extender does not get
>> notified with an event since they do not share the same scope. How can I
>> make sure that the camel-core extender should be notified with such events?
>> 
>> Is it enough to specify i.e. provide/require osgi.extender capabilities and
>> also specify them on the subsystem level? May another possible solution is
>> that the camel-core extender uses a bundle tracker on the system bundle,
>> since this should be notified with the events in all subsystems. Is this
>> correct? If yes, is this also the preferred way to do it?
>> 
>> I have seen that in the blueprint extender there is a property
>> ("org.apache.aries.blueprint.use.system.context") also to specify that the
>> bundle tracker is using the system context. Was this property added for the
>> same reason?
>> 
>> I would appreciate any help, hints or pointers to detailed information on
>> this issue (i.e. osgi spec section)?
>> 
>> Kind Regards,
>> Manuel


Re: Aries Subsystem & Extender

Posted by David Bosschaert <da...@gmail.com>.
Hi Manuel,

There are really three possible situations if I'm not mistaken.

1. The extender is in the same subsystem as the extendee(s). In this
case things should just work as-is.
2. The extender is in a parent subsystem of the extendees. In this
case there are two sub-situations:
2a. If all the child subsystems are feature subsystems (no isolation)
things should still work as-is.
2b. If any of the child subsystems has isolation (application /
composite subsystems) then something special needs to be done - the
extender needs to be 'subsystem-aware'. This means that it needs to
use the right bundle context to listen for bundle/service changes
(such as the framework bundle context) and it needs to register any
new services under the right bundle context so that the isolated child
subsystem can see them but not others. The synthesized bundle
associated with each isolated subsystem can be used for this. In the
case of 'global' service registrations (e.g. something like the
ConfigAdmin service) you most likely need separate instances or
facades for each isolated child subsystem, in order to not leak any
information from other isolated subsystem.

I think that your case is the 2b case. The camel extender needs to be
made subsystem aware. What this means precisely is a little bit
different from case to case but I can think of the camel extender
using the bundle context associated with the subsystem that it's
running in to watch for bundle events. So if you're running in the
root subsystem, you use the framework bundle context. If you're
running in a child subsystem, you'd use its associated bundle context.
That way the camel extender will always see what's in child
subsystems, but not in any parent subsystem, which I guess is what you
really want. If the camel bundle registers OSGi services and/or other
global components then you need to think about limiting the visibility
for isolated subsystems...

Cheers,

David

On 6 March 2015 at 09:34, Manuel Holzleitner
<ma...@gmail.com> wrote:
> Hello,
>
> I would like to understand how to use the subsystem in combination with
> extenders but I couldn't find any details on how to do it in the right way.
>
> Specifically, I have bundle in the root subsystem:
> org.apache.camel.camel-core which uses a bundle tracker (on its own bundle
> context) to extend camel component bundles (e.g. camel-ftp). I would like to
> separate the camel components along with their dependencies into isolated
> composite subsystems.
>
> When now starting a camel component subsystem the extender does not get
> notified with an event since they do not share the same scope. How can I
> make sure that the camel-core extender should be notified with such events?
>
> Is it enough to specify i.e. provide/require osgi.extender capabilities and
> also specify them on the subsystem level? May another possible solution is
> that the camel-core extender uses a bundle tracker on the system bundle,
> since this should be notified with the events in all subsystems. Is this
> correct? If yes, is this also the preferred way to do it?
>
> I have seen that in the blueprint extender there is a property
> ("org.apache.aries.blueprint.use.system.context") also to specify that the
> bundle tracker is using the system context. Was this property added for the
> same reason?
>
> I would appreciate any help, hints or pointers to detailed information on
> this issue (i.e. osgi spec section)?
>
> Kind Regards,
> Manuel