You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@felix.apache.org by Guillaume Nodet <gn...@gmail.com> on 2009/05/07 12:30:29 UTC

Corner case where ServiceListener do not receive events for matching services

I've just finished debugging a corner case in karaf  where a
ServiceListener did not receive events when a matching service was
registered.
The problem is not very simple:
  * the service is exposed via a ServiceFactory
  * the service factory does not belong to the same classloader as
the interface of the exposed service
  * the bundle exporting the service does not have a direct import on
the interface exposed

This leads to the service listener not being invoked because
Util.isServiceAssignable() returns false.
I think it's a problem, but I've no idea how to solve it.  The only
way I can think about is to actually check the service class returned
by the factory instead of the factory, but it may cause side effects,
not sure.

Thoughts?

--
Cheers,
Guillaume Nodet
------------------------
Blog: http://gnodet.blogspot.com/
------------------------
Open Source SOA
http://fusesource.com

Re: Corner case where ServiceListener do not receive events for matching services

Posted by "Richard S. Hall" <he...@ungoverned.org>.
On 5/13/09 2:21 AM, Guillaume Nodet wrote:
> Actually, I think loading the class is a very bad idea.
> I know the lazy activation policy has not been implemented, but it
> would be, loading the class at this point would trigger the bundle and
> would kinda break the lazy activation policy.
> I think the only right way is to use the wires between the bundle to
> check if the class is compatible.
>    

That's the issue. If there were wires we wouldn't need to load the 
class, since we use the wires first if they exist. I commented on this here:

     https://issues.apache.org/jira/browse/FELIX-1131

-> richard
> 2009/5/7 Karl Pauls<ka...@gmail.com>:
>    
>> I guess the idea behind the way we currently do things is that we want
>> to be lazy. If we would check on the class of the object created by
>> the service factory we might trigger unnecessary service creations.
>> However, your case might force us to do that unless we can find a
>> smart way to figure out this information by looking at the wiring of
>> the bundles. From your description I doubt that this is possible but
>> we probably have to think about it.
>>
>> Definitely sounds to me that you should create a JIRA issue and maybe
>> attach your example.
>>
>> regards,
>>
>> Karl
>>
>> On Thu, May 7, 2009 at 1:49 PM, Guillaume Nodet<gn...@gmail.com>  wrote:
>>      
>>> On Thu, May 7, 2009 at 13:41, Felix Meschberger<fm...@gmail.com>  wrote:
>>>        
>>>> Hi,
>>>>
>>>> I am bit confused, too ;-)
>>>>
>>>> Guillaume Nodet schrieb:
>>>>          
>>>>> I've just finished debugging a corner case in karaf  where a
>>>>> ServiceListener did not receive events when a matching service was
>>>>> registered.
>>>>> The problem is not very simple:
>>>>>    * the service is exposed via a ServiceFactory
>>>>>            
>>>> So, the ServiceFactory must create objects implementing the service
>>>> interface, right ?
>>>>
>>>>          
>>>>>    * the service factory does not belong to the same classloader as
>>>>> the interface of the exposed service
>>>>>            
>>>> No problem. In case the factory and service interface are in different
>>>> bundles, this is expected.
>>>>
>>>>          
>>>>>    * the bundle exporting the service does not have a direct import on
>>>>> the interface exposed
>>>>>            
>>>> You mean, the bundle registering the ServiceFactory ?
>>>>
>>>> In this case, I would assume, this is an invalid service registration,
>>>> since the registering bundle does not know about the service interface,
>>>> unless the service interface is contained in the same bundle as the
>>>> ServiceFactory implementation.
>>>>
>>>> This leads to the suspicion, that there are two actual service interface
>>>> class objects: The public one used by the listener and another one
>>>> (exported or not) used by the ServiceFactory implementation.
>>>>
>>>> Or are there three bundles ? (1) exporting the service interface, (2)
>>>> exporting the service implementation and (3) registering the
>>>> ServiceFactory as a service for the service interface defined by (1) and
>>>> creating implementations located in (2) ?
>>>>
>>>> Or, maybe, I am completely wrong ....
>>>>          
>>> In my case, the bundle exporting the service defines a class that
>>> indirectly implement the required interface by inheriting a class from
>>> another package.
>>> So I have 3 bundles:
>>>   * bundle A defines an interface R and a class S in different
>>> packages, whith S implementing R
>>>   * bundle B defines a class T extending S, it has an import statement
>>> on S package, but not on R package
>>>   * bundle C defines a ServiceFactory that export T service without
>>> any import on any package from R, S, T
>>> Maybe the service registration is invalid because bundle B does not
>>> import R package, but the service actually implement the right
>>> interface
>>>
>>>        
>>>> Regards
>>>> Felix
>>>>
>>>>          
>>>>> This leads to the service listener not being invoked because
>>>>> Util.isServiceAssignable() returns false.
>>>>> I think it's a problem, but I've no idea how to solve it.  The only
>>>>> way I can think about is to actually check the service class returned
>>>>> by the factory instead of the factory, but it may cause side effects,
>>>>> not sure.
>>>>>
>>>>> Thoughts?
>>>>>
>>>>> --
>>>>> Cheers,
>>>>> Guillaume Nodet
>>>>> ------------------------
>>>>> Blog: http://gnodet.blogspot.com/
>>>>> ------------------------
>>>>> Open Source SOA
>>>>> http://fusesource.com
>>>>>
>>>>>            
>>>
>>> --
>>> Cheers,
>>> Guillaume Nodet
>>> ------------------------
>>> Blog: http://gnodet.blogspot.com/
>>> ------------------------
>>> Open Source SOA
>>> http://fusesource.com
>>>
>>>        
>>
>> --
>> Karl Pauls
>> karlpauls@gmail.com
>>
>>      
>
>
>
>    

