You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@felix.apache.org by Craig Phillips <lc...@praxiseng.com> on 2008/07/08 18:10:56 UTC

brain teaser - embedded felix / class cast exception

Hi,

Can't cast a class to it's own type... Huh?  I just got to believe it's
some kind of class loader thing going on... I really could use a pair of
eyes from one of the class loader experts out there, I anticipate (I
brought other eyes nearby to look, they're stumped too)...  Thanks,
Craig Phillips

Here's the stack error message:

java.lang.ClassCastException: org.craig.cache.CacheServiceMain cannot be
cast to org.craig.cache.CacheServiceMain

Here's the line of code:

CacheServiceMain cacheServiceMain = (CacheServiceMain) bc.getService(sr)

Here's the context snippet, that creates the felix container, more or
less:

System.getProperties().setProperty(Main.CONFIG_PROPERTIES_PROP,
 
"file:../webapps/craigbox/WEB-INF/felix_config.properties");
Main.loadSystemProperties();
Properties configProps = Main.loadConfigProperties();
List<AutoActivator> list = new ArrayList<AutoActivator>(); // pass
through
list.add(new AutoActivator(configProps)); // pass through
Map map = new StringMap(configProps, false); // pass through
felix = new Felix(map, list); // there isn't a default constructor
felix.start();
BundleContext bc = felix.getBundleContext();
ServiceReference sr =
bc.getServiceReference("org.craig.cache.api.CacheServiceMainApi");
if (sr != null)
{
   CacheServiceMain cacheServiceMain =  (CacheServiceMain)
bc.getService(sr);
   ... // and the rest, which of course doesn't come in to play


PS - To Karl -- As you can tell, I have not done the "set TCL to null",
but this is in the "parent" code... Note that I do have all the classes
in the parent dot.jar file, if that's any consolation...



RE: brain teaser - embedded felix / class cast exception

Posted by Craig Phillips <lc...@praxiseng.com>.
Hi,

I went to the config.properties bootdelegation line, as we did with the
pax logger stuff, and sure enough if it worked... Here's the latest
debug print:

org.osgi.framework.bootdelegation=sun.*,com.sun.*,org.craig.cache.*;

------------------------------------------------------------------------
--
DEBUG:CL Context:WebappClassLoader
  delegate: false
  repositories:
----------> Parent Classloader:
org.apache.catalina.loader.StandardClassLoader@d1e604

DEBUG:CL Current:WebappClassLoader
  delegate: false
  repositories:
----------> Parent Classloader:
org.apache.catalina.loader.StandardClassLoader@d1e604

DEBUG:CL Service:WebappClassLoader
  delegate: false
  repositories:
----------> Parent Classloader:
org.apache.catalina.loader.StandardClassLoader@d1e604
----------------------------------------------------------------------

So, I think if I just set it to the <<interface>> class, maybe I can
work 24x7 and change out the <<impl>> while the parent is none the
wiser...

I'll go back and retro fit the interface back and and remove the 'impl'
and see if that works...

Appreciate the assistance, Craig

-----Original Message-----
From: Craig Phillips [mailto:lcphillips@praxiseng.com] 
Sent: Tuesday, July 08, 2008 1:02 PM
To: dev@felix.apache.org
Subject: RE: brain teaser - embedded felix / class cast exception

Hi,

I'm willing to give reflection a try... seems like the best approach
from a 24x7 standpoint, where I want to have the ability to change the
impl and yet my parent is wired to the interface... or, so, that's my
plan...

I was thinking about how OSGi does it (without digging in to the code,
that is), and obviously the bundles work with classes loaded from each
others bundles... so, it seems I want to mimic/duplicate that exact same
functionality... how it does that, I haven't a clue... not sure if
that's reflection, but if it is, I'd be willing to give it a shot...

However, with all that said, I think the easiest way is what you
suggest: 
Tweaking config.properties for 'org.osgi.framework.system.packages'
(although, I like the reflection idea better...);

Deiter, et al... the "service" portion of the debug prints didn't print
anything? --
-------------------------------------------------------------
DEBUG:CL Context:WebappClassLoader
  delegate: false
  repositories:
----------> Parent Classloader:
org.apache.catalina.loader.StandardClassLoader@d1e604

DEBUG:CL Current:WebappClassLoader
  delegate: false
  repositories:
----------> Parent Classloader:
org.apache.catalina.loader.StandardClassLoader@d1e604

DEBUG:CL Service:7.0
------------------------------------------------------------
Not sure what's up with that...

Thanks again for your advisement(s) / assistance, Craig

-----Original Message-----
From: Sanjeeb.Sahoo@Sun.COM [mailto:Sanjeeb.Sahoo@Sun.COM] On Behalf Of
Sahoo
Sent: Tuesday, July 08, 2008 12:47 PM
To: dev@felix.apache.org
Subject: Re: brain teaser - embedded felix / class cast exception

Craig Phillips wrote:
> Sahoo, Dieter,
>
> Yeah, this is what I'm suspecting and I'll try what you suggest,
Deiter,
> to print them out and I think I/we'll know the answer -- they were
> loaded in two different class loaders... Note that they are from the
> same package -- I built everything so everything is on the same page
> from a compile/jar standpoint.
>   
This is clear from the error message.
> My parent is what creates the Felix container, so it is technically
not
> in a bundle, but I loaded the same class code in it's jar (since I'm
> going to be using it, of course) -- although, design wise, I'm using
the
> <<interface>> not the <<Impl>>, but I short circuited the interface
just
> to get to the bottom of the riddle...
This seems to be the problem. Felix does not use the class that's loaded

by your code, which is running outside Felix. To fix it, you have to 
make both Felix and your code use the same class. Since your code runs 
before Felix and you probably don't want to use reflection to use that 
class, the only option that I can think of is to configure Felix to use 
your class by adding org.craig.cache to the list of packages exported by

the parent class loader. The property name in config.property is: 
org.osgi.framework.system.packages. See OSGi documentation for more 
details about this property.

Thanks,
Sahoo
 

RE: brain teaser - embedded felix / class cast exception

Posted by Craig Phillips <lc...@praxiseng.com>.
Hi,
 
I read the launching/embedding page, but it was a few weeks ago and I will go back and take another look...
 
I went with the Sahoo's suggestion of setting the delegation property and that is perfect for my needs...
 
I agree I don't want any code outside of a bundle, if at all possible... Unfortunately, my parent has to do some "delegation" of its own -- but only to the very top API of my cache bundle interface... hence, my parent is a "medium" in a sense, where I get external requests and pass them through to the top level service api.... At that point, it's all OSGi based bundles... Otherwise, I'd be doing some other means to get from the external to the top level service bundle, like RMI or socket or other non-lightweight message passing means... By just adding my top level service api (which is nothing more than an interface and bundle thereof) to the config.properties delegation list, I think I'm golden... and, yes, if that interface changes, my parent must change too... I can live with that... however, I can make non-interface changes to the impl and not have to touch the parent, even at run time -- still pretty cool!
 
Thanks to Angelo for the code snippet on the reflection... I would never have figured that out on my own... I entertained my thoughts and quickly went down the reflection path and I basically got wrapped up in 'Class', 'Method' and the like (I hate to admit this, but I'm pretty good with JNI... I didn't like the Sun tutorial and I wrote my own 60 page power point briefing on JNI... a sort of how to cheat sheet... I learned all about reflection by doing JNI); But, I didn't want to go to this much trouble... in the end, delegation worked just fine for me...
 
Thanks again for all your help... this is good discussion stuff...   Craig
 
PS - If anyone would like a copy of my JNI briefing, just holler...

________________________________

From: Richard S. Hall [mailto:heavy@ungoverned.org]
Sent: Tue 7/8/2008 3:54 PM
To: dev@felix.apache.org
Subject: Re: brain teaser - embedded felix / class cast exception



Craig,

Not sure if you read this document:

    http://cwiki.apache.org/FELIX/launching-and-embedding-apache-felix.html

But this document discusses these issues and touches upon the various
solutions/approaches, such as reflection.

However, I am in agreement with the others, your life will be greatly
simplified if you can package everything as bundles.

-> richard


Angelo van der Sijpt wrote:
> Hi,
>
> On 8 Jul 2008, at 19:19, Dieter Wimberger wrote:
>
>> I guess that 7.0 is the output from the felix classloader. When
>> allowing parent delegation (what Sahoo suggested), then you get the
>> result you were looking for.
>
> The 7.0 is indeed the name of the classloader of bundle ID 7 (the 0 is
> the version; if the bundle gets updated, this number will be
> incremented), which has to be the bundle that exports the
> CacheServiceMain object.
>
>> On 8 Jul 2008, at 18:47, Sahoo wrote:
>>>> My parent is what creates the Felix container, so it is technically
>>>> not
>>>> in a bundle, but I loaded the same class code in it's jar (since I'm
>>>> going to be using it, of course) -- although, design wise, I'm
>>>> using the
>>>> <<interface>> not the <<Impl>>, but I short circuited the interface
>>>> just
>>>> to get to the bottom of the riddle...
>>> This seems to be the problem. Felix does not use the class that's
>>> loaded by your code, which is running outside Felix. To fix it, you
>>> have to make both Felix and your code use the same class. Since your
>>> code runs before Felix and you probably don't want to use reflection
>>> to use that class, the only option that I can think of is to
>>> configure Felix to use your class by adding org.craig.cache to the
>>> list of packages exported by the parent class loader. The property
>>> name in config.property is: org.osgi.framework.system.packages. See
>>> OSGi documentation for more details about this property.
>
>
> True: Felix is a bundle too (that is why you can get its
> BundleContext), the system bundle to be precise. This system bundle
> does import the package from bundle 7 as soon as that class would get
> used. You can get the service reference for the class you want because
> it is possible to resolve the package import from the system bundle
> (that is, if it would not be possible because of e.g. versioning, you
> would not get the service reference).
>
> If you really want to use the service outside of the Felix instance,
> Sahoo's suggestion of delegating to the system classloader seems the
> best way to go.
> Still, I think I would package whatever it is you want to be using
> service with as a bundle, and run all code from inside that bundle.
>
> If neither of these is an option, reflection might help you out. For
> instance, if you have a service MyService of which you are sure the
> definitions are identical, but just not loaded by the same
> classloader, you can use a proxy like such:
>
>     final Object object =
> bc.getService(bc.getServiceReference(MyService.class.getName()));
>
>     MyService service = (MyService)
> Proxy.newProxyInstance(MyService.class.getClassLoader(), new Class[] {
> MyService.class },
>         new InvocationHandler() {
>             public Object invoke(Object proxy, Method method, Object[]
> args) throws Throwable {
>                 Method bridge =
> object.getClass().getDeclaredMethod(method.getName(),
> method.getParameterTypes());
>                 return bridge.invoke(object, args);
>             }
>     });
>
>
> Hope this helps,
>
> Angelo



