Important Pax Web 8 milestone achieved

34 views
Skip to first unread message

Grzegorz Grzybek

unread,
Jul 30, 2021, 8:19:40 AM7/30/21
to op...@googlegroups.com, Karaf Dev
Hello

I'd like to share great news about Pax Web 8 state.

For last few days I was working on tiny, single test related to Whiteboard-registration of WebSockets...

Normally (WAR) websockets are registered by some ServletContainerInitializer based ONLY on the classes passed to SCI.onStartup() and scanned using (usually) the information like this:

@HandlesTypes({
    ServerEndpoint.class,
    ServerApplicationConfig.class,
    Endpoint.class
})

WAR scenario in Pax Web 8 was easy - simply an existing SCI (or custom one for Undertow) was sufficient.

The problem was the dynamics of Whiteboard approach. What should happen when you simply "add a websocket"?
Pax Web 7, when registering a websocket was adding an SCI to be invoked at (re)start time of the target (Jetty, Tomcat, Undertow) context. So easy calculation - 10 websockets == 10 SCIs.

This fact made me think wider - how restarts and SCIs should be handled?

I got back to most trivial question - how many ways there are to register a servlet? In Pax Web case there are FIVE:
  1. webcontainer.registerServlet()
  2. Whiteboard registration of javax.servlet.Servlet service
  3. an SCI may invoke servletContext.addServlet()
  4. a ServletContextListener may invoke servletContext.addServlet()
  5. an Undertow extension may add additional servlets to DeploymentInfo
the same is for filters and listeners (except that a ServletContextListener can't register more ServletContextListeners)

So when we register and SCI that registers a websocket we want it to be run, right? so we effectively want to "restart a context". But (and that's what I was working on during last 3 days):
  • we don't want to lose servlets/filters/listeners registered previously through Whiteboard/HttpService
  • we want to lose the servlets/filters/listeners registered by SCIs and ServletContextListeners, because if we call them again, we don't want conflicts!
  • we want to clear the context attributes that could've been set by SCIs/ServletContextListeners before, because that's how SCis "mark" the context as processed - leaving there some flags that prevents them from doing some tasks more than once
And finally I have a working scenario:
  • an SCI is Whiteboard registered and calls sc.addFilter() in onStartup()
  • a ServletContextListener is Whiteboard registered and calls sc.setAttribute() and sc.addServlet() in contextInitialized()
  • a servlet is Whiteboard registered
  • a filter is Whiteboard registered
  • a WebSocket (1) is registered by instance
  • a WebSocket (2) is registered by class
  • a WebSocket (2) is unregistered
In between the registrations, GET requests are performed to check the expected behavior - and everything works consistently across all 3 container runtimes!

And yes - I added the possibility to register actual WebSocket instance - Pax Web 7, even if you've registered a @ServerEndpoint-annotated object as WebSocket, was simply taking its getClass() and was using this class (instantiated later by actual runtime).

And what's more - even if you register/unregister more WebSockets, single, dedicated SCI is used to (re)register all needed WebSockets!

I hope the actual 8.0.0.GA is finally coming.

kind regards
Grzegorz Grzybek

infinite...@gmail.com

unread,
Feb 24, 2023, 5:59:41 PM2/24/23
to OPS4J
I am in the process of upgrading from pax web 7.3.9 to 8.0.6 and have discovered issues with regard to spring integration with web sockets in version 8 of Pax Web with Jetty. I have been using the ServerEndpointExporter APIs in spring to register my web socket beans with Jetty and that was working fine with version 7 of pax web. However, with the major refactor that occurred in version 8, that spring integration does not appear to be working anymore. It looks like the underlying ServletContext implementation was changed and that due to that, the WebSocketInitializer is not getting triggered any longer and therefore the ServerContainer is no longer being assigned as an attribute in the servlet context with a key of "javax.websocket.server.ServerContainer", which is how it is located by spring in the exporter class. Was this change in behavior intentional? If so, what is the correct way in pax web 8 to integrate with the ServerEndpointExporter APIs. Thanks.

-hs

Grzegorz Grzybek

unread,
Mar 1, 2023, 7:12:46 AM3/1/23
to op...@googlegroups.com
Hello

Pax Web 8 has indeed a refactored mechanism for WebSocket handling - it's now much more close to JSR 356.

But the attribute should be there if you install proper websocket bundles. Which Karaf features did you install? There's special pax-web-jetty-websockets feature which installs 7 Jetty bundles for websockets.

And javax-websocket-server-impl-9.4.50.v20221201.jar contains /META-INF/services/javax.servlet.ServletContainerInitializer which declares org.eclipse.jetty.websocket.jsr356.server.deploy.WebSocketServerContainerInitializer SCE which should properly install your endpoints.

And definitely - Pax Web has to have custom implementation of ServletContext!

However you're right - Pax Web 8 doesn't explicitly tests Spring's mechanism for WebSocket publishing...

regards
Grzegorz Grzybek

--
--
------------------
OPS4J - http://www.ops4j.org - op...@googlegroups.com

---
You received this message because you are subscribed to the Google Groups "OPS4J" group.
To unsubscribe from this group and stop receiving emails from it, send an email to ops4j+un...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/ops4j/fb3b3c75-e0a8-4179-8463-759904423333n%40googlegroups.com.

Infinite Universe

unread,
Mar 2, 2023, 3:36:13 PM3/2/23
to op...@googlegroups.com

Hi,

Thank you very much for your response. I was able to track down part of the problem. The web app I am working with is quite large (many wars installed) and due to the new fragment scanning it was taking a very long time to start up. As a workaround we had limited the jars to scan and hadn’t included the jetty websocket jars. Now that I’ve added those to the include list I can see that the initializer is firing. However, that revealed a second problem that I’m now trying to track down. Previously I had included a context parameter in the web.xml file to not add the dynamic filter: “org.eclipse.jetty.websocket.jsr356.addDynamicFilter”. I can see that the context param is still getting read when the web.xml is processed by pax, and added to the OsgiContextModel in the BundleWebApplication.buildModel, however in the jetty WebSockerServerContainer.initialize method that parameter doesn’t seem to be visible in the servlet context. I can see that context parameters seem to be getting copied around as various contexts are created but it’s not obvious to me where the disconnect is happening. This was working in pax 7, is there something new that needs to be done with regard to context parms now? Thanks again.

-hs

On Mar 1, 2023, at 6:12 AM, Grzegorz Grzybek <gr.gr...@gmail.com> wrote:


Reply all
Reply to author
Forward
0 new messages