Re: Corner case where ServiceListener do not receive events for matching services

Posted by Guillaume Nodet <gn...@gmail.com>.
Actually, I think loading the class is a very bad idea.
I know the lazy activation policy has not been implemented, but it
would be, loading the class at this point would trigger the bundle and
would kinda break the lazy activation policy.
I think the only right way is to use the wires between the bundle to
check if the class is compatible.

2009/5/7 Karl Pauls <ka...@gmail.com>:
> I guess the idea behind the way we currently do things is that we want
> to be lazy. If we would check on the class of the object created by
> the service factory we might trigger unnecessary service creations.
> However, your case might force us to do that unless we can find a
> smart way to figure out this information by looking at the wiring of
> the bundles. From your description I doubt that this is possible but
> we probably have to think about it.
>
> Definitely sounds to me that you should create a JIRA issue and maybe
> attach your example.
>
> regards,
>
> Karl
>
> On Thu, May 7, 2009 at 1:49 PM, Guillaume Nodet <gn...@gmail.com> wrote:
>> On Thu, May 7, 2009 at 13:41, Felix Meschberger <fm...@gmail.com> wrote:
>>> Hi,
>>>
>>> I am bit confused, too ;-)
>>>
>>> Guillaume Nodet schrieb:
>>>> I've just finished debugging a corner case in karaf  where a
>>>> ServiceListener did not receive events when a matching service was
>>>> registered.
>>>> The problem is not very simple:
>>>>   * the service is exposed via a ServiceFactory
>>>
>>> So, the ServiceFactory must create objects implementing the service
>>> interface, right ?
>>>
>>>>   * the service factory does not belong to the same classloader as
>>>> the interface of the exposed service
>>>
>>> No problem. In case the factory and service interface are in different
>>> bundles, this is expected.
>>>
>>>>   * the bundle exporting the service does not have a direct import on
>>>> the interface exposed
>>>
>>> You mean, the bundle registering the ServiceFactory ?
>>>
>>> In this case, I would assume, this is an invalid service registration,
>>> since the registering bundle does not know about the service interface,
>>> unless the service interface is contained in the same bundle as the
>>> ServiceFactory implementation.
>>>
>>> This leads to the suspicion, that there are two actual service interface
>>> class objects: The public one used by the listener and another one
>>> (exported or not) used by the ServiceFactory implementation.
>>>
>>> Or are there three bundles ? (1) exporting the service interface, (2)
>>> exporting the service implementation and (3) registering the
>>> ServiceFactory as a service for the service interface defined by (1) and
>>> creating implementations located in (2) ?
>>>
>>> Or, maybe, I am completely wrong ....
>>
>> In my case, the bundle exporting the service defines a class that
>> indirectly implement the required interface by inheriting a class from
>> another package.
>> So I have 3 bundles:
>>  * bundle A defines an interface R and a class S in different
>> packages, whith S implementing R
>>  * bundle B defines a class T extending S, it has an import statement
>> on S package, but not on R package
>>  * bundle C defines a ServiceFactory that export T service without
>> any import on any package from R, S, T
>> Maybe the service registration is invalid because bundle B does not
>> import R package, but the service actually implement the right
>> interface
>>
>>> Regards
>>> Felix
>>>
>>>>
>>>> This leads to the service listener not being invoked because
>>>> Util.isServiceAssignable() returns false.
>>>> I think it's a problem, but I've no idea how to solve it.  The only
>>>> way I can think about is to actually check the service class returned
>>>> by the factory instead of the factory, but it may cause side effects,
>>>> not sure.
>>>>
>>>> Thoughts?
>>>>
>>>> --
>>>> Cheers,
>>>> Guillaume Nodet
>>>> ------------------------
>>>> Blog: http://gnodet.blogspot.com/
>>>> ------------------------
>>>> Open Source SOA
>>>> http://fusesource.com
>>>>
>>>
>>
>>
>>
>> --
>> Cheers,
>> Guillaume Nodet
>> ------------------------
>> Blog: http://gnodet.blogspot.com/
>> ------------------------
>> Open Source SOA
>> http://fusesource.com
>>
>
>
>
> --
> Karl Pauls
> karlpauls@gmail.com
>