Re: brain teaser - embedded felix / class cast exception

Posted by "Richard S. Hall" <he...@ungoverned.org>.
Craig,

Not sure if you read this document:

    http://cwiki.apache.org/FELIX/launching-and-embedding-apache-felix.html

But this document discusses these issues and touches upon the various 
solutions/approaches, such as reflection.

However, I am in agreement with the others, your life will be greatly 
simplified if you can package everything as bundles.

-> richard


Angelo van der Sijpt wrote:
> Hi,
>
> On 8 Jul 2008, at 19:19, Dieter Wimberger wrote:
>
>> I guess that 7.0 is the output from the felix classloader. When 
>> allowing parent delegation (what Sahoo suggested), then you get the 
>> result you were looking for.
>
> The 7.0 is indeed the name of the classloader of bundle ID 7 (the 0 is 
> the version; if the bundle gets updated, this number will be 
> incremented), which has to be the bundle that exports the 
> CacheServiceMain object.
>
>> On 8 Jul 2008, at 18:47, Sahoo wrote:
>>>> My parent is what creates the Felix container, so it is technically 
>>>> not
>>>> in a bundle, but I loaded the same class code in it's jar (since I'm
>>>> going to be using it, of course) -- although, design wise, I'm 
>>>> using the
>>>> <<interface>> not the <<Impl>>, but I short circuited the interface 
>>>> just
>>>> to get to the bottom of the riddle...
>>> This seems to be the problem. Felix does not use the class that's 
>>> loaded by your code, which is running outside Felix. To fix it, you 
>>> have to make both Felix and your code use the same class. Since your 
>>> code runs before Felix and you probably don't want to use reflection 
>>> to use that class, the only option that I can think of is to 
>>> configure Felix to use your class by adding org.craig.cache to the 
>>> list of packages exported by the parent class loader. The property 
>>> name in config.property is: org.osgi.framework.system.packages. See 
>>> OSGi documentation for more details about this property.
>
>
> True: Felix is a bundle too (that is why you can get its 
> BundleContext), the system bundle to be precise. This system bundle 
> does import the package from bundle 7 as soon as that class would get 
> used. You can get the service reference for the class you want because 
> it is possible to resolve the package import from the system bundle 
> (that is, if it would not be possible because of e.g. versioning, you 
> would not get the service reference).
>
> If you really want to use the service outside of the Felix instance, 
> Sahoo's suggestion of delegating to the system classloader seems the 
> best way to go.
> Still, I think I would package whatever it is you want to be using 
> service with as a bundle, and run all code from inside that bundle.
>
> If neither of these is an option, reflection might help you out. For 
> instance, if you have a service MyService of which you are sure the 
> definitions are identical, but just not loaded by the same 
> classloader, you can use a proxy like such:
>
>     final Object object = 
> bc.getService(bc.getServiceReference(MyService.class.getName()));
>
>     MyService service = (MyService) 
> Proxy.newProxyInstance(MyService.class.getClassLoader(), new Class[] { 
> MyService.class },
>         new InvocationHandler() {
>             public Object invoke(Object proxy, Method method, Object[] 
> args) throws Throwable {
>                 Method bridge = 
> object.getClass().getDeclaredMethod(method.getName(), 
> method.getParameterTypes());
>                 return bridge.invoke(object, args);
>             }
>     });
>
>
> Hope this helps,
>
> Angelo

