I'm trying to start a Wicket Application using Felix implementation of OSGi HTTP service, for that I just register the service using WicketServlet
with applicationClassName
parameter:
props.put("applicationClassName", MainApplication.class.getName());
service = (HttpService)context.getService(httpReference);
service.registerServlet("/", new WicketServlet(), props, null);
I have also tried using Felix Whiteboard implementation and registering the web service as a Servlet
one:
props.put("alias", "/");
props.put("init.applicationClassName", MainApplication.class.getName());
registration = context.registerService(Servlet.class.getName(), new WicketServlet(), props);
In both cases it fails when I deploy it using Pax Runner and Felix (mvn package install pax:run -Dframework=felix -Dprofiles=log,config
), the exception seems to be related with the ClassLoader
:
[Jetty HTTP Service] ERROR org.apache.felix.http.whiteboard - Failed to register servlet
org.apache.wicket.WicketRuntimeException: Unable to create application of class es.warp.sample.HTTPLocalGUI.MainApplication
....
....
at java.lang.ClassLoader.loadClass(ClassLoader.java:252)
at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:320)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:247)
....
....
I have tried to export everything in the bundle and it does the same.
The strangest thing is that it works perfectly if I deploy it using Equinox (mvn package install pax:run -Dframework=felix -Dprofiles=log,config
).
It seems to be a visibilty issue, but I don't know how to fix it, am I doing something wrong? Should I try to extend WicketServlet
to take control on the instantiation of the application? Or maybe using an application Factory?
Update: Or maybe using an application Factory?
I tried to set the parameter applicationFactoryClassName
to ContextParamWebApplicationFactory.class.getName()
it and didn't help, still failing with felix and working with equinox.
Any light is welcomed.
The problem here is that Wicket seems to load the applicationClass badly. I have not looked at the code that does this, but I suspect it's using current thread's context classloader.
I did the following to overcome this:
- Create my own
WicketFilter
(calledMyWicketFilter
) and overridegetClassLoader
. This returnsthis.getClass().getClassLoader()
. - Register the
MyWicketFilter
as a Filter service to be picked up by the whiteboard http service.
Code for activator start:
Hashtable<String, String> props = new Hashtable<String, String>();
props.put("pattern", "/.*");
props.put("init.applicationClassName", MyApplication.class.getName());
final MyWicketFilter service = new MyWicketFilter();
context.registerService(Filter.class.getName(), service, props);
Code for MyWicketFilter:
public final class MyWicketFilter
extends WicketFilter
{
@Override
protected ClassLoader getClassLoader()
{
return this.getClass().getClassLoader();
}
}
You can also use WicketServlet
, but this involves overriding
newWicketFilter
and return MyWicketFilter from here.
来源:https://stackoverflow.com/questions/2432263/starting-wicket-web-application-with-osgi-http-service