Sorry, I omitted the RestletHandler bean in my last snipped. Here is the
complete file:
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.osgi.org/xmlns/blueprint/v1.0.0"
default-activation="eager">
<service interface="org.apache.aries.blueprint.NamespaceHandler"
ref="RestletHandler">
<service-properties>
<entry key="osgi.service.blueprint.namespace"
value="http://code4you.org/xmlns/aries/restlet/v1.0.0"/>
</service-properties>
</service>
<bean id="RestletHandler"
class="org.code4you.osgi.restlet.aries.parsing.RestletElementHandler"/>
</blueprint>
Best regards
Roger
On 15.08.13 11:57, Roger Stocker wrote:
Hi Tom
thanks for replying!
I am aware of what you say about the manifest headers. And there are
no non-OSGi compatible libraries in my setup.
Let me clarify what I did: I wrote a namespace handler for the
blueprint extender who is able to parse tags like
<restlet:xxx>
This namespacehandler is registered in its own bundle and exports a
service like this:
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.osgi.org/xmlns/blueprint/v1.0.0"
default-activation="eager">
<service interface="org.apache.aries.blueprint.NamespaceHandler"
ref="RestletHandler">
<service-properties>
<entry key="osgi.service.blueprint.namespace"
value="http://code4you.org/xmlns/aries/restlet/v1.0.0"/>
</service-properties>
</service>
</blueprint>
This namespace handler creates the necessary BeanMetadata objects for
the blueprint extender, which in turn instantiates the declared
objects from the org.restlet bundle (which is a legitimate OSGi bundle
as well). The problematic part comes into play later, when the
blueprint extender is trying to attach a resource class to the
declared virtual host (whith the <restlet:attachDefault> tag). This
resources package can't be imported neither by the restlet bundle nor
by the namespacehandler bundle, because it's provided by the bundle
which is declaring the <restlet:component> component in its
context.xml file (within OSGI-INF/blueprint/).
The problematic part lies inside the restlets EngineClassloader where
it tries to load the afforementioned resource class. It does this by
trying out several classloaders: first a user provided
"userclassloader", then the current thread's class loader, and lastly
the bundle classloader. By writing this, I become aware of this
userclassloader, which I will try to use now.... (it's always useful
to explain complicated things to others, as you see :))
My main question about all this was, how the spring-extender is able
to perform it out of the box. The spring-extender is part of the
reference implementation of Gemini Blueprint
(http://www.eclipse.org/gemini/blueprint/). The whole Gemini blueprint
has to be seen as an alternative implementation of the OSGi blueprint
specification, in contrast to Aries. I wonder if the spring-extender
is instantiating objects for its custom namespacehandlers within the
thread's context classloader of the defining bundle. Probably that's
why it's working out-of-the-box there...
Thanks
Roger
On 15.08.13 06:43, Tom Leung wrote:
If can run the program successfully without OSGi container, then the problem
is probably about class loading.
Osgi requires all imported bundles should be explicitly stated inside bundle
"MANIFEST.MF"
For non-OSGI compatible libraries, it is a problem
if run the program inside Apache karaf, you can solve the classloading
problem by using "dev:dynamic-import" command inside Karaf shell.
or
add the following declaration inside the "MANIFEST.MF"
DynamicImport-Package: *
Best Rgds,
Tom
-----Original Message-----
From: Roger Stocker [mailto:[email protected]]
Sent: Thursday, August 15, 2013 2:48 AM
To:[email protected]
Subject: Classloader issues with namespace handler
Hi
I wrote a namespace handler for the restlet framework.
Now I ran into a classloader issue with this in the context.xml file:
<restlet:component id="component">
<restlet:server protocol="http" port="8081" />
<restlet:defaultHost>
<restlet:attachDefault
targetClass="org.code4you.osgi.restlet.resource.DefaultResource" />
</restlet:defaultHost>
</restlet:component>
This is the stack trace:
java.lang.ClassNotFoundException:
org.code4you.osgi.restlet.resource.DefaultResource
at
org.restlet.engine.util.EngineClassLoader.findClass(EngineClassLoader.java:1
04)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
at org.restlet.engine.Engine.loadClass(Engine.java:359)
at
org.restlet.ext.spring.SpringRouter.setAttachment(SpringRouter.java:91)
at org.restlet.ext.spring.SpringHost.setAttachment(SpringHost.java:121)
at
org.restlet.ext.spring.SpringHost.setDefaultAttachment(SpringHost.java:133)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57
)
at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl
.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at
org.apache.aries.blueprint.utils.ReflectionUtils$MethodPropertyDescriptor.in
ternalSet(ReflectionUtils.java:628)
at
org.apache.aries.blueprint.utils.ReflectionUtils$PropertyDescriptor.set(Refl
ectionUtils.java:378)
at
org.apache.aries.blueprint.container.BeanRecipe.setProperty(BeanRecipe.java:
939)
at
org.apache.aries.blueprint.container.BeanRecipe.setProperties(BeanRecipe.jav
a:907)
at
org.apache.aries.blueprint.container.BeanRecipe.setProperties(BeanRecipe.jav
a:888)
at
org.apache.aries.blueprint.container.BeanRecipe.internalCreate2(BeanRecipe.j
ava:820)
at
org.apache.aries.blueprint.container.BeanRecipe.internalCreate(BeanRecipe.ja
va:787)
at
org.apache.aries.blueprint.di.AbstractRecipe$1.call(AbstractRecipe.java:79)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:334)
at java.util.concurrent.FutureTask.run(FutureTask.java:166)
at
org.apache.aries.blueprint.di.AbstractRecipe.create(AbstractRecipe.java:88)
at
org.apache.aries.blueprint.container.BeanRecipe.setProperty(BeanRecipe.java:
933)
at
org.apache.aries.blueprint.container.BeanRecipe.setProperties(BeanRecipe.jav
a:907)
at
org.apache.aries.blueprint.container.BeanRecipe.setProperties(BeanRecipe.jav
a:888)
at
org.apache.aries.blueprint.container.BeanRecipe.internalCreate2(BeanRecipe.j
ava:820)
at
org.apache.aries.blueprint.container.BeanRecipe.internalCreate(BeanRecipe.ja
va:787)
at
org.apache.aries.blueprint.di.AbstractRecipe$1.call(AbstractRecipe.java:79)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:334)
at java.util.concurrent.FutureTask.run(FutureTask.java:166)
at
org.apache.aries.blueprint.di.AbstractRecipe.create(AbstractRecipe.java:88)
at
org.apache.aries.blueprint.container.BlueprintRepository.createInstances(Blu
eprintRepository.java:245)
at
org.apache.aries.blueprint.container.BlueprintRepository.createAll(Blueprint
Repository.java:183)
at
org.apache.aries.blueprint.container.BlueprintContainerImpl.instantiateEager
Components(BlueprintContainerImpl.java:668)
at
org.apache.aries.blueprint.container.BlueprintContainerImpl.doRun(BlueprintC
ontainerImpl.java:370)
at
org.apache.aries.blueprint.container.BlueprintContainerImpl.run(BlueprintCon
tainerImpl.java:261)
at
java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:334)
at java.util.concurrent.FutureTask.run(FutureTask.java:166)
at
org.apache.aries.blueprint.container.ExecutorServiceWrapper.run(ExecutorServ
iceWrapper.java:106)
at
org.apache.aries.blueprint.utils.threading.impl.DiscardableRunnable.run(Disc
ardableRunnable.java:48)
at
java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:334)
at java.util.concurrent.FutureTask.run(FutureTask.java:166)
at
java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$
201(ScheduledThreadPoolExecutor.java:178)
at
java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(Sch
eduledThreadPoolExecutor.java:292)
at
java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:11
45)
at
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:6
15)
at java.lang.Thread.run(Thread.java:724)
The class DefaultResource is in the same bundle where the restlet component
is defined in the context.
I tried the same with the spring-blueprint-extender, and it worked there.
Any ideas?