[
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)