This is an automated email from the ASF dual-hosted git repository.

paulrutter pushed a commit to branch 
maintenance/FELIX-6746-websocketservlet-init-NPE
in repository https://gitbox.apache.org/repos/asf/felix-dev.git


The following commit(s) were added to 
refs/heads/maintenance/FELIX-6746-websocketservlet-init-NPE by this push:
     new 0de03ea42d FELIX-6746 JettyWebSocketServlet: Error during calling 
init() - Call init lazy in case of servlets that extend JettyWebSocketServlet - 
This fixes the IT as well
0de03ea42d is described below

commit 0de03ea42d170aa982cafdccaf9b059596313e96
Author: Paul Rütter <[email protected]>
AuthorDate: Mon Dec 30 11:36:52 2024 +0100

    FELIX-6746 JettyWebSocketServlet: Error during calling init()
    - Call init lazy in case of servlets that extend JettyWebSocketServlet
    - This fixes the IT as well
---
 .../http/base/internal/handler/ServletHandler.java | 54 ++++++++++++++++++----
 .../http/jetty/it/JettySpecificWebsocketIT.java    | 10 ++--
 2 files changed, 49 insertions(+), 15 deletions(-)

diff --git 
a/http/base/src/main/java/org/apache/felix/http/base/internal/handler/ServletHandler.java
 
b/http/base/src/main/java/org/apache/felix/http/base/internal/handler/ServletHandler.java
index 5a9c97a0ac..1291c7a8a0 100644
--- 
a/http/base/src/main/java/org/apache/felix/http/base/internal/handler/ServletHandler.java
+++ 
b/http/base/src/main/java/org/apache/felix/http/base/internal/handler/ServletHandler.java
@@ -42,6 +42,9 @@ public abstract class ServletHandler implements 
Comparable<ServletHandler>
 
     private static final String JAVA_SERVLET_TEMP_DIR_PROP = 
"jakarta.servlet.content.tempdir";
 
+    // The Jetty class used for Jetty WebSocket servlets
+    private static final String JETTY_WEB_SOCKET_SERVLET_CLASS = 
"JettyWebSocketServlet";
+
     private final long contextServiceId;
 
     private final ServletInfo servletInfo;
@@ -52,6 +55,8 @@ public abstract class ServletHandler implements 
Comparable<ServletHandler>
 
     protected volatile int useCount;
 