-- 
Cheers,
Guillaume Nodet
------------------------
Blog: http://gnodet.blogspot.com/
------------------------
Open Source SOA
http://fusesource.com

Re: Corner case where ServiceListener do not receive events for matching services

Posted by Karl Pauls <ka...@gmail.com>.
I guess the idea behind the way we currently do things is that we want
to be lazy. If we would check on the class of the object created by
the service factory we might trigger unnecessary service creations.
However, your case might force us to do that unless we can find a
smart way to figure out this information by looking at the wiring of
the bundles. From your description I doubt that this is possible but
we probably have to think about it.

Definitely sounds to me that you should create a JIRA issue and maybe
attach your example.

regards,

Karl

On Thu, May 7, 2009 at 1:49 PM, Guillaume Nodet <gn...@gmail.com> wrote:
> On Thu, May 7, 2009 at 13:41, Felix Meschberger <fm...@gmail.com> wrote:
>> Hi,
>>
>> I am bit confused, too ;-)
>>
>> Guillaume Nodet schrieb:
>>> I've just finished debugging a corner case in karaf  where a
>>> ServiceListener did not receive events when a matching service was
>>> registered.
>>> The problem is not very simple:
>>>   * the service is exposed via a ServiceFactory
>>
>> So, the ServiceFactory must create objects implementing the service
>> interface, right ?
>>
>>>   * the service factory does not belong to the same classloader as
>>> the interface of the exposed service
>>
>> No problem. In case the factory and service interface are in different
>> bundles, this is expected.
>>
>>>   * the bundle exporting the service does not have a direct import on
>>> the interface exposed
>>
>> You mean, the bundle registering the ServiceFactory ?
>>
>> In this case, I would assume, this is an invalid service registration,
>> since the registering bundle does not know about the service interface,
>> unless the service interface is contained in the same bundle as the
>> ServiceFactory implementation.
>>
>> This leads to the suspicion, that there are two actual service interface
>> class objects: The public one used by the listener and another one
>> (exported or not) used by the ServiceFactory implementation.
>>
>> Or are there three bundles ? (1) exporting the service interface, (2)
>> exporting the service implementation and (3) registering the
>> ServiceFactory as a service for the service interface defined by (1) and
>> creating implementations located in (2) ?
>>
>> Or, maybe, I am completely wrong ....
>
> In my case, the bundle exporting the service defines a class that
> indirectly implement the required interface by inheriting a class from
> another package.
> So I have 3 bundles:
>  * bundle A defines an interface R and a class S in different
> packages, whith S implementing R
>  * bundle B defines a class T extending S, it has an import statement
> on S package, but not on R package
>  * bundle C defines a ServiceFactory that export T service without
> any import on any package from R, S, T
> Maybe the service registration is invalid because bundle B does not
> import R package, but the service actually implement the right
> interface
>
>> Regards
>> Felix
>>
>>>
>>> This leads to the service listener not being invoked because
>>> Util.isServiceAssignable() returns false.
>>> I think it's a problem, but I've no idea how to solve it.  The only
>>> way I can think about is to actually check the service class returned
>>> by the factory instead of the factory, but it may cause side effects,
>>> not sure.
>>>
>>> Thoughts?
>>>
>>> --
>>> Cheers,
>>> Guillaume Nodet
>>> ------------------------
>>> Blog: http://gnodet.blogspot.com/
>>> ------------------------
>>> Open Source SOA
>>> http://fusesource.com
>>>
>>
>
>
>
> --
> Cheers,
> Guillaume Nodet
> ------------------------
> Blog: http://gnodet.blogspot.com/
> ------------------------
> Open Source SOA
> http://fusesource.com
>



-- 
Karl Pauls
karlpauls@gmail.com

Re: Corner case where ServiceListener do not receive events for matching services

Posted by "Richard S. Hall" <he...@ungoverned.org>.
On 5/7/09 9:25 AM, Stuart McCulloch wrote:
> That sounds like a question for the osgi-dev list - certainly it can't 
> check
> the actual instance without breaking the laziness of service factories. It
> could perhaps check the wiring, but there may be reasons why this isn't done
> (lazy package resolution?)
>
> Or do i miss something ?
>    