Re: brain teaser - embedded felix / class cast exception

Posted by Angelo van der Sijpt <an...@luminis.nl>.
Hi,

On 8 Jul 2008, at 19:19, Dieter Wimberger wrote:

> I guess that 7.0 is the output from the felix classloader. When  
> allowing parent delegation (what Sahoo suggested), then you get the  
> result you were looking for.

The 7.0 is indeed the name of the classloader of bundle ID 7 (the 0 is  
the version; if the bundle gets updated, this number will be  
incremented), which has to be the bundle that exports the  
CacheServiceMain object.

> On 8 Jul 2008, at 18:47, Sahoo wrote:
>>> My parent is what creates the Felix container, so it is  
>>> technically not
>>> in a bundle, but I loaded the same class code in it's jar (since I'm
>>> going to be using it, of course) -- although, design wise, I'm  
>>> using the
>>> <<interface>> not the <<Impl>>, but I short circuited the  
>>> interface just
>>> to get to the bottom of the riddle...
>> This seems to be the problem. Felix does not use the class that's  
>> loaded by your code, which is running outside Felix. To fix it, you  
>> have to make both Felix and your code use the same class. Since  
>> your code runs before Felix and you probably don't want to use  
>> reflection to use that class, the only option that I can think of  
>> is to configure Felix to use your class by adding org.craig.cache  
>> to the list of packages exported by the parent class loader. The  
>> property name in config.property is:  
>> org.osgi.framework.system.packages. See OSGi documentation for more  
>> details about this property.


