| Summary: | ClassCastException when registering a org.eclipse.jetty.servlet.DefaultServlet on org.osgi.service.http.HttpService (OSGi) | ||
|---|---|---|---|
| Product: | [RT] Jetty | Reporter: | Julio Gonnet <julio.gonnet> |
| Component: | osgi | Assignee: | Hugues Malphettes <hmalphettes> |
| Status: | RESOLVED FIXED | QA Contact: | |
| Severity: | normal | ||
| Priority: | P3 | CC: | jetty-inbox, julio.gonnet, mgorovoy |
| Version: | 7.2.2 | ||
| Target Milestone: | 7.2.x | ||
| Hardware: | Macintosh | ||
| OS: | Mac OS X - Carbon (unsup.) | ||
| Whiteboard: | |||
Forwarding to Hugues for triage. Jetty's DefaultServlet can only be deployed "directly" on a jetty itself. The upside is that it has access to low level internal APIs of jetty which are necessary to serve static content efficiently. The downside is: it assumes that it is deployed on jetty itself; not another servlet container and not the equinox http servlet. I am quite sure that if we were to extend the DefaultServlet and override a few methods we should be able to reuse it. Would you like to give it a try: extend the DefaultServlet, override the getServletContext() method to return the jetty object wrapped by equinox? We could add this DefaultServletHttpEquinox to the jetty distribution if the experiment goes well. Please let us know. Sure, I can give it a try - currently working on something else right now, but should be able to look at it sometime this week. I have tried to reproduce the bug and in fact it does not happen when using org.eclipse.jetty.osgi.httpservice to setup the HttpServiceServlet.
Nevertheless I have committed a small change in DefaultServlet to be able to override the part of the initialization of the DefaultServlet where the jetty context handler is located:
Extend the DefaultServlet and override:
protected ContextHandler initContextHandler(ServletContext servletContext)
Will let you support custom logic to find the jetty contexthandler.
Here is the untested method for equinox's httpservice:
/**
* Compute the field _contextHandler.
* In the case where the DefaultServlet is deployed on the HttpService it is very likely that
* this method needs to be overwritten to unwrap the ServletContext until we reach
* the original jetty's ContextHandler.Context
* @return the jetty's ContextHandler for this servletContext
*/
@Override
protected ContextHandler initContextHandler(ServletContext servletContext)
{
ContextHandler.Context scontext=ContextHandler.getCurrentContext();
if (scontext==null)
{
if (servletContext instanceof ContextHandler.Context)
return ((ContextHandler.Context)servletContext).getContextHandler();
else
{
ServletContext unwrapped = null;
try
{
java.lang.reflect.Field servletContextField = servletContext.getClass().getDeclaredField("servletContext");
servletContextField.setAccessible(true);
unwrapped = (ServletContext) servletContextField.get(servletContext);
}
catch (Throwable t)
{
throw new IllegalArgumentException("The servletContext " + servletContext + " " +
servletContext.getClass().getName() + " is not " + ContextHandler.Context.class.getName() +
" and failed to unwrap a facade for it.", t);
}
return super.initContextHandler(unwrapped);
}
}
else
return scontext.getContextHandler();
}
|
Hi, I'm getting the following ClassCastException when registering a DefaultServlet on a HttpService in OSGi: java.lang.ClassCastException: org.eclipse.equinox.http.servlet.internal.ServletContextAdaptor cannot be cast to org.eclipse.jetty.server.handler.ContextHandler$Context at org.eclipse.jetty.servlet.DefaultServlet.init(DefaultServlet.java:167) at javax.servlet.GenericServlet.init(GenericServlet.java:241) at org.eclipse.equinox.http.servlet.internal.ServletRegistration.init(ServletRegistration.java:49) at org.eclipse.equinox.http.servlet.internal.ProxyServlet.registerServlet(ProxyServlet.java:177) at org.eclipse.equinox.http.servlet.internal.HttpServiceImpl.registerServlet(HttpServiceImpl.java:66) ... Here's what I'm calling: ... private org.osgi.service.http.HttpService httpService; ... public void init(){ httpService.registerServlet("/", new DefaultServlet(), getServletInitParams(), null); } ... I'm running the following relevant bundles: org.eclipse.osgi 3.6.1.R36x_v20100806 org.eclipse.osgi.services 3.2.100.v20100503 org.eclipse.equinox.http.servlet 1.1.0.v20100503.jar jetty-all-server 7.2.2.v20101205 (aggregate) jetty-httpservice 7.2.2.v20101205 jetty-osgi-boot 7.2.2.v20101205 It seems that ProxyServlet in org.eclipse.equinox.http.servlet.internal.ProxyServlet (which is what's backing the OSGi HttpService) wraps the ServletContext.