Service factories weren't created for purposes of laziness, they were so 
the service could know who is requesting it and possibly tailor the 
service for the requester.

In this case, we would have to modify our check to always eagerly get 
the service object from the factory. Sort of sucks, but I don't see 
another way.

-> richard

>> On Thu, May 7, 2009 at 15:07, Felix Meschberger<fm...@gmail.com>
>> wrote:
>>      
>>> Hi,
>>>
>>> Guillaume Nodet schrieb:
>>>        
>>>> In my case, the bundle exporting the service defines a class that
>>>> indirectly implement the required interface by inheriting a class from
>>>> another package.
>>>> So I have 3 bundles:
>>>>    * bundle A defines an interface R and a class S in different
>>>> packages, whith S implementing R
>>>>    * bundle B defines a class T extending S, it has an import statement
>>>> on S package, but not on R package
>>>>    * bundle C defines a ServiceFactory that export T service without
>>>> any import on any package from R, S, T
>>>> Maybe the service registration is invalid because bundle B does not
>>>> import R package, but the service actually implement the right
>>>> interface
>>>>          
>>> Hmm, I fear, that in this case the framework is not able to validate the
>>> registration and thus send events since the framework has no way of
>>> telling which service interface (class object) is really implemented by
>>> the factory.
>>>
>>> As I understand it, this corner case is not properly handled in the
>>> spec, yet I would conclude from the specification, that not sending a
>>> ServiceEvent is correct in this case: An event is only sent if the
>>> service providing bundle and the event listener bundle use the service
>>> class from the same source, or specifically if
>>> ServiceReference.isAssignableTo(Bundle, String) returns true.
>>>
>>> Now, given the bundle providing the service (bundle C here) has no
>>> wiring to the actual service class (R exported by bundle A) and hence
>>> the isAssignableTo method will always return false.
>>>
>>> Regards
>>> Felix
>>>
>>>        
>>>>> Regards
>>>>> Felix
>>>>>
>>>>>            
>>>>>> This leads to the service listener not being invoked because
>>>>>> Util.isServiceAssignable() returns false.
>>>>>> I think it's a problem, but I've no idea how to solve it.  The only
>>>>>> way I can think about is to actually check the service class returned
>>>>>> by the factory instead of the factory, but it may cause side effects,
>>>>>> not sure.
>>>>>>
>>>>>> Thoughts?
>>>>>>
>>>>>> --
>>>>>> Cheers,
>>>>>> Guillaume Nodet
>>>>>> ------------------------
>>>>>> Blog: http://gnodet.blogspot.com/
>>>>>> ------------------------
>>>>>> Open Source SOA
>>>>>> http://fusesource.com
>>>>>>
>>>>>>              
>>>>
>>>>          
>>
>> --
>> Cheers,
>> Guillaume Nodet
>> ------------------------
>> Blog: http://gnodet.blogspot.com/
>> ------------------------
>> Open Source SOA
>> http://fusesource.com
>>
>>      
>
>
>
>    

Re: Corner case where ServiceListener do not receive events for matching services

Posted by Stuart McCulloch <mc...@gmail.com>.
2009/5/7 Guillaume Nodet <gn...@gmail.com>

> So I guess in this case the registration should throw an exception.
> Currently the test is as follow:
>
>        try
>        {
>            // Check to make sure that the service object is
>            // an instance of all service classes; ignore if
>            // service object is a service factory.
>            if (!(svcObj instanceof ServiceFactory))
>            {
>                for (int i = 0; i < classNames.length; i++)
>                {
>                    Class clazz =
> Util.loadClassUsingClass(svcObj.getClass(), classNames[i]);
>                    if (clazz == null)
>                    {
>                        throw new IllegalArgumentException(
>                            "Cannot cast service: " + classNames[i]);
>                    }
>                    else if (!clazz.isAssignableFrom(svcObj.getClass()))
>                    {
>                        throw new IllegalArgumentException(
>                            "Service object is not an instance of \""
>                            + classNames[i] + "\".");
>                    }
>                }
>            }
>
>            reg = m_registry.registerService(bundle, classNames, svcObj,
> dict);
>        }
>
>
> I think it should be consistent with isAssignable and reject and
> registration if the exporting bundle does not have any wire to all the
> packages of the exported classes.
>

That sounds like a question for the osgi-dev list - certainly it can't check
the actual instance without breaking the laziness of service factories. It
could perhaps check the wiring, but there may be reasons why this isn't done
(lazy package resolution?)