+    private boolean isInitialized = false;
+
     private final MultipartConfig mpConfig;
 
     public ServletHandler(final long contextServiceId,
@@ -125,6 +130,16 @@ public abstract class ServletHandler implements 
Comparable<ServletHandler>
         final Servlet local = this.servlet;
         if ( local != null )
         {
+            if (!isInitialized){
+                // Lazy init if needed
+                try {
+                    servlet.init(new ServletConfigImpl(getName(), 
getContext(), getServletInfo().getInitParameters()));
+                    isInitialized = true;
+                } catch (final Exception e) {
+                    
SystemLogger.LOGGER.error(SystemLogger.formatMessage(this.getServletInfo().getServiceReference(),
+                                    "Error calling init() lazy on servlet 
".concat(this.servletInfo.getClassName(this.servlet))),
+                            e);}
+            }
             local.service(req, res);
         }
         else
@@ -173,21 +188,40 @@ public abstract class ServletHandler implements 
Comparable<ServletHandler>
             return DTOConstants.FAILURE_REASON_SERVICE_NOT_GETTABLE;
         }
 
-        try
-        {
-            servlet.init(new ServletConfigImpl(getName(), getContext(), 
getServletInfo().getInitParameters()));
-        }
-        catch (final Exception e)
-        {
-            
SystemLogger.LOGGER.error(SystemLogger.formatMessage(this.getServletInfo().getServiceReference(),
-                    "Error during calling init() on servlet 
".concat(this.servletInfo.getClassName(this.servlet))),
-                    e);
-            return DTOConstants.FAILURE_REASON_EXCEPTION_ON_INIT;
+        if (!isJettyWebSocketServlet()) {
+            try {
+                servlet.init(new ServletConfigImpl(getName(), getContext(), 
getServletInfo().getInitParameters()));
+                isInitialized = true;
+            } catch (final Exception e) {
+                
SystemLogger.LOGGER.error(SystemLogger.formatMessage(this.getServletInfo().getServiceReference(),
+                                "Error during calling init() on servlet 
".concat(this.servletInfo.getClassName(this.servlet))),
+                        e);
+                return DTOConstants.FAILURE_REASON_EXCEPTION_ON_INIT;
+            }
         }
         this.useCount++;
         return -1;
     }
 
+    /**
+     * Check if the servlet is a JettyWebSocketServlet.
+     * JettyWebSocket classes are handled differently due to FELIX-6746
+     * @return true if the servlet is a JettyWebSocketServlet, false otherwise
+     */
+    private boolean isJettyWebSocketServlet() {
+        final Class<?> superClass = servlet.getClass().getSuperclass();
+        SystemLogger.LOGGER.debug("Checking if the servlet is a 
JettyWebSocketServlet: '" + superClass.getSimpleName() + "'");
+
+        // Now check if the servlet class extends 'JettyWebSocketServlet'
+        boolean isJettyWebSocketServlet = 
superClass.getSimpleName().endsWith(JETTY_WEB_SOCKET_SERVLET_CLASS);
+        if (!isJettyWebSocketServlet && servlet instanceof 
org.apache.felix.http.javaxwrappers.ServletWrapper) {
+            // In case the servlet is wrapped, we need to check the wrapped 
servlet
+            isJettyWebSocketServlet = 
((org.apache.felix.http.javaxwrappers.ServletWrapper) servlet)
+                    
.getServlet().getClass().getSuperclass().getSimpleName().endsWith(JETTY_WEB_SOCKET_SERVLET_CLASS);
+        }
+        return isJettyWebSocketServlet;
+    }
+
 
     public boolean destroy()
     {
diff --git 
a/http/jetty12/src/test/java/org/apache/felix/http/jetty/it/JettySpecificWebsocketIT.java
 
b/http/jetty12/src/test/java/org/apache/felix/http/jetty/it/JettySpecificWebsocketIT.java
index 097dc83fe3..7f883370c5 100644
--- 
a/http/jetty12/src/test/java/org/apache/felix/http/jetty/it/JettySpecificWebsocketIT.java
+++ 
b/http/jetty12/src/test/java/org/apache/felix/http/jetty/it/JettySpecificWebsocketIT.java
@@ -138,15 +138,15 @@ public class JettySpecificWebsocketIT extends 
AbstractJettyTestSupport {
 
     @Test
     public void testWebSocketServletWhiteboard() throws Exception {
-        final JettyWebSocketServlet webSocketServlet2 = new 
JettyWebSocketServlet() {
+        final JettyWebSocketServlet webSocketServlet = new 
JettyWebSocketServlet() {
             @Override
             protected void configure(JettyWebSocketServletFactory 
jettyWebSocketServletFactory) {
                 jettyWebSocketServletFactory.register(MyServerWebSocket.class);
             }
         };
-        final Dictionary<String, Object> webSocketServletProps2 = new 
Hashtable<>();
-        webSocketServletProps2.put(HTTP_WHITEBOARD_SERVLET_PATTERN, 
"/websocketservlet/*");
-        bundleContext.registerService(Servlet.class, webSocketServlet2, 
webSocketServletProps2);
+        final Dictionary<String, Object> props = new Hashtable<>();
+        props.put(HTTP_WHITEBOARD_SERVLET_PATTERN, "/websocketservlet");
+        bundleContext.registerService(Servlet.class, webSocketServlet, props);
 
         HttpClientTransportOverHTTP transport = new 
HttpClientTransportOverHTTP();
         HttpClient httpClient = new 
org.eclipse.jetty.client.HttpClient(transport);
@@ -155,7 +155,7 @@ public class JettySpecificWebsocketIT extends 
AbstractJettyTestSupport {
 
         Object value = 
bundleContext.getServiceReference(HttpService.class).getProperty("org.osgi.service.http.port");
         int httpPort = Integer.parseInt((String)value);
-        URI destUri = new 
URI(String.format("ws://localhost:%d/websocketservlet/test", httpPort));
+        URI destUri = new 
URI(String.format("ws://localhost:%d/websocketservlet", httpPort));
 
         MyClientWebSocket clientWebSocket = new MyClientWebSocket();
         ClientUpgradeRequest request = new ClientUpgradeRequest();

Reply via email to