You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@felix.apache.org by Mark Derricutt <ma...@talios.com> on 2008/04/30 01:54:20 UTC

isAssignableFrom - class loading issues when reloading bundles

Hey all,

Running into a small problem with reloading bundles which I'm sure's been
solved by something simple I'm not quite seeing.

The scenario is that I have two bundles A and B - A provides an interface
MountProvider, and B has a class that implements it.

When bundle A starts it looks for all bundles that provide an instance of
MountProvider, bundle A also listens to other bundles starting up which
provide the instance.

Things all work fine on startup.  Bundle A starts, Bundle B starts.  Bundle
A detects the MountProvider instance using the following code:

  String classname = (String)
bundle.getHeaders().get(SMX3_RESTLET_PROVIDER);
  Class activatorClass = bundle.loadClass(classname);
  if (MountProvider.class.isAssignableFrom(activatorClass)) {
    MountProvider mountRequestEvent = (MountProvider)
restActivatorClass.newInstance();
    mountRequestEvent.mountResources(mountManager);
  }


If I restart bundle B, the above code reruns fine as expected, finding the
updated MountProvider instance.

However, if I restart bundle A - when bundle B is processed again, the check
fails and processing isn't performed.  My assumption here is that the
MountProvider class from bundle B is an instance of "the original bundle A's
MountProvider", and not the "current bundle A's MountProvider" class so the
call to isAssignableFrom fails.

Whats the proper/OSGi way to check for this that respects the change in
class loaders?  Should I do something like:

  Class activatorClass = bundle.loadClass(classname);
  Class mountProviderClass =
bundle.loadClass(MountProvider.class.getName());
  if (mountProviderClass.isAssignableFrom(activatorClass)) {

instead?  And using an indirect reference to my MountProvider interface, as
seen by the bundle?

Thanks in advance,
Mark




-- 
"It is easier to optimize correct code than to correct optimized code." --
Bill Harlan

Re: isAssignableFrom - class loading issues when reloading bundles

Posted by Mark Derricutt <ma...@talios.com>.
Answering myself :)  This works, however I now need to use reflection to
call methods on my interface, as any casting to MountProvider triggers a
ClassCastException.  Reflection also seems to causing classloader issues
with objects being passed into Bundle B's methods.

On Wed, Apr 30, 2008 at 11:54 AM, Mark Derricutt <ma...@talios.com> wrote:

>   Class activatorClass = bundle.loadClass(classname);
>   Class mountProviderClass =
> bundle.loadClass(MountProvider.class.getName());
>   if (mountProviderClass.isAssignableFrom(activatorClass)) {
>


-- 
"It is easier to optimize correct code than to correct optimized code." --
Bill Harlan

Re: isAssignableFrom - class loading issues when reloading bundles

Posted by "Richard S. Hall" <he...@ungoverned.org>.
Stuart McCulloch wrote:
> 2008/4/30 Mark Derricutt <ma...@talios.com>:
>
>   
>> Oops - my bad.  Yes, simply stopping/starting Bundle A works fine, if I
>> update Bundle A however it doesn't.
>>
>> I can work around things by using reflection to execute the class I'm
>> loading from Bundle B, and moving the object I was passing over as a
>> parameter to be an exported OSGi service which is then looked up, it's not
>> as clean as I'd hoped.
>>
>>     
>
> if you want to update A (ie. to change it's implementation) but avoid
> the class cast issues then I'd suggest moving its public API classes
> into a separate bundle (A-interface)
>
> then you can start/stop/update A or B as much as you like...
>   

Yes, this is another good option and is also described in the FAQ...

-> richard

> Mark
>   
>> On Wed, Apr 30, 2008 at 3:37 PM, Richard S. Hall <he...@ungoverned.org>
>> wrote:
>>
>>     
>>> If I am understanding correctly, something seems fishy here.
>>>
>>> Simply restarting A should not cause a new class loader to be recreated.
>>>       
>> I
>>     
>>> believe you should only see a new class loader if you are updating A,
>>>       
>> for
>>     
>>> example.
>>>
>>> Is your description below accurate or are you updating the bundle?
>>>
>>> -> richard
>>>
>>>
>>> Mark Derricutt wrote:
>>>
>>>       
>>>> Hey all,
>>>>
>>>> Running into a small problem with reloading bundles which I'm sure's
>>>> been
>>>> solved by something simple I'm not quite seeing.
>>>>
>>>> The scenario is that I have two bundles A and B - A provides an
>>>> interface
>>>> MountProvider, and B has a class that implements it.
>>>>
>>>> When bundle A starts it looks for all bundles that provide an instance
>>>> of
>>>> MountProvider, bundle A also listens to other bundles starting up
>>>>         
>> which
>>     
>>>> provide the instance.
>>>>
>>>> Things all work fine on startup.  Bundle A starts, Bundle B starts.
>>>>  Bundle
>>>> A detects the MountProvider instance using the following code:
>>>>
>>>>  String classname = (String)
>>>> bundle.getHeaders().get(SMX3_RESTLET_PROVIDER);
>>>>  Class activatorClass = bundle.loadClass(classname);
>>>>  if (MountProvider.class.isAssignableFrom(activatorClass)) {
>>>>    MountProvider mountRequestEvent = (MountProvider)
>>>> restActivatorClass.newInstance();
>>>>    mountRequestEvent.mountResources(mountManager);
>>>>  }
>>>>
>>>>
>>>> If I restart bundle B, the above code reruns fine as expected, finding
>>>> the
>>>> updated MountProvider instance.
>>>>
>>>> However, if I restart bundle A - when bundle B is processed again, the
>>>> check
>>>> fails and processing isn't performed.  My assumption here is that the
>>>> MountProvider class from bundle B is an instance of "the original
>>>>         
>> bundle
>>     
>>>> A's
>>>> MountProvider", and not the "current bundle A's MountProvider" class
>>>>         
>> so
>>     
>>>> the
>>>> call to isAssignableFrom fails.
>>>>
>>>> Whats the proper/OSGi way to check for this that respects the change
>>>>         
>> in
>>     
>>>> class loaders?  Should I do something like:
>>>>
>>>>  Class activatorClass = bundle.loadClass(classname);
>>>>  Class mountProviderClass =
>>>> bundle.loadClass(MountProvider.class.getName());
>>>>  if (mountProviderClass.isAssignableFrom(activatorClass)) {
>>>>
>>>> instead?  And using an indirect reference to my MountProvider
>>>>         
>> interface,
>>     
>>>> as
>>>> seen by the bundle?
>>>>
>>>> Thanks in advance,
>>>> Mark
>>>>
>>>>
>>>>
>>>>
>>>>
>>>>
>>>>         
>>> ---------------------------------------------------------------------
>>> To unsubscribe, e-mail: users-unsubscribe@felix.apache.org
>>> For additional commands, e-mail: users-help@felix.apache.org
>>>
>>>
>>>       
>> --
>> "It is easier to optimize correct code than to correct optimized code." --
>> Bill Harlan
>>
>>     
>
>
>
>   

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@felix.apache.org
For additional commands, e-mail: users-help@felix.apache.org


Re: isAssignableFrom - class loading issues when reloading bundles

Posted by Stuart McCulloch <st...@jayway.net>.
2008/4/30 Mark Derricutt <ma...@talios.com>:

> Oops - my bad.  Yes, simply stopping/starting Bundle A works fine, if I
> update Bundle A however it doesn't.
>
> I can work around things by using reflection to execute the class I'm
> loading from Bundle B, and moving the object I was passing over as a
> parameter to be an exported OSGi service which is then looked up, it's not
> as clean as I'd hoped.
>

if you want to update A (ie. to change it's implementation) but avoid
the class cast issues then I'd suggest moving its public API classes
into a separate bundle (A-interface)

then you can start/stop/update A or B as much as you like...

Mark
>
> On Wed, Apr 30, 2008 at 3:37 PM, Richard S. Hall <he...@ungoverned.org>
> wrote:
>
> > If I am understanding correctly, something seems fishy here.
> >
> > Simply restarting A should not cause a new class loader to be recreated.
> I
> > believe you should only see a new class loader if you are updating A,
> for
> > example.
> >
> > Is your description below accurate or are you updating the bundle?
> >
> > -> richard
> >
> >
> > Mark Derricutt wrote:
> >
> > > Hey all,
> > >
> > > Running into a small problem with reloading bundles which I'm sure's
> > > been
> > > solved by something simple I'm not quite seeing.
> > >
> > > The scenario is that I have two bundles A and B - A provides an
> > > interface
> > > MountProvider, and B has a class that implements it.
> > >
> > > When bundle A starts it looks for all bundles that provide an instance
> > > of
> > > MountProvider, bundle A also listens to other bundles starting up
> which
> > > provide the instance.
> > >
> > > Things all work fine on startup.  Bundle A starts, Bundle B starts.
> > >  Bundle
> > > A detects the MountProvider instance using the following code:
> > >
> > >  String classname = (String)
> > > bundle.getHeaders().get(SMX3_RESTLET_PROVIDER);
> > >  Class activatorClass = bundle.loadClass(classname);
> > >  if (MountProvider.class.isAssignableFrom(activatorClass)) {
> > >    MountProvider mountRequestEvent = (MountProvider)
> > > restActivatorClass.newInstance();
> > >    mountRequestEvent.mountResources(mountManager);
> > >  }
> > >
> > >
> > > If I restart bundle B, the above code reruns fine as expected, finding
> > > the
> > > updated MountProvider instance.
> > >
> > > However, if I restart bundle A - when bundle B is processed again, the
> > > check
> > > fails and processing isn't performed.  My assumption here is that the
> > > MountProvider class from bundle B is an instance of "the original
> bundle
> > > A's
> > > MountProvider", and not the "current bundle A's MountProvider" class
> so
> > > the
> > > call to isAssignableFrom fails.
> > >
> > > Whats the proper/OSGi way to check for this that respects the change
> in
> > > class loaders?  Should I do something like:
> > >
> > >  Class activatorClass = bundle.loadClass(classname);
> > >  Class mountProviderClass =
> > > bundle.loadClass(MountProvider.class.getName());
> > >  if (mountProviderClass.isAssignableFrom(activatorClass)) {
> > >
> > > instead?  And using an indirect reference to my MountProvider
> interface,
> > > as
> > > seen by the bundle?
> > >
> > > Thanks in advance,
> > > Mark
> > >
> > >
> > >
> > >
> > >
> > >
> >
> > ---------------------------------------------------------------------
> > To unsubscribe, e-mail: users-unsubscribe@felix.apache.org
> > For additional commands, e-mail: users-help@felix.apache.org
> >
> >
>
>
> --
> "It is easier to optimize correct code than to correct optimized code." --
> Bill Harlan
>



-- 
Cheers, Stuart

Re: isAssignableFrom - class loading issues when reloading bundles

Posted by "Richard S. Hall" <he...@ungoverned.org>.
Mark Derricutt wrote:
> Oops - my bad.  Yes, simply stopping/starting Bundle A works fine, if I
> update Bundle A however it doesn't.
>
> I can work around things by using reflection to execute the class I'm
> loading from Bundle B, and moving the object I was passing over as a
> parameter to be an exported OSGi service which is then looked up, it's not
> as clean as I'd hoped.
>   

You have two options:

   1. If the interface in A hasn't actually changed, you can have A both
      import and export the interface package, in which case the updated
      bundle will be wired to the old version of the interface.
   2. If the interface in A has changed, then you will need to perform
      PackageAdmin.refreshPackages(), which can be done in the shell by
      typing "refresh".

Read the FAQ for more details of some of these issues:

    http://cwiki.apache.org/FELIX/apache-felix-osgi-faq.html

-> richard


   
> Mark
>
> On Wed, Apr 30, 2008 at 3:37 PM, Richard S. Hall <he...@ungoverned.org>
> wrote:
>
>   
>> If I am understanding correctly, something seems fishy here.
>>
>> Simply restarting A should not cause a new class loader to be recreated. I
>> believe you should only see a new class loader if you are updating A, for
>> example.
>>
>> Is your description below accurate or are you updating the bundle?
>>
>> -> richard
>>
>>
>> Mark Derricutt wrote:
>>
>>     
>>> Hey all,
>>>
>>> Running into a small problem with reloading bundles which I'm sure's
>>> been
>>> solved by something simple I'm not quite seeing.
>>>
>>> The scenario is that I have two bundles A and B - A provides an
>>> interface
>>> MountProvider, and B has a class that implements it.
>>>
>>> When bundle A starts it looks for all bundles that provide an instance
>>> of
>>> MountProvider, bundle A also listens to other bundles starting up which
>>> provide the instance.
>>>
>>> Things all work fine on startup.  Bundle A starts, Bundle B starts.
>>>  Bundle
>>> A detects the MountProvider instance using the following code:
>>>
>>>  String classname = (String)
>>> bundle.getHeaders().get(SMX3_RESTLET_PROVIDER);
>>>  Class activatorClass = bundle.loadClass(classname);
>>>  if (MountProvider.class.isAssignableFrom(activatorClass)) {
>>>    MountProvider mountRequestEvent = (MountProvider)
>>> restActivatorClass.newInstance();
>>>    mountRequestEvent.mountResources(mountManager);
>>>  }
>>>
>>>
>>> If I restart bundle B, the above code reruns fine as expected, finding
>>> the
>>> updated MountProvider instance.
>>>
>>> However, if I restart bundle A - when bundle B is processed again, the
>>> check
>>> fails and processing isn't performed.  My assumption here is that the
>>> MountProvider class from bundle B is an instance of "the original bundle
>>> A's
>>> MountProvider", and not the "current bundle A's MountProvider" class so
>>> the
>>> call to isAssignableFrom fails.
>>>
>>> Whats the proper/OSGi way to check for this that respects the change in
>>> class loaders?  Should I do something like:
>>>
>>>  Class activatorClass = bundle.loadClass(classname);
>>>  Class mountProviderClass =
>>> bundle.loadClass(MountProvider.class.getName());
>>>  if (mountProviderClass.isAssignableFrom(activatorClass)) {
>>>
>>> instead?  And using an indirect reference to my MountProvider interface,
>>> as
>>> seen by the bundle?
>>>
>>> Thanks in advance,
>>> Mark
>>>
>>>
>>>
>>>
>>>
>>>
>>>       
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: users-unsubscribe@felix.apache.org
>> For additional commands, e-mail: users-help@felix.apache.org
>>
>>
>>     
>
>
>   

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@felix.apache.org
For additional commands, e-mail: users-help@felix.apache.org


Re: isAssignableFrom - class loading issues when reloading bundles

Posted by Mark Derricutt <ma...@talios.com>.
Oops - my bad.  Yes, simply stopping/starting Bundle A works fine, if I
update Bundle A however it doesn't.

I can work around things by using reflection to execute the class I'm
loading from Bundle B, and moving the object I was passing over as a
parameter to be an exported OSGi service which is then looked up, it's not
as clean as I'd hoped.

Mark

On Wed, Apr 30, 2008 at 3:37 PM, Richard S. Hall <he...@ungoverned.org>
wrote:

> If I am understanding correctly, something seems fishy here.
>
> Simply restarting A should not cause a new class loader to be recreated. I
> believe you should only see a new class loader if you are updating A, for
> example.
>
> Is your description below accurate or are you updating the bundle?
>
> -> richard
>
>
> Mark Derricutt wrote:
>
> > Hey all,
> >
> > Running into a small problem with reloading bundles which I'm sure's
> > been
> > solved by something simple I'm not quite seeing.
> >
> > The scenario is that I have two bundles A and B - A provides an
> > interface
> > MountProvider, and B has a class that implements it.
> >
> > When bundle A starts it looks for all bundles that provide an instance
> > of
> > MountProvider, bundle A also listens to other bundles starting up which
> > provide the instance.
> >
> > Things all work fine on startup.  Bundle A starts, Bundle B starts.
> >  Bundle
> > A detects the MountProvider instance using the following code:
> >
> >  String classname = (String)
> > bundle.getHeaders().get(SMX3_RESTLET_PROVIDER);
> >  Class activatorClass = bundle.loadClass(classname);
> >  if (MountProvider.class.isAssignableFrom(activatorClass)) {
> >    MountProvider mountRequestEvent = (MountProvider)
> > restActivatorClass.newInstance();
> >    mountRequestEvent.mountResources(mountManager);
> >  }
> >
> >
> > If I restart bundle B, the above code reruns fine as expected, finding
> > the
> > updated MountProvider instance.
> >
> > However, if I restart bundle A - when bundle B is processed again, the
> > check
> > fails and processing isn't performed.  My assumption here is that the
> > MountProvider class from bundle B is an instance of "the original bundle
> > A's
> > MountProvider", and not the "current bundle A's MountProvider" class so
> > the
> > call to isAssignableFrom fails.
> >
> > Whats the proper/OSGi way to check for this that respects the change in
> > class loaders?  Should I do something like:
> >
> >  Class activatorClass = bundle.loadClass(classname);
> >  Class mountProviderClass =
> > bundle.loadClass(MountProvider.class.getName());
> >  if (mountProviderClass.isAssignableFrom(activatorClass)) {
> >
> > instead?  And using an indirect reference to my MountProvider interface,
> > as
> > seen by the bundle?
> >
> > Thanks in advance,
> > Mark
> >
> >
> >
> >
> >
> >
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@felix.apache.org
> For additional commands, e-mail: users-help@felix.apache.org
>
>


-- 
"It is easier to optimize correct code than to correct optimized code." --
Bill Harlan

Re: isAssignableFrom - class loading issues when reloading bundles

Posted by "Richard S. Hall" <he...@ungoverned.org>.
If I am understanding correctly, something seems fishy here.

Simply restarting A should not cause a new class loader to be recreated. 
I believe you should only see a new class loader if you are updating A, 
for example.

Is your description below accurate or are you updating the bundle?

-> richard

Mark Derricutt wrote:
> Hey all,
>
> Running into a small problem with reloading bundles which I'm sure's been
> solved by something simple I'm not quite seeing.
>
> The scenario is that I have two bundles A and B - A provides an interface
> MountProvider, and B has a class that implements it.
>
> When bundle A starts it looks for all bundles that provide an instance of
> MountProvider, bundle A also listens to other bundles starting up which
> provide the instance.
>
> Things all work fine on startup.  Bundle A starts, Bundle B starts.  Bundle
> A detects the MountProvider instance using the following code:
>
>   String classname = (String)
> bundle.getHeaders().get(SMX3_RESTLET_PROVIDER);
>   Class activatorClass = bundle.loadClass(classname);
>   if (MountProvider.class.isAssignableFrom(activatorClass)) {
>     MountProvider mountRequestEvent = (MountProvider)
> restActivatorClass.newInstance();
>     mountRequestEvent.mountResources(mountManager);
>   }
>
>
> If I restart bundle B, the above code reruns fine as expected, finding the
> updated MountProvider instance.
>
> However, if I restart bundle A - when bundle B is processed again, the check
> fails and processing isn't performed.  My assumption here is that the
> MountProvider class from bundle B is an instance of "the original bundle A's
> MountProvider", and not the "current bundle A's MountProvider" class so the
> call to isAssignableFrom fails.
>
> Whats the proper/OSGi way to check for this that respects the change in
> class loaders?  Should I do something like:
>
>   Class activatorClass = bundle.loadClass(classname);
>   Class mountProviderClass =
> bundle.loadClass(MountProvider.class.getName());
>   if (mountProviderClass.isAssignableFrom(activatorClass)) {
>
> instead?  And using an indirect reference to my MountProvider interface, as
> seen by the bundle?
>
> Thanks in advance,
> Mark
>
>
>
>
>   

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@felix.apache.org
For additional commands, e-mail: users-help@felix.apache.org