Or do i miss something ?
>
> On Thu, May 7, 2009 at 15:07, Felix Meschberger <fm...@gmail.com>
> wrote:
> > Hi,
> >
> > Guillaume Nodet schrieb:
> >>
> >> In my case, the bundle exporting the service defines a class that
> >> indirectly implement the required interface by inheriting a class from
> >> another package.
> >> So I have 3 bundles:
> >>   * bundle A defines an interface R and a class S in different
> >> packages, whith S implementing R
> >>   * bundle B defines a class T extending S, it has an import statement
> >> on S package, but not on R package
> >>   * bundle C defines a ServiceFactory that export T service without
> >> any import on any package from R, S, T
> >> Maybe the service registration is invalid because bundle B does not
> >> import R package, but the service actually implement the right
> >> interface
> >
> > Hmm, I fear, that in this case the framework is not able to validate the
> > registration and thus send events since the framework has no way of
> > telling which service interface (class object) is really implemented by
> > the factory.
> >
> > As I understand it, this corner case is not properly handled in the
> > spec, yet I would conclude from the specification, that not sending a
> > ServiceEvent is correct in this case: An event is only sent if the
> > service providing bundle and the event listener bundle use the service
> > class from the same source, or specifically if
> > ServiceReference.isAssignableTo(Bundle, String) returns true.
> >
> > Now, given the bundle providing the service (bundle C here) has no
> > wiring to the actual service class (R exported by bundle A) and hence
> > the isAssignableTo method will always return false.
> >
> > Regards
> > Felix
> >
> >>
> >>> Regards
> >>> Felix
> >>>
> >>>> This leads to the service listener not being invoked because
> >>>> Util.isServiceAssignable() returns false.
> >>>> I think it's a problem, but I've no idea how to solve it.  The only
> >>>> way I can think about is to actually check the service class returned
> >>>> by the factory instead of the factory, but it may cause side effects,
> >>>> not sure.
> >>>>
> >>>> Thoughts?
> >>>>
> >>>> --
> >>>> Cheers,
> >>>> Guillaume Nodet
> >>>> ------------------------
> >>>> Blog: http://gnodet.blogspot.com/
> >>>> ------------------------
> >>>> Open Source SOA
> >>>> http://fusesource.com
> >>>>
> >>
> >>
> >>
> >
>
>
>
> --
> Cheers,
> Guillaume Nodet
> ------------------------
> Blog: http://gnodet.blogspot.com/
> ------------------------
> Open Source SOA
> http://fusesource.com
>



-- 
Cheers, Stuart

Re: Corner case where ServiceListener do not receive events for matching services

Posted by Guillaume Nodet <gn...@gmail.com>.
So I guess in this case the registration should throw an exception.
Currently the test is as follow:

        try
        {
            // Check to make sure that the service object is
            // an instance of all service classes; ignore if
            // service object is a service factory.
            if (!(svcObj instanceof ServiceFactory))
            {
                for (int i = 0; i < classNames.length; i++)
                {
                    Class clazz =
Util.loadClassUsingClass(svcObj.getClass(), classNames[i]);
                    if (clazz == null)
                    {
                        throw new IllegalArgumentException(
                            "Cannot cast service: " + classNames[i]);
                    }
                    else if (!clazz.isAssignableFrom(svcObj.getClass()))
                    {
                        throw new IllegalArgumentException(
                            "Service object is not an instance of \""
                            + classNames[i] + "\".");
                    }
                }
            }

            reg = m_registry.registerService(bundle, classNames, svcObj, dict);
        }


I think it should be consistent with isAssignable and reject and
registration if the exporting bundle does not have any wire to all the
packages of the exported classes.
Or do i miss something ?

On Thu, May 7, 2009 at 15:07, Felix Meschberger <fm...@gmail.com> wrote:
> Hi,
>
> Guillaume Nodet schrieb:
>>
>> In my case, the bundle exporting the service defines a class that
>> indirectly implement the required interface by inheriting a class from
>> another package.
>> So I have 3 bundles:
>>   * bundle A defines an interface R and a class S in different
>> packages, whith S implementing R
>>   * bundle B defines a class T extending S, it has an import statement
>> on S package, but not on R package
>>   * bundle C defines a ServiceFactory that export T service without
>> any import on any package from R, S, T
>> Maybe the service registration is invalid because bundle B does not
>> import R package, but the service actually implement the right
>> interface
>
> Hmm, I fear, that in this case the framework is not able to validate the
> registration and thus send events since the framework has no way of
> telling which service interface (class object) is really implemented by
> the factory.
>
> As I understand it, this corner case is not properly handled in the
> spec, yet I would conclude from the specification, that not sending a
> ServiceEvent is correct in this case: An event is only sent if the
> service providing bundle and the event listener bundle use the service
> class from the same source, or specifically if
> ServiceReference.isAssignableTo(Bundle, String) returns true.
>
> Now, given the bundle providing the service (bundle C here) has no
> wiring to the actual service class (R exported by bundle A) and hence
> the isAssignableTo method will always return false.
>
> Regards
> Felix
>
>>
>>> Regards
>>> Felix
>>>
>>>> This leads to the service listener not being invoked because
>>>> Util.isServiceAssignable() returns false.
>>>> I think it's a problem, but I've no idea how to solve it.  The only
>>>> way I can think about is to actually check the service class returned
>>>> by the factory instead of the factory, but it may cause side effects,
>>>> not sure.
>>>>
>>>> Thoughts?
>>>>
>>>> --
>>>> Cheers,
>>>> Guillaume Nodet
>>>> ------------------------
>>>> Blog: http://gnodet.blogspot.com/
>>>> ------------------------
>>>> Open Source SOA
>>>> http://fusesource.com
>>>>
>>
>>
>>
>



