You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@celix.apache.org by Alexander Broekhuis <a....@gmail.com> on 2012/06/26 14:28:55 UTC

Celix and Declarative Services

Hi all,

After Ferry's question I've been looking a little at the OSGi Declarative
Services spec, and I think most of it can be realized using the current
Celix implementation.

One of the problems I've seen so far is related to service registration.
Using Java a service is an interface, and through reflection and the
implementation of the component, this interface can be registered as a
service by the DS implementation.
In Celix a service is a struct with function pointers, which has to be
instantiated by the user. It is not possible to do this dynamically, the DS
implementation does not know the functions of the component etc.
A simple solution would be to use an additional function in the component
in which the service struct is created. Downside of this is, that there is
no strict separation of component and framework code....

Perhaps someone else has some ideas how this can be solved differently....

-- 
Met vriendelijke groet,

Alexander Broekhuis

Re: Celix and Declarative Services

Posted by Ferry Huberts <ma...@hupie.com>.

On 26-06-12 20:51, Pepijn Noltes wrote:
> Hi All,
>
> On Tue, Jun 26, 2012 at 2:59 PM, Ferry Huberts <ma...@hupie.com> wrote:
>>
>>
>> On 26-06-12 14:28, Alexander Broekhuis wrote:
>>>
>>> Hi all,
>>>
>>> After Ferry's question I've been looking a little at the OSGi Declarative
>>> Services spec, and I think most of it can be realized using the current
>>> Celix implementation.
>>>
>>
>> that would be absolutely awesome!
> I agree this would be a really nice feature.
>>
>>
>>> One of the problems I've seen so far is related to service registration.
>>> Using Java a service is an interface, and through reflection and the
>>> implementation of the component, this interface can be registered as a
>>> service by the DS implementation.
>>> In Celix a service is a struct with function pointers, which has to be
>>> instantiated by the user. It is not possible to do this dynamically, the
>>> DS
>>> implementation does not know the functions of the component etc.
>>> A simple solution would be to use an additional function in the component
>>> in which the service struct is created. Downside of this is, that there is
>>> no strict separation of component and framework code....
>>
>>
>> Why not? (maybe I'm missing something)
>>
>> IMHO it's just a method extra on the 'activator' interface (or an extra
>> 'special' interface).
>>
>> Right now you have start/stop/etc there. You'd just be adding something like
>> 'instantiateServiceRegistrationStruct' there, wouldn't you?
>>
>
> A Service Component Runtime (SCR) needs to have access to functions in
> another module for activating/deactivating the component. Because
> Apache Celix has no module layer (yet), the only way to provide this
> is by creating and registering a service. (Or am I missing
> something?). So a declarative service service would be needed to make
> this work and I think thats not the way to go.
>
> I agree with Alexander that a simple solution would be to add this to
> the framework. In that case the framework SCR has access to the shared
> libraries and can use dynamic object loading with the names (for
> activate/deactivate/etc) provided in the DS XML. Although not a nice
> as a separated SRC bundle, IMO this is -for now - the best solution.
>

that's what I meant as well. I see now that my mail wasn't really clear 
on that ;-)

> Greetings,
> Pepijn
>

-- 
Ferry Huberts



Re: Celix and Declarative Services

Posted by Ferry Huberts <ma...@hupie.com>.

On 27-06-12 09:37, Alexander Broekhuis wrote:
> I've thought about this a little more, and I'll try to explain what I have
> in mind.
>
>> A Service Component Runtime (SCR) needs to have access to functions in
>>> another module for activating/deactivating the component. Because
>>> Apache Celix has no module layer (yet), the only way to provide this
>>> is by creating and registering a service. (Or am I missing
>>> something?).
>>
>> I want to use dynamic loading for this. Already did some testing and this
>> works.
>>
> Looking at this, the module layer isn't involved at all. In Java OSGi the
> module layer is used to extend the classpath of bundles. This is done using
> the bundle's own private/exported packages and all imported packages.
>
> For DS, it is not possible to use the module layer for 2 reasons:
> 1) Components are typically (and probably should be) placed in the private
> package, and as such are not available to other bundles via the module layer
> 2) If component are exported, the DS bundle needs an import for all these
> bundle (a dynamic-import: * would probably work.. but (1) makes this a
> needless point anyway)
>
> What actually is done in DS, is some usage of reflection to instantiate a
> class based on the information in the component.xml. This simply bypasses
> the module layer.
> One could as well say that the DS implementation takes over the job (from
> the framework) of executing the activator. Of course it does some more
> things, like dependency injection.
>
> For Celix an (maybe not complete) alternative for reflection is dynamic
> loading. The framework uses this to invoke the activator. This can be done
> since the names of the activator functions are known.
> Using dynamic loading on other places is still possible though (I don't
> think Celix should put any restrictions on the language/libraries, although
> some best practices are important! Ie in Java OSGi it is still possible to
> mess with the classloader, but doing so is most of the times a (really) bad
> idea.).
> Since for a DS component, metadata is stored in the component.xml, the DS
> implementation knows some entry points of the component library. Combining
> these two, usage of dynamic loading and the component metadata, makes it
> possible for DS to create/update the component and inject its dependencies.
> The fact that there is no module layer/classpath even makes this a little
> bit simpler, in Java the DS has to create the component on the bundle's own
> classloader, for Celix it is simply an invocation of a function pointer
> created using dlopen and dlsym.
> This also fits the analogy I made earlier, for Celix DS again takes over
> the job of the framework and creates the component etc.
>
>
>>> So a declarative service service would be needed to make
>>> this work and I think thats not the way to go.
>>>
>>> I agree with Alexander that a simple solution would be to add this to
>>> the framework. In that case the framework SCR has access to the shared
>>> libraries and can use dynamic object loading with the names (for
>>> activate/deactivate/etc) provided in the DS XML. Although not a nice
>>> as a separated SRC bundle, IMO this is -for now - the best solution.
>>
>> I think a separate bundle can work for this..
>>
> I never meant to add something to the framework, I guess my wording in a
> previous email was a little awkward..
>
> As stated above, I do think a separate bundle is doable, without strange
> hacks/workaround needed in either the DS implementation or the framework.
>
> I hope this makes sense, and feel free to shoot if you see any gaps/issues!
>