True: Felix is a bundle too (that is why you can get its  
BundleContext), the system bundle to be precise. This system bundle  
does import the package from bundle 7 as soon as that class would get  
used. You can get the service reference for the class you want because  
it is possible to resolve the package import from the system bundle  
(that is, if it would not be possible because of e.g. versioning, you  
would not get the service reference).

If you really want to use the service outside of the Felix instance,  
Sahoo's suggestion of delegating to the system classloader seems the  
best way to go.
Still, I think I would package whatever it is you want to be using  
service with as a bundle, and run all code from inside that bundle.

If neither of these is an option, reflection might help you out. For  
instance, if you have a service MyService of which you are sure the  
definitions are identical, but just not loaded by the same  
classloader, you can use a proxy like such:

     final Object object =  
bc.getService(bc.getServiceReference(MyService.class.getName()));

     MyService service = (MyService)  
Proxy.newProxyInstance(MyService.class.getClassLoader(), new Class[]  
{ MyService.class },
         new InvocationHandler() {
             public Object invoke(Object proxy, Method method,  
Object[] args) throws Throwable {
                 Method bridge =  
object.getClass().getDeclaredMethod(method.getName(),  
method.getParameterTypes());
                 return bridge.invoke(object, args);
             }
     });


Hope this helps,

Angelo