-- 
Cheers,
Guillaume Nodet
------------------------
Blog: http://gnodet.blogspot.com/
------------------------
Open Source SOA
http://fusesource.com

Re: Corner case where ServiceListener do not receive events for matching services

Posted by Stuart McCulloch <mc...@gmail.com>.
2009/5/7 Felix Meschberger <fm...@gmail.com>

> Hi,
>
> Guillaume Nodet schrieb:
> >
> > In my case, the bundle exporting the service defines a class that
> > indirectly implement the required interface by inheriting a class from
> > another package.
> > So I have 3 bundles:
> >   * bundle A defines an interface R and a class S in different
> > packages, whith S implementing R
> >   * bundle B defines a class T extending S, it has an import statement
> > on S package, but not on R package
> >   * bundle C defines a ServiceFactory that export T service without
> > any import on any package from R, S, T
> > Maybe the service registration is invalid because bundle B does not
> > import R package, but the service actually implement the right
> > interface
>
> Hmm, I fear, that in this case the framework is not able to validate the
> registration and thus send events since the framework has no way of
> telling which service interface (class object) is really implemented by
> the factory.
>
> As I understand it, this corner case is not properly handled in the
> spec, yet I would conclude from the specification, that not sending a
> ServiceEvent is correct in this case: An event is only sent if the
> service providing bundle and the event listener bundle use the service
> class from the same source, or specifically if
> ServiceReference.isAssignableTo(Bundle, String) returns true.
>
> Now, given the bundle providing the service (bundle C here) has no
> wiring to the actual service class (R exported by bundle A) and hence
> the isAssignableTo method will always return false.
>

yes, that's how I read the spec:


http://www.osgi.org/javadoc/r4v41/org/osgi/framework/ServiceReference.html#isAssignableTo(org.osgi.framework.Bundle,%20java.lang.String)

   "For the bundle that registered the service referenced by this
ServiceReference (registrant bundle); find the source for the package. If no
source is found then return true if the registrant bundle is equal to the
specified bundle; otherwise return false."

so if C is doing the registering, but doesn't have a wire for one of the
packages then it seems only it can see the service.

btw, you can always extend AllServiceListener to listen for all service
events, regardless of class-compatibility

Regards
> Felix
>
> >
> >> Regards
> >> Felix
> >>
> >>> This leads to the service listener not being invoked because
> >>> Util.isServiceAssignable() returns false.
> >>> I think it's a problem, but I've no idea how to solve it.  The only
> >>> way I can think about is to actually check the service class returned
> >>> by the factory instead of the factory, but it may cause side effects,
> >>> not sure.
> >>>
> >>> Thoughts?
> >>>
> >>> --
> >>> Cheers,
> >>> Guillaume Nodet
> >>> ------------------------
> >>> Blog: http://gnodet.blogspot.com/
> >>> ------------------------
> >>> Open Source SOA
> >>> http://fusesource.com
> >>>
> >
> >
> >
>



-- 
Cheers, Stuart

Re: Corner case where ServiceListener do not receive events for matching services

Posted by Felix Meschberger <fm...@gmail.com>.
Hi,

Guillaume Nodet schrieb:
> 
> In my case, the bundle exporting the service defines a class that
> indirectly implement the required interface by inheriting a class from
> another package.
> So I have 3 bundles:
>   * bundle A defines an interface R and a class S in different
> packages, whith S implementing R
>   * bundle B defines a class T extending S, it has an import statement
> on S package, but not on R package
>   * bundle C defines a ServiceFactory that export T service without
> any import on any package from R, S, T
> Maybe the service registration is invalid because bundle B does not
> import R package, but the service actually implement the right
> interface

Hmm, I fear, that in this case the framework is not able to validate the
registration and thus send events since the framework has no way of
telling which service interface (class object) is really implemented by
the factory.

As I understand it, this corner case is not properly handled in the
spec, yet I would conclude from the specification, that not sending a
ServiceEvent is correct in this case: An event is only sent if the
service providing bundle and the event listener bundle use the service
class from the same source, or specifically if
ServiceReference.isAssignableTo(Bundle, String) returns true.