good explanation.
thanks

-- 
Ferry Huberts



Re: Celix and Declarative Services

Posted by Alexander Broekhuis <a....@gmail.com>.
I've thought about this a little more, and I'll try to explain what I have
in mind.

> A Service Component Runtime (SCR) needs to have access to functions in
> > another module for activating/deactivating the component. Because
> > Apache Celix has no module layer (yet), the only way to provide this
> > is by creating and registering a service. (Or am I missing
> > something?).
>
> I want to use dynamic loading for this. Already did some testing and this
> works.
>
Looking at this, the module layer isn't involved at all. In Java OSGi the
module layer is used to extend the classpath of bundles. This is done using
the bundle's own private/exported packages and all imported packages.

For DS, it is not possible to use the module layer for 2 reasons:
1) Components are typically (and probably should be) placed in the private
package, and as such are not available to other bundles via the module layer
2) If component are exported, the DS bundle needs an import for all these
bundle (a dynamic-import: * would probably work.. but (1) makes this a
needless point anyway)

What actually is done in DS, is some usage of reflection to instantiate a
class based on the information in the component.xml. This simply bypasses
the module layer.
One could as well say that the DS implementation takes over the job (from
the framework) of executing the activator. Of course it does some more
things, like dependency injection.

For Celix an (maybe not complete) alternative for reflection is dynamic
loading. The framework uses this to invoke the activator. This can be done
since the names of the activator functions are known.
Using dynamic loading on other places is still possible though (I don't
think Celix should put any restrictions on the language/libraries, although
some best practices are important! Ie in Java OSGi it is still possible to
mess with the classloader, but doing so is most of the times a (really) bad
idea.).
Since for a DS component, metadata is stored in the component.xml, the DS
implementation knows some entry points of the component library. Combining
these two, usage of dynamic loading and the component metadata, makes it
possible for DS to create/update the component and inject its dependencies.
The fact that there is no module layer/classpath even makes this a little
bit simpler, in Java the DS has to create the component on the bundle's own
classloader, for Celix it is simply an invocation of a function pointer
created using dlopen and dlsym.
This also fits the analogy I made earlier, for Celix DS again takes over
the job of the framework and creates the component etc.


> > So a declarative service service would be needed to make
> > this work and I think thats not the way to go.
> >
> > I agree with Alexander that a simple solution would be to add this to
> > the framework. In that case the framework SCR has access to the shared
> > libraries and can use dynamic object loading with the names (for
> > activate/deactivate/etc) provided in the DS XML. Although not a nice
> > as a separated SRC bundle, IMO this is -for now - the best solution.
>
> I think a separate bundle can work for this..
>
I never meant to add something to the framework, I guess my wording in a
previous email was a little awkward..

As stated above, I do think a separate bundle is doable, without strange
hacks/workaround needed in either the DS implementation or the framework.

I hope this makes sense, and feel free to shoot if you see any gaps/issues!

-- 
Met vriendelijke groet,

Alexander Broekhuis

Re: Celix and Declarative Services