Re: brain teaser - embedded felix / class cast exception

Posted by Dieter Wimberger <di...@wimpi.net>.
Craig:

I guess that 7.0 is the output from the felix classloader. When  
allowing parent delegation (what Sahoo suggested), then you get the  
result you were looking for.

Honestly, one of the reasons for switching to OSGi is the much better  
classloading approach. I have had all kinds of problems in Servlet  
containers and finally opted to do it the other way around.

Probably you should consider going with OSGi and loading your servlet  
container into the OSGi container, rather then the other way around.

That's actually also what BEA guys commented at a conference for a  
monitoring product of theirs (24/7 type of stuff):
http://www.parleys.com/display/PARLEYS/OSGi,+the+good+the+bad+the+ugly

Regards,
Dieter


> -------------------------------------------------------------
> DEBUG:CL Context:WebappClassLoader
>  delegate: false
>  repositories:
> ----------> Parent Classloader:
> org.apache.catalina.loader.StandardClassLoader@d1e604
>
> DEBUG:CL Current:WebappClassLoader
>  delegate: false
>  repositories:
> ----------> Parent Classloader:
> org.apache.catalina.loader.StandardClassLoader@d1e604
>
> DEBUG:CL Service:7.0
> ------------------------------------------------------------
> Not sure what's up with that...
>


RE: brain teaser - embedded felix / class cast exception

Posted by Craig Phillips <lc...@praxiseng.com>.
Hi,

I'm willing to give reflection a try... seems like the best approach
from a 24x7 standpoint, where I want to have the ability to change the
impl and yet my parent is wired to the interface... or, so, that's my
plan...

I was thinking about how OSGi does it (without digging in to the code,
that is), and obviously the bundles work with classes loaded from each
others bundles... so, it seems I want to mimic/duplicate that exact same
functionality... how it does that, I haven't a clue... not sure if
that's reflection, but if it is, I'd be willing to give it a shot...

However, with all that said, I think the easiest way is what you
suggest: 
Tweaking config.properties for 'org.osgi.framework.system.packages'
(although, I like the reflection idea better...);

Deiter, et al... the "service" portion of the debug prints didn't print
anything? --
-------------------------------------------------------------
DEBUG:CL Context:WebappClassLoader
  delegate: false
  repositories:
----------> Parent Classloader:
org.apache.catalina.loader.StandardClassLoader@d1e604

DEBUG:CL Current:WebappClassLoader
  delegate: false
  repositories:
----------> Parent Classloader:
org.apache.catalina.loader.StandardClassLoader@d1e604

DEBUG:CL Service:7.0
------------------------------------------------------------
Not sure what's up with that...

Thanks again for your advisement(s) / assistance, Craig

-----Original Message-----
From: Sanjeeb.Sahoo@Sun.COM [mailto:Sanjeeb.Sahoo@Sun.COM] On Behalf Of
Sahoo
Sent: Tuesday, July 08, 2008 12:47 PM
To: dev@felix.apache.org
Subject: Re: brain teaser - embedded felix / class cast exception

Craig Phillips wrote:
> Sahoo, Dieter,
>
> Yeah, this is what I'm suspecting and I'll try what you suggest,
Deiter,
> to print them out and I think I/we'll know the answer -- they were
> loaded in two different class loaders... Note that they are from the
> same package -- I built everything so everything is on the same page
> from a compile/jar standpoint.
>   
This is clear from the error message.
> My parent is what creates the Felix container, so it is technically
not
> in a bundle, but I loaded the same class code in it's jar (since I'm
> going to be using it, of course) -- although, design wise, I'm using
the
> <<interface>> not the <<Impl>>, but I short circuited the interface
just
> to get to the bottom of the riddle...
This seems to be the problem. Felix does not use the class that's loaded

by your code, which is running outside Felix. To fix it, you have to 
make both Felix and your code use the same class. Since your code runs 
before Felix and you probably don't want to use reflection to use that 
class, the only option that I can think of is to configure Felix to use 
your class by adding org.craig.cache to the list of packages exported by