Now, given the bundle providing the service (bundle C here) has no
wiring to the actual service class (R exported by bundle A) and hence
the isAssignableTo method will always return false.

Regards
Felix

> 
>> Regards
>> Felix
>>
>>> This leads to the service listener not being invoked because
>>> Util.isServiceAssignable() returns false.
>>> I think it's a problem, but I've no idea how to solve it.  The only
>>> way I can think about is to actually check the service class returned
>>> by the factory instead of the factory, but it may cause side effects,
>>> not sure.
>>>
>>> Thoughts?
>>>
>>> --
>>> Cheers,
>>> Guillaume Nodet
>>> ------------------------
>>> Blog: http://gnodet.blogspot.com/
>>> ------------------------
>>> Open Source SOA
>>> http://fusesource.com
>>>
> 
> 
> 

Re: Corner case where ServiceListener do not receive events for matching services

Posted by Guillaume Nodet <gn...@gmail.com>.
On Thu, May 7, 2009 at 13:41, Felix Meschberger <fm...@gmail.com> wrote:
> Hi,
>
> I am bit confused, too ;-)
>
> Guillaume Nodet schrieb:
>> I've just finished debugging a corner case in karaf  where a
>> ServiceListener did not receive events when a matching service was
>> registered.
>> The problem is not very simple:
>>   * the service is exposed via a ServiceFactory
>
> So, the ServiceFactory must create objects implementing the service
> interface, right ?
>
>>   * the service factory does not belong to the same classloader as
>> the interface of the exposed service
>
> No problem. In case the factory and service interface are in different
> bundles, this is expected.
>
>>   * the bundle exporting the service does not have a direct import on
>> the interface exposed
>
> You mean, the bundle registering the ServiceFactory ?
>
> In this case, I would assume, this is an invalid service registration,
> since the registering bundle does not know about the service interface,
> unless the service interface is contained in the same bundle as the
> ServiceFactory implementation.
>
> This leads to the suspicion, that there are two actual service interface
> class objects: The public one used by the listener and another one
> (exported or not) used by the ServiceFactory implementation.
>
> Or are there three bundles ? (1) exporting the service interface, (2)
> exporting the service implementation and (3) registering the
> ServiceFactory as a service for the service interface defined by (1) and
> creating implementations located in (2) ?
>
> Or, maybe, I am completely wrong ....

In my case, the bundle exporting the service defines a class that
indirectly implement the required interface by inheriting a class from
another package.
So I have 3 bundles:
  * bundle A defines an interface R and a class S in different
packages, whith S implementing R
  * bundle B defines a class T extending S, it has an import statement
on S package, but not on R package
  * bundle C defines a ServiceFactory that export T service without
any import on any package from R, S, T
Maybe the service registration is invalid because bundle B does not
import R package, but the service actually implement the right
interface

> Regards
> Felix
>
>>
>> This leads to the service listener not being invoked because
>> Util.isServiceAssignable() returns false.
>> I think it's a problem, but I've no idea how to solve it.  The only
>> way I can think about is to actually check the service class returned
>> by the factory instead of the factory, but it may cause side effects,
>> not sure.
>>
>> Thoughts?
>>
>> --
>> Cheers,
>> Guillaume Nodet
>> ------------------------
>> Blog: http://gnodet.blogspot.com/
>> ------------------------
>> Open Source SOA
>> http://fusesource.com
>>
>



-- 
Cheers,
Guillaume Nodet
------------------------
Blog: http://gnodet.blogspot.com/
------------------------
Open Source SOA
http://fusesource.com

Re: Corner case where ServiceListener do not receive events for matching services

Posted by Felix Meschberger <fm...@gmail.com>.
Hi,

I am bit confused, too ;-)

Guillaume Nodet schrieb:
> I've just finished debugging a corner case in karaf  where a
> ServiceListener did not receive events when a matching service was
> registered.
> The problem is not very simple:
>   * the service is exposed via a ServiceFactory

So, the ServiceFactory must create objects implementing the service
interface, right ?

>   * the service factory does not belong to the same classloader as
> the interface of the exposed service

No problem. In case the factory and service interface are in different
bundles, this is expected.

>   * the bundle exporting the service does not have a direct import on
> the interface exposed

You mean, the bundle registering the ServiceFactory ?

In this case, I would assume, this is an invalid service registration,
since the registering bundle does not know about the service interface,
unless the service interface is contained in the same bundle as the
ServiceFactory implementation.

This leads to the suspicion, that there are two actual service interface
class objects: The public one used by the listener and another one
(exported or not) used by the ServiceFactory implementation.