Posted by Pepijn Noltes <pe...@gmail.com>.
On Tue, Jun 26, 2012 at 9:01 PM, Alexander Broekhuis
<a....@gmail.com> wrote:
> Sent from my mobile.. So might be strangely formatted.
>
>>
>> A Service Component Runtime (SCR) needs to have access to functions in
>> another module for activating/deactivating the component. Because
>> Apache Celix has no module layer (yet), the only way to provide this
>> is by creating and registering a service. (Or am I missing
>> something?).
>
> I want to use dynamic loading for this. Already did some testing and this
> works.
>
>> So a declarative service service would be needed to make
>> this work and I think thats not the way to go.
>>
>> I agree with Alexander that a simple solution would be to add this to
>> the framework. In that case the framework SCR has access to the shared
>> libraries and can use dynamic object loading with the names (for
>> activate/deactivate/etc) provided in the DS XML. Although not a nice
>> as a separated SRC bundle, IMO this is -for now - the best solution.
>
> I think a separate bundle can work for this..

Ok, great the hear. I'm curious how this can work with separate
bundles, so keep us informed if you have some more results ;)


>
>>
>> Greetings,
>> Pepijn

Re: Celix and Declarative Services

Posted by Alexander Broekhuis <a....@gmail.com>.
Sent from my mobile.. So might be strangely formatted.

>
> A Service Component Runtime (SCR) needs to have access to functions in
> another module for activating/deactivating the component. Because
> Apache Celix has no module layer (yet), the only way to provide this
> is by creating and registering a service. (Or am I missing
> something?).

I want to use dynamic loading for this. Already did some testing and this
works.

> So a declarative service service would be needed to make
> this work and I think thats not the way to go.
>
> I agree with Alexander that a simple solution would be to add this to
> the framework. In that case the framework SCR has access to the shared
> libraries and can use dynamic object loading with the names (for
> activate/deactivate/etc) provided in the DS XML. Although not a nice
> as a separated SRC bundle, IMO this is -for now - the best solution.

I think a separate bundle can work for this..

>
> Greetings,
> Pepijn

Re: Celix and Declarative Services

Posted by Pepijn Noltes <pe...@gmail.com>.
Hi All,

On Tue, Jun 26, 2012 at 2:59 PM, Ferry Huberts <ma...@hupie.com> wrote:
>
>
> On 26-06-12 14:28, Alexander Broekhuis wrote:
>>
>> Hi all,
>>
>> After Ferry's question I've been looking a little at the OSGi Declarative
>> Services spec, and I think most of it can be realized using the current
>> Celix implementation.
>>
>
> that would be absolutely awesome!
I agree this would be a really nice feature.
>
>
>> One of the problems I've seen so far is related to service registration.
>> Using Java a service is an interface, and through reflection and the
>> implementation of the component, this interface can be registered as a
>> service by the DS implementation.
>> In Celix a service is a struct with function pointers, which has to be
>> instantiated by the user. It is not possible to do this dynamically, the
>> DS
>> implementation does not know the functions of the component etc.
>> A simple solution would be to use an additional function in the component
>> in which the service struct is created. Downside of this is, that there is
>> no strict separation of component and framework code....
>
>
> Why not? (maybe I'm missing something)
>
> IMHO it's just a method extra on the 'activator' interface (or an extra
> 'special' interface).
>
> Right now you have start/stop/etc there. You'd just be adding something like
> 'instantiateServiceRegistrationStruct' there, wouldn't you?
>

A Service Component Runtime (SCR) needs to have access to functions in
another module for activating/deactivating the component. Because
Apache Celix has no module layer (yet), the only way to provide this
is by creating and registering a service. (Or am I missing
something?). So a declarative service service would be needed to make
this work and I think thats not the way to go.

I agree with Alexander that a simple solution would be to add this to
the framework. In that case the framework SCR has access to the shared
libraries and can use dynamic object loading with the names (for
activate/deactivate/etc) provided in the DS XML. Although not a nice
as a separated SRC bundle, IMO this is -for now - the best solution.

Greetings,
Pepijn

Re: Celix and Declarative Services

Posted by Ferry Huberts <ma...@hupie.com>.

On 26-06-12 14:28, Alexander Broekhuis wrote:
> Hi all,
>
> After Ferry's question I've been looking a little at the OSGi Declarative
> Services spec, and I think most of it can be realized using the current
> Celix implementation.
>

that would be absolutely awesome!

> One of the problems I've seen so far is related to service registration.
> Using Java a service is an interface, and through reflection and the
> implementation of the component, this interface can be registered as a
> service by the DS implementation.
> In Celix a service is a struct with function pointers, which has to be
> instantiated by the user. It is not possible to do this dynamically, the DS
> implementation does not know the functions of the component etc.
> A simple solution would be to use an additional function in the component
> in which the service struct is created. Downside of this is, that there is
> no strict separation of component and framework code....

Why not? (maybe I'm missing something)

IMHO it's just a method extra on the 'activator' interface (or an extra 
'special' interface).

Right now you have start/stop/etc there. You'd just be adding something 
like 'instantiateServiceRegistrationStruct' there, wouldn't you?

Seeing as it's C, for me that'd be ok.

A disadvantage would be that you'd probably still have to implement that 
function even if you're not using DS, right?

>
> Perhaps someone else has some ideas how this can be solved differently....
>

-- 
Ferry Huberts