[ https://issues.apache.org/jira/browse/FELIX-5310?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17838577#comment-17838577 ]
Paul Rütter (BlueConic) commented on FELIX-5310: ------------------------------------------------ See example here: [https://github.com/apache/felix-dev/pull/298/files] Based on Jetty12. > Felix HTTP Jetty WebSockets do not work out of the box > ------------------------------------------------------ > > Key: FELIX-5310 > URL: https://issues.apache.org/jira/browse/FELIX-5310 > Project: Felix > Issue Type: Bug > Components: HTTP Service > Affects Versions: http.jetty-3.2.0 > Reporter: Timothy James Ward > Priority: Major > > I have encountered two significant problems when trying to use the Jetty > WebSocketServlet with the Jetty based Felix HTTP service whiteboard. Both > problems occur in the init method of my servlet. > 1. I have to set the TCCL for the Jetty Web Socket implementation to be able > to find its own internal implementation of Websockets (specifically > org.eclipse.jetty.websocket.server.WebSocketServerFactory). This is really > stupid, as the TCCL I have to use is the Felix HTTP Jetty bundle's class > loader! > 2. The Jetty Web Socket implementation does one (and only one) check to check > that it's running on Jetty. It looks as though the only reason for this is to > get hold of an Executor which is available via a getter. This check involves > trying to establish the Jetty Context by casting the ServletContext to a > Jetty internal type. This does not work as the HTTP Whiteboard wrappers the > ServletContext. I can work around this by delaying initialisation to the > first request so that there is a context to get hold of, but this also sucks > :( > In summary, my servlet has to look like this, most of which should not be > necessary! > {code:java} > public class EchoServlet extends WebSocketServlet { > > private static final Logger LOGGER = > LoggerFactory.getLogger(EchoServlet.class); > > private final AtomicBoolean firstCall = new AtomicBoolean(true); > > private final CountDownLatch initBarrier = new CountDownLatch(1); > > @Override > public void init() throws ServletException { > LOGGER.info("The Echo servlet has been initialized, but we delay > initialization until the first request so that a Jetty Context is > available"); > } > > @Override > public void service(ServletRequest arg0, ServletResponse arg1) throws > ServletException, IOException { > if(firstCall.compareAndSet(true, false)) { > try { > delayedInit(); > } finally { > initBarrier.countDown(); > } > } else { > try { > initBarrier.await(); > } catch (InterruptedException e) { > throw new ServletException("Timed out waiting for > initialisation", e); > } > } > > super.service(arg0, arg1); > } > private void delayedInit() throws ServletException { > // Overide the TCCL so that the internal factory can be found > // Jetty tries to use ServiceLoader, and their fallback is to > // use TCCL, it would be better if we could provide a loader... > > Thread currentThread = Thread.currentThread(); > ClassLoader tccl = currentThread.getContextClassLoader(); > > currentThread.setContextClassLoader(WebSocketServlet.class.getClassLoader()); > try { > super.init(); > } finally { > currentThread.setContextClassLoader(tccl); > } > } > @Override > public void configure(WebSocketServletFactory wsf) { > wsf.setCreator((req,res) -> new WebSocketAdaptor() { > public void onWebSocketText(String message) { > getRemote().sendStringByFuture("Echo: " + message); > } > }); > } > } > {code} -- This message was sent by Atlassian Jira (v8.20.10#820010)