the parent class loader. The property name in config.property is: 
org.osgi.framework.system.packages. See OSGi documentation for more 
details about this property.

Thanks,
Sahoo
 

Re: brain teaser - embedded felix / class cast exception

Posted by Sahoo <Sa...@Sun.COM>.
Craig Phillips wrote:
> Sahoo, Dieter,
>
> Yeah, this is what I'm suspecting and I'll try what you suggest, Deiter,
> to print them out and I think I/we'll know the answer -- they were
> loaded in two different class loaders... Note that they are from the
> same package -- I built everything so everything is on the same page
> from a compile/jar standpoint.
>   
This is clear from the error message.
> My parent is what creates the Felix container, so it is technically not
> in a bundle, but I loaded the same class code in it's jar (since I'm
> going to be using it, of course) -- although, design wise, I'm using the
> <<interface>> not the <<Impl>>, but I short circuited the interface just
> to get to the bottom of the riddle...
This seems to be the problem. Felix does not use the class that's loaded 
by your code, which is running outside Felix. To fix it, you have to 
make both Felix and your code use the same class. Since your code runs 
before Felix and you probably don't want to use reflection to use that 
class, the only option that I can think of is to configure Felix to use 
your class by adding org.craig.cache to the list of packages exported by 
the parent class loader. The property name in config.property is: 
org.osgi.framework.system.packages. See OSGi documentation for more 
details about this property.