Or are there three bundles ? (1) exporting the service interface, (2)
exporting the service implementation and (3) registering the
ServiceFactory as a service for the service interface defined by (1) and
creating implementations located in (2) ?

Or, maybe, I am completely wrong ....

Regards
Felix

> 
> This leads to the service listener not being invoked because
> Util.isServiceAssignable() returns false.
> I think it's a problem, but I've no idea how to solve it.  The only
> way I can think about is to actually check the service class returned
> by the factory instead of the factory, but it may cause side effects,
> not sure.
> 
> Thoughts?
> 
> --
> Cheers,
> Guillaume Nodet
> ------------------------
> Blog: http://gnodet.blogspot.com/
> ------------------------
> Open Source SOA
> http://fusesource.com
> 

Re: Corner case where ServiceListener do not receive events for matching services

Posted by Guillaume Nodet <gn...@gmail.com>.
Well, in my case, the line 426 of ServiceRegistrationImpl is executed:

                        allow =
getServiceRegistration().isClassAccessible(requestClass);

which looks like:

    protected boolean isClassAccessible(Class clazz)
    {
        try
        {
            // Try to load from the service object or service factory class.
            Class sourceClass = (m_factory != null)
                ? m_factory.getClass() : m_svcObj.getClass();
            Class targetClass = Util.loadClassUsingClass(sourceClass,
clazz.getName());
            return (targetClass == clazz);
        }
        catch (Exception ex)
        {
            // Ignore this and return false.
        }
        return false;
    }

So felix checks if the classloader used to load the factory can also
load the interface, which is not the case in my example.
So isClassAccessible returns false and the event is not dispatched to
the service listener.

On Thu, May 7, 2009 at 12:51, Stuart McCulloch <mc...@gmail.com> wrote:
> 2009/5/7 Guillaume Nodet <gn...@gmail.com>
>
>> I've just finished debugging a corner case in karaf  where a
>> ServiceListener did not receive events when a matching service was
>> registered.
>> The problem is not very simple:
>>   * the service is exposed via a ServiceFactory
>>   * the service factory does not belong to the same classloader as
>> the interface of the exposed service
>>   * the bundle exporting the service does not have a direct import on
>> the interface exposed
>>
>> This leads to the service listener not being invoked because
>> Util.isServiceAssignable() returns false.
>> I think it's a problem, but I've no idea how to solve it.  The only
>> way I can think about is to actually check the service class returned
>> by the factory instead of the factory, but it may cause side effects,
>> not sure.
>>
>> Thoughts?
>>
>
> not sure I quite understand where ServiceFactory comes into it...
>
> IIUIC "isAssignableTo()" checks the packages listed under the "objectClass"
> property and sees if there's any conflict between the wires for the
> registering
> bundle compared to the client bundle.
>
> so I would expect a normal instance and service factory to behave the same,
> as long as they provided the same set of packages as their "objectClass"
>
> are there a different set of packages in "objectClass" for the factory case?
>
> --
>> Cheers,
>> Guillaume Nodet
>> ------------------------
>> Blog: http://gnodet.blogspot.com/
>> ------------------------
>> Open Source SOA
>> http://fusesource.com
>>
>
>
>
> --
> Cheers, Stuart
>



-- 
Cheers,
Guillaume Nodet
------------------------
Blog: http://gnodet.blogspot.com/
------------------------
Open Source SOA
http://fusesource.com

Re: Corner case where ServiceListener do not receive events for matching services

Posted by Stuart McCulloch <mc...@gmail.com>.
2009/5/7 Guillaume Nodet <gn...@gmail.com>

> I've just finished debugging a corner case in karaf  where a
> ServiceListener did not receive events when a matching service was
> registered.
> The problem is not very simple:
>   * the service is exposed via a ServiceFactory
>   * the service factory does not belong to the same classloader as
> the interface of the exposed service
>   * the bundle exporting the service does not have a direct import on
> the interface exposed
>
> This leads to the service listener not being invoked because
> Util.isServiceAssignable() returns false.
> I think it's a problem, but I've no idea how to solve it.  The only
> way I can think about is to actually check the service class returned
> by the factory instead of the factory, but it may cause side effects,
> not sure.
>
> Thoughts?
>

not sure I quite understand where ServiceFactory comes into it...

IIUIC "isAssignableTo()" checks the packages listed under the "objectClass"
property and sees if there's any conflict between the wires for the
registering
bundle compared to the client bundle.

so I would expect a normal instance and service factory to behave the same,
as long as they provided the same set of packages as their "objectClass"

are there a different set of packages in "objectClass" for the factory case?

--
> Cheers,
> Guillaume Nodet
> ------------------------
> Blog: http://gnodet.blogspot.com/
> ------------------------
> Open Source SOA
> http://fusesource.com
>



-- 
Cheers, Stuart