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

rombert pushed a commit to branch master
in repository 
https://gitbox.apache.org/repos/asf/sling-org-apache-sling-mcp-server.git


The following commit(s) were added to refs/heads/master by this push:
     new a6ac6c9  feat: make bundle compatible with javax.servlet APIs (#2)
a6ac6c9 is described below

commit a6ac6c9f7ce04ea9268efc0b1afd3062fb263799
Author: Robert Munteanu <[email protected]>
AuthorDate: Wed Mar 4 15:51:04 2026 +0100

    feat: make bundle compatible with javax.servlet APIs (#2)
    
    Since the Servlets from the SDK use the jakarta.servlet APIs we embed those 
APIs and the felix wrappers in a secondary artifact with the 'legacy' 
classifier. This allows MCP SDK servlets to function unaltered and the Sling 
McpServlet to use the old javax.servlet API.
    
    We also restrict slf4j imports to work with the older Sling commons.log 
version on the premise that projects that compile against slf4j 2.0 don't 
actually use any of the new APIs and can function with 1.7.x as well.
---
 README.md                                          |   3 +
 bnd-legacy.bnd                                     |  18 ++++
 bnd.bnd                                            |   3 +
 pom.xml                                            | 103 ++++++++++++++++++++-
 .../appended-resources-legacy/META-INF/LICENSE     |  13 +++
 src/main/appended-resources-legacy/META-INF/NOTICE |   2 +
 src/main/appended-resources/META-INF/LICENSE       |  14 +++
 .../apache/sling/mcp/server/impl/McpServlet.java   |  61 ++++++++----
 8 files changed, 197 insertions(+), 20 deletions(-)

diff --git a/README.md b/README.md
index 60b78f3..b189d5d 100644
--- a/README.md
+++ b/README.md
@@ -18,3 +18,6 @@ $ mvn -f whiteboard/mcp-server-contributions/ install 
sling:install
 
 Then open up your coding assistant tool and add an remote MCP server with 
location http://localhost:8080/mcp .
 
+## Legacy artifact
+
+For applications still using the older slf4j 1.x and javax.servlet APIs a 
classifier with the 'legacy' classifier is built.
diff --git a/bnd-legacy.bnd b/bnd-legacy.bnd
new file mode 100644
index 0000000..8a6fd89
--- /dev/null
+++ b/bnd-legacy.bnd
@@ -0,0 +1,18 @@
+# 1. workaround for https://github.com/modelcontextprotocol/java-sdk/issues/562
+# 2. compatibility with javax.servlet
+Private-Package: io.modelcontextprotocol.json.jackson, \
+    io.modelcontextprotocol.json.schema.jackson, \
+    jakarta.servlet, \
+    jakarta.servlet.annotation, \
+    jakarta.servlet.descriptor, \
+    jakarta.servlet.http, \
+    org.apache.felix.http.jakartawrappers, \
+    org.apache.felix.http.javaxwrappers
+
+# compatibility with slf4j 1.7 and 2.0. A bit of the gamble since we assume 
that libraries
+# that compile against slf4j 2.x only use 1.7 APIs
+Import-Package:  org.slf4j;version="[1.7,2)", \
+    *
+
+# Strictly control exports to prevent bnd from exporting packages that from 
embedded dependencies
+-exportcontents: org.apache.sling.mcp.server.spi
diff --git a/bnd.bnd b/bnd.bnd
index c7ccc7c..a4ad25e 100644
--- a/bnd.bnd
+++ b/bnd.bnd
@@ -1,3 +1,6 @@
 # workaround for https://github.com/modelcontextprotocol/java-sdk/issues/562
 Private-Package: io.modelcontextprotocol.json.jackson, \
     io.modelcontextprotocol.json.schema.jackson
+
+# Strictly control exports to prevent bnd from exporting packages that from 
embedded dependencies
+-exportcontents: org.apache.sling.mcp.server.spi
diff --git a/pom.xml b/pom.xml
index ab1074a..1208b57 100644
--- a/pom.xml
+++ b/pom.xml
@@ -42,6 +42,8 @@
         <sling.java.version>17</sling.java.version>
         <!-- Run with 
-Dslingfeature.app.vmOption=-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=30303
 for debug mode-->
         <slingfeature.app.vmOption />
+        <!-- Directory for legacy variant classes -->
+        
<legacy.classes.directory>${project.build.directory}/classes-legacy</legacy.classes.directory>
     </properties>
 
     <dependencies>
@@ -93,7 +95,7 @@
         <dependency>
             <groupId>org.apache.sling</groupId>
             <artifactId>org.apache.sling.api</artifactId>
-            <version>3.0.2</version>
+            <version>2.27.6</version>
             <scope>provided</scope>
         </dependency>
         <dependency>
@@ -102,10 +104,20 @@
             <version>2.10.2</version>
             <scope>provided</scope>
         </dependency>
+        <dependency>
+            <groupId>javax.servlet</groupId>
+            <artifactId>javax.servlet-api</artifactId>
+            <scope>provided</scope>
+        </dependency>
         <dependency>
             <groupId>jakarta.servlet</groupId>
             <artifactId>jakarta.servlet-api</artifactId>
-            <scope>provided</scope>
+            <scope>compile</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.felix</groupId>
+            <artifactId>org.apache.felix.http.wrappers</artifactId>
+            <scope>compile</scope>
         </dependency>
         <dependency>
             <groupId>io.modelcontextprotocol.sdk</groupId>
@@ -266,7 +278,94 @@
                     </launches>
                 </configuration>
             </plugin>
+            <plugin>
+                <groupId>org.apache.rat</groupId>
+                <artifactId>apache-rat-plugin</artifactId>
+                <configuration>
+                    <excludes combine.children="append">
+                        <exclude>bnd-legacy.bnd</exclude>
+                        
<exclude>src/main/appended-resources/META-INF/*</exclude>
+                        
<exclude>src/main/appended-resources-legacy/META-INF/*</exclude>
+                    </excludes>
+                </configuration>
+            </plugin>
         </plugins>
     </build>
 
+    <profiles>
+        <!-- legacy compatibility (slf4j 1.x, javax.servlet) -->
+        <profile>
+            <id>legacy-compat</id>
+            <activation>
+                <activeByDefault>true</activeByDefault>
+            </activation>
+            <build>
+                <plugins>
+                    <!-- Append legacy-specific license content to 
bnd-generated LICENSE/NOTICE -->
+                    <plugin>
+                        <groupId>org.apache.maven.plugins</groupId>
+                        <artifactId>maven-antrun-plugin</artifactId>
+                        <executions>
+                            <execution>
+                                <id>append-legacy-license</id>
+                                <goals>
+                                    <goal>run</goal>
+                                </goals>
+                                <phase>prepare-package</phase>
+                                <configuration>
+                                    <target>
+                                        <concat append="true" 
destfile="${legacy.classes.directory}/META-INF/LICENSE">
+                                            <filelist 
dir="src/main/appended-resources-legacy/META-INF" files="LICENSE" />
+                                        </concat>
+                                        <concat append="true" 
destfile="${legacy.classes.directory}/META-INF/NOTICE">
+                                            <filelist 
dir="src/main/appended-resources-legacy/META-INF" files="NOTICE" />
+                                        </concat>
+                                    </target>
+                                </configuration>
+                            </execution>
+                        </executions>
+                    </plugin>
+                    <!-- Configure bnd-maven-plugin to generate an additional 
jar based on a different bnd file -->
+                    <plugin>
+                        <groupId>biz.aQute.bnd</groupId>
+                        <artifactId>bnd-maven-plugin</artifactId>
+                        <executions>
+                            <execution>
+                                <id>bnd-process-legacy</id>
+                                <goals>
+                                    <goal>bnd-process</goal>
+                                </goals>
+                                <configuration>
+                                    <bndfile>bnd-legacy.bnd</bndfile>
+                                    
<manifestPath>${legacy.classes.directory}/META-INF/MANIFEST.MF</manifestPath>
+                                    
<outputDir>${legacy.classes.directory}</outputDir>
+                                </configuration>
+                            </execution>
+                        </executions>
+                    </plugin>
+                    <!-- Configure jar plugin to create legacy variant from 
classes-legacy -->
+                    <plugin>
+                        <groupId>org.apache.maven.plugins</groupId>
+                        <artifactId>maven-jar-plugin</artifactId>
+                        <executions>
+                            <execution>
+                                <id>legacy-jar</id>
+                                <goals>
+                                    <goal>jar</goal>
+                                </goals>
+                                <configuration>
+                                    <classifier>legacy</classifier>
+                                    
<classesDirectory>${legacy.classes.directory}</classesDirectory>
+                                    <archive>
+                                        
<manifestFile>${legacy.classes.directory}/META-INF/MANIFEST.MF</manifestFile>
+                                    </archive>
+                                </configuration>
+                            </execution>
+                        </executions>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+    </profiles>
+
 </project>
diff --git a/src/main/appended-resources-legacy/META-INF/LICENSE 
b/src/main/appended-resources-legacy/META-INF/LICENSE
new file mode 100644
index 0000000..21d103a
--- /dev/null
+++ b/src/main/appended-resources-legacy/META-INF/LICENSE
@@ -0,0 +1,13 @@
+
+
+For Jakarta Servlet API 6.1.0 (jakarta.servlet:jakarta.servlet-api)
+
+This product bundles Jakarta Servlet API 6.1.0, which is available under
+"Eclipse Public License v. 2.0 OR GPL-2.0 WITH Classpath-exception-2.0"
+license. For details, see https://jakarta.ee/specifications/servlet/
+
+
+For Apache Felix HTTP Wrappers 6.1.0 
(org.apache.felix:org.apache.felix.http.wrappers)
+
+This product bundles Apache Felix HTTP Wrappers 6.1.0, which is available
+under the Apache License 2.0. For details, see https://felix.apache.org/
diff --git a/src/main/appended-resources-legacy/META-INF/NOTICE 
b/src/main/appended-resources-legacy/META-INF/NOTICE
new file mode 100644
index 0000000..fc65cac
--- /dev/null
+++ b/src/main/appended-resources-legacy/META-INF/NOTICE
@@ -0,0 +1,2 @@
+Apache Felix Http Wrappers
+Copyright 2006-2024 The Apache Software Foundation
diff --git a/src/main/appended-resources/META-INF/LICENSE 
b/src/main/appended-resources/META-INF/LICENSE
new file mode 100644
index 0000000..04e3bb7
--- /dev/null
+++ b/src/main/appended-resources/META-INF/LICENSE
@@ -0,0 +1,14 @@
+
+
+
+APACHE SLING MCP SERVER SUBCOMPONENTS:
+
+The Apache Sling MCP Server includes a number of subcomponents
+with separate copyright notices and license terms. Your use of the source
+code for these subcomponents is subject to the terms and conditions
+of the following licenses.
+
+For MCP SDK 0.17.0 (io.modelcontextprotocol:mcp-json-jackson2)
+
+This product bundles MCP SDK 0.17.0, which is available under a "MIT"
+license. For details, see https://github.com/modelcontextprotocol/java-sdk
diff --git a/src/main/java/org/apache/sling/mcp/server/impl/McpServlet.java 
b/src/main/java/org/apache/sling/mcp/server/impl/McpServlet.java
index 643265c..2ba0354 100644
--- a/src/main/java/org/apache/sling/mcp/server/impl/McpServlet.java
+++ b/src/main/java/org/apache/sling/mcp/server/impl/McpServlet.java
@@ -18,6 +18,9 @@
  */
 package org.apache.sling.mcp.server.impl;
 
+import javax.servlet.Servlet;
+import javax.servlet.ServletException;
+
 import java.io.IOException;
 import java.lang.invoke.MethodHandle;
 import java.lang.invoke.MethodHandles;
@@ -35,13 +38,11 @@ import 
io.modelcontextprotocol.server.McpStatelessSyncServer;
 import 
io.modelcontextprotocol.server.transport.HttpServletStatelessServerTransport;
 import io.modelcontextprotocol.spec.McpSchema;
 import io.modelcontextprotocol.spec.McpSchema.ServerCapabilities;
-import jakarta.servlet.Servlet;
-import jakarta.servlet.ServletException;
-import jakarta.servlet.http.HttpServletRequest;
-import jakarta.servlet.http.HttpServletResponse;
-import org.apache.sling.api.SlingJakartaHttpServletRequest;
-import org.apache.sling.api.SlingJakartaHttpServletResponse;
-import org.apache.sling.api.servlets.SlingJakartaAllMethodsServlet;
+import org.apache.felix.http.jakartawrappers.HttpServletRequestWrapper;
+import org.apache.felix.http.jakartawrappers.HttpServletResponseWrapper;
+import org.apache.sling.api.SlingHttpServletRequest;
+import org.apache.sling.api.SlingHttpServletResponse;
+import org.apache.sling.api.servlets.SlingAllMethodsServlet;
 import org.apache.sling.mcp.server.spi.McpServerContribution;
 import org.apache.sling.servlets.annotations.SlingServletPaths;
 import org.jetbrains.annotations.NotNull;
@@ -64,7 +65,7 @@ import static 
org.osgi.service.component.annotations.ReferencePolicyOption.GREED
 @Component(service = Servlet.class)
 @SlingServletPaths(value = {McpServlet.ENDPOINT})
 @Designate(ocd = McpServlet.Config.class)
-public class McpServlet extends SlingJakartaAllMethodsServlet {
+public class McpServlet extends SlingAllMethodsServlet {
 
     @ObjectClassDefinition(name = "Apache Sling MCP Server Configuration")
     public @interface Config {
@@ -102,8 +103,11 @@ public class McpServlet extends 
SlingJakartaAllMethodsServlet {
         transportProvider = HttpServletStatelessServerTransport.builder()
                 .messageEndpoint(ENDPOINT)
                 .jsonMapper(jsonMapper)
-                .contextExtractor(request -> McpTransportContext.create(
-                        Map.of("resourceResolver", 
((SlingJakartaHttpServletRequest) request).getResourceResolver())))
+                .contextExtractor(request -> McpTransportContext.create(Map.of(
+                        "resourceResolver",
+                        ((BridgedJakartaHttpServletRequest) request)
+                                .getSlingRequest()
+                                .getResourceResolver())))
                 .build();
 
         MethodHandles.Lookup privateLookup =
@@ -113,12 +117,16 @@ public class McpServlet extends 
SlingJakartaAllMethodsServlet {
                 HttpServletStatelessServerTransport.class,
                 "doGet",
                 java.lang.invoke.MethodType.methodType(
-                        void.class, HttpServletRequest.class, 
HttpServletResponse.class));
+                        void.class,
+                        jakarta.servlet.http.HttpServletRequest.class,
+                        jakarta.servlet.http.HttpServletResponse.class));
         doPostMethod = privateLookup.findVirtual(
                 HttpServletStatelessServerTransport.class,
                 "doPost",
                 java.lang.invoke.MethodType.methodType(
-                        void.class, HttpServletRequest.class, 
HttpServletResponse.class));
+                        void.class,
+                        jakarta.servlet.http.HttpServletRequest.class,
+                        jakarta.servlet.http.HttpServletResponse.class));
 
         String serverVersion = config.serverVersion();
         if (serverVersion == null || serverVersion.isEmpty()) {
@@ -205,11 +213,13 @@ public class McpServlet extends 
SlingJakartaAllMethodsServlet {
     }
 
     @Override
-    protected void doGet(
-            @NotNull SlingJakartaHttpServletRequest request, @NotNull 
SlingJakartaHttpServletResponse response)
+    protected void doGet(@NotNull SlingHttpServletRequest request, @NotNull 
SlingHttpServletResponse response)
             throws ServletException, IOException {
         try {
-            doGetMethod.invoke(transportProvider, request, response);
+            doGetMethod.invoke(
+                    transportProvider,
+                    new BridgedJakartaHttpServletRequest(request),
+                    new HttpServletResponseWrapper(response));
         } catch (ServletException | IOException | RuntimeException | Error e) {
             throw e;
         } catch (Throwable t) {
@@ -218,11 +228,13 @@ public class McpServlet extends 
SlingJakartaAllMethodsServlet {
     }
 
     @Override
-    protected void doPost(
-            @NotNull SlingJakartaHttpServletRequest request, @NotNull 
SlingJakartaHttpServletResponse response)
+    protected void doPost(@NotNull SlingHttpServletRequest request, @NotNull 
SlingHttpServletResponse response)
             throws ServletException, IOException {
         try {
-            doPostMethod.invoke(transportProvider, request, response);
+            doPostMethod.invoke(
+                    transportProvider,
+                    new BridgedJakartaHttpServletRequest(request),
+                    new HttpServletResponseWrapper(response));
         } catch (ServletException | IOException | RuntimeException | Error e) {
             throw e;
         } catch (Throwable t) {
@@ -236,4 +248,17 @@ public class McpServlet extends 
SlingJakartaAllMethodsServlet {
             syncServer.close();
         }
     }
+
+    static class BridgedJakartaHttpServletRequest extends 
HttpServletRequestWrapper {
+        private SlingHttpServletRequest slingRequest;
+
+        public BridgedJakartaHttpServletRequest(SlingHttpServletRequest 
request) {
+            super(request);
+            this.slingRequest = request;
+        }
+
+        public SlingHttpServletRequest getSlingRequest() {
+            return slingRequest;
+        }
+    }
 }

Reply via email to