Thanks,
Sahoo
> I don't exactly understand the rest of the questions enough to give a
> technically sufficient response... [sorry]...
>
> I'll post back the output of the debug statements as Dieter suggests in
> a few...
>
> As always, much appreciative, Craig
>
> -----Original Message-----
> From: Sanjeeb.Sahoo@sun.com [mailto:Sanjeeb.Sahoo@sun.com] On Behalf Of
> Sahoo
> Sent: Tuesday, July 08, 2008 12:26 PM
> To: dev@felix.apache.org
> Subject: Re: brain teaser - embedded felix / class cast exception
>
> That basically means the same named class has been defined by two 
> different class loaders. Can you check if the bundle that's exporting 
> the service and the bundle that's consuming the service are not wired to
>
> the same org.craig.cache package?
>
> Which bundle is exporting the above package?
> How are the service producer and consumer bundles specifying their 
> package dependency for the above bundle?
>
> Thanks,
> Sahoo
>
> Craig Phillips wrote:
>   
>> Hi,
>>
>> Can't cast a class to it's own type... Huh?  I just got to believe
>>     
> it's
>   
>> some kind of class loader thing going on... I really could use a pair
>>     
> of
>   
>> eyes from one of the class loader experts out there, I anticipate (I
>> brought other eyes nearby to look, they're stumped too)...  Thanks,
>> Craig Phillips
>>
>> Here's the stack error message:
>>
>> java.lang.ClassCastException: org.craig.cache.CacheServiceMain cannot
>>     
> be
>   
>> cast to org.craig.cache.CacheServiceMain
>>
>> Here's the line of code:
>>
>> CacheServiceMain cacheServiceMain = (CacheServiceMain)
>>     
> bc.getService(sr)
>   
>> Here's the context snippet, that creates the felix container, more or
>> less:
>>
>> System.getProperties().setProperty(Main.CONFIG_PROPERTIES_PROP,
>>  
>> "file:../webapps/craigbox/WEB-INF/felix_config.properties");
>> Main.loadSystemProperties();
>> Properties configProps = Main.loadConfigProperties();
>> List<AutoActivator> list = new ArrayList<AutoActivator>(); // pass
>> through
>> list.add(new AutoActivator(configProps)); // pass through
>> Map map = new StringMap(configProps, false); // pass through
>> felix = new Felix(map, list); // there isn't a default constructor
>> felix.start();
>> BundleContext bc = felix.getBundleContext();
>> ServiceReference sr =
>> bc.getServiceReference("org.craig.cache.api.CacheServiceMainApi");
>> if (sr != null)
>> {
>>    CacheServiceMain cacheServiceMain =  (CacheServiceMain)
>> bc.getService(sr);
>>    ... // and the rest, which of course doesn't come in to play
>>
>>
>> PS - To Karl -- As you can tell, I have not done the "set TCL to
>>     
> null",
>   
>> but this is in the "parent" code... Note that I do have all the
>>     
> classes
>   
>> in the parent dot.jar file, if that's any consolation...
>>
>>
>>   
>>     

RE: brain teaser - embedded felix / class cast exception

Posted by Craig Phillips <lc...@praxiseng.com>.
Sahoo, Dieter,

Yeah, this is what I'm suspecting and I'll try what you suggest, Deiter,
to print them out and I think I/we'll know the answer -- they were
loaded in two different class loaders... Note that they are from the
same package -- I built everything so everything is on the same page
from a compile/jar standpoint.

My parent is what creates the Felix container, so it is technically not
in a bundle, but I loaded the same class code in it's jar (since I'm
going to be using it, of course) -- although, design wise, I'm using the
<<interface>> not the <<Impl>>, but I short circuited the interface just
to get to the bottom of the riddle...

I don't exactly understand the rest of the questions enough to give a
technically sufficient response... [sorry]...

I'll post back the output of the debug statements as Dieter suggests in
a few...

As always, much appreciative, Craig

-----Original Message-----
From: Sanjeeb.Sahoo@sun.com [mailto:Sanjeeb.Sahoo@sun.com] On Behalf Of
Sahoo
Sent: Tuesday, July 08, 2008 12:26 PM
To: dev@felix.apache.org
Subject: Re: brain teaser - embedded felix / class cast exception

That basically means the same named class has been defined by two 
different class loaders. Can you check if the bundle that's exporting 
the service and the bundle that's consuming the service are not wired to

the same org.craig.cache package?

Which bundle is exporting the above package?
How are the service producer and consumer bundles specifying their 
package dependency for the above bundle?

Thanks,
Sahoo

Craig Phillips wrote:
> Hi,
>
> Can't cast a class to it's own type... Huh?  I just got to believe
it's
> some kind of class loader thing going on... I really could use a pair
of
> eyes from one of the class loader experts out there, I anticipate (I
> brought other eyes nearby to look, they're stumped too)...  Thanks,
> Craig Phillips
>
> Here's the stack error message:
>
> java.lang.ClassCastException: org.craig.cache.CacheServiceMain cannot
be
> cast to org.craig.cache.CacheServiceMain
>
> Here's the line of code:
>
> CacheServiceMain cacheServiceMain = (CacheServiceMain)
bc.getService(sr)
>
> Here's the context snippet, that creates the felix container, more or
> less:
>
> System.getProperties().setProperty(Main.CONFIG_PROPERTIES_PROP,
>  
> "file:../webapps/craigbox/WEB-INF/felix_config.properties");
> Main.loadSystemProperties();
> Properties configProps = Main.loadConfigProperties();
> List<AutoActivator> list = new ArrayList<AutoActivator>(); // pass
> through
> list.add(new AutoActivator(configProps)); // pass through
> Map map = new StringMap(configProps, false); // pass through
> felix = new Felix(map, list); // there isn't a default constructor
> felix.start();
> BundleContext bc = felix.getBundleContext();
> ServiceReference sr =
> bc.getServiceReference("org.craig.cache.api.CacheServiceMainApi");
> if (sr != null)
> {
>    CacheServiceMain cacheServiceMain =  (CacheServiceMain)
> bc.getService(sr);
>    ... // and the rest, which of course doesn't come in to play
>
>
> PS - To Karl -- As you can tell, I have not done the "set TCL to
null",
> but this is in the "parent" code... Note that I do have all the
classes
> in the parent dot.jar file, if that's any consolation...
>
>
>   

Re: brain teaser - embedded felix / class cast exception

Posted by Sahoo <sa...@sun.com>.
That basically means the same named class has been defined by two 
different class loaders. Can you check if the bundle that's exporting 
the service and the bundle that's consuming the service are not wired to 
the same org.craig.cache package?

Which bundle is exporting the above package?
How are the service producer and consumer bundles specifying their 
package dependency for the above bundle?

Thanks,
Sahoo

Craig Phillips wrote:
> Hi,
>
> Can't cast a class to it's own type... Huh?  I just got to believe it's
> some kind of class loader thing going on... I really could use a pair of
> eyes from one of the class loader experts out there, I anticipate (I
> brought other eyes nearby to look, they're stumped too)...  Thanks,
> Craig Phillips
>
> Here's the stack error message:
>
> java.lang.ClassCastException: org.craig.cache.CacheServiceMain cannot be
> cast to org.craig.cache.CacheServiceMain
>
> Here's the line of code:
>
> CacheServiceMain cacheServiceMain = (CacheServiceMain) bc.getService(sr)
>
> Here's the context snippet, that creates the felix container, more or
> less:
>
> System.getProperties().setProperty(Main.CONFIG_PROPERTIES_PROP,
>  
> "file:../webapps/craigbox/WEB-INF/felix_config.properties");
> Main.loadSystemProperties();
> Properties configProps = Main.loadConfigProperties();
> List<AutoActivator> list = new ArrayList<AutoActivator>(); // pass
> through
> list.add(new AutoActivator(configProps)); // pass through
> Map map = new StringMap(configProps, false); // pass through
> felix = new Felix(map, list); // there isn't a default constructor
> felix.start();
> BundleContext bc = felix.getBundleContext();
> ServiceReference sr =
> bc.getServiceReference("org.craig.cache.api.CacheServiceMainApi");
> if (sr != null)
> {
>    CacheServiceMain cacheServiceMain =  (CacheServiceMain)
> bc.getService(sr);
>    ... // and the rest, which of course doesn't come in to play
>
>
> PS - To Karl -- As you can tell, I have not done the "set TCL to null",
> but this is in the "parent" code... Note that I do have all the classes
> in the parent dot.jar file, if that's any consolation...
>
>
>   

Re: brain teaser - embedded felix / class cast exception

Posted by Dieter Wimberger <di...@wimpi.net>.
Craig:

Something you could try to figure out what is going wrong with  
classloading is to debug print the associated classloaders. This  
information could indicate what is actually going wrong.

In particular, it would be interesting to see the output of the  
following:
Object o = bc.getService(sr);

System.out.println("DEBUG:CL Context:" +  
Thread.currentThread().getContextClassLoader().toString());
System.out.println("DEBUG:CL Current:" +  
this.getClass().getClassLoader().toString());
System.out.println("DEBUG:CL Service:" +  
o.getClass().getClassLoader().toString());

Regards,
Dieter

> Here's the line of code:
>
> CacheServiceMain cacheServiceMain = (CacheServiceMain)  
> bc.getService(sr)


> Hi,
>
> Can't cast a class to it's own type... Huh?  I just got to believe  
> it's
> some kind of class loader thing going on... I really could use a  
> pair of
> eyes from one of the class loader experts out there, I anticipate (I
> brought other eyes nearby to look, they're stumped too)...  Thanks,
> Craig Phillips
>
> Here's the stack error message:
>
> java.lang.ClassCastException: org.craig.cache.CacheServiceMain  
> cannot be
> cast to org.craig.cache.CacheServiceMain
>
> Here's the line of code:
>
> CacheServiceMain cacheServiceMain = (CacheServiceMain)  
> bc.getService(sr)
>
> Here's the context snippet, that creates the felix container, more or
> less:
>
> System.getProperties().setProperty(Main.CONFIG_PROPERTIES_PROP,
>
> "file:../webapps/craigbox/WEB-INF/felix_config.properties");
> Main.loadSystemProperties();
> Properties configProps = Main.loadConfigProperties();
> List<AutoActivator> list = new ArrayList<AutoActivator>(); // pass
> through
> list.add(new AutoActivator(configProps)); // pass through
> Map map = new StringMap(configProps, false); // pass through
> felix = new Felix(map, list); // there isn't a default constructor
> felix.start();
> BundleContext bc = felix.getBundleContext();
> ServiceReference sr =
> bc.getServiceReference("org.craig.cache.api.CacheServiceMainApi");
> if (sr != null)
> {
>   CacheServiceMain cacheServiceMain =  (CacheServiceMain)
> bc.getService(sr);
>   ... // and the rest, which of course doesn't come in to play
>
>
> PS - To Karl -- As you can tell, I have not done the "set TCL to  
> null",
> but this is in the "parent" code... Note that I do have all the  
> classes
> in the parent dot.jar file, if that's any consolation...
>
>