You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@felix.apache.org by cz...@apache.org on 2022/02/13 11:12:13 UTC

[felix-dev] 01/13: Update jetty to Jetty 11, jakarta servlet api

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

cziegeler pushed a commit to branch http/jakarta
in repository https://gitbox.apache.org/repos/asf/felix-dev.git

commit df270c0c07c26a2c853127fcaed5ff57f0480e9c
Author: Carsten Ziegeler <cz...@adobe.com>
AuthorDate: Sun Jan 2 14:54:35 2022 +0100

    Update jetty to Jetty 11, jakarta servlet api
---
 http/base/pom.xml                                  |  10 +-
 .../felix/http/base/internal/EventDispatcher.java  |   6 +-
 .../http/base/internal/HttpServiceController.java  |  32 +-
 .../base/internal/console/HttpServicePlugin.java   |  10 +-
 .../base/internal/context/ExtServletContext.java   |  19 +-
 .../internal/context/ExtServletContextWrapper.java |  40 +-
 .../http/base/internal/dispatch/Dispatcher.java    |  24 +-
 .../base/internal/dispatch/DispatcherServlet.java  |   8 +-
 .../base/internal/dispatch/InvocationChain.java    |  16 +-
 .../internal/dispatch/RequestDispatcherImpl.java   |  14 +-
 .../internal/dispatch/ServletRequestWrapper.java   | 102 +++--
 .../internal/dispatch/ServletResponseWrapper.java  |  16 +-
 .../base/internal/handler/FilterConfigImpl.java    |   4 +-
 .../http/base/internal/handler/FilterHandler.java  |  28 +-
 .../handler/HttpServiceServletHandler.java         |  22 +-
 .../base/internal/handler/HttpSessionWrapper.java  |  12 +-
 .../base/internal/handler/ListenerHandler.java     |   8 +-
 .../base/internal/handler/PreprocessorHandler.java |  25 +-
 .../base/internal/handler/ServletConfigImpl.java   |   4 +-
 .../http/base/internal/handler/ServletHandler.java |  23 +-
 .../internal/handler/WhiteboardServletHandler.java |  14 +-
 .../jakartawrappers/AsyncContextWrapper.java       | 109 ++++++
 .../jakartawrappers/AsyncListenerWrapper.java      |  76 ++++
 .../internal/jakartawrappers/CookieWrapper.java    | 111 ++++++
 .../jakartawrappers/EventListenerWrapper.java      | 229 +++++++++++
 .../jakartawrappers/FilterRegistrationWrapper.java | 115 ++++++
 .../internal/jakartawrappers/FilterWrapper.java    |  78 ++++
 .../jakartawrappers/HttpServletRequestWrapper.java | 241 ++++++++++++
 .../HttpServletResponseWrapper.java                | 151 ++++++++
 .../jakartawrappers/HttpSessionContextWrapper.java |  55 +++
 .../jakartawrappers/HttpSessionWrapper.java        | 132 +++++++
 .../base/internal/jakartawrappers/PartWrapper.java |  91 +++++
 .../PreprocessorWrapper.java}                      |  51 ++-
 .../ReadListenerWrapper.java}                      |  60 +--
 .../jakartawrappers/RequestDispatcherWrapper.java  |  62 +++
 .../jakartawrappers/ServletConfigWrapper.java      |  60 +++
 .../ServletContextHelperWrapper.java               |  85 +++++
 .../jakartawrappers/ServletContextWrapper.java     | 417 +++++++++++++++++++++
 .../jakartawrappers/ServletExceptionUtil.java      |  50 +++
 .../jakartawrappers/ServletInputStreamWrapper.java | 128 +++++++
 .../ServletOutputStreamWrapper.java                | 150 ++++++++
 .../ServletRegistrationWrapper.java                |  86 +++++
 .../jakartawrappers/ServletRequestWrapper.java     | 339 +++++++++++++++++
 .../jakartawrappers/ServletResponseWrapper.java    | 145 +++++++
 .../internal/jakartawrappers/ServletWrapper.java   |  98 +++++
 .../SessionCookieConfigWrapper.java                | 107 ++++++
 .../WriteListenerWrapper.java}                     |  56 ++-
 .../javaxwrappers/AsyncContextWrapper.java         | 104 +++++
 .../javaxwrappers/AsyncListenerWrapper.java        |  78 ++++
 .../base/internal/javaxwrappers/CookieWrapper.java | 111 ++++++
 .../internal/javaxwrappers/FilterChainWrapper.java |  54 +++
 .../javaxwrappers/FilterConfigWrapper.java         |  59 +++
 .../javaxwrappers/FilterRegistrationWrapper.java   | 115 ++++++
 .../javaxwrappers/HttpServletRequestWrapper.java   | 238 ++++++++++++
 .../javaxwrappers/HttpServletResponseWrapper.java  | 151 ++++++++
 .../javaxwrappers/HttpSessionContextWrapper.java   |  55 +++
 .../internal/javaxwrappers/HttpSessionWrapper.java | 130 +++++++
 .../base/internal/javaxwrappers/PartWrapper.java   |  91 +++++
 .../ReadListenerWrapper.java}                      |  60 +--
 .../javaxwrappers/RequestDispatcherWrapper.java    |  61 +++
 .../javaxwrappers/ServletConfigWrapper.java        |  59 +++
 .../javaxwrappers/ServletContextWrapper.java       | 416 ++++++++++++++++++++
 .../javaxwrappers/ServletExceptionUtil.java        |  50 +++
 .../javaxwrappers/ServletInputStreamWrapper.java   | 128 +++++++
 .../javaxwrappers/ServletOutputStreamWrapper.java  | 150 ++++++++
 .../javaxwrappers/ServletRegistrationWrapper.java  |  86 +++++
 .../javaxwrappers/ServletRequestWrapper.java       | 334 +++++++++++++++++
 .../javaxwrappers/ServletResponseWrapper.java      | 145 +++++++
 .../internal/javaxwrappers/ServletWrapper.java     |  83 ++++
 .../javaxwrappers/SessionCookieConfigWrapper.java  | 107 ++++++
 .../WriteListenerWrapper.java}                     |  56 ++-
 .../internal/registry/EventListenerRegistry.java   |  28 +-
 .../base/internal/registry/FilterRegistry.java     |   2 +-
 .../base/internal/registry/HandlerRegistry.java    |   2 +-
 .../registry/PerContextHandlerRegistry.java        |   2 +-
 .../http/base/internal/runtime/AbstractInfo.java   |  27 ++
 .../http/base/internal/runtime/FilterInfo.java     |  31 +-
 .../http/base/internal/runtime/ListenerInfo.java   |  69 +++-
 .../base/internal/runtime/PreprocessorInfo.java    |  24 +-
 .../http/base/internal/runtime/ResourceInfo.java   |   8 +-
 .../internal/runtime/ServletContextHelperInfo.java |  18 +-
 .../http/base/internal/runtime/ServletInfo.java    |  23 +-
 .../internal/runtime/dto/FilterDTOBuilder.java     |   2 +-
 .../internal/runtime/dto/ListenerDTOBuilder.java   |   2 +-
 .../runtime/dto/RequestInfoDTOBuilder.java         |   2 +-
 .../runtime/dto/ServletContextDTOBuilder.java      |   2 +-
 .../base/internal/service/DefaultHttpContext.java  |  13 +-
 ...ltHttpContext.java => HttpResourceServlet.java} |  35 +-
 .../base/internal/service/HttpServiceFactory.java  |  12 +-
 .../internal/service/PerBundleHttpServiceImpl.java |  49 ++-
 .../base/internal/service/ServletContextImpl.java  |  93 +++--
 .../internal/service/ServletContextManager.java    |   2 +-
 .../internal/service/SharedHttpServiceImpl.java    |  48 ++-
 .../internal/whiteboard/FailureStateHandler.java   |   2 +-
 .../whiteboard/HttpServiceContextHandler.java      |   2 +-
 .../whiteboard/PerBundleServletContextImpl.java    |  53 +--
 .../whiteboard/RegistrationFailureException.java   |   2 +-
 .../{service => whiteboard}/ResourceServlet.java   |  91 ++---
 .../whiteboard/SharedServletContextImpl.java       |  31 +-
 .../whiteboard/WhiteboardContextHandler.java       |  12 +-
 .../internal/whiteboard/WhiteboardManager.java     |  55 +--
 .../internal/whiteboard/tracker/FilterTracker.java |   4 +-
 .../whiteboard/tracker/JavaxFilterTracker.java     |  88 +++++
 .../whiteboard/tracker/JavaxListenersTracker.java  | 169 +++++++++
 .../tracker/JavaxPreprocessorTracker.java          |  82 ++++
 ....java => JavaxServletContextHelperTracker.java} |  64 +++-
 .../whiteboard/tracker/JavaxServletTracker.java    |  88 +++++
 .../whiteboard/tracker/ListenersTracker.java       |  16 +-
 .../whiteboard/tracker/PreprocessorTracker.java    |   6 +-
 .../tracker/ServletContextHelperTracker.java       |   5 +-
 .../whiteboard/tracker/ServletTracker.java         |   4 +-
 .../whiteboard/Preprocessor.java}                  |  42 +--
 .../base/osgi/whiteboard/ServletContextHelper.java |  97 +++++
 .../internal/context/ServletContextImplTest.java   |  46 +--
 .../context/ServletContextManagerTest.java         |   2 +-
 .../internal/handler/FilterConfigImplTest.java     |   2 +-
 .../base/internal/handler/FilterHandlerTest.java   |  21 +-
 .../handler/HttpServiceServletHandlerTest.java     |  20 +-
 .../internal/handler/HttpSessionWrapperTest.java   |   4 +-
 .../internal/handler/ServletConfigImplTest.java    |   2 +-
 .../internal/registry/ErrorPageRegistryTest.java   |  10 +-
 .../registry/EventListenerRegistryTest.java        |   6 +-
 .../base/internal/registry/FilterRegistryTest.java |  10 +-
 .../internal/registry/HandlerRegistryTest.java     |  12 +-
 .../internal/registry/ServletRegistryTest.java     |  10 +-
 .../internal/runtime/AbstractInfoOrderingTest.java |   6 +
 .../base/internal/runtime/ListenerInfoTest.java    |   2 +-
 .../internal/service/HttpServiceFactoryTest.java   |   2 +-
 http/itest/pom.xml                                 |   4 +-
 .../felix/http/itest/BaseIntegrationTest.java      |   2 +
 http/jetty/pom.xml                                 |  24 +-
 .../felix/http/jetty/internal/JettyService.java    |   8 +-
 .../jetty/internal/webapp/WebAppBundleTracker.java |   4 +-
 .../org/apache/felix/http/jetty/package-info.java  |   4 +-
 .../http/jetty/internal/JettyServiceTest.java      |  28 +-
 135 files changed, 7522 insertions(+), 754 deletions(-)

diff --git a/http/base/pom.xml b/http/base/pom.xml
index 84db8e3..e119077 100644
--- a/http/base/pom.xml
+++ b/http/base/pom.xml
@@ -28,7 +28,7 @@
 
     <name>Apache Felix Http Base</name>
     <artifactId>org.apache.felix.http.base</artifactId>
-    <version>4.1.7-SNAPSHOT</version>
+    <version>5.0.0-SNAPSHOT</version>
     <packaging>jar</packaging>
 
     <scm>
@@ -39,7 +39,7 @@
   </scm>
 
     <properties>
-        <felix.java.version>8</felix.java.version>
+        <felix.java.version>11</felix.java.version>
     </properties>
 
     <dependencies>
@@ -49,6 +49,12 @@
             <version>4.0.1</version>
         </dependency>
         <dependency>
+            <groupId>jakarta.servlet</groupId>
+            <artifactId>jakarta.servlet-api</artifactId>
+            <version>5.0.0</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
             <groupId>org.osgi</groupId>
             <artifactId>osgi.core</artifactId>
         </dependency>
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/EventDispatcher.java b/http/base/src/main/java/org/apache/felix/http/base/internal/EventDispatcher.java
index 044ed15..1525251 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/EventDispatcher.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/EventDispatcher.java
@@ -18,9 +18,9 @@
  */
 package org.apache.felix.http.base.internal;
 
-import javax.servlet.http.HttpSessionEvent;
-import javax.servlet.http.HttpSessionIdListener;
-import javax.servlet.http.HttpSessionListener;
+import jakarta.servlet.http.HttpSessionEvent;
+import jakarta.servlet.http.HttpSessionIdListener;
+import jakarta.servlet.http.HttpSessionListener;
 
 /**
  * The <code>EventDispatcher</code> dispatches events sent from the servlet
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/HttpServiceController.java b/http/base/src/main/java/org/apache/felix/http/base/internal/HttpServiceController.java
index 67610f9..570e9fe 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/HttpServiceController.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/HttpServiceController.java
@@ -18,12 +18,6 @@ package org.apache.felix.http.base.internal;
 
 import java.util.Hashtable;
 
-import javax.servlet.Servlet;
-import javax.servlet.ServletContext;
-import javax.servlet.http.HttpSessionEvent;
-import javax.servlet.http.HttpSessionIdListener;
-import javax.servlet.http.HttpSessionListener;
-
 import org.apache.felix.http.base.internal.dispatch.Dispatcher;
 import org.apache.felix.http.base.internal.dispatch.DispatcherServlet;
 import org.apache.felix.http.base.internal.handler.HttpSessionWrapper;
@@ -33,6 +27,15 @@ import org.apache.felix.http.base.internal.whiteboard.WhiteboardManager;
 import org.jetbrains.annotations.NotNull;
 import org.osgi.framework.BundleContext;
 
+import jakarta.servlet.Servlet;
+import jakarta.servlet.ServletContext;
+import jakarta.servlet.http.HttpSessionEvent;
+import jakarta.servlet.http.HttpSessionIdListener;
+import jakarta.servlet.http.HttpSessionListener;
+
+/**
+ * Controller for the http service
+ */
 public final class HttpServiceController
 {
     private final BundleContext bundleContext;
@@ -46,6 +49,10 @@ public final class HttpServiceController
 
     private volatile HttpSessionListener httpSessionListener;
 
+    /**
+     * Create new controller
+     * @param bundleContext The bundle context
+     */
     public HttpServiceController(final BundleContext bundleContext)
     {
         this.bundleContext = bundleContext;
@@ -56,6 +63,9 @@ public final class HttpServiceController
         this.whiteboardManager = new WhiteboardManager(bundleContext, this.httpServiceFactory, this.registry);
     }
 
+    /**
+     * Stop the controller
+     */
     public void stop()
     {
         this.unregister();
@@ -70,12 +80,16 @@ public final class HttpServiceController
         return new DispatcherServlet(this.dispatcher);
     }
 
-    public EventDispatcher getEventDispatcher()
+    /**
+     * Get the event dispatcher
+     * @return The event dispatcher
+     */
+    public @NotNull EventDispatcher getEventDispatcher()
     {
         return this.eventDispatcher;
     }
 
-    HttpSessionListener getSessionListener()
+    @NotNull HttpSessionListener getSessionListener()
     {
         // we don't need to sync here, if the object gets created several times
         // its not a problem
@@ -97,7 +111,7 @@ public final class HttpServiceController
         return httpSessionListener;
     }
 
-    HttpSessionIdListener getSessionIdListener()
+    @NotNull HttpSessionIdListener getSessionIdListener()
     {
         return new HttpSessionIdListener() {
 
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/console/HttpServicePlugin.java b/http/base/src/main/java/org/apache/felix/http/base/internal/console/HttpServicePlugin.java
index d48e6f5..63235fc 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/console/HttpServicePlugin.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/console/HttpServicePlugin.java
@@ -31,11 +31,11 @@ import java.util.Hashtable;
 import java.util.List;
 import java.util.Map;
 
-import javax.servlet.Servlet;
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
+import jakarta.servlet.Servlet;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.http.HttpServlet;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
 
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.Constants;
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/context/ExtServletContext.java b/http/base/src/main/java/org/apache/felix/http/base/internal/context/ExtServletContext.java
index 1dd59fa..a9a6c1e 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/context/ExtServletContext.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/context/ExtServletContext.java
@@ -18,16 +18,19 @@ package org.apache.felix.http.base.internal.context;
 
 import java.io.IOException;
 
-import javax.servlet.ServletContext;
-import javax.servlet.ServletRequestAttributeListener;
-import javax.servlet.ServletRequestListener;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import javax.servlet.http.HttpSessionAttributeListener;
-import javax.servlet.http.HttpSessionListener;
-
 import org.apache.felix.http.base.internal.HttpConfig;
 
+import jakarta.servlet.ServletContext;
+import jakarta.servlet.ServletRequestAttributeListener;
+import jakarta.servlet.ServletRequestListener;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+import jakarta.servlet.http.HttpSessionAttributeListener;
+import jakarta.servlet.http.HttpSessionListener;
+
+/**
+ * Internal extension of the servlet context
+ */
 public interface ExtServletContext extends ServletContext
 {
     boolean handleSecurity(HttpServletRequest req, HttpServletResponse res) throws IOException;
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/context/ExtServletContextWrapper.java b/http/base/src/main/java/org/apache/felix/http/base/internal/context/ExtServletContextWrapper.java
index 6a04c24..25da936 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/context/ExtServletContextWrapper.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/context/ExtServletContextWrapper.java
@@ -25,23 +25,23 @@ import java.util.EventListener;
 import java.util.Map;
 import java.util.Set;
 
-import javax.servlet.Filter;
-import javax.servlet.FilterRegistration;
-import javax.servlet.RequestDispatcher;
-import javax.servlet.Servlet;
-import javax.servlet.ServletContext;
-import javax.servlet.ServletException;
-import javax.servlet.ServletRegistration;
-import javax.servlet.ServletRegistration.Dynamic;
-import javax.servlet.ServletRequestAttributeListener;
-import javax.servlet.ServletRequestListener;
-import javax.servlet.SessionCookieConfig;
-import javax.servlet.SessionTrackingMode;
-import javax.servlet.descriptor.JspConfigDescriptor;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import javax.servlet.http.HttpSessionAttributeListener;
-import javax.servlet.http.HttpSessionListener;
+import jakarta.servlet.Filter;
+import jakarta.servlet.FilterRegistration;
+import jakarta.servlet.RequestDispatcher;
+import jakarta.servlet.Servlet;
+import jakarta.servlet.ServletContext;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.ServletRegistration;
+import jakarta.servlet.ServletRegistration.Dynamic;
+import jakarta.servlet.ServletRequestAttributeListener;
+import jakarta.servlet.ServletRequestListener;
+import jakarta.servlet.SessionCookieConfig;
+import jakarta.servlet.SessionTrackingMode;
+import jakarta.servlet.descriptor.JspConfigDescriptor;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+import jakarta.servlet.http.HttpSessionAttributeListener;
+import jakarta.servlet.http.HttpSessionListener;
 
 /**
  * Wrapper of an {code ExtServletContex}.
@@ -297,21 +297,21 @@ public abstract class ExtServletContextWrapper implements ExtServletContext
 	}
 
 	@Override
-    public javax.servlet.FilterRegistration.Dynamic addFilter(
+    public jakarta.servlet.FilterRegistration.Dynamic addFilter(
 	        final String filterName, final String className)
 	{
 		return delegate.addFilter(filterName, className);
 	}
 
 	@Override
-    public javax.servlet.FilterRegistration.Dynamic addFilter(
+    public jakarta.servlet.FilterRegistration.Dynamic addFilter(
 	        final String filterName, final Filter filter)
 	{
 		return delegate.addFilter(filterName, filter);
 	}
 
 	@Override
-    public javax.servlet.FilterRegistration.Dynamic addFilter(
+    public jakarta.servlet.FilterRegistration.Dynamic addFilter(
 	        final String filterName, final Class<? extends Filter> filterClass)
 	{
 		return delegate.addFilter(filterName, filterClass);
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/dispatch/Dispatcher.java b/http/base/src/main/java/org/apache/felix/http/base/internal/dispatch/Dispatcher.java
index bcf5d76..95b0233 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/dispatch/Dispatcher.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/dispatch/Dispatcher.java
@@ -19,17 +19,6 @@ package org.apache.felix.http.base.internal.dispatch;
 import java.io.IOException;
 import java.util.Set;
 
-import javax.servlet.FilterChain;
-import javax.servlet.FilterConfig;
-import javax.servlet.RequestDispatcher;
-import javax.servlet.ServletException;
-import javax.servlet.ServletRequest;
-import javax.servlet.ServletRequestEvent;
-import javax.servlet.ServletResponse;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import javax.servlet.http.HttpSession;
-
 import org.apache.felix.http.base.internal.context.ExtServletContext;
 import org.apache.felix.http.base.internal.handler.FilterHandler;
 import org.apache.felix.http.base.internal.handler.HttpSessionWrapper;
@@ -38,8 +27,19 @@ import org.apache.felix.http.base.internal.registry.HandlerRegistry;
 import org.apache.felix.http.base.internal.registry.PathResolution;
 import org.apache.felix.http.base.internal.registry.PerContextHandlerRegistry;
 import org.apache.felix.http.base.internal.whiteboard.WhiteboardManager;
+import org.apache.felix.http.base.osgi.whiteboard.Preprocessor;
 import org.jetbrains.annotations.Nullable;
-import org.osgi.service.http.whiteboard.Preprocessor;
+
+import jakarta.servlet.FilterChain;
+import jakarta.servlet.FilterConfig;
+import jakarta.servlet.RequestDispatcher;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.ServletRequest;
+import jakarta.servlet.ServletRequestEvent;
+import jakarta.servlet.ServletResponse;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+import jakarta.servlet.http.HttpSession;
 
 public final class Dispatcher
 {
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/dispatch/DispatcherServlet.java b/http/base/src/main/java/org/apache/felix/http/base/internal/dispatch/DispatcherServlet.java
index 47544bf..ccb3e75 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/dispatch/DispatcherServlet.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/dispatch/DispatcherServlet.java
@@ -18,10 +18,10 @@ package org.apache.felix.http.base.internal.dispatch;
 
 import java.io.IOException;
 
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.http.HttpServlet;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
 
 import org.apache.felix.http.base.internal.HttpServiceController;
 
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/dispatch/InvocationChain.java b/http/base/src/main/java/org/apache/felix/http/base/internal/dispatch/InvocationChain.java
index ca547d4..78af52d 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/dispatch/InvocationChain.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/dispatch/InvocationChain.java
@@ -16,18 +16,18 @@
  */
 package org.apache.felix.http.base.internal.dispatch;
 
-import static javax.servlet.http.HttpServletResponse.SC_FORBIDDEN;
-import static javax.servlet.http.HttpServletResponse.SC_OK;
+import static jakarta.servlet.http.HttpServletResponse.SC_FORBIDDEN;
+import static jakarta.servlet.http.HttpServletResponse.SC_OK;
 
 import java.io.IOException;
 
 import org.jetbrains.annotations.NotNull;
-import javax.servlet.FilterChain;
-import javax.servlet.ServletException;
-import javax.servlet.ServletRequest;
-import javax.servlet.ServletResponse;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
+import jakarta.servlet.FilterChain;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.ServletRequest;
+import jakarta.servlet.ServletResponse;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
 
 import org.apache.felix.http.base.internal.handler.FilterHandler;
 import org.apache.felix.http.base.internal.handler.ServletHandler;
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/dispatch/RequestDispatcherImpl.java b/http/base/src/main/java/org/apache/felix/http/base/internal/dispatch/RequestDispatcherImpl.java
index ea9813c..fe70c4f 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/dispatch/RequestDispatcherImpl.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/dispatch/RequestDispatcherImpl.java
@@ -18,13 +18,13 @@ package org.apache.felix.http.base.internal.dispatch;
 
 import java.io.IOException;
 
-import javax.servlet.DispatcherType;
-import javax.servlet.FilterChain;
-import javax.servlet.RequestDispatcher;
-import javax.servlet.ServletException;
-import javax.servlet.ServletRequest;
-import javax.servlet.ServletResponse;
-import javax.servlet.http.HttpServletRequest;
+import jakarta.servlet.DispatcherType;
+import jakarta.servlet.FilterChain;
+import jakarta.servlet.RequestDispatcher;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.ServletRequest;
+import jakarta.servlet.ServletResponse;
+import jakarta.servlet.http.HttpServletRequest;
 
 import org.apache.felix.http.base.internal.handler.FilterHandler;
 import org.apache.felix.http.base.internal.registry.ServletResolution;
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/dispatch/ServletRequestWrapper.java b/http/base/src/main/java/org/apache/felix/http/base/internal/dispatch/ServletRequestWrapper.java
index 0c676c5..18b320d 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/dispatch/ServletRequestWrapper.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/dispatch/ServletRequestWrapper.java
@@ -16,18 +16,16 @@
  */
 package org.apache.felix.http.base.internal.dispatch;
 
-import static javax.servlet.RequestDispatcher.FORWARD_CONTEXT_PATH;
-import static javax.servlet.RequestDispatcher.FORWARD_MAPPING;
-import static javax.servlet.RequestDispatcher.FORWARD_PATH_INFO;
-import static javax.servlet.RequestDispatcher.FORWARD_QUERY_STRING;
-import static javax.servlet.RequestDispatcher.FORWARD_REQUEST_URI;
-import static javax.servlet.RequestDispatcher.FORWARD_SERVLET_PATH;
-import static javax.servlet.RequestDispatcher.INCLUDE_CONTEXT_PATH;
-import static javax.servlet.RequestDispatcher.INCLUDE_MAPPING;
-import static javax.servlet.RequestDispatcher.INCLUDE_PATH_INFO;
-import static javax.servlet.RequestDispatcher.INCLUDE_QUERY_STRING;
-import static javax.servlet.RequestDispatcher.INCLUDE_REQUEST_URI;
-import static javax.servlet.RequestDispatcher.INCLUDE_SERVLET_PATH;
+import static jakarta.servlet.RequestDispatcher.FORWARD_CONTEXT_PATH;
+import static jakarta.servlet.RequestDispatcher.FORWARD_PATH_INFO;
+import static jakarta.servlet.RequestDispatcher.FORWARD_QUERY_STRING;
+import static jakarta.servlet.RequestDispatcher.FORWARD_REQUEST_URI;
+import static jakarta.servlet.RequestDispatcher.FORWARD_SERVLET_PATH;
+import static jakarta.servlet.RequestDispatcher.INCLUDE_CONTEXT_PATH;
+import static jakarta.servlet.RequestDispatcher.INCLUDE_PATH_INFO;
+import static jakarta.servlet.RequestDispatcher.INCLUDE_QUERY_STRING;
+import static jakarta.servlet.RequestDispatcher.INCLUDE_REQUEST_URI;
+import static jakarta.servlet.RequestDispatcher.INCLUDE_SERVLET_PATH;
 import static org.apache.felix.http.base.internal.util.UriUtils.concat;
 
 import java.io.File;
@@ -42,37 +40,41 @@ import java.util.Collection;
 import java.util.Iterator;
 import java.util.List;
 
-import javax.servlet.AsyncContext;
-import javax.servlet.DispatcherType;
-import javax.servlet.RequestDispatcher;
-import javax.servlet.ServletContext;
-import javax.servlet.ServletException;
-import javax.servlet.ServletRequest;
-import javax.servlet.ServletRequestAttributeEvent;
-import javax.servlet.ServletResponse;
-import javax.servlet.http.HttpServletMapping;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletRequestWrapper;
-import javax.servlet.http.HttpSession;
-import javax.servlet.http.Part;
-
 import org.apache.commons.fileupload.FileItem;
+import org.apache.commons.fileupload.FileUpload;
+import org.apache.commons.fileupload.FileUploadBase;
 import org.apache.commons.fileupload.FileUploadException;
+import org.apache.commons.fileupload.RequestContext;
 import org.apache.commons.fileupload.disk.DiskFileItemFactory;
-import org.apache.commons.fileupload.servlet.ServletFileUpload;
-import org.apache.commons.fileupload.servlet.ServletRequestContext;
 import org.apache.felix.http.base.internal.context.ExtServletContext;
 import org.apache.felix.http.base.internal.handler.HttpSessionWrapper;
 import org.osgi.framework.Bundle;
 import org.osgi.service.http.HttpContext;
 import org.osgi.service.useradmin.Authorization;
 
+import jakarta.servlet.AsyncContext;
+import jakarta.servlet.DispatcherType;
+import jakarta.servlet.RequestDispatcher;
+import jakarta.servlet.ServletContext;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.ServletRequest;
+import jakarta.servlet.ServletRequestAttributeEvent;
+import jakarta.servlet.ServletResponse;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletRequestWrapper;
+import jakarta.servlet.http.HttpSession;
+import jakarta.servlet.http.Part;
+
 final class ServletRequestWrapper extends HttpServletRequestWrapper
 {
     private static final List<String> FORBIDDEN_ATTRIBUTES = Arrays.asList(FORWARD_CONTEXT_PATH,
             FORWARD_MAPPING, FORWARD_PATH_INFO, FORWARD_QUERY_STRING, FORWARD_REQUEST_URI, FORWARD_SERVLET_PATH,
             INCLUDE_CONTEXT_PATH, INCLUDE_MAPPING, INCLUDE_PATH_INFO, INCLUDE_QUERY_STRING, INCLUDE_REQUEST_URI,
             INCLUDE_SERVLET_PATH);
+    /**
+     * Constant for HTTP POST method.
+     */
+    private static final String POST_METHOD = "POST";
 
     private final DispatcherType type;
     private final RequestInfo requestInfo;
@@ -107,7 +109,7 @@ final class ServletRequestWrapper extends HttpServletRequestWrapper
         HttpServletRequest request = (HttpServletRequest) getRequest();
         if (isInclusionDispatcher() && !this.requestInfo.nameMatch)
         {
-            // The javax.servlet.include.* attributes refer to the information of the *included* request,
+            // The jakarta.servlet.include.* attributes refer to the information of the *included* request,
             // meaning that the request information comes from the *original* request...
             if (INCLUDE_REQUEST_URI.equals(name))
             {
@@ -136,7 +138,7 @@ final class ServletRequestWrapper extends HttpServletRequestWrapper
         }
         else if (isForwardingDispatcher() && !this.requestInfo.nameMatch)
         {
-            // The javax.servlet.forward.* attributes refer to the information of the *original* request,
+            // The jakarta.servlet.forward.* attributes refer to the information of the *original* request,
             // meaning that the request information comes from the *forwarded* request...
             if (FORWARD_REQUEST_URI.equals(name))
             {
@@ -377,11 +379,39 @@ final class ServletRequestWrapper extends HttpServletRequestWrapper
         return this.asyncSupported;
     }
 
+
     private Collection<Part> checkMultipart() throws IOException, ServletException
     {
         if ( parts == null )
         {
-            if ( ServletFileUpload.isMultipartContent(this) )
+            final RequestContext multipartContext;
+            if (!POST_METHOD.equalsIgnoreCase(this.getMethod())) {
+                multipartContext = null;
+            } else {
+                multipartContext = new RequestContext() {
+
+                    @Override
+                    public InputStream getInputStream() throws IOException {
+                        return ServletRequestWrapper.this.getInputStream();
+                    }
+
+                    @Override
+                    public String getContentType() {
+                        return ServletRequestWrapper.this.getContentType();
+                    }
+
+                    @Override
+                    public int getContentLength() {
+                        return ServletRequestWrapper.this.getContentLength();
+                    }
+
+                    @Override
+                    public String getCharacterEncoding() {
+                        return ServletRequestWrapper.this.getCharacterEncoding();
+                    }
+                };
+            }
+            if ( multipartContext != null && FileUploadBase.isMultipartContent(multipartContext) )
             {
                 if ( this.multipartConfig == null)
                 {
@@ -390,7 +420,7 @@ final class ServletRequestWrapper extends HttpServletRequestWrapper
 
                 if ( System.getSecurityManager() == null )
                 {
-                    handleMultipart();
+                    handleMultipart(multipartContext);
                 }
                 else
                 {
@@ -403,7 +433,7 @@ final class ServletRequestWrapper extends HttpServletRequestWrapper
                         {
                             try
                             {
-                                handleMultipart();
+                                handleMultipart(multipartContext);
                             }
                             catch ( final IOException ioe)
                             {
@@ -427,10 +457,10 @@ final class ServletRequestWrapper extends HttpServletRequestWrapper
         return parts;
     }
 
-    private void handleMultipart() throws IOException
+    private void handleMultipart(final RequestContext multipartContext) throws IOException
     {
         // Create a new file upload handler
-        final ServletFileUpload upload = new ServletFileUpload();
+        final FileUpload upload = new FileUpload();
         upload.setSizeMax(this.multipartConfig.multipartMaxRequestSize);
         upload.setFileSizeMax(this.multipartConfig.multipartMaxFileSize);
         upload.setFileItemFactory(new DiskFileItemFactory(this.multipartConfig.multipartThreshold,
@@ -440,7 +470,7 @@ final class ServletRequestWrapper extends HttpServletRequestWrapper
         List<FileItem> items = null;
         try
         {
-            items = upload.parseRequest(new ServletRequestContext(this));
+            items = upload.parseRequest(multipartContext);
         }
         catch (final FileUploadException fue)
         {
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/dispatch/ServletResponseWrapper.java b/http/base/src/main/java/org/apache/felix/http/base/internal/dispatch/ServletResponseWrapper.java
index e0a2615..c0e8dbe 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/dispatch/ServletResponseWrapper.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/dispatch/ServletResponseWrapper.java
@@ -19,13 +19,15 @@ package org.apache.felix.http.base.internal.dispatch;
 import java.io.IOException;
 import java.util.concurrent.atomic.AtomicInteger;
 
-import javax.servlet.DispatcherType;
-import javax.servlet.FilterChain;
-import javax.servlet.RequestDispatcher;
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import javax.servlet.http.HttpServletResponseWrapper;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.annotations.NotNull;
+import jakarta.servlet.DispatcherType;
+import jakarta.servlet.FilterChain;
+import jakarta.servlet.RequestDispatcher;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+import jakarta.servlet.http.HttpServletResponseWrapper;
 
 import org.apache.felix.http.base.internal.handler.FilterHandler;
 import org.apache.felix.http.base.internal.handler.ServletHandler;
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/handler/FilterConfigImpl.java b/http/base/src/main/java/org/apache/felix/http/base/internal/handler/FilterConfigImpl.java
index 342260f..2fa2cbc 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/handler/FilterConfigImpl.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/handler/FilterConfigImpl.java
@@ -20,8 +20,8 @@ import java.util.Collections;
 import java.util.Enumeration;
 import java.util.Map;
 
-import javax.servlet.FilterConfig;
-import javax.servlet.ServletContext;
+import jakarta.servlet.FilterConfig;
+import jakarta.servlet.ServletContext;
 
 /**
  * Implementation of the filter configuration.
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/handler/FilterHandler.java b/http/base/src/main/java/org/apache/felix/http/base/internal/handler/FilterHandler.java
index 09de56f..99eeb86 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/handler/FilterHandler.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/handler/FilterHandler.java
@@ -18,21 +18,19 @@ package org.apache.felix.http.base.internal.handler;
 
 import java.io.IOException;
 
-import javax.servlet.Filter;
-import javax.servlet.FilterChain;
-import javax.servlet.ServletException;
-import javax.servlet.ServletRequest;
-import javax.servlet.ServletResponse;
-
 import org.apache.felix.http.base.internal.context.ExtServletContext;
 import org.apache.felix.http.base.internal.logger.SystemLogger;
 import org.apache.felix.http.base.internal.runtime.FilterInfo;
-import org.apache.felix.http.base.internal.util.ServiceUtils;
 import org.jetbrains.annotations.NotNull;
 import org.osgi.framework.BundleContext;
-import org.osgi.framework.ServiceReference;
 import org.osgi.service.http.runtime.dto.DTOConstants;
 
+import jakarta.servlet.Filter;
+import jakarta.servlet.FilterChain;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.ServletRequest;
+import jakarta.servlet.ServletResponse;
+
 /**
  * The filter handler handles the initialization and destruction of filter
  * objects.
@@ -96,7 +94,7 @@ public class FilterHandler implements Comparable<FilterHandler>
             final Filter local = this.filter;
             if ( local != null )
             {
-                name = local.getClass().getName();
+                name = this.filterInfo.getClassName(local);
             }
         }
         return name;
@@ -114,8 +112,7 @@ public class FilterHandler implements Comparable<FilterHandler>
             return -1;
         }
 
-        final ServiceReference<Filter> serviceReference = getFilterInfo().getServiceReference();
-        this.filter = ServiceUtils.safeGetServiceObjects(this.bundleContext, serviceReference);
+        this.filter = getFilterInfo().getService(this.bundleContext);
 
         if (this.filter == null)
         {
@@ -129,9 +126,9 @@ public class FilterHandler implements Comparable<FilterHandler>
         catch (final Exception e)
         {
             SystemLogger.error(this.getFilterInfo().getServiceReference(),
-                    "Error during calling init() on filter " + this.filter,
+                    "Error during calling init() on filter " + this.filterInfo.getClassName(this.filter),
                     e);
-            ServiceUtils.safeUngetServiceObjects(this.bundleContext, serviceReference, this.getFilter());
+            getFilterInfo().ungetService(this.bundleContext, this.filter);
             return DTOConstants.FAILURE_REASON_EXCEPTION_ON_INIT;
         }
 
@@ -171,12 +168,11 @@ public class FilterHandler implements Comparable<FilterHandler>
                 {
                     // we ignore this
                     SystemLogger.error(this.getFilterInfo().getServiceReference(),
-                            "Error during calling destroy() on filter " + f,
+                            "Error during calling destroy() on filter " + this.getFilterInfo().getClassName(f),
                             ignore);
                 }
 
-                ServiceUtils.safeUngetServiceObjects(this.bundleContext,
-                        getFilterInfo().getServiceReference(), f);
+                getFilterInfo().ungetService(this.bundleContext, f);
 
                 return true;
             }
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/handler/HttpServiceServletHandler.java b/http/base/src/main/java/org/apache/felix/http/base/internal/handler/HttpServiceServletHandler.java
index ec1781c..74967e3 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/handler/HttpServiceServletHandler.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/handler/HttpServiceServletHandler.java
@@ -16,24 +16,38 @@
  */
 package org.apache.felix.http.base.internal.handler;
 
-import javax.servlet.Servlet;
-
 import org.apache.felix.http.base.internal.context.ExtServletContext;
+import org.apache.felix.http.base.internal.jakartawrappers.ServletWrapper;
 import org.apache.felix.http.base.internal.runtime.ServletInfo;
 import org.apache.felix.http.base.internal.service.HttpServiceFactory;
 
+import jakarta.servlet.Servlet;
+
 /**
  * Servlet handler for servlets registered through the http service.
  */
 public final class HttpServiceServletHandler extends ServletHandler
 {
+    /**
+     * New handler
+     * @param context The context
+     * @param servletInfo The servlet info
+     * @param servlet The servlet
+     */
     public HttpServiceServletHandler(final ExtServletContext context,
             final ServletInfo servletInfo,
-            final Servlet servlet)
+            final javax.servlet.Servlet servlet)
     {
-        this(HttpServiceFactory.HTTP_SERVICE_CONTEXT_SERVICE_ID, context, servletInfo, servlet);
+        this(HttpServiceFactory.HTTP_SERVICE_CONTEXT_SERVICE_ID, context, servletInfo, ServletWrapper.getRegisteredServlet(servlet));
     }
 
+    /**
+     * New handler
+     * @param contextServiceId The context id
+     * @param context The context
+     * @param servletInfo The servlet info
+     * @param servlet The servlet
+     */
     public HttpServiceServletHandler(final long contextServiceId,
             final ExtServletContext context,
             final ServletInfo servletInfo,
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/handler/HttpSessionWrapper.java b/http/base/src/main/java/org/apache/felix/http/base/internal/handler/HttpSessionWrapper.java
index 1b963d6..9165689 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/handler/HttpSessionWrapper.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/handler/HttpSessionWrapper.java
@@ -27,12 +27,12 @@ import java.util.List;
 import java.util.NoSuchElementException;
 import java.util.Set;
 
-import javax.servlet.ServletContext;
-import javax.servlet.http.HttpSession;
-import javax.servlet.http.HttpSessionBindingEvent;
-import javax.servlet.http.HttpSessionBindingListener;
-import javax.servlet.http.HttpSessionContext;
-import javax.servlet.http.HttpSessionEvent;
+import jakarta.servlet.ServletContext;
+import jakarta.servlet.http.HttpSession;
+import jakarta.servlet.http.HttpSessionBindingEvent;
+import jakarta.servlet.http.HttpSessionBindingListener;
+import jakarta.servlet.http.HttpSessionContext;
+import jakarta.servlet.http.HttpSessionEvent;
 
 import org.apache.felix.http.base.internal.HttpConfig;
 import org.apache.felix.http.base.internal.context.ExtServletContext;
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/handler/ListenerHandler.java b/http/base/src/main/java/org/apache/felix/http/base/internal/handler/ListenerHandler.java
index 57e3063..11b3f9f 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/handler/ListenerHandler.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/handler/ListenerHandler.java
@@ -20,9 +20,7 @@ import java.util.EventListener;
 
 import org.apache.felix.http.base.internal.context.ExtServletContext;
 import org.apache.felix.http.base.internal.runtime.ListenerInfo;
-import org.apache.felix.http.base.internal.util.ServiceUtils;
 import org.osgi.framework.BundleContext;
-import org.osgi.framework.ServiceReference;
 import org.osgi.service.http.runtime.dto.DTOConstants;
 
 /**
@@ -90,8 +88,7 @@ public class ListenerHandler implements Comparable<ListenerHandler>
             {
                 this.listener = null;
 
-                ServiceUtils.safeUngetServiceObjects(this.bundleContext,
-                        getListenerInfo().getServiceReference(), l);
+                this.getListenerInfo().ungetService(this.bundleContext, l);
 
                 return true;
             }
@@ -118,8 +115,7 @@ public class ListenerHandler implements Comparable<ListenerHandler>
             return -1;
         }
 
-        final ServiceReference<EventListener> serviceReference = getListenerInfo().getServiceReference();
-        this.listener = ServiceUtils.safeGetServiceObjects(this.bundleContext, serviceReference);
+        this.listener = getListenerInfo().getService(this.bundleContext);
 
         final int reason;
         if (this.listener == null)
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/handler/PreprocessorHandler.java b/http/base/src/main/java/org/apache/felix/http/base/internal/handler/PreprocessorHandler.java
index b2efa0a..c7c05c0 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/handler/PreprocessorHandler.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/handler/PreprocessorHandler.java
@@ -18,20 +18,19 @@ package org.apache.felix.http.base.internal.handler;
 
 import java.io.IOException;
 
-import javax.servlet.FilterChain;
-import javax.servlet.ServletContext;
-import javax.servlet.ServletException;
-import javax.servlet.ServletRequest;
-import javax.servlet.ServletResponse;
-
 import org.apache.felix.http.base.internal.logger.SystemLogger;
 import org.apache.felix.http.base.internal.runtime.PreprocessorInfo;
-import org.apache.felix.http.base.internal.util.ServiceUtils;
+import org.apache.felix.http.base.osgi.whiteboard.Preprocessor;
 import org.jetbrains.annotations.NotNull;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.ServiceReference;
 import org.osgi.service.http.runtime.dto.DTOConstants;
-import org.osgi.service.http.whiteboard.Preprocessor;
+
+import jakarta.servlet.FilterChain;
+import jakarta.servlet.ServletContext;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.ServletRequest;
+import jakarta.servlet.ServletResponse;
 
 /**
  * The preprocessor handler handles the initialization and destruction of preprocessor
@@ -75,7 +74,7 @@ public class PreprocessorHandler implements Comparable<PreprocessorHandler>
     public int init()
     {
         final ServiceReference<Preprocessor> serviceReference = this.info.getServiceReference();
-        this.preprocessor = ServiceUtils.safeGetService(this.bundleContext, serviceReference);
+        this.preprocessor = this.getPreprocessorInfo().getService(this.bundleContext);
 
         if (this.preprocessor == null)
         {
@@ -91,11 +90,11 @@ public class PreprocessorHandler implements Comparable<PreprocessorHandler>
         catch (final Exception e)
         {
             SystemLogger.error(this.getPreprocessorInfo().getServiceReference(),
-                    "Error during calling init() on preprocessor " + this.preprocessor,
+                    "Error during calling init() on preprocessor " + this.info.getClassName(this.preprocessor),
                     e);
 
+            this.getPreprocessorInfo().ungetService(this.bundleContext, this.preprocessor);
             this.preprocessor = null;
-            ServiceUtils.safeUngetService(this.bundleContext, serviceReference);
 
             return DTOConstants.FAILURE_REASON_EXCEPTION_ON_INIT;
         }
@@ -118,11 +117,11 @@ public class PreprocessorHandler implements Comparable<PreprocessorHandler>
         {
             // we ignore this
             SystemLogger.error(this.getPreprocessorInfo().getServiceReference(),
-                    "Error during calling destroy() on preprocessor " + this.preprocessor,
+                    "Error during calling destroy() on preprocessor " + this.info.getClassName(this.preprocessor),
                     ignore);
         }
+        this.getPreprocessorInfo().ungetService(this.bundleContext, this.preprocessor);
         this.preprocessor = null;
-        ServiceUtils.safeUngetService(this.bundleContext, this.info.getServiceReference());
 
         return true;
     }
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/handler/ServletConfigImpl.java b/http/base/src/main/java/org/apache/felix/http/base/internal/handler/ServletConfigImpl.java
index 4ac55d6..dc283fa 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/handler/ServletConfigImpl.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/handler/ServletConfigImpl.java
@@ -20,8 +20,8 @@ import java.util.Collections;
 import java.util.Enumeration;
 import java.util.Map;
 
-import javax.servlet.ServletConfig;
-import javax.servlet.ServletContext;
+import jakarta.servlet.ServletConfig;
+import jakarta.servlet.ServletContext;
 
 /**
  * Implementation of the servlet configuration
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 9a3f2b3..940920c 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
@@ -19,18 +19,19 @@ package org.apache.felix.http.base.internal.handler;
 import java.io.File;
 import java.io.IOException;
 
-import javax.servlet.Servlet;
-import javax.servlet.ServletException;
-import javax.servlet.ServletRequest;
-import javax.servlet.ServletResponse;
-
 import org.apache.felix.http.base.internal.context.ExtServletContext;
 import org.apache.felix.http.base.internal.dispatch.MultipartConfig;
+import org.apache.felix.http.base.internal.jakartawrappers.ServletWrapper;
 import org.apache.felix.http.base.internal.logger.SystemLogger;
 import org.apache.felix.http.base.internal.runtime.ServletInfo;
 import org.osgi.framework.Bundle;
 import org.osgi.service.http.runtime.dto.DTOConstants;
 
+import jakarta.servlet.Servlet;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.ServletRequest;
+import jakarta.servlet.ServletResponse;
+
 /**
  * The servlet handler handles the initialization and destruction of
  * a servlet.
@@ -39,7 +40,7 @@ public abstract class ServletHandler implements Comparable<ServletHandler>
 {
     private static final String TEMP_DIR = System.getProperty("java.io.tmpdir");
 
-    private static final String JAVA_SERVLET_TEMP_DIR_PROP = "javax.servlet.content.tempdir";
+    private static final String JAVA_SERVLET_TEMP_DIR_PROP = "jakarta.servlet.content.tempdir";
 
     private final long contextServiceId;
 
@@ -144,7 +145,11 @@ public abstract class ServletHandler implements Comparable<ServletHandler>
             final Servlet local = this.servlet;
             if ( local != null )
             {
-                name = local.getClass().getName();
+                if (local instanceof ServletWrapper ) {
+                    name = ((ServletWrapper)local).getServlet().getClass().getName();
+                } else {
+                    name = local.getClass().getName();
+                }
             }
         }
         return name;
@@ -174,7 +179,7 @@ public abstract class ServletHandler implements Comparable<ServletHandler>
         catch (final Exception e)
         {
             SystemLogger.error(this.getServletInfo().getServiceReference(),
-                    "Error during calling init() on servlet " + this.servlet,
+                    "Error during calling init() on servlet " + this.servletInfo.getClassName(this.servlet),
                     e);
             return DTOConstants.FAILURE_REASON_EXCEPTION_ON_INIT;
         }
@@ -201,7 +206,7 @@ public abstract class ServletHandler implements Comparable<ServletHandler>
             {
                 // we ignore this
                 SystemLogger.error(this.getServletInfo().getServiceReference(),
-                        "Error during calling destroy() on servlet " + this.servlet,
+                        "Error during calling destroy() on servlet " + this.servletInfo.getClassName(this.servlet),
                         ignore);
             }
 
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/handler/WhiteboardServletHandler.java b/http/base/src/main/java/org/apache/felix/http/base/internal/handler/WhiteboardServletHandler.java
index 03b5a1a..095a0ef 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/handler/WhiteboardServletHandler.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/handler/WhiteboardServletHandler.java
@@ -18,16 +18,14 @@ package org.apache.felix.http.base.internal.handler;
 
 import java.io.FilePermission;
 
-import javax.servlet.Servlet;
-
 import org.apache.felix.http.base.internal.context.ExtServletContext;
 import org.apache.felix.http.base.internal.runtime.ServletInfo;
-import org.apache.felix.http.base.internal.util.ServiceUtils;
 import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleContext;
-import org.osgi.framework.ServiceReference;
 import org.osgi.service.http.runtime.dto.DTOConstants;
 
+import jakarta.servlet.Servlet;
+
 /**
  * Servlet handler for servlets registered through the http whiteboard.
  */
@@ -105,13 +103,12 @@ public final class WhiteboardServletHandler extends ServletHandler
             return -1;
         }
 
-        final ServiceReference<Servlet> serviceReference = getServletInfo().getServiceReference();
-        this.setServlet(ServiceUtils.safeGetServiceObjects(this.bundleContext, serviceReference));
+        this.setServlet(this.getServletInfo().getService(this.bundleContext));
 
         final int reason = super.init();
         if ( reason != -1 )
         {
-            ServiceUtils.safeUngetServiceObjects(this.bundleContext, serviceReference, this.getServlet());
+            this.getServletInfo().ungetService(this.bundleContext, this.getServlet());
             this.setServlet(null);
         }
         return reason;
@@ -125,8 +122,7 @@ public final class WhiteboardServletHandler extends ServletHandler
         {
             if ( super.destroy() )
             {
-                ServiceUtils.safeUngetServiceObjects(this.bundleContext,
-                        getServletInfo().getServiceReference(), s);
+                this.getServletInfo().ungetService(this.bundleContext, this.getServlet());
 
                 return true;
             }
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/jakartawrappers/AsyncContextWrapper.java b/http/base/src/main/java/org/apache/felix/http/base/internal/jakartawrappers/AsyncContextWrapper.java
new file mode 100644
index 0000000..4e6fae0
--- /dev/null
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/jakartawrappers/AsyncContextWrapper.java
@@ -0,0 +1,109 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.felix.http.base.internal.jakartawrappers;
+
+import org.jetbrains.annotations.NotNull;
+
+import jakarta.servlet.AsyncContext;
+import jakarta.servlet.AsyncListener;
+import jakarta.servlet.ServletContext;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.ServletRequest;
+import jakarta.servlet.ServletResponse;
+
+/**
+ * async context wrapper
+ */
+public class AsyncContextWrapper implements AsyncContext {
+
+    private final javax.servlet.AsyncContext context;
+
+    /**
+     * Create new context
+     * @param c Wrapped context
+     */
+    public AsyncContextWrapper(@NotNull final javax.servlet.AsyncContext c) {
+        this.context = c;
+    }
+
+    @Override
+    public ServletRequest getRequest() {
+        return ServletRequestWrapper.getWrapper(context.getRequest());
+    }
+
+    @Override
+    public ServletResponse getResponse() {
+        return ServletResponseWrapper.getWrapper(context.getResponse());
+    }
+
+    @Override
+    public boolean hasOriginalRequestAndResponse() {
+        return context.hasOriginalRequestAndResponse();
+    }
+
+    @Override
+    public void dispatch() {
+        context.dispatch();
+    }
+
+    @Override
+    public void dispatch(final String path) {
+        context.dispatch(path);
+    }
+
+    @Override
+    public void dispatch(final ServletContext sc, final String path) {
+        context.dispatch(new org.apache.felix.http.base.internal.javaxwrappers.ServletContextWrapper(sc), path);
+    }
+
+    @Override
+    public void complete() {
+        context.complete();
+    }
+
+    @Override
+    public void start(final Runnable run) {
+        context.start(run);
+    }
+
+    @Override
+    public void addListener(final AsyncListener listener) {
+        context.addListener(new org.apache.felix.http.base.internal.javaxwrappers.AsyncListenerWrapper(listener));
+    }
+
+    @Override
+    public void addListener(final AsyncListener listener, final ServletRequest servletRequest, final ServletResponse servletResponse) {
+        context.addListener(new org.apache.felix.http.base.internal.javaxwrappers.AsyncListenerWrapper(listener),
+                org.apache.felix.http.base.internal.javaxwrappers.ServletRequestWrapper.getWrapper(servletRequest),
+                org.apache.felix.http.base.internal.javaxwrappers.ServletResponseWrapper.getWrapper(servletResponse));
+    }
+
+    @Override
+    public <T extends AsyncListener> T createListener(final Class<T> clazz) throws ServletException {
+        throw new ServletException();
+    }
+
+    @Override
+    public void setTimeout(final long timeout) {
+        context.setTimeout(timeout);
+    }
+
+    @Override
+    public long getTimeout() {
+        return context.getTimeout();
+    }
+}
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/jakartawrappers/AsyncListenerWrapper.java b/http/base/src/main/java/org/apache/felix/http/base/internal/jakartawrappers/AsyncListenerWrapper.java
new file mode 100644
index 0000000..efa0168
--- /dev/null
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/jakartawrappers/AsyncListenerWrapper.java
@@ -0,0 +1,76 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.felix.http.base.internal.jakartawrappers;
+
+import java.io.IOException;
+
+import org.jetbrains.annotations.NotNull;
+
+import jakarta.servlet.AsyncEvent;
+import jakarta.servlet.AsyncListener;
+
+/**
+ * Async listener wrapper
+ */
+public class AsyncListenerWrapper implements AsyncListener {
+
+    private final javax.servlet.AsyncListener listener;
+
+    /**
+     * Create new listener
+     * @param c Wrapped listener
+     */
+    public AsyncListenerWrapper(@NotNull final javax.servlet.AsyncListener c) {
+        this.listener = c;
+    }
+
+    @Override
+    public void onComplete(final AsyncEvent event) throws IOException {
+        this.listener.onComplete(new javax.servlet.AsyncEvent(
+                new org.apache.felix.http.base.internal.javaxwrappers.AsyncContextWrapper(event.getAsyncContext()),
+                org.apache.felix.http.base.internal.javaxwrappers.ServletRequestWrapper.getWrapper(event.getSuppliedRequest()),
+                org.apache.felix.http.base.internal.javaxwrappers.ServletResponseWrapper.getWrapper(event.getSuppliedResponse()),
+                event.getThrowable()));
+    }
+
+    @Override
+    public void onTimeout(final AsyncEvent event) throws IOException {
+        this.listener.onTimeout(new javax.servlet.AsyncEvent(
+                new org.apache.felix.http.base.internal.javaxwrappers.AsyncContextWrapper(event.getAsyncContext()),
+                org.apache.felix.http.base.internal.javaxwrappers.ServletRequestWrapper.getWrapper(event.getSuppliedRequest()),
+                org.apache.felix.http.base.internal.javaxwrappers.ServletResponseWrapper.getWrapper(event.getSuppliedResponse()),
+                event.getThrowable()));
+    }
+
+    @Override
+    public void onError(final AsyncEvent event) throws IOException {
+        this.listener.onError(new javax.servlet.AsyncEvent(
+                new org.apache.felix.http.base.internal.javaxwrappers.AsyncContextWrapper(event.getAsyncContext()),
+                org.apache.felix.http.base.internal.javaxwrappers.ServletRequestWrapper.getWrapper(event.getSuppliedRequest()),
+                org.apache.felix.http.base.internal.javaxwrappers.ServletResponseWrapper.getWrapper(event.getSuppliedResponse()),
+                event.getThrowable()));
+    }
+
+    @Override
+    public void onStartAsync(final AsyncEvent event) throws IOException {
+        this.listener.onStartAsync(new javax.servlet.AsyncEvent(
+                new org.apache.felix.http.base.internal.javaxwrappers.AsyncContextWrapper(event.getAsyncContext()),
+                org.apache.felix.http.base.internal.javaxwrappers.ServletRequestWrapper.getWrapper(event.getSuppliedRequest()),
+                org.apache.felix.http.base.internal.javaxwrappers.ServletResponseWrapper.getWrapper(event.getSuppliedResponse()),
+                event.getThrowable()));
+    }
+}
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/jakartawrappers/CookieWrapper.java b/http/base/src/main/java/org/apache/felix/http/base/internal/jakartawrappers/CookieWrapper.java
new file mode 100644
index 0000000..d4be990
--- /dev/null
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/jakartawrappers/CookieWrapper.java
@@ -0,0 +1,111 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.felix.http.base.internal.jakartawrappers;
+
+import org.jetbrains.annotations.NotNull;
+
+import jakarta.servlet.http.Cookie;
+
+/**
+ * Cookie
+ */
+public class CookieWrapper extends Cookie {
+
+    private static final long serialVersionUID = 5230437594501050941L;
+
+    /**
+     * Wrap an array of cookies
+     * @param array The array
+     * @return The result
+     */
+    public static Cookie[] wrap(final javax.servlet.http.Cookie[] array) {
+        if ( array == null ) {
+            return null;
+        }
+        final Cookie[] result = new Cookie[array.length];
+        for(int i=0;i<array.length;i++) {
+            result[i] = new CookieWrapper(array[i]);
+        }
+        return result;
+    }
+
+    private final javax.servlet.http.Cookie cookie;
+
+    /**
+     * Create new cookie
+     * @param c Wrapped cookie
+     */
+    public CookieWrapper(@NotNull final javax.servlet.http.Cookie c) {
+        super(c.getName(), c.getValue());
+        this.cookie = c;
+        super.setComment(c.getComment());
+        super.setDomain(c.getDomain());
+        super.setHttpOnly(c.isHttpOnly());
+        super.setMaxAge(c.getMaxAge());
+        super.setPath(c.getPath());
+        super.setSecure(c.getSecure());
+        super.setVersion(c.getVersion());
+    }
+
+    @Override
+    public void setComment(final String purpose) {
+        this.cookie.setComment(purpose);
+        super.setComment(purpose);
+    }
+
+    @Override
+    public void setDomain(final String domain) {
+        this.cookie.setDomain(domain);
+        super.setDomain(domain);
+    }
+
+    @Override
+    public void setMaxAge(final int expiry) {
+        this.cookie.setMaxAge(expiry);
+        super.setMaxAge(expiry);
+    }
+
+    @Override
+    public void setPath(final String uri) {
+        this.cookie.setPath(uri);
+        super.setPath(uri);
+    }
+
+    @Override
+    public void setSecure(final boolean flag) {
+        this.cookie.setSecure(flag);
+        super.setSecure(flag);
+    }
+
+    @Override
+    public void setValue(final String newValue) {
+        this.cookie.setValue(newValue);
+        super.setValue(newValue);
+    }
+
+    @Override
+    public void setVersion(final int v) {
+        this.cookie.setVersion(v);
+        super.setVersion(v);
+    }
+
+    @Override
+    public void setHttpOnly(final boolean isHttpOnly) {
+        this.cookie.setHttpOnly(isHttpOnly);
+        super.setHttpOnly(isHttpOnly);
+    }
+}
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/jakartawrappers/EventListenerWrapper.java b/http/base/src/main/java/org/apache/felix/http/base/internal/jakartawrappers/EventListenerWrapper.java
new file mode 100644
index 0000000..3f540d2
--- /dev/null
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/jakartawrappers/EventListenerWrapper.java
@@ -0,0 +1,229 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.felix.http.base.internal.jakartawrappers;
+
+import java.util.EventListener;
+import java.util.Set;
+
+import org.apache.felix.http.base.internal.javaxwrappers.HttpSessionWrapper;
+import org.apache.felix.http.base.internal.javaxwrappers.ServletContextWrapper;
+import org.apache.felix.http.base.internal.javaxwrappers.ServletRequestWrapper;
+import org.jetbrains.annotations.NotNull;
+
+import jakarta.servlet.ServletContextAttributeEvent;
+import jakarta.servlet.ServletContextAttributeListener;
+import jakarta.servlet.ServletContextEvent;
+import jakarta.servlet.ServletContextListener;
+import jakarta.servlet.ServletRequestAttributeEvent;
+import jakarta.servlet.ServletRequestAttributeListener;
+import jakarta.servlet.ServletRequestEvent;
+import jakarta.servlet.ServletRequestListener;
+import jakarta.servlet.http.HttpSessionAttributeListener;
+import jakarta.servlet.http.HttpSessionBindingEvent;
+import jakarta.servlet.http.HttpSessionEvent;
+import jakarta.servlet.http.HttpSessionIdListener;
+import jakarta.servlet.http.HttpSessionListener;
+
+/**
+ * Wrapper for all listeners
+ */
+public class EventListenerWrapper implements HttpSessionAttributeListener,
+    HttpSessionIdListener,
+    HttpSessionListener,
+    ServletContextListener,
+    ServletContextAttributeListener,
+    ServletRequestListener,
+    ServletRequestAttributeListener {
+
+    private final javax.servlet.http.HttpSessionAttributeListener httpSessionAttributeListener;
+    private final javax.servlet.http.HttpSessionIdListener httpSessionIdListener;
+    private final javax.servlet.http.HttpSessionListener httpSessionListener;
+    private final javax.servlet.ServletContextListener servletContextListener;
+    private final javax.servlet.ServletContextAttributeListener servletContextAttributeListener;
+    private final javax.servlet.ServletRequestListener servletRequestListener;
+    private final javax.servlet.ServletRequestAttributeListener servletRequestAttributeListener;
+    private final EventListener listener;
+
+    /**
+     * Create new wrapper
+     * @param listener Wrapped listener
+     * @param listenerTypes Service interfaces
+     */
+    public EventListenerWrapper(@NotNull final EventListener listener,
+            @NotNull final Set<String> listenerTypes) {
+        this.listener = listener;
+        if ( listenerTypes.contains(HttpSessionAttributeListener.class.getName()) ) {
+            this.httpSessionAttributeListener = (javax.servlet.http.HttpSessionAttributeListener) listener;
+        } else {
+            this.httpSessionAttributeListener = null;
+        }
+        if ( listenerTypes.contains(HttpSessionIdListener.class.getName()) ) {
+            this.httpSessionIdListener = (javax.servlet.http.HttpSessionIdListener) listener;
+        } else {
+            this.httpSessionIdListener = null;
+        }
+        if ( listenerTypes.contains(HttpSessionListener.class.getName()) ) {
+            this.httpSessionListener = (javax.servlet.http.HttpSessionListener) listener;
+        } else {
+            this.httpSessionListener = null;
+        }
+        if ( listenerTypes.contains(ServletContextListener.class.getName()) ) {
+            this.servletContextListener = (javax.servlet.ServletContextListener) listener;
+        } else {
+            this.servletContextListener = null;
+        }
+        if ( listenerTypes.contains(ServletContextAttributeListener.class.getName()) ) {
+            this.servletContextAttributeListener = (javax.servlet.ServletContextAttributeListener) listener;
+        } else {
+            this.servletContextAttributeListener = null;
+        }
+        if ( listenerTypes.contains(ServletRequestListener.class.getName()) ) {
+            this.servletRequestListener = (javax.servlet.ServletRequestListener) listener;
+        } else {
+            this.servletRequestListener = null;
+        }
+        if ( listenerTypes.contains(ServletRequestAttributeListener.class.getName()) ) {
+            this.servletRequestAttributeListener = (javax.servlet.ServletRequestAttributeListener) listener;
+        } else {
+            this.servletRequestAttributeListener = null;
+        }
+    }
+
+    @Override
+    public void attributeAdded(final ServletRequestAttributeEvent srae) {
+        if ( this.servletRequestAttributeListener != null ) {
+            this.servletRequestAttributeListener.attributeAdded(new javax.servlet.ServletRequestAttributeEvent(new ServletContextWrapper(srae.getServletContext()),
+                    ServletRequestWrapper.getWrapper(srae.getServletRequest()), srae.getName(), srae.getValue()));
+        }
+    }
+    @Override
+    public void attributeRemoved(final ServletRequestAttributeEvent srae) {
+        if ( this.servletRequestAttributeListener != null ) {
+            this.servletRequestAttributeListener.attributeRemoved(new javax.servlet.ServletRequestAttributeEvent(new ServletContextWrapper(srae.getServletContext()),
+                    ServletRequestWrapper.getWrapper(srae.getServletRequest()), srae.getName(), srae.getValue()));
+        }
+    }
+
+    @Override
+    public void attributeReplaced(final ServletRequestAttributeEvent srae) {
+        if ( this.servletRequestAttributeListener != null ) {
+            this.servletRequestAttributeListener.attributeReplaced(new javax.servlet.ServletRequestAttributeEvent(new ServletContextWrapper(srae.getServletContext()),
+                    ServletRequestWrapper.getWrapper(srae.getServletRequest()), srae.getName(), srae.getValue()));
+        }
+    }
+
+    @Override
+    public void requestDestroyed(final ServletRequestEvent sre) {
+        if ( this.servletRequestListener != null ) {
+            this.servletRequestListener.requestDestroyed(new javax.servlet.ServletRequestEvent(new ServletContextWrapper(sre.getServletContext()),
+                    ServletRequestWrapper.getWrapper(sre.getServletRequest())));
+        }
+    }
+
+    @Override
+    public void requestInitialized(final ServletRequestEvent sre) {
+        if ( this.servletRequestListener != null ) {
+            this.servletRequestListener.requestInitialized(new javax.servlet.ServletRequestEvent(new ServletContextWrapper(sre.getServletContext()),
+                    ServletRequestWrapper.getWrapper(sre.getServletRequest())));
+        }
+    }
+
+    @Override
+    public void attributeAdded(final ServletContextAttributeEvent event) {
+        if ( this.servletContextAttributeListener != null ) {
+            this.servletContextAttributeListener.attributeAdded(new javax.servlet.ServletContextAttributeEvent(new ServletContextWrapper(event.getServletContext()), event.getName(), event.getValue()));
+        }
+    }
+
+    @Override
+    public void attributeRemoved(final ServletContextAttributeEvent event) {
+        if ( this.servletContextAttributeListener != null ) {
+            this.servletContextAttributeListener.attributeRemoved(new javax.servlet.ServletContextAttributeEvent(new ServletContextWrapper(event.getServletContext()), event.getName(), event.getValue()));
+        }
+    }
+
+    @Override
+    public void attributeReplaced(final ServletContextAttributeEvent event) {
+        if ( this.servletContextAttributeListener != null ) {
+            this.servletContextAttributeListener.attributeReplaced(new javax.servlet.ServletContextAttributeEvent(new ServletContextWrapper(event.getServletContext()), event.getName(), event.getValue()));
+        }
+    }
+
+    @Override
+    public void contextInitialized(final ServletContextEvent sce) {
+        if ( this.servletContextListener != null ) {
+            this.servletContextListener.contextInitialized(new javax.servlet.ServletContextEvent(new ServletContextWrapper(sce.getServletContext())));
+        }
+    }
+
+    @Override
+    public void contextDestroyed(final ServletContextEvent sce) {
+        if ( this.servletContextListener != null ) {
+            this.servletContextListener.contextDestroyed(new javax.servlet.ServletContextEvent(new ServletContextWrapper(sce.getServletContext())));
+        }
+    }
+
+    @Override
+    public void sessionCreated(final HttpSessionEvent se) {
+        if ( this.httpSessionListener != null ) {
+            this.httpSessionListener.sessionCreated(new javax.servlet.http.HttpSessionEvent(new HttpSessionWrapper(se.getSession())));
+        }
+    }
+
+    @Override
+    public void sessionDestroyed(final HttpSessionEvent se) {
+        if ( this.httpSessionListener != null ) {
+            this.httpSessionListener.sessionDestroyed(new javax.servlet.http.HttpSessionEvent(new HttpSessionWrapper(se.getSession())));
+        }
+    }
+
+    @Override
+    public void sessionIdChanged(final HttpSessionEvent event, final String oldSessionId) {
+        if ( this.httpSessionIdListener != null ) {
+            this.httpSessionIdListener.sessionIdChanged(new javax.servlet.http.HttpSessionEvent(new HttpSessionWrapper(event.getSession())), oldSessionId);
+        }
+    }
+
+    @Override
+    public void attributeAdded(final HttpSessionBindingEvent event) {
+        if ( this.httpSessionAttributeListener != null ) {
+            this.httpSessionAttributeListener.attributeAdded(new javax.servlet.http.HttpSessionBindingEvent(new HttpSessionWrapper(event.getSession()), event.getName(), event.getValue()));
+        }
+    }
+
+    @Override
+    public void attributeRemoved(final HttpSessionBindingEvent event) {
+        if ( this.httpSessionAttributeListener != null ) {
+            this.httpSessionAttributeListener.attributeRemoved(new javax.servlet.http.HttpSessionBindingEvent(new HttpSessionWrapper(event.getSession()), event.getName(), event.getValue()));
+        }
+    }
+
+    @Override
+    public void attributeReplaced(final HttpSessionBindingEvent event) {
+        if ( this.httpSessionAttributeListener != null ) {
+            this.httpSessionAttributeListener.attributeReplaced(new javax.servlet.http.HttpSessionBindingEvent(new HttpSessionWrapper(event.getSession()), event.getName(), event.getValue()));
+        }
+    }
+
+    /**
+     * Get the listener
+     * @return The listener
+     */
+    public @NotNull EventListener getListener() {
+        return this.listener;
+    }
+}
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/jakartawrappers/FilterRegistrationWrapper.java b/http/base/src/main/java/org/apache/felix/http/base/internal/jakartawrappers/FilterRegistrationWrapper.java
new file mode 100644
index 0000000..e8bb143
--- /dev/null
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/jakartawrappers/FilterRegistrationWrapper.java
@@ -0,0 +1,115 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.felix.http.base.internal.jakartawrappers;
+
+import java.util.Collection;
+import java.util.EnumSet;
+import java.util.Map;
+import java.util.Set;
+
+import org.jetbrains.annotations.NotNull;
+
+import jakarta.servlet.DispatcherType;
+import jakarta.servlet.FilterRegistration;
+
+/**
+ * Filter registration wrapper
+ */
+public class FilterRegistrationWrapper implements FilterRegistration {
+
+    private final javax.servlet.FilterRegistration reg;
+
+    /**
+     * Create new wrapper
+     * @param c Wrapped registration
+     */
+    public FilterRegistrationWrapper(@NotNull final javax.servlet.FilterRegistration c) {
+        this.reg = c;
+    }
+
+    private EnumSet<javax.servlet.DispatcherType> wrap(final EnumSet<DispatcherType> dispatcherTypes) {
+        final EnumSet<javax.servlet.DispatcherType> set = EnumSet.noneOf(javax.servlet.DispatcherType.class);
+        if ( dispatcherTypes.contains(DispatcherType.ASYNC)) {
+            set.add(javax.servlet.DispatcherType.ASYNC);
+        }
+        if ( dispatcherTypes.contains(DispatcherType.ERROR)) {
+            set.add(javax.servlet.DispatcherType.ERROR);
+        }
+        if ( dispatcherTypes.contains(DispatcherType.FORWARD)) {
+            set.add(javax.servlet.DispatcherType.FORWARD);
+        }
+        if ( dispatcherTypes.contains(DispatcherType.INCLUDE)) {
+            set.add(javax.servlet.DispatcherType.INCLUDE);
+        }
+        if ( dispatcherTypes.contains(DispatcherType.REQUEST)) {
+            set.add(javax.servlet.DispatcherType.REQUEST);
+        }
+        return set;
+    }
+
+    @Override
+    public void addMappingForServletNames(final EnumSet<DispatcherType> dispatcherTypes, final boolean isMatchAfter,
+            final String... servletNames) {
+        reg.addMappingForServletNames(wrap(dispatcherTypes), isMatchAfter, servletNames);
+    }
+
+    @Override
+    public String getName() {
+        return reg.getName();
+    }
+
+    @Override
+    public String getClassName() {
+        return reg.getClassName();
+    }
+
+    @Override
+    public boolean setInitParameter(final String name, final String value) {
+        return reg.setInitParameter(name, value);
+    }
+
+    @Override
+    public Collection<String> getServletNameMappings() {
+        return reg.getServletNameMappings();
+    }
+
+    @Override
+    public void addMappingForUrlPatterns(final EnumSet<DispatcherType> dispatcherTypes, final boolean isMatchAfter,
+            final String... urlPatterns) {
+        reg.addMappingForUrlPatterns(wrap(dispatcherTypes), isMatchAfter, urlPatterns);
+    }
+
+    @Override
+    public String getInitParameter(final String name) {
+        return reg.getInitParameter(name);
+    }
+
+    @Override
+    public Set<String> setInitParameters(final Map<String, String> initParameters) {
+        return reg.setInitParameters(initParameters);
+    }
+
+    @Override
+    public Collection<String> getUrlPatternMappings() {
+        return reg.getUrlPatternMappings();
+    }
+
+    @Override
+    public Map<String, String> getInitParameters() {
+        return reg.getInitParameters();
+    }
+}
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/jakartawrappers/FilterWrapper.java b/http/base/src/main/java/org/apache/felix/http/base/internal/jakartawrappers/FilterWrapper.java
new file mode 100644
index 0000000..1e66ca0
--- /dev/null
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/jakartawrappers/FilterWrapper.java
@@ -0,0 +1,78 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.felix.http.base.internal.jakartawrappers;
+
+import java.io.IOException;
+
+import org.jetbrains.annotations.NotNull;
+
+import jakarta.servlet.Filter;
+import jakarta.servlet.FilterChain;
+import jakarta.servlet.FilterConfig;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.ServletRequest;
+import jakarta.servlet.ServletResponse;
+
+/**
+ * Jakarta Filter based on a javax filter
+ */
+public class FilterWrapper implements Filter {
+
+    private final javax.servlet.Filter filter;
+
+    /**
+     * Create new filter
+     * @param filter wrapped filter
+     */
+    public FilterWrapper(@NotNull final javax.servlet.Filter filter) {
+        this.filter = filter;
+    }
+
+    @Override
+    public void init(final FilterConfig filterConfig) throws ServletException {
+        try {
+            this.filter.init(new org.apache.felix.http.base.internal.javaxwrappers.FilterConfigWrapper(filterConfig));
+        } catch (final javax.servlet.ServletException e) {
+            throw ServletExceptionUtil.getServletException(e);
+        }
+    }
+
+    @Override
+    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
+            throws IOException, ServletException {
+        try {
+            this.filter.doFilter(org.apache.felix.http.base.internal.javaxwrappers.ServletRequestWrapper.getWrapper(request),
+                    org.apache.felix.http.base.internal.javaxwrappers.ServletResponseWrapper.getWrapper(response),
+                    new org.apache.felix.http.base.internal.javaxwrappers.FilterChainWrapper(chain));
+        } catch (final javax.servlet.ServletException e) {
+            throw ServletExceptionUtil.getServletException(e);
+        }
+    }
+
+    @Override
+    public void destroy() {
+        this.filter.destroy();
+    }
+
+    /**
+     * Get the filter
+     * @return The filter
+     */
+    public @NotNull javax.servlet.Filter getFilter() {
+        return this.filter;
+    }
+}
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/jakartawrappers/HttpServletRequestWrapper.java b/http/base/src/main/java/org/apache/felix/http/base/internal/jakartawrappers/HttpServletRequestWrapper.java
new file mode 100644
index 0000000..b9dd3cc
--- /dev/null
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/jakartawrappers/HttpServletRequestWrapper.java
@@ -0,0 +1,241 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.felix.http.base.internal.jakartawrappers;
+
+import java.io.IOException;
+import java.security.Principal;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Enumeration;
+import java.util.List;
+
+import org.jetbrains.annotations.NotNull;
+
+import jakarta.servlet.ServletException;
+import jakarta.servlet.http.Cookie;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+import jakarta.servlet.http.HttpSession;
+import jakarta.servlet.http.HttpUpgradeHandler;
+import jakarta.servlet.http.Part;
+
+/**
+ * Http servlet request wrapper
+ */
+public class HttpServletRequestWrapper extends ServletRequestWrapper
+    implements HttpServletRequest {
+
+    private final javax.servlet.http.HttpServletRequest request;
+
+    /**
+     * Create new wrapper
+     * @param r Wrapped request
+     */
+    public HttpServletRequestWrapper(@NotNull final javax.servlet.http.HttpServletRequest r) {
+        super(r);
+        this.request = r;
+    }
+
+    @Override
+    public String getAuthType() {
+        return this.request.getAuthType();
+    }
+
+    @Override
+    public Cookie[] getCookies() {
+        return CookieWrapper.wrap(this.request.getCookies());
+    }
+
+    @Override
+    public long getDateHeader(final String name) {
+        return this.request.getDateHeader(name);
+    }
+
+    @Override
+    public String getHeader(final String name) {
+        return this.request.getHeader(name);
+    }
+
+    @Override
+    public Enumeration<String> getHeaders(final String name) {
+        return this.request.getHeaders(name);
+    }
+
+    @Override
+    public Enumeration<String> getHeaderNames() {
+        return this.request.getHeaderNames();
+    }
+
+    @Override
+    public int getIntHeader(final String name) {
+        return this.request.getIntHeader(name);
+    }
+
+    @Override
+    public String getMethod() {
+        return this.request.getMethod();
+    }
+
+    @Override
+    public String getPathInfo() {
+        return this.request.getPathInfo();
+    }
+
+    @Override
+    public String getPathTranslated() {
+        return this.request.getPathTranslated();
+    }
+
+    @Override
+    public String getContextPath() {
+        return this.request.getContextPath();
+    }
+
+    @Override
+    public String getQueryString() {
+        return this.request.getQueryString();
+    }
+
+    @Override
+    public String getRemoteUser() {
+        return this.request.getRemoteUser();
+    }
+
+    @Override
+    public boolean isUserInRole(final String role) {
+        return this.request.isUserInRole(role);
+    }
+
+    @Override
+    public Principal getUserPrincipal() {
+        return this.request.getUserPrincipal();
+    }
+
+    @Override
+    public String getRequestedSessionId() {
+        return this.request.getRequestedSessionId();
+    }
+
+    @Override
+    public String getRequestURI() {
+        return this.request.getRequestURI();
+    }
+
+    @Override
+    public StringBuffer getRequestURL() {
+        return this.request.getRequestURL();
+    }
+
+    @Override
+    public String getServletPath() {
+        return this.request.getServletPath();
+    }
+
+    @Override
+    public HttpSession getSession(final boolean create) {
+        final javax.servlet.http.HttpSession session = this.request.getSession(create);
+        if ( session != null ) {
+            return new HttpSessionWrapper(session);
+        }
+        return null;
+    }
+
+    @Override
+    public HttpSession getSession() {
+        return new HttpSessionWrapper(this.request.getSession());
+    }
+
+    @Override
+    public String changeSessionId() {
+        return this.request.changeSessionId();
+    }
+
+    @Override
+    public boolean isRequestedSessionIdValid() {
+        return this.request.isRequestedSessionIdValid();
+    }
+
+    @Override
+    public boolean isRequestedSessionIdFromCookie() {
+        return this.request.isRequestedSessionIdFromCookie();
+    }
+
+    @Override
+    public boolean isRequestedSessionIdFromURL() {
+        return this.request.isRequestedSessionIdFromURL();
+    }
+
+    @SuppressWarnings("deprecation")
+    @Override
+    public boolean isRequestedSessionIdFromUrl() {
+        return this.request.isRequestedSessionIdFromUrl();
+    }
+
+    @Override
+    public boolean authenticate(final HttpServletResponse response) throws IOException, ServletException {
+        try {
+            return this.request.authenticate((javax.servlet.http.HttpServletResponse)org.apache.felix.http.base.internal.javaxwrappers.ServletResponseWrapper.getWrapper(response));
+        } catch ( final javax.servlet.ServletException e ) {
+            throw ServletExceptionUtil.getServletException(e);
+        }
+    }
+
+    @Override
+    public void login(final String username, final String password) throws ServletException {
+        try {
+            this.request.login(username, password);
+        } catch ( final javax.servlet.ServletException e ) {
+            throw ServletExceptionUtil.getServletException(e);
+        }
+    }
+
+    @Override
+    public void logout() throws ServletException {
+        try {
+            this.request.logout();
+        } catch ( final javax.servlet.ServletException e ) {
+            throw ServletExceptionUtil.getServletException(e);
+        }
+    }
+
+    @Override
+    public Collection<Part> getParts() throws IOException, ServletException {
+        try {
+            final List<Part> result = new ArrayList<>();
+            for(final javax.servlet.http.Part p : this.request.getParts()) {
+                result.add(new PartWrapper(p));
+            }
+            return result;
+        } catch ( final javax.servlet.ServletException e ) {
+            throw ServletExceptionUtil.getServletException(e);
+        }
+    }
+
+    @Override
+    public Part getPart(final String name) throws IOException, ServletException {
+        try {
+            return new PartWrapper(this.request.getPart(name));
+        } catch ( final javax.servlet.ServletException e ) {
+            throw ServletExceptionUtil.getServletException(e);
+        }
+    }
+
+    @Override
+    public <T extends HttpUpgradeHandler> T upgrade(final Class<T> handlerClass) throws IOException, ServletException {
+        throw new UnsupportedOperationException();
+    }
+}
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/jakartawrappers/HttpServletResponseWrapper.java b/http/base/src/main/java/org/apache/felix/http/base/internal/jakartawrappers/HttpServletResponseWrapper.java
new file mode 100644
index 0000000..4cc2cbc
--- /dev/null
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/jakartawrappers/HttpServletResponseWrapper.java
@@ -0,0 +1,151 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.felix.http.base.internal.jakartawrappers;
+
+import java.io.IOException;
+import java.util.Collection;
+
+import org.jetbrains.annotations.NotNull;
+
+import jakarta.servlet.http.Cookie;
+import jakarta.servlet.http.HttpServletResponse;
+
+/**
+ * Http servlet response wrapper
+*/
+public class HttpServletResponseWrapper extends ServletResponseWrapper
+    implements HttpServletResponse {
+
+    private final javax.servlet.http.HttpServletResponse response;
+
+    /**
+     * Create a new response
+     * @param r Wrapped response
+     */
+    public HttpServletResponseWrapper(@NotNull final javax.servlet.http.HttpServletResponse r) {
+        super(r);
+        this.response = r;
+    }
+
+    @Override
+    public void addCookie(final Cookie cookie) {
+        this.response.addCookie(new org.apache.felix.http.base.internal.javaxwrappers.CookieWrapper(cookie));
+    }
+
+    @Override
+    public boolean containsHeader(final String name) {
+        return this.response.containsHeader(name);
+    }
+
+    @Override
+    public String encodeURL(final String url) {
+        return this.response.encodeURL(url);
+    }
+
+    @Override
+    public String encodeRedirectURL(final String url) {
+        return this.response.encodeRedirectURL(url);
+    }
+
+    @SuppressWarnings("deprecation")
+    @Override
+    public String encodeUrl(final String url) {
+        return this.response.encodeUrl(url);
+    }
+
+    @SuppressWarnings("deprecation")
+    @Override
+    public String encodeRedirectUrl(final String url) {
+        return this.response.encodeRedirectUrl(url);
+    }
+
+    @Override
+    public void sendError(final int sc, final String msg) throws IOException {
+        this.response.sendError(sc, msg);
+    }
+
+    @Override
+    public void sendError(final int sc) throws IOException {
+        this.response.sendError(sc);
+    }
+
+    @Override
+    public void sendRedirect(final String location) throws IOException {
+        this.response.sendRedirect(location);
+    }
+
+    @Override
+    public void setDateHeader(final String name, final long date) {
+        this.response.setDateHeader(name, date);
+    }
+
+    @Override
+    public void addDateHeader(final String name, final long date) {
+        this.response.addDateHeader(name, date);
+    }
+
+    @Override
+    public void setHeader(final String name, final String value) {
+        this.response.setHeader(name, value);
+    }
+
+    @Override
+    public void addHeader(final String name, final String value) {
+        this.response.addHeader(name, value);
+    }
+
+    @Override
+    public void setIntHeader(final String name, final int value) {
+        this.response.setIntHeader(name, value);
+    }
+
+    @Override
+    public void addIntHeader(final String name, final int value) {
+        this.response.addIntHeader(name, value);
+    }
+
+    @Override
+    public void setStatus(int sc) {
+        this.response.setStatus(sc);
+    }
+
+    @SuppressWarnings("deprecation")
+    @Override
+    public void setStatus(final int sc, final String sm) {
+        this.response.setStatus(sc, sm);
+    }
+
+    @Override
+    public int getStatus() {
+        return this.response.getStatus();
+    }
+
+    @Override
+    public String getHeader(final String name) {
+        return this.response.getHeader(name);
+    }
+
+    @Override
+    public Collection<String> getHeaders(final String name) {
+        return this.response.getHeaders(name);
+    }
+
+    @Override
+    public Collection<String> getHeaderNames() {
+        return this.response.getHeaderNames();
+    }
+}
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/jakartawrappers/HttpSessionContextWrapper.java b/http/base/src/main/java/org/apache/felix/http/base/internal/jakartawrappers/HttpSessionContextWrapper.java
new file mode 100644
index 0000000..786a84b
--- /dev/null
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/jakartawrappers/HttpSessionContextWrapper.java
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.felix.http.base.internal.jakartawrappers;
+
+import java.util.Enumeration;
+
+import org.jetbrains.annotations.NotNull;
+
+import jakarta.servlet.http.HttpSession;
+import jakarta.servlet.http.HttpSessionContext;
+
+/**
+ * http session context wrapper
+ */
+@SuppressWarnings("deprecation")
+public class HttpSessionContextWrapper implements HttpSessionContext {
+
+    private final javax.servlet.http.HttpSessionContext context;
+
+    /**
+     * Create new context
+     * @param c Wrapped context
+     */
+    public HttpSessionContextWrapper(@NotNull final javax.servlet.http.HttpSessionContext c) {
+        this.context = c;
+    }
+
+    @Override
+    public HttpSession getSession(final String sessionId) {
+        final javax.servlet.http.HttpSession session = context.getSession(sessionId);
+        if ( session != null ) {
+            return new HttpSessionWrapper(session);
+        }
+        return null;
+    }
+
+    @Override
+    public Enumeration<String> getIds() {
+        return context.getIds();
+    }
+}
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/jakartawrappers/HttpSessionWrapper.java b/http/base/src/main/java/org/apache/felix/http/base/internal/jakartawrappers/HttpSessionWrapper.java
new file mode 100644
index 0000000..27dc9dd
--- /dev/null
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/jakartawrappers/HttpSessionWrapper.java
@@ -0,0 +1,132 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.felix.http.base.internal.jakartawrappers;
+
+import java.util.Enumeration;
+
+import org.jetbrains.annotations.NotNull;
+
+import jakarta.servlet.ServletContext;
+import jakarta.servlet.http.HttpSession;
+import jakarta.servlet.http.HttpSessionContext;
+
+/**
+ * Http session wrapper
+ */
+public class HttpSessionWrapper implements HttpSession {
+
+    private final javax.servlet.http.HttpSession session;
+
+    /**
+     * Create new session
+     * @param session Wrapped session
+     */
+    public HttpSessionWrapper(@NotNull final javax.servlet.http.HttpSession session) {
+        this.session = session;
+    }
+
+
+    @Override
+    public long getCreationTime() {
+        return session.getCreationTime();
+    }
+
+    @Override
+    public String getId() {
+        return session.getId();
+    }
+
+    @Override
+    public long getLastAccessedTime() {
+        return session.getLastAccessedTime();
+    }
+
+    @Override
+    public ServletContext getServletContext() {
+        return new ServletContextWrapper(session.getServletContext());
+    }
+
+    @Override
+    public void setMaxInactiveInterval(int interval) {
+        session.setMaxInactiveInterval(interval);
+    }
+
+    @Override
+    public int getMaxInactiveInterval() {
+        return session.getMaxInactiveInterval();
+    }
+
+    @SuppressWarnings("deprecation")
+    @Override
+    public HttpSessionContext getSessionContext() {
+        return new HttpSessionContextWrapper(session.getSessionContext());
+    }
+
+    @Override
+    public Object getAttribute(String name) {
+        return session.getAttribute(name);
+    }
+
+    @SuppressWarnings("deprecation")
+    @Override
+    public Object getValue(String name) {
+        return session.getValue(name);
+    }
+
+    @Override
+    public Enumeration<String> getAttributeNames() {
+        return session.getAttributeNames();
+    }
+
+    @SuppressWarnings("deprecation")
+    @Override
+    public String[] getValueNames() {
+        return session.getValueNames();
+    }
+
+    @Override
+    public void setAttribute(String name, Object value) {
+        session.setAttribute(name, value);
+    }
+
+    @SuppressWarnings("deprecation")
+    @Override
+    public void putValue(String name, Object value) {
+        session.putValue(name, value);
+    }
+
+    @Override
+    public void removeAttribute(String name) {
+        session.removeAttribute(name);
+    }
+
+    @SuppressWarnings("deprecation")
+    @Override
+    public void removeValue(String name) {
+        session.removeValue(name);
+    }
+
+    @Override
+    public void invalidate() {
+        session.invalidate();
+    }
+
+    @Override
+    public boolean isNew() {
+        return session.isNew();
+    }
+}
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/jakartawrappers/PartWrapper.java b/http/base/src/main/java/org/apache/felix/http/base/internal/jakartawrappers/PartWrapper.java
new file mode 100644
index 0000000..6092c60
--- /dev/null
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/jakartawrappers/PartWrapper.java
@@ -0,0 +1,91 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.felix.http.base.internal.jakartawrappers;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Collection;
+
+import org.jetbrains.annotations.NotNull;
+
+import jakarta.servlet.http.Part;
+
+/**
+ * Part wrapper
+ */
+public class PartWrapper implements Part {
+
+    private final javax.servlet.http.Part part;
+
+    /**
+     * Create new part
+     * @param p Wrapped part
+     */
+    public PartWrapper(@NotNull final javax.servlet.http.Part p) {
+        this.part = p;
+    }
+
+    @Override
+    public InputStream getInputStream() throws IOException {
+        return this.part.getInputStream();
+    }
+
+    @Override
+    public String getContentType() {
+        return this.part.getContentType();
+    }
+
+    @Override
+    public String getName() {
+        return this.part.getName();
+    }
+
+    @Override
+    public String getSubmittedFileName() {
+        return this.part.getSubmittedFileName();
+    }
+
+    @Override
+    public long getSize() {
+        return this.part.getSize();
+    }
+
+    @Override
+    public void write(String fileName) throws IOException {
+        this.part.write(fileName);
+    }
+
+    @Override
+    public void delete() throws IOException {
+        this.part.delete();
+    }
+
+    @Override
+    public String getHeader(final String name) {
+        return this.part.getHeader(name);
+    }
+
+    @Override
+    public Collection<String> getHeaders(final String name) {
+        return this.part.getHeaders(name);
+    }
+
+    @Override
+    public Collection<String> getHeaderNames() {
+        return this.part.getHeaderNames();
+    }
+}
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/service/DefaultHttpContext.java b/http/base/src/main/java/org/apache/felix/http/base/internal/jakartawrappers/PreprocessorWrapper.java
similarity index 50%
copy from http/base/src/main/java/org/apache/felix/http/base/internal/service/DefaultHttpContext.java
copy to http/base/src/main/java/org/apache/felix/http/base/internal/jakartawrappers/PreprocessorWrapper.java
index 22a048d..7c6cb2b 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/service/DefaultHttpContext.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/jakartawrappers/PreprocessorWrapper.java
@@ -14,40 +14,31 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.felix.http.base.internal.service;
+package org.apache.felix.http.base.internal.jakartawrappers;
 
-import org.osgi.service.http.HttpContext;
-import org.osgi.framework.Bundle;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import java.net.URL;
+import org.apache.felix.http.base.osgi.whiteboard.Preprocessor;
+import org.jetbrains.annotations.NotNull;
 
-public final class DefaultHttpContext 
-    implements HttpContext
-{
-    private Bundle bundle;
-
-    public DefaultHttpContext(Bundle bundle)
-    {
-        this.bundle = bundle;
-    }
-
-    public String getMimeType(String name)
-    {
-        return null;
-    }
-
-    public URL getResource(String name)
-    {
-        if (name.startsWith("/")) {
-            name = name.substring(1);
-        }
+/**
+ * Preprocessor wrapper
+ */
+public class PreprocessorWrapper
+    extends FilterWrapper
+    implements Preprocessor {
 
-        return this.bundle.getResource(name);
+    /**
+     * Create new preprocessor
+     * @param filter wrapped filter
+     */
+    public PreprocessorWrapper(@NotNull final javax.servlet.Filter filter) {
+        super(filter);
     }
 
-    public boolean handleSecurity(HttpServletRequest req, HttpServletResponse res)
-    {
-        return true;
+    /**
+     * Get the preprocessor
+     * @return The preprocessor
+     */
+    public org.osgi.service.http.whiteboard.Preprocessor getPreprocessor() {
+        return (org.osgi.service.http.whiteboard.Preprocessor) super.getFilter();
     }
 }
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/service/DefaultHttpContext.java b/http/base/src/main/java/org/apache/felix/http/base/internal/jakartawrappers/ReadListenerWrapper.java
similarity index 51%
copy from http/base/src/main/java/org/apache/felix/http/base/internal/service/DefaultHttpContext.java
copy to http/base/src/main/java/org/apache/felix/http/base/internal/jakartawrappers/ReadListenerWrapper.java
index 22a048d..164e628 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/service/DefaultHttpContext.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/jakartawrappers/ReadListenerWrapper.java
@@ -14,40 +14,42 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.felix.http.base.internal.service;
-
-import org.osgi.service.http.HttpContext;
-import org.osgi.framework.Bundle;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import java.net.URL;
-
-public final class DefaultHttpContext 
-    implements HttpContext
-{
-    private Bundle bundle;
-
-    public DefaultHttpContext(Bundle bundle)
-    {
-        this.bundle = bundle;
-    }
+package org.apache.felix.http.base.internal.jakartawrappers;
+
+import java.io.IOException;
+
+import org.jetbrains.annotations.NotNull;
 
-    public String getMimeType(String name)
-    {
-        return null;
+import jakarta.servlet.ReadListener;
+
+/**
+ * Read listener
+ */
+public class ReadListenerWrapper implements ReadListener {
+
+    private final javax.servlet.ReadListener listener;
+
+    /**
+     * Create new lister
+     * @param listener Wrapped listener
+     */
+    public ReadListenerWrapper(@NotNull final javax.servlet.ReadListener listener) {
+        this.listener = listener;
     }
 
-    public URL getResource(String name)
-    {
-        if (name.startsWith("/")) {
-            name = name.substring(1);
-        }
+    @Override
+    public void onDataAvailable() throws IOException {
+        listener.onDataAvailable();
+    }
 
-        return this.bundle.getResource(name);
+    @Override
+    public void onAllDataRead() throws IOException {
+        listener.onAllDataRead();
     }
 
-    public boolean handleSecurity(HttpServletRequest req, HttpServletResponse res)
-    {
-        return true;
+    @Override
+    public void onError(Throwable t) {
+        listener.onError(t);
     }
+
 }
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/jakartawrappers/RequestDispatcherWrapper.java b/http/base/src/main/java/org/apache/felix/http/base/internal/jakartawrappers/RequestDispatcherWrapper.java
new file mode 100644
index 0000000..7e5a2dd
--- /dev/null
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/jakartawrappers/RequestDispatcherWrapper.java
@@ -0,0 +1,62 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.felix.http.base.internal.jakartawrappers;
+
+import java.io.IOException;
+
+import org.jetbrains.annotations.NotNull;
+
+import jakarta.servlet.RequestDispatcher;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.ServletRequest;
+import jakarta.servlet.ServletResponse;
+
+/**
+ * Dispatcher wrapper
+ */
+public class RequestDispatcherWrapper implements RequestDispatcher {
+
+    private final javax.servlet.RequestDispatcher dispatcher;
+
+    /**
+     * Create new dispatcher
+     * @param dispatcher Dispatcher
+     */
+    public RequestDispatcherWrapper(@NotNull javax.servlet.RequestDispatcher dispatcher) {
+        this.dispatcher = dispatcher;
+    }
+
+    @Override
+    public void forward(final ServletRequest request, final ServletResponse response) throws ServletException, IOException {
+        try {
+            dispatcher.forward(org.apache.felix.http.base.internal.javaxwrappers.ServletRequestWrapper.getWrapper(request),
+                    org.apache.felix.http.base.internal.javaxwrappers.ServletResponseWrapper.getWrapper(response));
+        } catch (final javax.servlet.ServletException e) {
+            throw ServletExceptionUtil.getServletException(e);
+        }
+    }
+
+    @Override
+    public void include(final ServletRequest request, final ServletResponse response) throws ServletException, IOException {
+        try {
+            dispatcher.include(org.apache.felix.http.base.internal.javaxwrappers.ServletRequestWrapper.getWrapper(request),
+                    org.apache.felix.http.base.internal.javaxwrappers.ServletResponseWrapper.getWrapper(response));
+        } catch (final javax.servlet.ServletException e) {
+            throw ServletExceptionUtil.getServletException(e);
+        }
+    }
+}
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/jakartawrappers/ServletConfigWrapper.java b/http/base/src/main/java/org/apache/felix/http/base/internal/jakartawrappers/ServletConfigWrapper.java
new file mode 100644
index 0000000..881ab60
--- /dev/null
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/jakartawrappers/ServletConfigWrapper.java
@@ -0,0 +1,60 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.felix.http.base.internal.jakartawrappers;
+
+import java.util.Enumeration;
+
+import org.jetbrains.annotations.NotNull;
+
+import jakarta.servlet.ServletConfig;
+import jakarta.servlet.ServletContext;
+
+/**
+ * Servlet config wrapper
+ */
+public class ServletConfigWrapper implements ServletConfig {
+
+    private final javax.servlet.ServletConfig config;
+
+    /**
+     * Create new servlet config
+     * @param config wrapped servlet config
+     */
+    public ServletConfigWrapper(@NotNull final javax.servlet.ServletConfig config) {
+        this.config = config;
+    }
+
+    @Override
+    public String getServletName() {
+        return config.getServletName();
+    }
+
+    @Override
+    public ServletContext getServletContext() {
+        return new ServletContextWrapper(config.getServletContext());
+    }
+
+    @Override
+    public String getInitParameter(final String name) {
+        return config.getInitParameter(name);
+    }
+
+    @Override
+    public Enumeration<String> getInitParameterNames() {
+        return config.getInitParameterNames();
+    }
+}
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/jakartawrappers/ServletContextHelperWrapper.java b/http/base/src/main/java/org/apache/felix/http/base/internal/jakartawrappers/ServletContextHelperWrapper.java
new file mode 100644
index 0000000..c2a2450
--- /dev/null
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/jakartawrappers/ServletContextHelperWrapper.java
@@ -0,0 +1,85 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.felix.http.base.internal.jakartawrappers;
+
+import java.io.IOException;
+import java.net.URL;
+import java.util.Set;
+
+import org.apache.felix.http.base.internal.javaxwrappers.ServletRequestWrapper;
+import org.apache.felix.http.base.internal.javaxwrappers.ServletResponseWrapper;
+import org.apache.felix.http.base.osgi.whiteboard.ServletContextHelper;
+import org.jetbrains.annotations.NotNull;
+
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+
+/**
+ * ServletContextHelper wrapper
+ */
+public class ServletContextHelperWrapper extends ServletContextHelper {
+
+    private final org.osgi.service.http.context.ServletContextHelper helper;
+
+    /**
+     * Create new wrapper
+     * @param helper Helper
+     */
+    public ServletContextHelperWrapper(@NotNull final org.osgi.service.http.context.ServletContextHelper helper) {
+        this.helper = helper;
+    }
+
+    @Override
+    public boolean handleSecurity(final HttpServletRequest request, final HttpServletResponse response) throws IOException {
+        return helper.handleSecurity((javax.servlet.http.HttpServletRequest)ServletRequestWrapper.getWrapper(request),
+                (javax.servlet.http.HttpServletResponse)ServletResponseWrapper.getWrapper(response));
+    }
+
+    @Override
+    public void finishSecurity(final HttpServletRequest request, final HttpServletResponse response) {
+        helper.finishSecurity((javax.servlet.http.HttpServletRequest)ServletRequestWrapper.getWrapper(request),
+                (javax.servlet.http.HttpServletResponse)ServletResponseWrapper.getWrapper(response));
+    }
+
+    @Override
+    public URL getResource(final String name) {
+        return helper.getResource(name);
+    }
+
+    @Override
+    public String getMimeType(final String name) {
+        return helper.getMimeType(name);
+    }
+
+    @Override
+    public Set<String> getResourcePaths(final String path) {
+        return helper.getResourcePaths(path);
+    }
+
+    @Override
+    public String getRealPath(final String path) {
+        return helper.getRealPath(path);
+    }
+
+    /**
+     * Get the helper
+     * @return The helper
+     */
+    public @NotNull org.osgi.service.http.context.ServletContextHelper getHelper() {
+        return this.helper;
+    }
+}
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/jakartawrappers/ServletContextWrapper.java b/http/base/src/main/java/org/apache/felix/http/base/internal/jakartawrappers/ServletContextWrapper.java
new file mode 100644
index 0000000..62a03ad
--- /dev/null
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/jakartawrappers/ServletContextWrapper.java
@@ -0,0 +1,417 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.felix.http.base.internal.jakartawrappers;
+
+import java.io.InputStream;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.EventListener;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import org.jetbrains.annotations.NotNull;
+
+import jakarta.servlet.Filter;
+import jakarta.servlet.FilterRegistration;
+import jakarta.servlet.RequestDispatcher;
+import jakarta.servlet.Servlet;
+import jakarta.servlet.ServletContext;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.ServletRegistration;
+import jakarta.servlet.ServletRegistration.Dynamic;
+import jakarta.servlet.SessionCookieConfig;
+import jakarta.servlet.SessionTrackingMode;
+import jakarta.servlet.descriptor.JspConfigDescriptor;
+
+/**
+ * Servlet context wrapper
+ */
+public class ServletContextWrapper implements ServletContext {
+
+    private final javax.servlet.ServletContext context;
+
+    /**
+     * Create new context
+     * @param c Wrapped context
+     */
+    public ServletContextWrapper(@NotNull final javax.servlet.ServletContext c) {
+        this.context = c;
+    }
+
+    @Override
+    public String getContextPath() {
+        return this.context.getContextPath();
+    }
+
+    @Override
+    public ServletContext getContext(final String uripath) {
+        final javax.servlet.ServletContext c = this.context.getContext(uripath);
+        if ( c != null ) {
+            return new ServletContextWrapper(c);
+        }
+        return null;
+    }
+
+    @Override
+    public int getMajorVersion() {
+        return this.context.getMajorVersion();
+    }
+
+    @Override
+    public int getMinorVersion() {
+        return this.context.getMinorVersion();
+    }
+
+    @Override
+    public int getEffectiveMajorVersion() {
+        return this.context.getEffectiveMajorVersion();
+    }
+
+    @Override
+    public int getEffectiveMinorVersion() {
+        return this.context.getEffectiveMinorVersion();
+    }
+
+    @Override
+    public String getMimeType(final String file) {
+        return this.context.getMimeType(file);
+    }
+
+    @Override
+    public Set<String> getResourcePaths(final String path) {
+        return this.context.getResourcePaths(path);
+    }
+
+    @Override
+    public URL getResource(final String path) throws MalformedURLException {
+        return this.context.getResource(path);
+    }
+
+    @Override
+    public InputStream getResourceAsStream(final String path) {
+        return this.context.getResourceAsStream(path);
+    }
+
+    @Override
+    public RequestDispatcher getRequestDispatcher(final String path) {
+        final javax.servlet.RequestDispatcher dispatcher = this.context.getRequestDispatcher(path);
+        if ( dispatcher != null ) {
+            return new RequestDispatcherWrapper(dispatcher);
+        }
+        return null;
+    }
+
+    @Override
+    public RequestDispatcher getNamedDispatcher(final String name) {
+        final javax.servlet.RequestDispatcher dispatcher = this.context.getNamedDispatcher(name);
+        if ( dispatcher != null ) {
+            return new RequestDispatcherWrapper(dispatcher);
+        }
+        return null;
+    }
+
+    @Override
+    public Servlet getServlet(final String name) throws ServletException {
+        return null;
+    }
+
+    @Override
+    public Enumeration<Servlet> getServlets() {
+        return Collections.emptyEnumeration();
+    }
+
+    @SuppressWarnings("deprecation")
+    @Override
+    public Enumeration<String> getServletNames() {
+        return this.context.getServletNames();
+    }
+
+    @Override
+    public void log(final String msg) {
+        this.context.log(msg);
+    }
+
+    @SuppressWarnings("deprecation")
+    @Override
+    public void log(final Exception exception, final String msg) {
+        this.context.log(exception, msg);
+    }
+
+    @Override
+    public void log(final String message, final Throwable throwable) {
+        this.context.log(message, throwable);
+    }
+
+    @Override
+    public String getRealPath(final String path) {
+        return this.context.getRealPath(path);
+    }
+
+    @Override
+    public String getServerInfo() {
+        return this.context.getServerInfo();
+    }
+
+    @Override
+    public String getInitParameter(final String name) {
+        return this.context.getInitParameter(name);
+    }
+
+    @Override
+    public Enumeration<String> getInitParameterNames() {
+        return this.context.getInitParameterNames();
+    }
+
+    @Override
+    public boolean setInitParameter(final String name, final String value) {
+        return this.context.setInitParameter(name, value);
+    }
+
+    @Override
+    public Object getAttribute(final String name) {
+        return this.context.getAttribute(name);
+    }
+
+    @Override
+    public Enumeration<String> getAttributeNames() {
+        return this.context.getAttributeNames();
+    }
+
+    @Override
+    public void setAttribute(final String name, final Object object) {
+        this.context.setAttribute(name, object);
+    }
+
+    @Override
+    public void removeAttribute(final String name) {
+        this.context.removeAttribute(name);
+    }
+
+    @Override
+    public String getServletContextName() {
+        return this.context.getServletContextName();
+    }
+
+    @Override
+    public ServletRegistration.Dynamic addServlet(final String servletName, final String className) {
+        throw new IllegalStateException();
+    }
+
+    @Override
+    public ServletRegistration.Dynamic addServlet(final String servletName, final Servlet servlet) {
+        throw new IllegalStateException();
+    }
+
+    @Override
+    public ServletRegistration.Dynamic addServlet(final String servletName, final Class<? extends Servlet> servletClass) {
+        throw new IllegalStateException();
+    }
+
+    @Override
+    public <T extends Servlet> T createServlet(final Class<T> clazz) throws ServletException {
+        throw new IllegalStateException();
+    }
+
+    @Override
+    public ServletRegistration getServletRegistration(final String servletName) {
+        final javax.servlet.ServletRegistration reg = this.context.getServletRegistration(servletName);
+        if ( reg != null ) {
+            return new ServletRegistrationWrapper(reg);
+        }
+        return null;
+    }
+
+    @SuppressWarnings({ "rawtypes", "unchecked" })
+    @Override
+    public Map<String, ? extends ServletRegistration> getServletRegistrations() {
+        final Map result = new HashMap<>();
+        for(final Map.Entry<String, ? extends javax.servlet.ServletRegistration> e : this.context.getServletRegistrations().entrySet()) {
+            result.put(e.getKey(), new ServletRegistrationWrapper(e.getValue()));
+        }
+        return result;
+    }
+
+    @Override
+    public FilterRegistration.Dynamic addFilter(final String filterName, final String className) {
+        throw new IllegalStateException();
+    }
+
+    @Override
+    public FilterRegistration.Dynamic addFilter(final String filterName, final Filter filter) {
+        throw new IllegalStateException();
+    }
+
+    @Override
+    public FilterRegistration.Dynamic addFilter(final String filterName, final Class<? extends Filter> filterClass) {
+        throw new IllegalStateException();
+    }
+
+    @Override
+    public <T extends Filter> T createFilter(final Class<T> clazz) throws ServletException {
+        throw new IllegalStateException();
+    }
+
+    @Override
+    public FilterRegistration getFilterRegistration(final String filterName) {
+        return new FilterRegistrationWrapper(this.context.getFilterRegistration(filterName));
+    }
+
+    @SuppressWarnings({ "rawtypes", "unchecked" })
+    @Override
+    public Map<String, ? extends FilterRegistration> getFilterRegistrations() {
+        final Map result = new HashMap<>();
+        for(final Map.Entry<String, ? extends javax.servlet.FilterRegistration> e : this.context.getFilterRegistrations().entrySet()) {
+            result.put(e.getKey(), new FilterRegistrationWrapper(e.getValue()));
+        }
+        return result;
+    }
+
+    @Override
+    public SessionCookieConfig getSessionCookieConfig() {
+        return new SessionCookieConfigWrapper(this.context.getSessionCookieConfig());
+    }
+
+    @Override
+    public void setSessionTrackingModes(final Set<SessionTrackingMode> sessionTrackingModes) {
+        if ( sessionTrackingModes == null ) {
+            this.context.setSessionTrackingModes(null);
+        } else {
+            final Set<javax.servlet.SessionTrackingMode> modes = new HashSet<>();
+            if ( sessionTrackingModes.contains(SessionTrackingMode.COOKIE)) {
+                modes.add(javax.servlet.SessionTrackingMode.COOKIE);
+            }
+            if ( sessionTrackingModes.contains(SessionTrackingMode.SSL)) {
+                modes.add(javax.servlet.SessionTrackingMode.SSL);
+            }
+            if ( sessionTrackingModes.contains(SessionTrackingMode.URL)) {
+                modes.add(javax.servlet.SessionTrackingMode.URL);
+            }
+            this.context.setSessionTrackingModes(modes);
+        }
+    }
+
+    @Override
+    public Set<SessionTrackingMode> getDefaultSessionTrackingModes() {
+        final Set<javax.servlet.SessionTrackingMode> sessionTrackingModes = this.context.getDefaultSessionTrackingModes();
+        final Set<SessionTrackingMode> modes = new HashSet<>();
+        if ( sessionTrackingModes.contains(javax.servlet.SessionTrackingMode.COOKIE)) {
+            modes.add(SessionTrackingMode.COOKIE);
+        }
+        if ( sessionTrackingModes.contains(javax.servlet.SessionTrackingMode.SSL)) {
+            modes.add(SessionTrackingMode.SSL);
+        }
+        if ( sessionTrackingModes.contains(javax.servlet.SessionTrackingMode.URL)) {
+            modes.add(SessionTrackingMode.URL);
+        }
+        return modes;
+    }
+
+    @Override
+    public Set<SessionTrackingMode> getEffectiveSessionTrackingModes() {
+        final Set<javax.servlet.SessionTrackingMode> sessionTrackingModes = this.context.getEffectiveSessionTrackingModes();
+        final Set<SessionTrackingMode> modes = new HashSet<>();
+        if ( sessionTrackingModes.contains(javax.servlet.SessionTrackingMode.COOKIE)) {
+            modes.add(SessionTrackingMode.COOKIE);
+        }
+        if ( sessionTrackingModes.contains(javax.servlet.SessionTrackingMode.SSL)) {
+            modes.add(SessionTrackingMode.SSL);
+        }
+        if ( sessionTrackingModes.contains(javax.servlet.SessionTrackingMode.URL)) {
+            modes.add(SessionTrackingMode.URL);
+        }
+        return modes;
+    }
+
+    @Override
+    public void addListener(String className) {
+        throw new IllegalStateException();
+    }
+
+    @Override
+    public <T extends EventListener> void addListener(final T t) {
+        throw new IllegalStateException();
+    }
+
+    @Override
+    public void addListener(final Class<? extends EventListener> listenerClass) {
+        throw new IllegalStateException();
+    }
+
+    @Override
+    public <T extends EventListener> T createListener(final Class<T> clazz) throws ServletException {
+        throw new IllegalStateException();
+    }
+
+    @Override
+    public JspConfigDescriptor getJspConfigDescriptor() {
+        return null;
+    }
+
+    @Override
+    public ClassLoader getClassLoader() {
+        return this.context.getClassLoader();
+    }
+
+    @Override
+    public void declareRoles(final String... roleNames) {
+        this.context.declareRoles(roleNames);
+    }
+
+    @Override
+    public String getVirtualServerName() {
+        return this.context.getVirtualServerName();
+    }
+
+    @Override
+    public Dynamic addJspFile(final String servletName, final String jspFile) {
+        throw new IllegalStateException();
+    }
+
+    @Override
+    public int getSessionTimeout() {
+        return this.context.getSessionTimeout();
+    }
+
+    @Override
+    public void setSessionTimeout(int sessionTimeout) {
+        this.context.setSessionTimeout(sessionTimeout);
+    }
+
+    @Override
+    public String getRequestCharacterEncoding() {
+        return this.context.getRequestCharacterEncoding();
+    }
+
+    @Override
+    public void setRequestCharacterEncoding(final String encoding) {
+        this.context.setRequestCharacterEncoding(encoding);
+    }
+
+    @Override
+    public String getResponseCharacterEncoding() {
+        return this.context.getResponseCharacterEncoding();
+    }
+
+    @Override
+    public void setResponseCharacterEncoding(final String encoding) {
+        this.context.setResponseCharacterEncoding(encoding);
+    }
+}
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/jakartawrappers/ServletExceptionUtil.java b/http/base/src/main/java/org/apache/felix/http/base/internal/jakartawrappers/ServletExceptionUtil.java
new file mode 100644
index 0000000..ee029fd
--- /dev/null
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/jakartawrappers/ServletExceptionUtil.java
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.felix.http.base.internal.jakartawrappers;
+
+import org.jetbrains.annotations.NotNull;
+
+import jakarta.servlet.ServletException;
+import jakarta.servlet.UnavailableException;
+
+/**
+ * Helper class to wrap servlet exceptions
+ */
+public class ServletExceptionUtil {
+
+    /**
+     * Throw jakarta servlet exception
+     * @param e javax exception
+     * @return The exception
+     */
+    public static ServletException getServletException(@NotNull final javax.servlet.ServletException e) {
+        if ( e instanceof javax.servlet.UnavailableException ) {
+            final UnavailableException t = new UnavailableException(e.getMessage(), ((javax.servlet.UnavailableException)e).getUnavailableSeconds());
+            if ( e.getCause() != null ) {
+                t.initCause(e.getCause());
+            }
+            return t;
+        }
+        if ( e.getCause() instanceof ServletException ) {
+            return (ServletException)e.getCause();
+        }
+        final ServletException ne = new ServletException(e.getMessage(), e.getCause());
+        ne.setStackTrace(e.getStackTrace());
+        return ne;
+    }
+
+}
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/jakartawrappers/ServletInputStreamWrapper.java b/http/base/src/main/java/org/apache/felix/http/base/internal/jakartawrappers/ServletInputStreamWrapper.java
new file mode 100644
index 0000000..8191f5c
--- /dev/null
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/jakartawrappers/ServletInputStreamWrapper.java
@@ -0,0 +1,128 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.felix.http.base.internal.jakartawrappers;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+import org.jetbrains.annotations.NotNull;
+
+import jakarta.servlet.ReadListener;
+import jakarta.servlet.ServletInputStream;
+
+/**
+ * Servlet input stream wrapper
+ */
+public class ServletInputStreamWrapper extends ServletInputStream {
+
+    private final javax.servlet.ServletInputStream stream;
+
+    /**
+     * Create input stream
+     * @param stream Wrapped stream
+     */
+    public ServletInputStreamWrapper(@NotNull final javax.servlet.ServletInputStream stream) {
+        this.stream = stream;
+    }
+
+    @Override
+    public int readLine(final byte[] b, final int off, final int len) throws IOException {
+        return this.stream.readLine(b, off, len);
+    }
+
+    @Override
+    public boolean isFinished() {
+        return this.stream.isFinished();
+    }
+
+    @Override
+    public boolean isReady() {
+        return this.stream.isReady();
+    }
+
+    @Override
+    public void setReadListener(final ReadListener readListener) {
+        this.stream.setReadListener(new org.apache.felix.http.base.internal.javaxwrappers.ReadListenerWrapper(readListener));
+    }
+
+    @Override
+    public int read() throws IOException {
+        return this.stream.read();
+    }
+
+    @Override
+    public int read(final byte[] b) throws IOException {
+        return this.stream.read(b);
+    }
+
+    @Override
+    public int read(final byte[] b, final int off, final int len) throws IOException {
+        return this.stream.read(b, off, len);
+    }
+
+    @Override
+    public byte[] readAllBytes() throws IOException {
+        return this.stream.readAllBytes();
+    }
+
+    @Override
+    public byte[] readNBytes(final int len) throws IOException {
+        return this.stream.readNBytes(len);
+    }
+
+    @Override
+    public int readNBytes(final byte[] b, final int off, final int len) throws IOException {
+        return this.stream.readNBytes(b, off, len);
+    }
+
+    @Override
+    public long skip(final long n) throws IOException {
+        return this.stream.skip(n);
+    }
+
+    @Override
+    public int available() throws IOException {
+        return this.stream.available();
+    }
+
+    @Override
+    public void close() throws IOException {
+        this.stream.close();
+    }
+
+    @Override
+    public synchronized void mark(final int readlimit) {
+        this.stream.mark(readlimit);
+    }
+
+    @Override
+    public synchronized void reset() throws IOException {
+        this.stream.reset();
+    }
+
+    @Override
+    public boolean markSupported() {
+        return this.stream.markSupported();
+    }
+
+    @Override
+    public long transferTo(final OutputStream out) throws IOException {
+        return this.stream.transferTo(out);
+    }
+
+
+}
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/jakartawrappers/ServletOutputStreamWrapper.java b/http/base/src/main/java/org/apache/felix/http/base/internal/jakartawrappers/ServletOutputStreamWrapper.java
new file mode 100644
index 0000000..064fb17
--- /dev/null
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/jakartawrappers/ServletOutputStreamWrapper.java
@@ -0,0 +1,150 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.felix.http.base.internal.jakartawrappers;
+
+import java.io.IOException;
+
+import org.jetbrains.annotations.NotNull;
+
+import jakarta.servlet.ServletOutputStream;
+import jakarta.servlet.WriteListener;
+
+/**
+ * Servlet output stream
+ */
+public class ServletOutputStreamWrapper extends ServletOutputStream {
+
+    private final javax.servlet.ServletOutputStream stream;
+
+    /**
+     * Create new stream
+     * @param stream wrapped stream
+     */
+    public ServletOutputStreamWrapper(@NotNull final javax.servlet.ServletOutputStream stream) {
+        this.stream = stream;
+    }
+
+    @Override
+    public void print(final String s) throws IOException {
+        this.stream.print(s);
+    }
+
+    @Override
+    public void print(final boolean b) throws IOException {
+        this.stream.print(b);
+    }
+
+    @Override
+    public void print(final char c) throws IOException {
+        this.stream.print(c);
+    }
+
+    @Override
+    public void print(final int i) throws IOException {
+        this.stream.print(i);
+    }
+
+    @Override
+    public void print(final long l) throws IOException {
+        this.stream.print(l);
+    }
+
+    @Override
+    public void print(final float f) throws IOException {
+        this.stream.print(f);
+    }
+
+    @Override
+    public void print(final double d) throws IOException {
+        this.stream.print(d);
+    }
+
+    @Override
+    public void println() throws IOException {
+        this.stream.println();
+    }
+
+    @Override
+    public void println(final String s) throws IOException {
+        this.stream.println(s);
+    }
+
+    @Override
+    public void println(final boolean b) throws IOException {
+        this.stream.println(b);
+    }
+
+    @Override
+    public void println(final char c) throws IOException {
+        this.stream.println(c);
+    }
+
+    @Override
+    public void println(final int i) throws IOException {
+        this.stream.println(i);
+    }
+
+    @Override
+    public void println(final long l) throws IOException {
+        this.stream.println(l);
+    }
+
+    @Override
+    public void println(final float f) throws IOException {
+        this.stream.println(f);
+    }
+
+    @Override
+    public void println(final double d) throws IOException {
+        this.stream.println(d);
+    }
+
+    @Override
+    public boolean isReady() {
+        return this.stream.isReady();
+    }
+
+    @Override
+    public void setWriteListener(final WriteListener writeListener) {
+        this.stream.setWriteListener(new org.apache.felix.http.base.internal.javaxwrappers.WriteListenerWrapper(writeListener));
+    }
+
+    @Override
+    public void write(final int b) throws IOException {
+        this.stream.write(b);
+    }
+
+    @Override
+    public void write(final byte[] b) throws IOException {
+        this.stream.write(b);
+    }
+
+    @Override
+    public void write(final byte[] b, final int off, final int len) throws IOException {
+        this.stream.write(b, off, len);
+    }
+
+    @Override
+    public void flush() throws IOException {
+        this.stream.flush();
+    }
+
+    @Override
+    public void close() throws IOException {
+        this.stream.close();
+    }
+}
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/jakartawrappers/ServletRegistrationWrapper.java b/http/base/src/main/java/org/apache/felix/http/base/internal/jakartawrappers/ServletRegistrationWrapper.java
new file mode 100644
index 0000000..4381a73
--- /dev/null
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/jakartawrappers/ServletRegistrationWrapper.java
@@ -0,0 +1,86 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.felix.http.base.internal.jakartawrappers;
+
+import java.util.Collection;
+import java.util.Map;
+import java.util.Set;
+
+import org.jetbrains.annotations.NotNull;
+
+import jakarta.servlet.ServletRegistration;
+
+/**
+ * servlet registration wrapper
+ */
+public class ServletRegistrationWrapper implements ServletRegistration {
+
+    private final javax.servlet.ServletRegistration reg;
+
+    /**
+     * Create new wrapper
+     * @param c Wrapped registration
+     */
+    public ServletRegistrationWrapper(@NotNull final javax.servlet.ServletRegistration c) {
+        this.reg = c;
+    }
+
+    @Override
+    public Set<String> addMapping(final String... urlPatterns) {
+        return reg.addMapping(urlPatterns);
+    }
+
+    @Override
+    public String getName() {
+        return reg.getName();
+    }
+
+    @Override
+    public Collection<String> getMappings() {
+        return reg.getMappings();
+    }
+
+    @Override
+    public String getClassName() {
+        return reg.getClassName();
+    }
+
+    @Override
+    public boolean setInitParameter(final String name, final String value) {
+        return reg.setInitParameter(name, value);
+    }
+
+    @Override
+    public String getRunAsRole() {
+        return reg.getRunAsRole();
+    }
+
+    @Override
+    public String getInitParameter(final String name) {
+        return reg.getInitParameter(name);
+    }
+
+    @Override
+    public Set<String> setInitParameters(final Map<String, String> initParameters) {
+        return reg.setInitParameters(initParameters);
+    }
+
+    @Override
+    public Map<String, String> getInitParameters() {
+        return reg.getInitParameters();
+    }
+}
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/jakartawrappers/ServletRequestWrapper.java b/http/base/src/main/java/org/apache/felix/http/base/internal/jakartawrappers/ServletRequestWrapper.java
new file mode 100644
index 0000000..c787525
--- /dev/null
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/jakartawrappers/ServletRequestWrapper.java
@@ -0,0 +1,339 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.felix.http.base.internal.jakartawrappers;
+
+import static jakarta.servlet.RequestDispatcher.ERROR_EXCEPTION;
+import static jakarta.servlet.RequestDispatcher.ERROR_EXCEPTION_TYPE;
+import static jakarta.servlet.RequestDispatcher.ERROR_MESSAGE;
+import static jakarta.servlet.RequestDispatcher.ERROR_REQUEST_URI;
+import static jakarta.servlet.RequestDispatcher.ERROR_SERVLET_NAME;
+import static jakarta.servlet.RequestDispatcher.ERROR_STATUS_CODE;
+import static jakarta.servlet.RequestDispatcher.FORWARD_CONTEXT_PATH;
+import static jakarta.servlet.RequestDispatcher.FORWARD_PATH_INFO;
+import static jakarta.servlet.RequestDispatcher.FORWARD_QUERY_STRING;
+import static jakarta.servlet.RequestDispatcher.FORWARD_REQUEST_URI;
+import static jakarta.servlet.RequestDispatcher.FORWARD_SERVLET_PATH;
+import static jakarta.servlet.RequestDispatcher.INCLUDE_CONTEXT_PATH;
+import static jakarta.servlet.RequestDispatcher.INCLUDE_PATH_INFO;
+import static jakarta.servlet.RequestDispatcher.INCLUDE_QUERY_STRING;
+import static jakarta.servlet.RequestDispatcher.INCLUDE_REQUEST_URI;
+import static jakarta.servlet.RequestDispatcher.INCLUDE_SERVLET_PATH;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.util.Enumeration;
+import java.util.Locale;
+import java.util.Map;
+
+import org.jetbrains.annotations.NotNull;
+
+import jakarta.servlet.AsyncContext;
+import jakarta.servlet.DispatcherType;
+import jakarta.servlet.RequestDispatcher;
+import jakarta.servlet.ServletContext;
+import jakarta.servlet.ServletInputStream;
+import jakarta.servlet.ServletRequest;
+import jakarta.servlet.ServletResponse;
+
+/**
+ * Servlet request wrapper
+ */
+public class ServletRequestWrapper implements ServletRequest {
+
+    private final javax.servlet.ServletRequest request;
+
+    /**
+     * Get the wrapper
+     * @param r The request
+     * @return The wrapped request
+     */
+    public static ServletRequest getWrapper(final javax.servlet.ServletRequest r) {
+        if ( r instanceof org.apache.felix.http.base.internal.javaxwrappers.ServletRequestWrapper) {
+            return ((org.apache.felix.http.base.internal.javaxwrappers.ServletRequestWrapper)r).getRequest();
+        }
+        if ( r instanceof javax.servlet.http.HttpServletRequest ) {
+            return new HttpServletRequestWrapper((javax.servlet.http.HttpServletRequest)r);
+        }
+        return new ServletRequestWrapper(r);
+    }
+
+    /**
+     * Create a wrapper
+     * @param r The wrapped request
+     */
+    public ServletRequestWrapper(@NotNull final javax.servlet.ServletRequest r) {
+        this.request = r;
+    }
+
+
+    /**
+     * Get the request
+     * @return The request
+     */
+    public javax.servlet.ServletRequest getRequest() {
+        return this.request;
+    }
+
+    @Override
+    public Object getAttribute(final String name) {
+        if ( FORWARD_CONTEXT_PATH.equals(name) ) {
+            return this.request.getAttribute(javax.servlet.RequestDispatcher.FORWARD_CONTEXT_PATH);
+
+        } else if ( FORWARD_PATH_INFO.equals(name) ) {
+            return this.request.getAttribute(javax.servlet.RequestDispatcher.FORWARD_PATH_INFO);
+
+        } else if ( FORWARD_QUERY_STRING.equals(name) ) {
+            return this.request.getAttribute(javax.servlet.RequestDispatcher.FORWARD_QUERY_STRING);
+
+        } else if ( FORWARD_REQUEST_URI.equals(name) ) {
+            return this.request.getAttribute(javax.servlet.RequestDispatcher.FORWARD_REQUEST_URI);
+
+        } else if ( FORWARD_SERVLET_PATH.equals(name) ) {
+            return this.request.getAttribute(javax.servlet.RequestDispatcher.FORWARD_SERVLET_PATH);
+
+        } else if ( INCLUDE_CONTEXT_PATH.equals(name) ) {
+            return this.request.getAttribute(javax.servlet.RequestDispatcher.INCLUDE_CONTEXT_PATH);
+
+        } else if ( INCLUDE_PATH_INFO.equals(name) ) {
+            return this.request.getAttribute(javax.servlet.RequestDispatcher.INCLUDE_PATH_INFO);
+
+        } else if ( INCLUDE_QUERY_STRING.equals(name) ) {
+            return this.request.getAttribute(javax.servlet.RequestDispatcher.INCLUDE_QUERY_STRING);
+
+        } else if ( INCLUDE_REQUEST_URI.equals(name) ) {
+            return this.request.getAttribute(javax.servlet.RequestDispatcher.INCLUDE_REQUEST_URI);
+
+        } else if ( INCLUDE_SERVLET_PATH.equals(name) ) {
+            return this.request.getAttribute(javax.servlet.RequestDispatcher.INCLUDE_SERVLET_PATH);
+
+        } else if ( ERROR_EXCEPTION.equals(name) ) {
+            return this.request.getAttribute(javax.servlet.RequestDispatcher.ERROR_EXCEPTION);
+
+        } else if ( ERROR_EXCEPTION_TYPE.equals(name) ) {
+            return this.request.getAttribute(javax.servlet.RequestDispatcher.ERROR_EXCEPTION_TYPE);
+
+        } else if ( ERROR_MESSAGE.equals(name) ) {
+            return this.request.getAttribute(javax.servlet.RequestDispatcher.ERROR_MESSAGE);
+
+        } else if ( ERROR_REQUEST_URI.equals(name) ) {
+            return this.request.getAttribute(javax.servlet.RequestDispatcher.ERROR_REQUEST_URI);
+
+        } else if ( ERROR_SERVLET_NAME.equals(name) ) {
+            return this.request.getAttribute(javax.servlet.RequestDispatcher.ERROR_SERVLET_NAME);
+
+        } else if ( ERROR_STATUS_CODE.equals(name) ) {
+            return this.request.getAttribute(javax.servlet.RequestDispatcher.ERROR_STATUS_CODE);
+        }
+        return this.request.getAttribute(name);
+    }
+
+    @Override
+    public Enumeration<String> getAttributeNames() {
+        return this.request.getAttributeNames();
+    }
+
+    @Override
+    public String getCharacterEncoding() {
+        return this.request.getCharacterEncoding();
+    }
+
+    @Override
+    public void setCharacterEncoding(String env) throws UnsupportedEncodingException {
+        this.request.setCharacterEncoding(env);
+    }
+
+    @Override
+    public int getContentLength() {
+        return this.request.getContentLength();
+    }
+
+    @Override
+    public long getContentLengthLong() {
+        return this.request.getContentLengthLong();
+    }
+
+    @Override
+    public String getContentType() {
+        return this.request.getContentType();
+    }
+
+    @Override
+    public ServletInputStream getInputStream() throws IOException {
+        return new ServletInputStreamWrapper(this.request.getInputStream());
+    }
+
+    @Override
+    public String getParameter(String name) {
+        return this.request.getParameter(name);
+    }
+
+    @Override
+    public Enumeration<String> getParameterNames() {
+        return this.request.getParameterNames();
+    }
+
+    @Override
+    public String[] getParameterValues(final String name) {
+        return this.request.getParameterValues(name);
+    }
+
+    @Override
+    public Map<String, String[]> getParameterMap() {
+        return this.request.getParameterMap();
+    }
+
+    @Override
+    public String getProtocol() {
+        return this.request.getProtocol();
+    }
+
+    @Override
+    public String getScheme() {
+        return this.request.getScheme();
+    }
+
+    @Override
+    public String getServerName() {
+        return this.request.getServerName();
+    }
+
+    @Override
+    public int getServerPort() {
+        return this.request.getServerPort();
+    }
+
+    @Override
+    public BufferedReader getReader() throws IOException {
+        return this.request.getReader();
+    }
+
+    @Override
+    public String getRemoteAddr() {
+        return this.request.getRemoteAddr();
+    }
+
+    @Override
+    public String getRemoteHost() {
+        return this.request.getRemoteHost();
+    }
+
+    @Override
+    public void setAttribute(final String name, final Object o) {
+        this.request.setAttribute(name, o);
+    }
+
+    @Override
+    public void removeAttribute(final String name) {
+        this.request.removeAttribute(name);
+    }
+
+    @Override
+    public Locale getLocale() {
+        return this.request.getLocale();
+    }
+
+    @Override
+    public Enumeration<Locale> getLocales() {
+        return this.request.getLocales();
+    }
+
+    @Override
+    public boolean isSecure() {
+        return this.request.isSecure();
+    }
+
+    @Override
+    public RequestDispatcher getRequestDispatcher(final String path) {
+        final javax.servlet.RequestDispatcher dispatcher = this.request.getRequestDispatcher(path);
+        if ( dispatcher != null ) {
+            return new RequestDispatcherWrapper(dispatcher);
+        }
+        return null;
+    }
+
+    @SuppressWarnings("deprecation")
+    @Override
+    public String getRealPath(final String path) {
+        return this.request.getRealPath(path);
+    }
+
+    @Override
+    public int getRemotePort() {
+        return this.request.getRemotePort();
+    }
+
+    @Override
+    public String getLocalName() {
+        return this.request.getLocalName();
+    }
+
+    @Override
+    public String getLocalAddr() {
+        return this.request.getLocalAddr();
+    }
+
+    @Override
+    public int getLocalPort() {
+        return this.request.getLocalPort();
+    }
+
+    @Override
+    public ServletContext getServletContext() {
+        return new ServletContextWrapper(this.request.getServletContext());
+    }
+
+    @Override
+    public AsyncContext startAsync() throws IllegalStateException {
+        return new AsyncContextWrapper(this.request.startAsync());
+    }
+
+    @Override
+    public AsyncContext startAsync(ServletRequest servletRequest, ServletResponse servletResponse)
+            throws IllegalStateException {
+        return new AsyncContextWrapper(this.request.startAsync(
+                org.apache.felix.http.base.internal.javaxwrappers.ServletRequestWrapper.getWrapper(servletRequest),
+                org.apache.felix.http.base.internal.javaxwrappers.ServletResponseWrapper.getWrapper(servletResponse)));
+    }
+
+    @Override
+    public boolean isAsyncStarted() {
+        return this.request.isAsyncStarted();
+    }
+
+    @Override
+    public boolean isAsyncSupported() {
+        return this.request.isAsyncSupported();
+    }
+
+    @Override
+    public AsyncContext getAsyncContext() {
+        return new AsyncContextWrapper(this.request.getAsyncContext());
+    }
+
+    @Override
+    public DispatcherType getDispatcherType() {
+        switch (this.request.getDispatcherType()) {
+        case ASYNC : return DispatcherType.ASYNC;
+        case ERROR : return DispatcherType.ERROR;
+        case FORWARD : return DispatcherType.FORWARD;
+        case INCLUDE : return DispatcherType.INCLUDE;
+        case REQUEST : return DispatcherType.REQUEST;
+        }
+        return null;
+    }
+}
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/jakartawrappers/ServletResponseWrapper.java b/http/base/src/main/java/org/apache/felix/http/base/internal/jakartawrappers/ServletResponseWrapper.java
new file mode 100644
index 0000000..6778578
--- /dev/null
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/jakartawrappers/ServletResponseWrapper.java
@@ -0,0 +1,145 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.felix.http.base.internal.jakartawrappers;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.Locale;
+
+import org.jetbrains.annotations.NotNull;
+
+import jakarta.servlet.ServletOutputStream;
+import jakarta.servlet.ServletResponse;
+
+/**
+ * Servlet response wrapper
+ */
+public class ServletResponseWrapper implements ServletResponse {
+
+    private final javax.servlet.ServletResponse response;
+
+    /**
+     * Get a wrapper
+     * @param r Response
+     * @return Wrapped response
+     */
+    public static ServletResponse getWrapper(final javax.servlet.ServletResponse r) {
+        if ( r instanceof org.apache.felix.http.base.internal.javaxwrappers.ServletResponseWrapper) {
+            return ((org.apache.felix.http.base.internal.javaxwrappers.ServletResponseWrapper)r).getResponse();
+        }
+        if ( r instanceof javax.servlet.http.HttpServletResponse ) {
+            return new HttpServletResponseWrapper((javax.servlet.http.HttpServletResponse)r);
+        }
+        return new ServletResponseWrapper(r);
+    }
+
+    /**
+     * Create new response
+     * @param r Wrapped response
+     */
+    public ServletResponseWrapper(@NotNull final javax.servlet.ServletResponse r) {
+        this.response = r;
+    }
+
+    /**
+     * Get the wrapped response
+     * @return The response
+     */
+    public javax.servlet.ServletResponse getResponse() {
+        return this.response;
+    }
+
+    @Override
+    public String getCharacterEncoding() {
+        return this.response.getCharacterEncoding();
+    }
+
+    @Override
+    public String getContentType() {
+        return this.response.getContentType();
+    }
+
+    @Override
+    public ServletOutputStream getOutputStream() throws IOException {
+        return new ServletOutputStreamWrapper(this.response.getOutputStream());
+    }
+
+    @Override
+    public PrintWriter getWriter() throws IOException {
+        return this.response.getWriter();
+    }
+
+    @Override
+    public void setCharacterEncoding(final String charset) {
+        this.response.setCharacterEncoding(charset);
+    }
+
+    @Override
+    public void setContentLength(final int len) {
+        this.response.setContentLength(len);
+    }
+
+    @Override
+    public void setContentLengthLong(final long len) {
+        this.response.setContentLengthLong(len);
+    }
+
+    @Override
+    public void setContentType(final String type) {
+        this.response.setContentType(type);
+    }
+
+    @Override
+    public void setBufferSize(final int size) {
+        this.response.setBufferSize(size);
+    }
+
+    @Override
+    public int getBufferSize() {
+        return this.response.getBufferSize();
+    }
+
+    @Override
+    public void flushBuffer() throws IOException {
+        this.response.flushBuffer();
+    }
+
+    @Override
+    public void resetBuffer() {
+        this.response.resetBuffer();
+    }
+
+    @Override
+    public boolean isCommitted() {
+        return this.response.isCommitted();
+    }
+
+    @Override
+    public void reset() {
+        this.response.reset();
+    }
+
+    @Override
+    public void setLocale(final Locale loc) {
+        this.response.setLocale(loc);
+    }
+
+    @Override
+    public Locale getLocale() {
+        return this.response.getLocale();
+    }
+}
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/jakartawrappers/ServletWrapper.java b/http/base/src/main/java/org/apache/felix/http/base/internal/jakartawrappers/ServletWrapper.java
new file mode 100644
index 0000000..3c38b0b
--- /dev/null
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/jakartawrappers/ServletWrapper.java
@@ -0,0 +1,98 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.felix.http.base.internal.jakartawrappers;
+
+import java.io.IOException;
+
+import org.jetbrains.annotations.NotNull;
+
+import jakarta.servlet.Servlet;
+import jakarta.servlet.ServletConfig;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.ServletRequest;
+import jakarta.servlet.ServletResponse;
+
+/**
+ * Servlet wrapper
+ */
+public class ServletWrapper implements Servlet {
+
+    private final javax.servlet.Servlet servlet;
+
+    /**
+     * Get the registered servlet
+     * @param s The servlet
+     * @return The registered servlet
+     */
+    public static Servlet getRegisteredServlet(final javax.servlet.Servlet s) {
+        if ( s instanceof org.apache.felix.http.base.internal.javaxwrappers.ServletWrapper ) {
+            return ((org.apache.felix.http.base.internal.javaxwrappers.ServletWrapper)s).getServlet();
+        }
+        return new ServletWrapper(s);
+    }
+
+    /**
+     * Create new servlet
+     * @param servlet wrapped servlet
+     */
+    public ServletWrapper(@NotNull final javax.servlet.Servlet servlet) {
+        this.servlet = servlet;
+    }
+
+    @Override
+    public void init(final ServletConfig config) throws ServletException {
+        try {
+            servlet.init(new org.apache.felix.http.base.internal.javaxwrappers.ServletConfigWrapper(config));
+        } catch (javax.servlet.ServletException e) {
+            throw ServletExceptionUtil.getServletException(e);
+        }
+    }
+
+    @Override
+    public ServletConfig getServletConfig() {
+        return new ServletConfigWrapper(servlet.getServletConfig());
+    }
+
+    @Override
+    public void service(final ServletRequest req, final ServletResponse res)
+            throws ServletException, IOException {
+        try {
+            servlet.service(org.apache.felix.http.base.internal.javaxwrappers.ServletRequestWrapper.getWrapper(req),
+                    org.apache.felix.http.base.internal.javaxwrappers.ServletResponseWrapper.getWrapper(res));
+        } catch (javax.servlet.ServletException e) {
+            throw ServletExceptionUtil.getServletException(e);
+        }
+    }
+
+    @Override
+    public String getServletInfo() {
+        return servlet.getServletInfo();
+    }
+
+    @Override
+    public void destroy() {
+        servlet.destroy();
+    }
+
+    /**
+     * Get the wrapped servlet
+     * @return The servlet
+     */
+    public @NotNull javax.servlet.Servlet getServlet() {
+        return this.servlet;
+    }
+}
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/jakartawrappers/SessionCookieConfigWrapper.java b/http/base/src/main/java/org/apache/felix/http/base/internal/jakartawrappers/SessionCookieConfigWrapper.java
new file mode 100644
index 0000000..50f77dc
--- /dev/null
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/jakartawrappers/SessionCookieConfigWrapper.java
@@ -0,0 +1,107 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.felix.http.base.internal.jakartawrappers;
+
+import org.jetbrains.annotations.NotNull;
+
+import jakarta.servlet.SessionCookieConfig;
+
+/**
+ * Session cookie config wrapper
+ */
+public class SessionCookieConfigWrapper implements SessionCookieConfig {
+
+    private final javax.servlet.SessionCookieConfig config;
+
+    /**
+     * Create new config
+     * @param c Wrapped config
+     */
+    public SessionCookieConfigWrapper(@NotNull final javax.servlet.SessionCookieConfig c) {
+        this.config = c;
+    }
+
+    @Override
+    public void setName(String name) {
+        config.setName(name);
+    }
+
+    @Override
+    public String getName() {
+        return config.getName();
+    }
+
+    @Override
+    public void setDomain(final String domain) {
+        config.setDomain(domain);
+    }
+
+    @Override
+    public String getDomain() {
+        return config.getDomain();
+    }
+
+    @Override
+    public void setPath(final String path) {
+        config.setPath(path);
+    }
+
+    @Override
+    public String getPath() {
+        return config.getPath();
+    }
+
+    @Override
+    public void setComment(final String comment) {
+        config.setComment(comment);
+    }
+
+    @Override
+    public String getComment() {
+        return config.getComment();
+    }
+
+    @Override
+    public void setHttpOnly(final boolean httpOnly) {
+        config.setHttpOnly(httpOnly);
+    }
+
+    @Override
+    public boolean isHttpOnly() {
+        return config.isHttpOnly();
+    }
+
+    @Override
+    public void setSecure(final boolean secure) {
+        config.setSecure(secure);
+    }
+
+    @Override
+    public boolean isSecure() {
+        return config.isSecure();
+    }
+
+    @Override
+    public void setMaxAge(final int maxAge) {
+        config.setMaxAge(maxAge);
+    }
+
+    @Override
+    public int getMaxAge() {
+        return config.getMaxAge();
+    }
+}
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/service/DefaultHttpContext.java b/http/base/src/main/java/org/apache/felix/http/base/internal/jakartawrappers/WriteListenerWrapper.java
similarity index 51%
copy from http/base/src/main/java/org/apache/felix/http/base/internal/service/DefaultHttpContext.java
copy to http/base/src/main/java/org/apache/felix/http/base/internal/jakartawrappers/WriteListenerWrapper.java
index 22a048d..3f5d673 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/service/DefaultHttpContext.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/jakartawrappers/WriteListenerWrapper.java
@@ -14,40 +14,36 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.felix.http.base.internal.service;
-
-import org.osgi.service.http.HttpContext;
-import org.osgi.framework.Bundle;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import java.net.URL;
-
-public final class DefaultHttpContext 
-    implements HttpContext
-{
-    private Bundle bundle;
-
-    public DefaultHttpContext(Bundle bundle)
-    {
-        this.bundle = bundle;
-    }
+package org.apache.felix.http.base.internal.jakartawrappers;
 
-    public String getMimeType(String name)
-    {
-        return null;
-    }
+import java.io.IOException;
+
+import org.jetbrains.annotations.NotNull;
+
+import jakarta.servlet.WriteListener;
 
-    public URL getResource(String name)
-    {
-        if (name.startsWith("/")) {
-            name = name.substring(1);
-        }
+/**
+ * Write listener
+ */
+public class WriteListenerWrapper implements WriteListener {
+
+    private final javax.servlet.WriteListener listener;
+
+    /**
+     * Create new lister
+     * @param listener Wrapped listener
+     */
+    public WriteListenerWrapper(@NotNull final javax.servlet.WriteListener listener) {
+        this.listener = listener;
+    }
 
-        return this.bundle.getResource(name);
+    @Override
+    public void onWritePossible() throws IOException {
+        listener.onWritePossible();
     }
 
-    public boolean handleSecurity(HttpServletRequest req, HttpServletResponse res)
-    {
-        return true;
+    @Override
+    public void onError(final Throwable t) {
+        listener.onError(t);
     }
 }
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/javaxwrappers/AsyncContextWrapper.java b/http/base/src/main/java/org/apache/felix/http/base/internal/javaxwrappers/AsyncContextWrapper.java
new file mode 100644
index 0000000..470034e
--- /dev/null
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/javaxwrappers/AsyncContextWrapper.java
@@ -0,0 +1,104 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.felix.http.base.internal.javaxwrappers;
+
+import org.jetbrains.annotations.NotNull;
+
+import jakarta.servlet.AsyncContext;
+
+/**
+ * async context wrapper
+ */
+public class AsyncContextWrapper implements javax.servlet.AsyncContext {
+
+    private final AsyncContext context;
+
+    /**
+     * Create new context
+     * @param c Wrapped context
+     */
+    public AsyncContextWrapper(@NotNull final AsyncContext c) {
+        this.context = c;
+    }
+
+    @Override
+    public javax.servlet.ServletRequest getRequest() {
+        return ServletRequestWrapper.getWrapper(context.getRequest());
+    }
+
+    @Override
+    public javax.servlet.ServletResponse getResponse() {
+        return ServletResponseWrapper.getWrapper(context.getResponse());
+    }
+
+    @Override
+    public boolean hasOriginalRequestAndResponse() {
+        return context.hasOriginalRequestAndResponse();
+    }
+
+    @Override
+    public void dispatch() {
+        context.dispatch();
+    }
+
+    @Override
+    public void dispatch(final String path) {
+        context.dispatch(path);
+    }
+
+    @Override
+    public void dispatch(final javax.servlet.ServletContext sc, final String path) {
+        context.dispatch(new org.apache.felix.http.base.internal.jakartawrappers.ServletContextWrapper(sc), path);
+    }
+
+    @Override
+    public void complete() {
+        context.complete();
+    }
+
+    @Override
+    public void start(final Runnable run) {
+        context.start(run);
+    }
+
+    @Override
+    public void addListener(final javax.servlet.AsyncListener listener) {
+        context.addListener(new org.apache.felix.http.base.internal.jakartawrappers.AsyncListenerWrapper(listener));
+    }
+
+    @Override
+    public void addListener(final javax.servlet.AsyncListener listener, javax.servlet.ServletRequest servletRequest, javax.servlet.ServletResponse servletResponse) {
+        context.addListener(new org.apache.felix.http.base.internal.jakartawrappers.AsyncListenerWrapper(listener),
+                org.apache.felix.http.base.internal.jakartawrappers.ServletRequestWrapper.getWrapper(servletRequest),
+                org.apache.felix.http.base.internal.jakartawrappers.ServletResponseWrapper.getWrapper(servletResponse));
+    }
+
+    @Override
+    public <T extends javax.servlet.AsyncListener> T createListener(final Class<T> clazz) throws javax.servlet.ServletException {
+        throw new javax.servlet.ServletException();
+    }
+
+    @Override
+    public void setTimeout(final long timeout) {
+        context.setTimeout(timeout);
+    }
+
+    @Override
+    public long getTimeout() {
+        return context.getTimeout();
+    }
+}
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/javaxwrappers/AsyncListenerWrapper.java b/http/base/src/main/java/org/apache/felix/http/base/internal/javaxwrappers/AsyncListenerWrapper.java
new file mode 100644
index 0000000..d709bc4
--- /dev/null
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/javaxwrappers/AsyncListenerWrapper.java
@@ -0,0 +1,78 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.felix.http.base.internal.javaxwrappers;
+
+import java.io.IOException;
+
+import org.apache.felix.http.base.internal.jakartawrappers.ServletRequestWrapper;
+import org.apache.felix.http.base.internal.jakartawrappers.ServletResponseWrapper;
+import org.jetbrains.annotations.NotNull;
+
+import jakarta.servlet.AsyncEvent;
+import jakarta.servlet.AsyncListener;
+
+/**
+ * Async listener wrapper
+ */
+public class AsyncListenerWrapper implements javax.servlet.AsyncListener {
+
+    private final AsyncListener listener;
+
+    /**
+     * Create new listener
+     * @param c Wrapped listener
+     */
+    public AsyncListenerWrapper(@NotNull final AsyncListener c) {
+        this.listener = c;
+    }
+
+    @Override
+    public void onComplete(final javax.servlet.AsyncEvent event) throws IOException {
+        this.listener.onComplete(new AsyncEvent(
+                new org.apache.felix.http.base.internal.jakartawrappers.AsyncContextWrapper(event.getAsyncContext()),
+                ServletRequestWrapper.getWrapper(event.getSuppliedRequest()),
+                ServletResponseWrapper.getWrapper(event.getSuppliedResponse()),
+                event.getThrowable()));
+    }
+
+    @Override
+    public void onTimeout(final javax.servlet.AsyncEvent event) throws IOException {
+        this.listener.onTimeout(new AsyncEvent(
+                new org.apache.felix.http.base.internal.jakartawrappers.AsyncContextWrapper(event.getAsyncContext()),
+                ServletRequestWrapper.getWrapper(event.getSuppliedRequest()),
+                ServletResponseWrapper.getWrapper(event.getSuppliedResponse()),
+                event.getThrowable()));
+    }
+
+    @Override
+    public void onError(final javax.servlet.AsyncEvent event) throws IOException {
+        this.listener.onError(new AsyncEvent(
+                new org.apache.felix.http.base.internal.jakartawrappers.AsyncContextWrapper(event.getAsyncContext()),
+                ServletRequestWrapper.getWrapper(event.getSuppliedRequest()),
+                ServletResponseWrapper.getWrapper(event.getSuppliedResponse()),
+                event.getThrowable()));
+    }
+
+    @Override
+    public void onStartAsync(final javax.servlet.AsyncEvent event) throws IOException {
+        this.listener.onStartAsync(new AsyncEvent(
+                new org.apache.felix.http.base.internal.jakartawrappers.AsyncContextWrapper(event.getAsyncContext()),
+                ServletRequestWrapper.getWrapper(event.getSuppliedRequest()),
+                ServletResponseWrapper.getWrapper(event.getSuppliedResponse()),
+                event.getThrowable()));
+    }
+}
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/javaxwrappers/CookieWrapper.java b/http/base/src/main/java/org/apache/felix/http/base/internal/javaxwrappers/CookieWrapper.java
new file mode 100644
index 0000000..38db88d
--- /dev/null
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/javaxwrappers/CookieWrapper.java
@@ -0,0 +1,111 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.felix.http.base.internal.javaxwrappers;
+
+import org.jetbrains.annotations.NotNull;
+
+import jakarta.servlet.http.Cookie;
+
+/**
+ * Javax cookie based on a jakarta cookie
+ */
+public class CookieWrapper extends javax.servlet.http.Cookie {
+
+    private static final long serialVersionUID = -6762987885237379239L;
+
+    /**
+     * Wrap an array of cookies
+     * @param array The array
+     * @return The result
+     */
+    public static javax.servlet.http.Cookie[] wrap(final Cookie[] array) {
+        if ( array == null ) {
+            return null;
+        }
+        final javax.servlet.http.Cookie[] result = new javax.servlet.http.Cookie[array.length];
+        for(int i=0;i<array.length;i++) {
+            result[i] = new CookieWrapper(array[i]);
+        }
+        return result;
+    }
+
+    private final Cookie cookie;
+
+    /**
+     * Create new cookie
+     * @param c Wrapped cookie
+     */
+    public CookieWrapper(@NotNull final Cookie c) {
+        super(c.getName(), c.getValue());
+        this.cookie = c;
+        super.setComment(c.getComment());
+        super.setDomain(c.getDomain());
+        super.setHttpOnly(c.isHttpOnly());
+        super.setMaxAge(c.getMaxAge());
+        super.setPath(c.getPath());
+        super.setSecure(c.getSecure());
+        super.setVersion(c.getVersion());
+    }
+
+    @Override
+    public void setComment(final String purpose) {
+        this.cookie.setComment(purpose);
+        super.setComment(purpose);
+    }
+
+    @Override
+    public void setDomain(final String domain) {
+        this.cookie.setDomain(domain);
+        super.setDomain(domain);
+    }
+
+    @Override
+    public void setMaxAge(final int expiry) {
+        this.cookie.setMaxAge(expiry);
+        super.setMaxAge(expiry);
+    }
+
+    @Override
+    public void setPath(final String uri) {
+        this.cookie.setPath(uri);
+        super.setPath(uri);
+    }
+
+    @Override
+    public void setSecure(final boolean flag) {
+        this.cookie.setSecure(flag);
+        super.setSecure(flag);
+    }
+
+    @Override
+    public void setValue(final String newValue) {
+        this.cookie.setValue(newValue);
+        super.setValue(newValue);
+    }
+
+    @Override
+    public void setVersion(final int v) {
+        this.cookie.setVersion(v);
+        super.setVersion(v);
+    }
+
+    @Override
+    public void setHttpOnly(final boolean isHttpOnly) {
+        this.cookie.setHttpOnly(isHttpOnly);
+        super.setHttpOnly(isHttpOnly);
+    }
+}
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/javaxwrappers/FilterChainWrapper.java b/http/base/src/main/java/org/apache/felix/http/base/internal/javaxwrappers/FilterChainWrapper.java
new file mode 100644
index 0000000..2135bdf
--- /dev/null
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/javaxwrappers/FilterChainWrapper.java
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.felix.http.base.internal.javaxwrappers;
+
+import java.io.IOException;
+
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+
+import org.apache.felix.http.base.internal.jakartawrappers.ServletResponseWrapper;
+import org.jetbrains.annotations.NotNull;
+
+import jakarta.servlet.FilterChain;
+
+/**
+ * Javax filter chain based on a jakarta filter chain
+ */
+public class FilterChainWrapper implements javax.servlet.FilterChain {
+
+    private final FilterChain filterChain;
+
+    /**
+     * Create new chain
+     * @param chain Wrapped chain
+     */
+    public FilterChainWrapper(@NotNull final FilterChain chain) {
+        this.filterChain = chain;
+    }
+
+    @Override
+    public void doFilter(final ServletRequest request, final ServletResponse response) throws IOException, ServletException {
+        try {
+            filterChain.doFilter(org.apache.felix.http.base.internal.jakartawrappers.ServletRequestWrapper.getWrapper(request),
+                    ServletResponseWrapper.getWrapper(response));
+        } catch (final jakarta.servlet.ServletException e) {
+            throw ServletExceptionUtil.getServletException(e);
+        }
+    }
+}
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/javaxwrappers/FilterConfigWrapper.java b/http/base/src/main/java/org/apache/felix/http/base/internal/javaxwrappers/FilterConfigWrapper.java
new file mode 100644
index 0000000..c6ebe17
--- /dev/null
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/javaxwrappers/FilterConfigWrapper.java
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.felix.http.base.internal.javaxwrappers;
+
+import java.util.Enumeration;
+
+import org.jetbrains.annotations.NotNull;
+
+import jakarta.servlet.FilterConfig;
+
+/**
+ * Filter config wrapper
+ */
+public class FilterConfigWrapper implements javax.servlet.FilterConfig {
+
+    private final FilterConfig filterConfig;
+
+    /**
+     * Create config
+     * @param filterConfig wrapped config
+     */
+    public FilterConfigWrapper(@NotNull final FilterConfig filterConfig) {
+        this.filterConfig = filterConfig;
+    }
+
+    @Override
+    public String getFilterName() {
+        return this.filterConfig.getFilterName();
+    }
+
+    @Override
+    public javax.servlet.ServletContext getServletContext() {
+        return new ServletContextWrapper(this.filterConfig.getServletContext());
+    }
+
+    @Override
+    public String getInitParameter(final String name) {
+        return this.filterConfig.getInitParameter(name);
+    }
+
+    @Override
+    public Enumeration<String> getInitParameterNames() {
+        return this.filterConfig.getInitParameterNames();
+    }
+}
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/javaxwrappers/FilterRegistrationWrapper.java b/http/base/src/main/java/org/apache/felix/http/base/internal/javaxwrappers/FilterRegistrationWrapper.java
new file mode 100644
index 0000000..7535f5f
--- /dev/null
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/javaxwrappers/FilterRegistrationWrapper.java
@@ -0,0 +1,115 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.felix.http.base.internal.javaxwrappers;
+
+import java.util.Collection;
+import java.util.EnumSet;
+import java.util.Map;
+import java.util.Set;
+
+import org.jetbrains.annotations.NotNull;
+
+import jakarta.servlet.DispatcherType;
+import jakarta.servlet.FilterRegistration;
+
+/**
+ * Filter registration wrapper
+ */
+public class FilterRegistrationWrapper implements javax.servlet.FilterRegistration {
+
+    private final FilterRegistration reg;
+
+    /**
+     * Create new wrapper
+     * @param c Wrapped registration
+     */
+    public FilterRegistrationWrapper(@NotNull final FilterRegistration c) {
+        this.reg = c;
+    }
+
+    private EnumSet<DispatcherType> wrap(final EnumSet<javax.servlet.DispatcherType> dispatcherTypes) {
+        final EnumSet<DispatcherType> set = EnumSet.noneOf(DispatcherType.class);
+        if ( dispatcherTypes.contains(javax.servlet.DispatcherType.ASYNC)) {
+            set.add(DispatcherType.ASYNC);
+        }
+        if ( dispatcherTypes.contains(javax.servlet.DispatcherType.ERROR)) {
+            set.add(DispatcherType.ERROR);
+        }
+        if ( dispatcherTypes.contains(javax.servlet.DispatcherType.FORWARD)) {
+            set.add(DispatcherType.FORWARD);
+        }
+        if ( dispatcherTypes.contains(javax.servlet.DispatcherType.INCLUDE)) {
+            set.add(DispatcherType.INCLUDE);
+        }
+        if ( dispatcherTypes.contains(javax.servlet.DispatcherType.REQUEST)) {
+            set.add(DispatcherType.REQUEST);
+        }
+        return set;
+    }
+
+    @Override
+    public void addMappingForServletNames(final EnumSet<javax.servlet.DispatcherType> dispatcherTypes, final boolean isMatchAfter,
+            final String... servletNames) {
+        reg.addMappingForServletNames(wrap(dispatcherTypes), isMatchAfter, servletNames);
+    }
+
+    @Override
+    public String getName() {
+        return reg.getName();
+    }
+
+    @Override
+    public String getClassName() {
+        return reg.getClassName();
+    }
+
+    @Override
+    public boolean setInitParameter(final String name, final String value) {
+        return reg.setInitParameter(name, value);
+    }
+
+    @Override
+    public Collection<String> getServletNameMappings() {
+        return reg.getServletNameMappings();
+    }
+
+    @Override
+    public void addMappingForUrlPatterns(final EnumSet<javax.servlet.DispatcherType> dispatcherTypes, final boolean isMatchAfter,
+            final String... urlPatterns) {
+        reg.addMappingForUrlPatterns(wrap(dispatcherTypes), isMatchAfter, urlPatterns);
+    }
+
+    @Override
+    public String getInitParameter(final String name) {
+        return reg.getInitParameter(name);
+    }
+
+    @Override
+    public Set<String> setInitParameters(final Map<String, String> initParameters) {
+        return reg.setInitParameters(initParameters);
+    }
+
+    @Override
+    public Collection<String> getUrlPatternMappings() {
+        return reg.getUrlPatternMappings();
+    }
+
+    @Override
+    public Map<String, String> getInitParameters() {
+        return reg.getInitParameters();
+    }
+}
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/javaxwrappers/HttpServletRequestWrapper.java b/http/base/src/main/java/org/apache/felix/http/base/internal/javaxwrappers/HttpServletRequestWrapper.java
new file mode 100644
index 0000000..8d4e5ce
--- /dev/null
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/javaxwrappers/HttpServletRequestWrapper.java
@@ -0,0 +1,238 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.felix.http.base.internal.javaxwrappers;
+
+import java.io.IOException;
+import java.security.Principal;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Enumeration;
+import java.util.List;
+
+import org.jetbrains.annotations.NotNull;
+
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+import jakarta.servlet.http.HttpSession;
+import jakarta.servlet.http.Part;
+
+/**
+ * Http servlet request wrapper
+ */
+public class HttpServletRequestWrapper extends ServletRequestWrapper
+    implements javax.servlet.http.HttpServletRequest {
+
+    private final HttpServletRequest request;
+
+    /**
+     * Create new request
+     * @param r wrapped request
+     */
+    public HttpServletRequestWrapper(@NotNull final HttpServletRequest r) {
+        super(r);
+        this.request = r;
+    }
+
+    @Override
+    public String getAuthType() {
+        return this.request.getAuthType();
+    }
+
+    @Override
+    public javax.servlet.http.Cookie[] getCookies() {
+        return CookieWrapper.wrap(this.request.getCookies());
+    }
+
+    @Override
+    public long getDateHeader(final String name) {
+        return this.request.getDateHeader(name);
+    }
+
+    @Override
+    public String getHeader(final String name) {
+        return this.request.getHeader(name);
+    }
+
+    @Override
+    public Enumeration<String> getHeaders(final String name) {
+        return this.request.getHeaders(name);
+    }
+
+    @Override
+    public Enumeration<String> getHeaderNames() {
+        return this.request.getHeaderNames();
+    }
+
+    @Override
+    public int getIntHeader(final String name) {
+        return this.request.getIntHeader(name);
+    }
+
+    @Override
+    public String getMethod() {
+        return this.request.getMethod();
+    }
+
+    @Override
+    public String getPathInfo() {
+        return this.request.getPathInfo();
+    }
+
+    @Override
+    public String getPathTranslated() {
+        return this.request.getPathTranslated();
+    }
+
+    @Override
+    public String getContextPath() {
+        return this.request.getContextPath();
+    }
+
+    @Override
+    public String getQueryString() {
+        return this.request.getQueryString();
+    }
+
+    @Override
+    public String getRemoteUser() {
+        return this.request.getRemoteUser();
+    }
+
+    @Override
+    public boolean isUserInRole(final String role) {
+        return this.request.isUserInRole(role);
+    }
+
+    @Override
+    public Principal getUserPrincipal() {
+        return this.request.getUserPrincipal();
+    }
+
+    @Override
+    public String getRequestedSessionId() {
+        return this.request.getRequestedSessionId();
+    }
+
+    @Override
+    public String getRequestURI() {
+        return this.request.getRequestURI();
+    }
+
+    @Override
+    public StringBuffer getRequestURL() {
+        return this.request.getRequestURL();
+    }
+
+    @Override
+    public String getServletPath() {
+        return this.request.getServletPath();
+    }
+
+    @Override
+    public javax.servlet.http.HttpSession getSession(final boolean create) {
+        final HttpSession session = this.request.getSession(create);
+        if ( session != null ) {
+            return new HttpSessionWrapper(session);
+        }
+        return null;
+    }
+
+    @Override
+    public javax.servlet.http.HttpSession getSession() {
+        return new HttpSessionWrapper(this.request.getSession());
+    }
+
+    @Override
+    public String changeSessionId() {
+        return this.request.changeSessionId();
+    }
+
+    @Override
+    public boolean isRequestedSessionIdValid() {
+        return this.request.isRequestedSessionIdValid();
+    }
+
+    @Override
+    public boolean isRequestedSessionIdFromCookie() {
+        return this.request.isRequestedSessionIdFromCookie();
+    }
+
+    @Override
+    public boolean isRequestedSessionIdFromURL() {
+        return this.request.isRequestedSessionIdFromURL();
+    }
+
+    @SuppressWarnings("deprecation")
+    @Override
+    public boolean isRequestedSessionIdFromUrl() {
+        return this.request.isRequestedSessionIdFromUrl();
+    }
+
+    @Override
+    public boolean authenticate(final javax.servlet.http.HttpServletResponse response) throws IOException, javax.servlet.ServletException {
+        try {
+            return this.request.authenticate((HttpServletResponse)org.apache.felix.http.base.internal.jakartawrappers.ServletResponseWrapper.getWrapper(response));
+        } catch ( final jakarta.servlet.ServletException e ) {
+            throw ServletExceptionUtil.getServletException(e);
+        }
+    }
+
+    @Override
+    public void login(final String username, final String password) throws javax.servlet.ServletException {
+        try {
+            this.request.login(username, password);
+        } catch ( final jakarta.servlet.ServletException e ) {
+            throw ServletExceptionUtil.getServletException(e);
+        }
+    }
+
+    @Override
+    public void logout() throws javax.servlet.ServletException {
+        try {
+            this.request.logout();
+        } catch ( final jakarta.servlet.ServletException e ) {
+            throw ServletExceptionUtil.getServletException(e);
+        }
+    }
+
+    @Override
+    public Collection<javax.servlet.http.Part> getParts() throws IOException, javax.servlet.ServletException {
+        try {
+            final List<javax.servlet.http.Part> result = new ArrayList<>();
+            for(final Part p : this.request.getParts()) {
+                result.add(new PartWrapper(p));
+            }
+            return result;
+        } catch ( final jakarta.servlet.ServletException e ) {
+            throw ServletExceptionUtil.getServletException(e);
+        }
+    }
+
+    @Override
+    public javax.servlet.http.Part getPart(final String name) throws IOException, javax.servlet.ServletException {
+        try {
+            return new PartWrapper(this.request.getPart(name));
+        } catch ( final jakarta.servlet.ServletException e ) {
+            throw ServletExceptionUtil.getServletException(e);
+        }
+    }
+
+    @Override
+    public <T extends javax.servlet.http.HttpUpgradeHandler> T upgrade(final Class<T> handlerClass) throws IOException, javax.servlet.ServletException {
+        throw new UnsupportedOperationException();
+    }
+}
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/javaxwrappers/HttpServletResponseWrapper.java b/http/base/src/main/java/org/apache/felix/http/base/internal/javaxwrappers/HttpServletResponseWrapper.java
new file mode 100644
index 0000000..a22738c
--- /dev/null
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/javaxwrappers/HttpServletResponseWrapper.java
@@ -0,0 +1,151 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.felix.http.base.internal.javaxwrappers;
+
+import java.io.IOException;
+import java.util.Collection;
+
+import org.apache.felix.http.base.internal.jakartawrappers.CookieWrapper;
+import org.jetbrains.annotations.NotNull;
+
+import jakarta.servlet.http.HttpServletResponse;
+
+/**
+ * Http servlet response wrapper
+*/
+public class HttpServletResponseWrapper extends ServletResponseWrapper
+    implements javax.servlet.http.HttpServletResponse {
+
+    private final HttpServletResponse response;
+
+    /**
+     * Create a new response
+     * @param r Wrapped response
+     */
+    public HttpServletResponseWrapper(@NotNull final HttpServletResponse r) {
+        super(r);
+        this.response = r;
+    }
+
+    @Override
+    public void addCookie(final javax.servlet.http.Cookie cookie) {
+        this.response.addCookie(new CookieWrapper(cookie));
+    }
+
+    @Override
+    public boolean containsHeader(final String name) {
+        return this.response.containsHeader(name);
+    }
+
+    @Override
+    public String encodeURL(final String url) {
+        return this.response.encodeURL(url);
+    }
+
+    @Override
+    public String encodeRedirectURL(final String url) {
+        return this.response.encodeRedirectURL(url);
+    }
+
+    @SuppressWarnings("deprecation")
+    @Override
+    public String encodeUrl(final String url) {
+        return this.response.encodeUrl(url);
+    }
+
+    @SuppressWarnings("deprecation")
+    @Override
+    public String encodeRedirectUrl(final String url) {
+        return this.response.encodeRedirectUrl(url);
+    }
+
+    @Override
+    public void sendError(final int sc, final String msg) throws IOException {
+        this.response.sendError(sc, msg);
+    }
+
+    @Override
+    public void sendError(final int sc) throws IOException {
+        this.response.sendError(sc);
+    }
+
+    @Override
+    public void sendRedirect(final String location) throws IOException {
+        this.response.sendRedirect(location);
+    }
+
+    @Override
+    public void setDateHeader(final String name, final long date) {
+        this.response.setDateHeader(name, date);
+    }
+
+    @Override
+    public void addDateHeader(final String name, final long date) {
+        this.response.addDateHeader(name, date);
+    }
+
+    @Override
+    public void setHeader(final String name, final String value) {
+        this.response.setHeader(name, value);
+    }
+
+    @Override
+    public void addHeader(final String name, final String value) {
+        this.response.addHeader(name, value);
+    }
+
+    @Override
+    public void setIntHeader(final String name, final int value) {
+        this.response.setIntHeader(name, value);
+    }
+
+    @Override
+    public void addIntHeader(final String name, final int value) {
+        this.response.addIntHeader(name, value);
+    }
+
+    @Override
+    public void setStatus(int sc) {
+        this.response.setStatus(sc);
+    }
+
+    @SuppressWarnings("deprecation")
+    @Override
+    public void setStatus(final int sc, final String sm) {
+        this.response.setStatus(sc, sm);
+    }
+
+    @Override
+    public int getStatus() {
+        return this.response.getStatus();
+    }
+
+    @Override
+    public String getHeader(final String name) {
+        return this.response.getHeader(name);
+    }
+
+    @Override
+    public Collection<String> getHeaders(final String name) {
+        return this.response.getHeaders(name);
+    }
+
+    @Override
+    public Collection<String> getHeaderNames() {
+        return this.response.getHeaderNames();
+    }
+}
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/javaxwrappers/HttpSessionContextWrapper.java b/http/base/src/main/java/org/apache/felix/http/base/internal/javaxwrappers/HttpSessionContextWrapper.java
new file mode 100644
index 0000000..b54a369
--- /dev/null
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/javaxwrappers/HttpSessionContextWrapper.java
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.felix.http.base.internal.javaxwrappers;
+
+import java.util.Enumeration;
+
+import org.jetbrains.annotations.NotNull;
+
+import jakarta.servlet.http.HttpSession;
+import jakarta.servlet.http.HttpSessionContext;
+
+/**
+ * http session context wrapper
+ */
+@SuppressWarnings("deprecation")
+public class HttpSessionContextWrapper implements javax.servlet.http.HttpSessionContext {
+
+    private final HttpSessionContext context;
+
+    /**
+     * Create new context
+     * @param c Wrapped context
+     */
+    public HttpSessionContextWrapper(@NotNull final HttpSessionContext c) {
+        this.context = c;
+    }
+
+    @Override
+    public javax.servlet.http.HttpSession getSession(final String sessionId) {
+        final HttpSession session = context.getSession(sessionId);
+        if ( session != null ) {
+            return new HttpSessionWrapper(session);
+        }
+        return null;
+    }
+
+    @Override
+    public Enumeration<String> getIds() {
+        return context.getIds();
+    }
+}
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/javaxwrappers/HttpSessionWrapper.java b/http/base/src/main/java/org/apache/felix/http/base/internal/javaxwrappers/HttpSessionWrapper.java
new file mode 100644
index 0000000..06412d3
--- /dev/null
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/javaxwrappers/HttpSessionWrapper.java
@@ -0,0 +1,130 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.felix.http.base.internal.javaxwrappers;
+
+import java.util.Enumeration;
+
+import org.jetbrains.annotations.NotNull;
+
+import jakarta.servlet.http.HttpSession;
+
+/**
+ * Http session wrapper
+ */
+public class HttpSessionWrapper implements javax.servlet.http.HttpSession {
+
+    private final HttpSession session;
+
+    /**
+     * Create new session
+     * @param session Wrapped session
+     */
+    public HttpSessionWrapper(@NotNull final HttpSession session) {
+        this.session = session;
+    }
+
+
+    @Override
+    public long getCreationTime() {
+        return session.getCreationTime();
+    }
+
+    @Override
+    public String getId() {
+        return session.getId();
+    }
+
+    @Override
+    public long getLastAccessedTime() {
+        return session.getLastAccessedTime();
+    }
+
+    @Override
+    public javax.servlet.ServletContext getServletContext() {
+        return new ServletContextWrapper(session.getServletContext());
+    }
+
+    @Override
+    public void setMaxInactiveInterval(int interval) {
+        session.setMaxInactiveInterval(interval);
+    }
+
+    @Override
+    public int getMaxInactiveInterval() {
+        return session.getMaxInactiveInterval();
+    }
+
+    @SuppressWarnings("deprecation")
+    @Override
+    public javax.servlet.http.HttpSessionContext getSessionContext() {
+        return new HttpSessionContextWrapper(session.getSessionContext());
+    }
+
+    @Override
+    public Object getAttribute(String name) {
+        return session.getAttribute(name);
+    }
+
+    @SuppressWarnings("deprecation")
+    @Override
+    public Object getValue(String name) {
+        return session.getValue(name);
+    }
+
+    @Override
+    public Enumeration<String> getAttributeNames() {
+        return session.getAttributeNames();
+    }
+
+    @SuppressWarnings("deprecation")
+    @Override
+    public String[] getValueNames() {
+        return session.getValueNames();
+    }
+
+    @Override
+    public void setAttribute(String name, Object value) {
+        session.setAttribute(name, value);
+    }
+
+    @SuppressWarnings("deprecation")
+    @Override
+    public void putValue(String name, Object value) {
+        session.putValue(name, value);
+    }
+
+    @Override
+    public void removeAttribute(String name) {
+        session.removeAttribute(name);
+    }
+
+    @SuppressWarnings("deprecation")
+    @Override
+    public void removeValue(String name) {
+        session.removeValue(name);
+    }
+
+    @Override
+    public void invalidate() {
+        session.invalidate();
+    }
+
+    @Override
+    public boolean isNew() {
+        return session.isNew();
+    }
+}
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/javaxwrappers/PartWrapper.java b/http/base/src/main/java/org/apache/felix/http/base/internal/javaxwrappers/PartWrapper.java
new file mode 100644
index 0000000..2d91b90
--- /dev/null
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/javaxwrappers/PartWrapper.java
@@ -0,0 +1,91 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.felix.http.base.internal.javaxwrappers;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Collection;
+
+import org.jetbrains.annotations.NotNull;
+
+import jakarta.servlet.http.Part;
+
+/**
+ * Part wrapper
+ */
+public class PartWrapper implements javax.servlet.http.Part {
+
+    private final Part part;
+
+    /**
+     * Create new part
+     * @param p Wrapped part
+     */
+    public PartWrapper(@NotNull final Part p) {
+        this.part = p;
+    }
+
+    @Override
+    public InputStream getInputStream() throws IOException {
+        return this.part.getInputStream();
+    }
+
+    @Override
+    public String getContentType() {
+        return this.part.getContentType();
+    }
+
+    @Override
+    public String getName() {
+        return this.part.getName();
+    }
+
+    @Override
+    public String getSubmittedFileName() {
+        return this.part.getSubmittedFileName();
+    }
+
+    @Override
+    public long getSize() {
+        return this.part.getSize();
+    }
+
+    @Override
+    public void write(String fileName) throws IOException {
+        this.part.write(fileName);
+    }
+
+    @Override
+    public void delete() throws IOException {
+        this.part.delete();
+    }
+
+    @Override
+    public String getHeader(final String name) {
+        return this.part.getHeader(name);
+    }
+
+    @Override
+    public Collection<String> getHeaders(final String name) {
+        return this.part.getHeaders(name);
+    }
+
+    @Override
+    public Collection<String> getHeaderNames() {
+        return this.part.getHeaderNames();
+    }
+}
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/service/DefaultHttpContext.java b/http/base/src/main/java/org/apache/felix/http/base/internal/javaxwrappers/ReadListenerWrapper.java
similarity index 51%
copy from http/base/src/main/java/org/apache/felix/http/base/internal/service/DefaultHttpContext.java
copy to http/base/src/main/java/org/apache/felix/http/base/internal/javaxwrappers/ReadListenerWrapper.java
index 22a048d..7973a1b 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/service/DefaultHttpContext.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/javaxwrappers/ReadListenerWrapper.java
@@ -14,40 +14,42 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.felix.http.base.internal.service;
-
-import org.osgi.service.http.HttpContext;
-import org.osgi.framework.Bundle;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import java.net.URL;
-
-public final class DefaultHttpContext 
-    implements HttpContext
-{
-    private Bundle bundle;
-
-    public DefaultHttpContext(Bundle bundle)
-    {
-        this.bundle = bundle;
-    }
+package org.apache.felix.http.base.internal.javaxwrappers;
+
+import java.io.IOException;
+
+import org.jetbrains.annotations.NotNull;
 
-    public String getMimeType(String name)
-    {
-        return null;
+import jakarta.servlet.ReadListener;
+
+/**
+ * Read listener
+ */
+public class ReadListenerWrapper implements javax.servlet.ReadListener {
+
+    private final ReadListener listener;
+
+    /**
+     * Create new lister
+     * @param listener Wrapped listener
+     */
+    public ReadListenerWrapper(@NotNull final ReadListener listener) {
+        this.listener = listener;
     }
 
-    public URL getResource(String name)
-    {
-        if (name.startsWith("/")) {
-            name = name.substring(1);
-        }
+    @Override
+    public void onDataAvailable() throws IOException {
+        listener.onDataAvailable();
+    }
 
-        return this.bundle.getResource(name);
+    @Override
+    public void onAllDataRead() throws IOException {
+        listener.onAllDataRead();
     }
 
-    public boolean handleSecurity(HttpServletRequest req, HttpServletResponse res)
-    {
-        return true;
+    @Override
+    public void onError(Throwable t) {
+        listener.onError(t);
     }
+
 }
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/javaxwrappers/RequestDispatcherWrapper.java b/http/base/src/main/java/org/apache/felix/http/base/internal/javaxwrappers/RequestDispatcherWrapper.java
new file mode 100644
index 0000000..53af761
--- /dev/null
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/javaxwrappers/RequestDispatcherWrapper.java
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.felix.http.base.internal.javaxwrappers;
+
+import java.io.IOException;
+
+import org.jetbrains.annotations.NotNull;
+
+import jakarta.servlet.RequestDispatcher;
+import jakarta.servlet.ServletException;
+
+/**
+ * Dispatcher wrapper
+ */
+public class RequestDispatcherWrapper implements javax.servlet.RequestDispatcher {
+
+    private final RequestDispatcher dispatcher;
+
+    /**
+     * Create new dispatcher
+     * @param dispatcher Dispatcher
+     */
+    public RequestDispatcherWrapper(@NotNull RequestDispatcher dispatcher) {
+        this.dispatcher = dispatcher;
+    }
+
+    @Override
+    public void forward(final javax.servlet.ServletRequest request, final javax.servlet.ServletResponse response) throws javax.servlet.ServletException, IOException {
+        try {
+            dispatcher.forward(org.apache.felix.http.base.internal.jakartawrappers.ServletRequestWrapper.getWrapper(request),
+                    org.apache.felix.http.base.internal.jakartawrappers.ServletResponseWrapper.getWrapper(response));
+        } catch (final ServletException e) {
+            throw ServletExceptionUtil.getServletException(e);
+        }
+    }
+
+    @Override
+    public void include(final javax.servlet.ServletRequest request, final javax.servlet.ServletResponse response) throws javax.servlet.ServletException, IOException {
+        try {
+            dispatcher.include(org.apache.felix.http.base.internal.jakartawrappers.ServletRequestWrapper.getWrapper(request),
+                    org.apache.felix.http.base.internal.jakartawrappers.ServletResponseWrapper.getWrapper(response));
+        } catch (final ServletException e) {
+            throw ServletExceptionUtil.getServletException(e);
+        }
+    }
+
+}
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/javaxwrappers/ServletConfigWrapper.java b/http/base/src/main/java/org/apache/felix/http/base/internal/javaxwrappers/ServletConfigWrapper.java
new file mode 100644
index 0000000..ab428f8
--- /dev/null
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/javaxwrappers/ServletConfigWrapper.java
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.felix.http.base.internal.javaxwrappers;
+
+import java.util.Enumeration;
+
+import org.jetbrains.annotations.NotNull;
+
+import jakarta.servlet.ServletConfig;
+
+/**
+ * Servlet config wrapper
+ */
+public class ServletConfigWrapper implements javax.servlet.ServletConfig {
+
+    private final ServletConfig config;
+
+    /**
+     * Create new servlet config
+     * @param config wrapped servlet config
+     */
+    public ServletConfigWrapper(@NotNull final ServletConfig config) {
+        this.config = config;
+    }
+
+    @Override
+    public String getServletName() {
+        return config.getServletName();
+    }
+
+    @Override
+    public javax.servlet.ServletContext getServletContext() {
+        return new ServletContextWrapper(config.getServletContext());
+    }
+
+    @Override
+    public String getInitParameter(final String name) {
+        return config.getInitParameter(name);
+    }
+
+    @Override
+    public Enumeration<String> getInitParameterNames() {
+        return config.getInitParameterNames();
+    }
+}
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/javaxwrappers/ServletContextWrapper.java b/http/base/src/main/java/org/apache/felix/http/base/internal/javaxwrappers/ServletContextWrapper.java
new file mode 100644
index 0000000..21a9585
--- /dev/null
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/javaxwrappers/ServletContextWrapper.java
@@ -0,0 +1,416 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.felix.http.base.internal.javaxwrappers;
+
+import java.io.InputStream;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.EventListener;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import org.jetbrains.annotations.NotNull;
+
+import jakarta.servlet.FilterRegistration;
+import jakarta.servlet.RequestDispatcher;
+import jakarta.servlet.ServletContext;
+import jakarta.servlet.ServletRegistration;
+import jakarta.servlet.SessionTrackingMode;
+
+/**
+ * Javax servlet context based on a jakarta servlet context
+ */
+public class ServletContextWrapper implements javax.servlet.ServletContext {
+
+    private final ServletContext context;
+
+    /**
+     * Create new context
+     * @param c Wrapped context
+     */
+    public ServletContextWrapper(@NotNull final ServletContext c) {
+        this.context = c;
+    }
+
+    @Override
+    public String getContextPath() {
+        return this.context.getContextPath();
+    }
+
+    @Override
+    public javax.servlet.ServletContext getContext(final String uripath) {
+        final ServletContext c = this.context.getContext(uripath);
+        if ( c != null ) {
+            return new ServletContextWrapper(c);
+        }
+        return null;
+    }
+
+    @Override
+    public int getMajorVersion() {
+        return this.context.getMajorVersion();
+    }
+
+    @Override
+    public int getMinorVersion() {
+        return this.context.getMinorVersion();
+    }
+
+    @Override
+    public int getEffectiveMajorVersion() {
+        return this.context.getEffectiveMajorVersion();
+    }
+
+    @Override
+    public int getEffectiveMinorVersion() {
+        return this.context.getEffectiveMinorVersion();
+    }
+
+    @Override
+    public String getMimeType(final String file) {
+        return this.context.getMimeType(file);
+    }
+
+    @Override
+    public Set<String> getResourcePaths(final String path) {
+        return this.context.getResourcePaths(path);
+    }
+
+    @Override
+    public URL getResource(final String path) throws MalformedURLException {
+        return this.context.getResource(path);
+    }
+
+    @Override
+    public InputStream getResourceAsStream(final String path) {
+        return this.context.getResourceAsStream(path);
+    }
+
+    @Override
+    public javax.servlet.RequestDispatcher getRequestDispatcher(final String path) {
+        final RequestDispatcher dispatcher = this.context.getRequestDispatcher(path);
+        if ( dispatcher != null ) {
+            return new RequestDispatcherWrapper(dispatcher);
+        }
+        return null;
+
+    }
+
+    @Override
+    public javax.servlet.RequestDispatcher getNamedDispatcher(final String name) {
+        final RequestDispatcher dispatcher = this.context.getNamedDispatcher(name);
+        if ( dispatcher != null ) {
+            return new RequestDispatcherWrapper(dispatcher);
+        }
+        return null;
+    }
+
+    @Override
+    public javax.servlet.Servlet getServlet(final String name) throws javax.servlet.ServletException {
+        return null;
+    }
+
+    @Override
+    public Enumeration<javax.servlet.Servlet> getServlets() {
+        return Collections.emptyEnumeration();
+    }
+
+    @SuppressWarnings("deprecation")
+    @Override
+    public Enumeration<String> getServletNames() {
+        return this.context.getServletNames();
+    }
+
+    @Override
+    public void log(final String msg) {
+        this.context.log(msg);
+    }
+
+    @SuppressWarnings("deprecation")
+    @Override
+    public void log(final Exception exception, final String msg) {
+        this.context.log(exception, msg);
+    }
+
+    @Override
+    public void log(final String message, final Throwable throwable) {
+        this.context.log(message, throwable);
+    }
+
+    @Override
+    public String getRealPath(final String path) {
+        return this.context.getRealPath(path);
+    }
+
+    @Override
+    public String getServerInfo() {
+        return this.context.getServerInfo();
+    }
+
+    @Override
+    public String getInitParameter(final String name) {
+        return this.context.getInitParameter(name);
+    }
+
+    @Override
+    public Enumeration<String> getInitParameterNames() {
+        return this.context.getInitParameterNames();
+    }
+
+    @Override
+    public boolean setInitParameter(final String name, final String value) {
+        return this.context.setInitParameter(name, value);
+    }
+
+    @Override
+    public Object getAttribute(final String name) {
+        return this.context.getAttribute(name);
+    }
+
+    @Override
+    public Enumeration<String> getAttributeNames() {
+        return this.context.getAttributeNames();
+    }
+
+    @Override
+    public void setAttribute(final String name, final Object object) {
+        this.context.setAttribute(name, object);
+    }
+
+    @Override
+    public void removeAttribute(final String name) {
+        this.context.removeAttribute(name);
+    }
+
+    @Override
+    public String getServletContextName() {
+        return this.context.getServletContextName();
+    }
+
+    @Override
+    public javax.servlet.ServletRegistration.Dynamic addServlet(final String servletName, final String className) {
+        throw new IllegalStateException();
+    }
+
+    @Override
+    public javax.servlet.ServletRegistration.Dynamic addServlet(final String servletName, final javax.servlet.Servlet servlet) {
+        throw new IllegalStateException();
+    }
+
+    @Override
+    public javax.servlet.ServletRegistration.Dynamic addServlet(final String servletName, final Class<? extends javax.servlet.Servlet> servletClass) {
+        throw new IllegalStateException();
+    }
+
+    @Override
+    public <T extends javax.servlet.Servlet> T createServlet(final Class<T> clazz) throws javax.servlet.ServletException {
+        throw new IllegalStateException();
+    }
+
+    @Override
+    public javax.servlet.ServletRegistration getServletRegistration(final String servletName) {
+        final ServletRegistration reg = this.context.getServletRegistration(servletName);
+        if ( reg != null ) {
+            return new ServletRegistrationWrapper(reg);
+        }
+        return null;
+    }
+
+    @SuppressWarnings({ "rawtypes", "unchecked" })
+    @Override
+    public Map<String, ? extends javax.servlet.ServletRegistration> getServletRegistrations() {
+        final Map result = new HashMap<>();
+        for(final Map.Entry<String, ? extends ServletRegistration> e : this.context.getServletRegistrations().entrySet()) {
+            result.put(e.getKey(), new ServletRegistrationWrapper(e.getValue()));
+        }
+        return result;
+    }
+
+    @Override
+    public javax.servlet.FilterRegistration.Dynamic addFilter(final String filterName, final String className) {
+        throw new IllegalStateException();
+    }
+
+    @Override
+    public javax.servlet.FilterRegistration.Dynamic addFilter(final String filterName, final javax.servlet.Filter filter) {
+        throw new IllegalStateException();
+    }
+
+    @Override
+    public javax.servlet.FilterRegistration.Dynamic addFilter(final String filterName, final Class<? extends javax.servlet.Filter> filterClass) {
+        throw new IllegalStateException();
+    }
+
+    @Override
+    public <T extends javax.servlet.Filter> T createFilter(final Class<T> clazz) throws javax.servlet.ServletException {
+        throw new IllegalStateException();
+    }
+
+    @Override
+    public javax.servlet.FilterRegistration getFilterRegistration(final String filterName) {
+        final FilterRegistration reg = this.context.getFilterRegistration(filterName);
+        if ( reg != null ) {
+            return new FilterRegistrationWrapper(reg);
+        }
+        return null;
+    }
+
+    @SuppressWarnings({ "rawtypes", "unchecked" })
+    @Override
+    public Map<String, ? extends javax.servlet.FilterRegistration> getFilterRegistrations() {
+        final Map result = new HashMap<>();
+        for(final Map.Entry<String, ? extends FilterRegistration> e : this.context.getFilterRegistrations().entrySet()) {
+            result.put(e.getKey(), new FilterRegistrationWrapper(e.getValue()));
+        }
+        return result;
+    }
+
+    @Override
+    public javax.servlet.SessionCookieConfig getSessionCookieConfig() {
+        return new SessionCookieConfigWrapper(this.context.getSessionCookieConfig());
+    }
+
+    @Override
+    public void setSessionTrackingModes(final Set<javax.servlet.SessionTrackingMode> sessionTrackingModes) {
+        if ( sessionTrackingModes == null ) {
+            this.context.setSessionTrackingModes(null);
+        } else {
+            final Set<SessionTrackingMode> modes = new HashSet<>();
+            if ( sessionTrackingModes.contains(javax.servlet.SessionTrackingMode.COOKIE)) {
+                modes.add(SessionTrackingMode.COOKIE);
+            }
+            if ( sessionTrackingModes.contains(javax.servlet.SessionTrackingMode.SSL)) {
+                modes.add(SessionTrackingMode.SSL);
+            }
+            if ( sessionTrackingModes.contains(javax.servlet.SessionTrackingMode.URL)) {
+                modes.add(SessionTrackingMode.URL);
+            }
+            this.context.setSessionTrackingModes(modes);
+        }
+    }
+
+    @Override
+    public Set<javax.servlet.SessionTrackingMode> getDefaultSessionTrackingModes() {
+        final Set<SessionTrackingMode> sessionTrackingModes = this.context.getDefaultSessionTrackingModes();
+        final Set<javax.servlet.SessionTrackingMode> modes = new HashSet<>();
+        if ( sessionTrackingModes.contains(SessionTrackingMode.COOKIE)) {
+            modes.add(javax.servlet.SessionTrackingMode.COOKIE);
+        }
+        if ( sessionTrackingModes.contains(SessionTrackingMode.SSL)) {
+            modes.add(javax.servlet.SessionTrackingMode.SSL);
+        }
+        if ( sessionTrackingModes.contains(SessionTrackingMode.URL)) {
+            modes.add(javax.servlet.SessionTrackingMode.URL);
+        }
+        return modes;
+    }
+
+    @Override
+    public Set<javax.servlet.SessionTrackingMode> getEffectiveSessionTrackingModes() {
+        final Set<SessionTrackingMode> sessionTrackingModes = this.context.getEffectiveSessionTrackingModes();
+        final Set<javax.servlet.SessionTrackingMode> modes = new HashSet<>();
+        if ( sessionTrackingModes.contains(SessionTrackingMode.COOKIE)) {
+            modes.add(javax.servlet.SessionTrackingMode.COOKIE);
+        }
+        if ( sessionTrackingModes.contains(SessionTrackingMode.SSL)) {
+            modes.add(javax.servlet.SessionTrackingMode.SSL);
+        }
+        if ( sessionTrackingModes.contains(SessionTrackingMode.URL)) {
+            modes.add(javax.servlet.SessionTrackingMode.URL);
+        }
+        return modes;
+    }
+
+    @Override
+    public void addListener(String className) {
+        throw new IllegalStateException();
+    }
+
+    @Override
+    public <T extends EventListener> void addListener(final T t) {
+        throw new IllegalStateException();
+    }
+
+    @Override
+    public void addListener(final Class<? extends EventListener> listenerClass) {
+        throw new IllegalStateException();
+    }
+
+    @Override
+    public <T extends EventListener> T createListener(final Class<T> clazz) throws javax.servlet.ServletException {
+        throw new IllegalStateException();
+    }
+
+    @Override
+    public javax.servlet.descriptor.JspConfigDescriptor getJspConfigDescriptor() {
+        return null;
+    }
+
+    @Override
+    public ClassLoader getClassLoader() {
+        return this.context.getClassLoader();
+    }
+
+    @Override
+    public void declareRoles(final String... roleNames) {
+        this.context.declareRoles(roleNames);
+    }
+
+    @Override
+    public String getVirtualServerName() {
+        return this.context.getVirtualServerName();
+    }
+
+    @Override
+    public javax.servlet.ServletRegistration.Dynamic addJspFile(final String servletName, final String jspFile) {
+        throw new IllegalStateException();
+    }
+
+    @Override
+    public int getSessionTimeout() {
+        return this.context.getSessionTimeout();
+    }
+
+    @Override
+    public void setSessionTimeout(int sessionTimeout) {
+        this.context.setSessionTimeout(sessionTimeout);
+    }
+
+    @Override
+    public String getRequestCharacterEncoding() {
+        return this.context.getRequestCharacterEncoding();
+    }
+
+    @Override
+    public void setRequestCharacterEncoding(final String encoding) {
+        this.context.setRequestCharacterEncoding(encoding);
+    }
+
+    @Override
+    public String getResponseCharacterEncoding() {
+        return this.context.getResponseCharacterEncoding();
+    }
+
+    @Override
+    public void setResponseCharacterEncoding(final String encoding) {
+        this.context.setResponseCharacterEncoding(encoding);
+    }
+}
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/javaxwrappers/ServletExceptionUtil.java b/http/base/src/main/java/org/apache/felix/http/base/internal/javaxwrappers/ServletExceptionUtil.java
new file mode 100644
index 0000000..b7ac31d
--- /dev/null
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/javaxwrappers/ServletExceptionUtil.java
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.felix.http.base.internal.javaxwrappers;
+
+import org.jetbrains.annotations.NotNull;
+
+import jakarta.servlet.ServletException;
+import jakarta.servlet.UnavailableException;
+
+/**
+ * Helper class to wrap servlet exceptions
+ */
+public class ServletExceptionUtil {
+
+    /**
+     * Get javax servlet exception
+     * @param e Jakarta exception
+     * @return The exception
+     */
+    public static javax.servlet.ServletException getServletException(@NotNull final ServletException e) {
+        if ( e instanceof UnavailableException ) {
+            final javax.servlet.UnavailableException t = new javax.servlet.UnavailableException(e.getMessage(), ((UnavailableException)e).getUnavailableSeconds());
+            if ( e.getCause() != null ) {
+                t.initCause(e.getCause());
+            }
+            return t;
+        }
+        if ( e.getCause() instanceof javax.servlet.ServletException ) {
+            return (javax.servlet.ServletException)e.getCause();
+        }
+        final javax.servlet.ServletException ne = new javax.servlet.ServletException(e.getMessage(), e.getCause());
+        ne.setStackTrace(e.getStackTrace());
+        return ne;
+    }
+
+}
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/javaxwrappers/ServletInputStreamWrapper.java b/http/base/src/main/java/org/apache/felix/http/base/internal/javaxwrappers/ServletInputStreamWrapper.java
new file mode 100644
index 0000000..45356cd
--- /dev/null
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/javaxwrappers/ServletInputStreamWrapper.java
@@ -0,0 +1,128 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.felix.http.base.internal.javaxwrappers;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+import org.apache.felix.http.base.internal.jakartawrappers.ReadListenerWrapper;
+import org.jetbrains.annotations.NotNull;
+
+import jakarta.servlet.ServletInputStream;
+
+/**
+ * Servlet input stream wrapper
+ */
+public class ServletInputStreamWrapper extends javax.servlet.ServletInputStream {
+
+    private final ServletInputStream stream;
+
+    /**
+     * Create input stream
+     * @param stream Wrapped stream
+     */
+    public ServletInputStreamWrapper(@NotNull final ServletInputStream stream) {
+        this.stream = stream;
+    }
+
+    @Override
+    public int readLine(final byte[] b, final int off, final int len) throws IOException {
+        return this.stream.readLine(b, off, len);
+    }
+
+    @Override
+    public boolean isFinished() {
+        return this.stream.isFinished();
+    }
+
+    @Override
+    public boolean isReady() {
+        return this.stream.isReady();
+    }
+
+    @Override
+    public void setReadListener(final javax.servlet.ReadListener readListener) {
+        this.stream.setReadListener(new ReadListenerWrapper(readListener));
+    }
+
+    @Override
+    public int read() throws IOException {
+        return this.stream.read();
+    }
+
+    @Override
+    public int read(final byte[] b) throws IOException {
+        return this.stream.read(b);
+    }
+
+    @Override
+    public int read(final byte[] b, final int off, final int len) throws IOException {
+        return this.stream.read(b, off, len);
+    }
+
+    @Override
+    public byte[] readAllBytes() throws IOException {
+        return this.stream.readAllBytes();
+    }
+
+    @Override
+    public byte[] readNBytes(final int len) throws IOException {
+        return this.stream.readNBytes(len);
+    }
+
+    @Override
+    public int readNBytes(final byte[] b, final int off, final int len) throws IOException {
+        return this.stream.readNBytes(b, off, len);
+    }
+
+    @Override
+    public long skip(final long n) throws IOException {
+        return this.stream.skip(n);
+    }
+
+    @Override
+    public int available() throws IOException {
+        return this.stream.available();
+    }
+
+    @Override
+    public void close() throws IOException {
+        this.stream.close();
+    }
+
+    @Override
+    public synchronized void mark(final int readlimit) {
+        this.stream.mark(readlimit);
+    }
+
+    @Override
+    public synchronized void reset() throws IOException {
+        this.stream.reset();
+    }
+
+    @Override
+    public boolean markSupported() {
+        return this.stream.markSupported();
+    }
+
+    @Override
+    public long transferTo(final OutputStream out) throws IOException {
+        return this.stream.transferTo(out);
+    }
+
+
+}
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/javaxwrappers/ServletOutputStreamWrapper.java b/http/base/src/main/java/org/apache/felix/http/base/internal/javaxwrappers/ServletOutputStreamWrapper.java
new file mode 100644
index 0000000..127a382
--- /dev/null
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/javaxwrappers/ServletOutputStreamWrapper.java
@@ -0,0 +1,150 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.felix.http.base.internal.javaxwrappers;
+
+import java.io.IOException;
+
+import org.apache.felix.http.base.internal.jakartawrappers.WriteListenerWrapper;
+import org.jetbrains.annotations.NotNull;
+
+import jakarta.servlet.ServletOutputStream;
+
+/**
+ * Servlet output stream
+ */
+public class ServletOutputStreamWrapper extends javax.servlet.ServletOutputStream {
+
+    private final ServletOutputStream stream;
+
+    /**
+     * Create new stream
+     * @param stream wrapped stream
+     */
+    public ServletOutputStreamWrapper(@NotNull final ServletOutputStream stream) {
+        this.stream = stream;
+    }
+
+    @Override
+    public void print(final String s) throws IOException {
+        this.stream.print(s);
+    }
+
+    @Override
+    public void print(final boolean b) throws IOException {
+        this.stream.print(b);
+    }
+
+    @Override
+    public void print(final char c) throws IOException {
+        this.stream.print(c);
+    }
+
+    @Override
+    public void print(final int i) throws IOException {
+        this.stream.print(i);
+    }
+
+    @Override
+    public void print(final long l) throws IOException {
+        this.stream.print(l);
+    }
+
+    @Override
+    public void print(final float f) throws IOException {
+        this.stream.print(f);
+    }
+
+    @Override
+    public void print(final double d) throws IOException {
+        this.stream.print(d);
+    }
+
+    @Override
+    public void println() throws IOException {
+        this.stream.println();
+    }
+
+    @Override
+    public void println(final String s) throws IOException {
+        this.stream.println(s);
+    }
+
+    @Override
+    public void println(final boolean b) throws IOException {
+        this.stream.println(b);
+    }
+
+    @Override
+    public void println(final char c) throws IOException {
+        this.stream.println(c);
+    }
+
+    @Override
+    public void println(final int i) throws IOException {
+        this.stream.println(i);
+    }
+
+    @Override
+    public void println(final long l) throws IOException {
+        this.stream.println(l);
+    }
+
+    @Override
+    public void println(final float f) throws IOException {
+        this.stream.println(f);
+    }
+
+    @Override
+    public void println(final double d) throws IOException {
+        this.stream.println(d);
+    }
+
+    @Override
+    public boolean isReady() {
+        return this.stream.isReady();
+    }
+
+    @Override
+    public void setWriteListener(final javax.servlet.WriteListener writeListener) {
+        this.stream.setWriteListener(new WriteListenerWrapper(writeListener));
+    }
+
+    @Override
+    public void write(final int b) throws IOException {
+        this.stream.write(b);
+    }
+
+    @Override
+    public void write(final byte[] b) throws IOException {
+        this.stream.write(b);
+    }
+
+    @Override
+    public void write(final byte[] b, final int off, final int len) throws IOException {
+        this.stream.write(b, off, len);
+    }
+
+    @Override
+    public void flush() throws IOException {
+        this.stream.flush();
+    }
+
+    @Override
+    public void close() throws IOException {
+        this.stream.close();
+    }
+}
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/javaxwrappers/ServletRegistrationWrapper.java b/http/base/src/main/java/org/apache/felix/http/base/internal/javaxwrappers/ServletRegistrationWrapper.java
new file mode 100644
index 0000000..f107f8f
--- /dev/null
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/javaxwrappers/ServletRegistrationWrapper.java
@@ -0,0 +1,86 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.felix.http.base.internal.javaxwrappers;
+
+import java.util.Collection;
+import java.util.Map;
+import java.util.Set;
+
+import org.jetbrains.annotations.NotNull;
+
+import jakarta.servlet.ServletRegistration;
+
+/**
+ * servlet registration wrapper
+ */
+public class ServletRegistrationWrapper implements javax.servlet.ServletRegistration {
+
+    private final ServletRegistration reg;
+
+    /**
+     * Create new wrapper
+     * @param c Wrapped registration
+     */
+    public ServletRegistrationWrapper(@NotNull final ServletRegistration c) {
+        this.reg = c;
+    }
+
+    @Override
+    public Set<String> addMapping(final String... urlPatterns) {
+        return reg.addMapping(urlPatterns);
+    }
+
+    @Override
+    public String getName() {
+        return reg.getName();
+    }
+
+    @Override
+    public Collection<String> getMappings() {
+        return reg.getMappings();
+    }
+
+    @Override
+    public String getClassName() {
+        return reg.getClassName();
+    }
+
+    @Override
+    public boolean setInitParameter(final String name, final String value) {
+        return reg.setInitParameter(name, value);
+    }
+
+    @Override
+    public String getRunAsRole() {
+        return reg.getRunAsRole();
+    }
+
+    @Override
+    public String getInitParameter(final String name) {
+        return reg.getInitParameter(name);
+    }
+
+    @Override
+    public Set<String> setInitParameters(final Map<String, String> initParameters) {
+        return reg.setInitParameters(initParameters);
+    }
+
+    @Override
+    public Map<String, String> getInitParameters() {
+        return reg.getInitParameters();
+    }
+}
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/javaxwrappers/ServletRequestWrapper.java b/http/base/src/main/java/org/apache/felix/http/base/internal/javaxwrappers/ServletRequestWrapper.java
new file mode 100644
index 0000000..d0bf473
--- /dev/null
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/javaxwrappers/ServletRequestWrapper.java
@@ -0,0 +1,334 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.felix.http.base.internal.javaxwrappers;
+
+import static jakarta.servlet.RequestDispatcher.ERROR_EXCEPTION;
+import static jakarta.servlet.RequestDispatcher.ERROR_EXCEPTION_TYPE;
+import static jakarta.servlet.RequestDispatcher.ERROR_MESSAGE;
+import static jakarta.servlet.RequestDispatcher.ERROR_REQUEST_URI;
+import static jakarta.servlet.RequestDispatcher.ERROR_SERVLET_NAME;
+import static jakarta.servlet.RequestDispatcher.ERROR_STATUS_CODE;
+import static jakarta.servlet.RequestDispatcher.FORWARD_CONTEXT_PATH;
+import static jakarta.servlet.RequestDispatcher.FORWARD_PATH_INFO;
+import static jakarta.servlet.RequestDispatcher.FORWARD_QUERY_STRING;
+import static jakarta.servlet.RequestDispatcher.FORWARD_REQUEST_URI;
+import static jakarta.servlet.RequestDispatcher.FORWARD_SERVLET_PATH;
+import static jakarta.servlet.RequestDispatcher.INCLUDE_CONTEXT_PATH;
+import static jakarta.servlet.RequestDispatcher.INCLUDE_PATH_INFO;
+import static jakarta.servlet.RequestDispatcher.INCLUDE_QUERY_STRING;
+import static jakarta.servlet.RequestDispatcher.INCLUDE_REQUEST_URI;
+import static jakarta.servlet.RequestDispatcher.INCLUDE_SERVLET_PATH;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.util.Enumeration;
+import java.util.Locale;
+import java.util.Map;
+
+import org.apache.felix.http.base.internal.jakartawrappers.ServletResponseWrapper;
+import org.jetbrains.annotations.NotNull;
+
+import jakarta.servlet.RequestDispatcher;
+import jakarta.servlet.ServletRequest;
+import jakarta.servlet.http.HttpServletRequest;
+
+/**
+ * Servlet request wrapper
+ */
+public class ServletRequestWrapper implements javax.servlet.ServletRequest {
+
+    private final ServletRequest request;
+
+    /**
+     * Get the wrapper
+     * @param r The request
+     * @return The wrapped request
+     */
+    public static javax.servlet.ServletRequest getWrapper(final ServletRequest r) {
+        if ( r instanceof org.apache.felix.http.base.internal.jakartawrappers.ServletRequestWrapper) {
+            return ((org.apache.felix.http.base.internal.jakartawrappers.ServletRequestWrapper)r).getRequest();
+        }
+        if ( r instanceof HttpServletRequest ) {
+            return new HttpServletRequestWrapper((HttpServletRequest)r);
+        }
+        return new ServletRequestWrapper(r);
+    }
+
+    /**
+     * Create a wrapper
+     * @param r The wrapped request
+     */
+    public ServletRequestWrapper(@NotNull final ServletRequest r) {
+        this.request = r;
+    }
+
+    /**
+     * Get the request
+     * @return The request
+     */
+    public ServletRequest getRequest() {
+        return this.request;
+    }
+
+    @Override
+    public Object getAttribute(final String name) {
+        if ( javax.servlet.RequestDispatcher.FORWARD_CONTEXT_PATH.equals(name) ) {
+            return this.request.getAttribute(FORWARD_CONTEXT_PATH);
+
+        } else if ( javax.servlet.RequestDispatcher.FORWARD_PATH_INFO.equals(name) ) {
+            return this.request.getAttribute(FORWARD_PATH_INFO);
+
+        } else if ( javax.servlet.RequestDispatcher.FORWARD_QUERY_STRING.equals(name) ) {
+            return this.request.getAttribute(FORWARD_QUERY_STRING);
+
+        } else if ( javax.servlet.RequestDispatcher.FORWARD_REQUEST_URI.equals(name) ) {
+            return this.request.getAttribute(FORWARD_REQUEST_URI);
+
+        } else if ( javax.servlet.RequestDispatcher.FORWARD_SERVLET_PATH.equals(name) ) {
+            return this.request.getAttribute(FORWARD_SERVLET_PATH);
+
+        } else if ( javax.servlet.RequestDispatcher.INCLUDE_CONTEXT_PATH.equals(name) ) {
+            return this.request.getAttribute(INCLUDE_CONTEXT_PATH);
+
+        } else if ( javax.servlet.RequestDispatcher.INCLUDE_PATH_INFO.equals(name) ) {
+            return this.request.getAttribute(INCLUDE_PATH_INFO);
+
+        } else if ( javax.servlet.RequestDispatcher.INCLUDE_QUERY_STRING.equals(name) ) {
+            return this.request.getAttribute(INCLUDE_QUERY_STRING);
+
+        } else if ( javax.servlet.RequestDispatcher.INCLUDE_REQUEST_URI.equals(name) ) {
+            return this.request.getAttribute(INCLUDE_REQUEST_URI);
+
+        } else if ( javax.servlet.RequestDispatcher.INCLUDE_SERVLET_PATH.equals(name) ) {
+            return this.request.getAttribute(INCLUDE_SERVLET_PATH);
+
+        } else if ( javax.servlet.RequestDispatcher.ERROR_EXCEPTION.equals(name) ) {
+            return this.request.getAttribute(ERROR_EXCEPTION);
+
+        } else if ( javax.servlet.RequestDispatcher.ERROR_EXCEPTION_TYPE.equals(name) ) {
+            return this.request.getAttribute(ERROR_EXCEPTION_TYPE);
+
+        } else if ( javax.servlet.RequestDispatcher.ERROR_MESSAGE.equals(name) ) {
+            return this.request.getAttribute(ERROR_MESSAGE);
+
+        } else if ( javax.servlet.RequestDispatcher.ERROR_REQUEST_URI.equals(name) ) {
+            return this.request.getAttribute(ERROR_REQUEST_URI);
+
+        } else if ( javax.servlet.RequestDispatcher.ERROR_SERVLET_NAME.equals(name) ) {
+            return this.request.getAttribute(ERROR_SERVLET_NAME);
+
+        } else if ( javax.servlet.RequestDispatcher.ERROR_STATUS_CODE.equals(name) ) {
+            return this.request.getAttribute(ERROR_STATUS_CODE);
+        }
+        return this.request.getAttribute(name);
+    }
+
+    @Override
+    public Enumeration<String> getAttributeNames() {
+        return this.request.getAttributeNames();
+    }
+
+    @Override
+    public String getCharacterEncoding() {
+        return this.request.getCharacterEncoding();
+    }
+
+    @Override
+    public void setCharacterEncoding(String env) throws UnsupportedEncodingException {
+        this.request.setCharacterEncoding(env);
+    }
+
+    @Override
+    public int getContentLength() {
+        return this.request.getContentLength();
+    }
+
+    @Override
+    public long getContentLengthLong() {
+        return this.request.getContentLengthLong();
+    }
+
+    @Override
+    public String getContentType() {
+        return this.request.getContentType();
+    }
+
+    @Override
+    public javax.servlet.ServletInputStream getInputStream() throws IOException {
+        return new ServletInputStreamWrapper(this.request.getInputStream());
+    }
+
+    @Override
+    public String getParameter(String name) {
+        return this.request.getParameter(name);
+    }
+
+    @Override
+    public Enumeration<String> getParameterNames() {
+        return this.request.getParameterNames();
+    }
+
+    @Override
+    public String[] getParameterValues(final String name) {
+        return this.request.getParameterValues(name);
+    }
+
+    @Override
+    public Map<String, String[]> getParameterMap() {
+        return this.request.getParameterMap();
+    }
+
+    @Override
+    public String getProtocol() {
+        return this.request.getProtocol();
+    }
+
+    @Override
+    public String getScheme() {
+        return this.request.getScheme();
+    }
+
+    @Override
+    public String getServerName() {
+        return this.request.getServerName();
+    }
+
+    @Override
+    public int getServerPort() {
+        return this.request.getServerPort();
+    }
+
+    @Override
+    public BufferedReader getReader() throws IOException {
+        return this.request.getReader();
+    }
+
+    @Override
+    public String getRemoteAddr() {
+        return this.request.getRemoteAddr();
+    }
+
+    @Override
+    public String getRemoteHost() {
+        return this.request.getRemoteHost();
+    }
+
+    @Override
+    public void setAttribute(final String name, final Object o) {
+        this.request.setAttribute(name, o);
+    }
+
+    @Override
+    public void removeAttribute(final String name) {
+        this.request.removeAttribute(name);
+    }
+
+    @Override
+    public Locale getLocale() {
+        return this.request.getLocale();
+    }
+
+    @Override
+    public Enumeration<Locale> getLocales() {
+        return this.request.getLocales();
+    }
+
+    @Override
+    public boolean isSecure() {
+        return this.request.isSecure();
+    }
+
+    @Override
+    public javax.servlet.RequestDispatcher getRequestDispatcher(final String path) {
+        final RequestDispatcher dispatcher = this.request.getRequestDispatcher(path);
+        if ( dispatcher != null ) {
+            return new RequestDispatcherWrapper(dispatcher);
+        }
+        return null;
+    }
+
+    @SuppressWarnings("deprecation")
+    @Override
+    public String getRealPath(final String path) {
+        return this.request.getRealPath(path);
+    }
+
+    @Override
+    public int getRemotePort() {
+        return this.request.getRemotePort();
+    }
+
+    @Override
+    public String getLocalName() {
+        return this.request.getLocalName();
+    }
+
+    @Override
+    public String getLocalAddr() {
+        return this.request.getLocalAddr();
+    }
+
+    @Override
+    public int getLocalPort() {
+        return this.request.getLocalPort();
+    }
+
+    @Override
+    public javax.servlet.ServletContext getServletContext() {
+        return new ServletContextWrapper(this.request.getServletContext());
+    }
+
+    @Override
+    public javax.servlet.AsyncContext startAsync() throws IllegalStateException {
+        return new AsyncContextWrapper(this.request.startAsync());
+    }
+
+    @Override
+    public javax.servlet.AsyncContext startAsync(final javax.servlet.ServletRequest servletRequest, final javax.servlet.ServletResponse servletResponse)
+            throws IllegalStateException {
+        return new AsyncContextWrapper(this.request.startAsync(org.apache.felix.http.base.internal.jakartawrappers.ServletRequestWrapper.getWrapper(servletRequest),
+                ServletResponseWrapper.getWrapper(servletResponse)));
+    }
+
+    @Override
+    public boolean isAsyncStarted() {
+        return this.request.isAsyncStarted();
+    }
+
+    @Override
+    public boolean isAsyncSupported() {
+        return this.request.isAsyncSupported();
+    }
+
+    @Override
+    public javax.servlet.AsyncContext getAsyncContext() {
+        return new AsyncContextWrapper(this.request.getAsyncContext());
+    }
+
+    @Override
+    public javax.servlet.DispatcherType getDispatcherType() {
+        switch (this.request.getDispatcherType()) {
+        case ASYNC : return javax.servlet.DispatcherType.ASYNC;
+        case ERROR : return javax.servlet.DispatcherType.ERROR;
+        case FORWARD : return javax.servlet.DispatcherType.FORWARD;
+        case INCLUDE : return javax.servlet.DispatcherType.INCLUDE;
+        case REQUEST : return javax.servlet.DispatcherType.REQUEST;
+        }
+        return null;
+    }
+}
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/javaxwrappers/ServletResponseWrapper.java b/http/base/src/main/java/org/apache/felix/http/base/internal/javaxwrappers/ServletResponseWrapper.java
new file mode 100644
index 0000000..638c802
--- /dev/null
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/javaxwrappers/ServletResponseWrapper.java
@@ -0,0 +1,145 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.felix.http.base.internal.javaxwrappers;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.Locale;
+
+import org.jetbrains.annotations.NotNull;
+
+import jakarta.servlet.ServletResponse;
+import jakarta.servlet.http.HttpServletResponse;
+
+/**
+ * Servlet response wrapper
+ */
+public class ServletResponseWrapper implements javax.servlet.ServletResponse {
+
+    private final ServletResponse response;
+
+    /**
+     * Get a wrapper
+     * @param r Response
+     * @return Wrapped response
+     */
+    public static javax.servlet.ServletResponse getWrapper(final ServletResponse r) {
+        if ( r instanceof org.apache.felix.http.base.internal.jakartawrappers.ServletResponseWrapper) {
+            return ((org.apache.felix.http.base.internal.jakartawrappers.ServletResponseWrapper)r).getResponse();
+        }
+        if ( r instanceof HttpServletResponse ) {
+            return new HttpServletResponseWrapper((HttpServletResponse)r);
+        }
+        return new ServletResponseWrapper(r);
+    }
+
+    /**
+     * Create new response
+     * @param r Wrapped response
+     */
+    public ServletResponseWrapper(@NotNull final ServletResponse r) {
+        this.response = r;
+    }
+
+    /**
+     * Get the wrapped response
+     * @return The response
+     */
+    public ServletResponse getResponse() {
+        return this.response;
+    }
+
+    @Override
+    public String getCharacterEncoding() {
+        return this.response.getCharacterEncoding();
+    }
+
+    @Override
+    public String getContentType() {
+        return this.response.getContentType();
+    }
+
+    @Override
+    public javax.servlet.ServletOutputStream getOutputStream() throws IOException {
+        return new ServletOutputStreamWrapper(this.response.getOutputStream());
+    }
+
+    @Override
+    public PrintWriter getWriter() throws IOException {
+        return this.response.getWriter();
+    }
+
+    @Override
+    public void setCharacterEncoding(final String charset) {
+        this.response.setCharacterEncoding(charset);
+    }
+
+    @Override
+    public void setContentLength(final int len) {
+        this.response.setContentLength(len);
+    }
+
+    @Override
+    public void setContentLengthLong(final long len) {
+        this.response.setContentLengthLong(len);
+    }
+
+    @Override
+    public void setContentType(final String type) {
+        this.response.setContentType(type);
+    }
+
+    @Override
+    public void setBufferSize(final int size) {
+        this.response.setBufferSize(size);
+    }
+
+    @Override
+    public int getBufferSize() {
+        return this.response.getBufferSize();
+    }
+
+    @Override
+    public void flushBuffer() throws IOException {
+        this.response.flushBuffer();
+    }
+
+    @Override
+    public void resetBuffer() {
+        this.response.resetBuffer();
+    }
+
+    @Override
+    public boolean isCommitted() {
+        return this.response.isCommitted();
+    }
+
+    @Override
+    public void reset() {
+        this.response.reset();
+    }
+
+    @Override
+    public void setLocale(final Locale loc) {
+        this.response.setLocale(loc);
+    }
+
+    @Override
+    public Locale getLocale() {
+        return this.response.getLocale();
+    }
+}
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/javaxwrappers/ServletWrapper.java b/http/base/src/main/java/org/apache/felix/http/base/internal/javaxwrappers/ServletWrapper.java
new file mode 100644
index 0000000..3689668
--- /dev/null
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/javaxwrappers/ServletWrapper.java
@@ -0,0 +1,83 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.felix.http.base.internal.javaxwrappers;
+
+import java.io.IOException;
+
+import org.jetbrains.annotations.NotNull;
+
+import jakarta.servlet.Servlet;
+import jakarta.servlet.ServletException;
+
+/**
+ * Servlet wrapper
+ */
+public class ServletWrapper implements javax.servlet.Servlet {
+
+    private final Servlet servlet;
+
+    /**
+     * Create new servlet
+     * @param servlet wrapped servlet
+     */
+    public ServletWrapper(@NotNull final Servlet servlet) {
+        this.servlet = servlet;
+    }
+
+    @Override
+    public void init(final javax.servlet.ServletConfig config) throws javax.servlet.ServletException {
+        try {
+            servlet.init(new org.apache.felix.http.base.internal.jakartawrappers.ServletConfigWrapper(config));
+        } catch (final ServletException e) {
+            throw ServletExceptionUtil.getServletException(e);
+        }
+    }
+
+    @Override
+    public javax.servlet.ServletConfig getServletConfig() {
+        return new ServletConfigWrapper(servlet.getServletConfig());
+    }
+
+    @Override
+    public void service(final javax.servlet.ServletRequest req, final javax.servlet.ServletResponse res)
+            throws javax.servlet.ServletException, IOException {
+        try {
+            servlet.service(org.apache.felix.http.base.internal.jakartawrappers.ServletRequestWrapper.getWrapper(req),
+                    org.apache.felix.http.base.internal.jakartawrappers.ServletResponseWrapper.getWrapper(res));
+        } catch (final ServletException e) {
+            throw ServletExceptionUtil.getServletException(e);
+        }
+    }
+
+    @Override
+    public String getServletInfo() {
+        return servlet.getServletInfo();
+    }
+
+    @Override
+    public void destroy() {
+        servlet.destroy();
+    }
+
+    /**
+     * Get the wrapped servlet
+     * @return The servlet
+     */
+    public @NotNull Servlet getServlet() {
+        return this.servlet;
+    }
+}
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/javaxwrappers/SessionCookieConfigWrapper.java b/http/base/src/main/java/org/apache/felix/http/base/internal/javaxwrappers/SessionCookieConfigWrapper.java
new file mode 100644
index 0000000..8ec4095
--- /dev/null
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/javaxwrappers/SessionCookieConfigWrapper.java
@@ -0,0 +1,107 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.felix.http.base.internal.javaxwrappers;
+
+import org.jetbrains.annotations.NotNull;
+
+import jakarta.servlet.SessionCookieConfig;
+
+/**
+ * Session cookie config wrapper
+ */
+public class SessionCookieConfigWrapper implements javax.servlet.SessionCookieConfig {
+
+    private final SessionCookieConfig config;
+
+    /**
+     * Create new config
+     * @param c Wrapped config
+     */
+    public SessionCookieConfigWrapper(@NotNull final SessionCookieConfig c) {
+        this.config = c;
+    }
+
+    @Override
+    public void setName(final String name) {
+        config.setName(name);
+    }
+
+    @Override
+    public String getName() {
+        return config.getName();
+    }
+
+    @Override
+    public void setDomain(final String domain) {
+        config.setDomain(domain);
+    }
+
+    @Override
+    public String getDomain() {
+        return config.getDomain();
+    }
+
+    @Override
+    public void setPath(final String path) {
+        config.setPath(path);
+    }
+
+    @Override
+    public String getPath() {
+        return config.getPath();
+    }
+
+    @Override
+    public void setComment(final String comment) {
+        config.setComment(comment);
+    }
+
+    @Override
+    public String getComment() {
+        return config.getComment();
+    }
+
+    @Override
+    public void setHttpOnly(final boolean httpOnly) {
+        config.setHttpOnly(httpOnly);
+    }
+
+    @Override
+    public boolean isHttpOnly() {
+        return config.isHttpOnly();
+    }
+
+    @Override
+    public void setSecure(final boolean secure) {
+        config.setSecure(secure);
+    }
+
+    @Override
+    public boolean isSecure() {
+        return config.isSecure();
+    }
+
+    @Override
+    public void setMaxAge(final int maxAge) {
+        config.setMaxAge(maxAge);
+    }
+
+    @Override
+    public int getMaxAge() {
+        return config.getMaxAge();
+    }
+}
\ No newline at end of file
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/service/DefaultHttpContext.java b/http/base/src/main/java/org/apache/felix/http/base/internal/javaxwrappers/WriteListenerWrapper.java
similarity index 52%
copy from http/base/src/main/java/org/apache/felix/http/base/internal/service/DefaultHttpContext.java
copy to http/base/src/main/java/org/apache/felix/http/base/internal/javaxwrappers/WriteListenerWrapper.java
index 22a048d..748e15d 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/service/DefaultHttpContext.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/javaxwrappers/WriteListenerWrapper.java
@@ -14,40 +14,36 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.felix.http.base.internal.service;
-
-import org.osgi.service.http.HttpContext;
-import org.osgi.framework.Bundle;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import java.net.URL;
-
-public final class DefaultHttpContext 
-    implements HttpContext
-{
-    private Bundle bundle;
-
-    public DefaultHttpContext(Bundle bundle)
-    {
-        this.bundle = bundle;
-    }
+package org.apache.felix.http.base.internal.javaxwrappers;
 
-    public String getMimeType(String name)
-    {
-        return null;
-    }
+import java.io.IOException;
+
+import org.jetbrains.annotations.NotNull;
+
+import jakarta.servlet.WriteListener;
 
-    public URL getResource(String name)
-    {
-        if (name.startsWith("/")) {
-            name = name.substring(1);
-        }
+/**
+ * Write listener
+ */
+public class WriteListenerWrapper implements javax.servlet.WriteListener {
+
+    private final WriteListener listener;
+
+    /**
+     * Create new lister
+     * @param listener Wrapped listener
+     */
+    public WriteListenerWrapper(@NotNull final WriteListener listener) {
+        this.listener = listener;
+    }
 
-        return this.bundle.getResource(name);
+    @Override
+    public void onWritePossible() throws IOException {
+        listener.onWritePossible();
     }
 
-    public boolean handleSecurity(HttpServletRequest req, HttpServletResponse res)
-    {
-        return true;
+    @Override
+    public void onError(final Throwable t) {
+        listener.onError(t);
     }
 }
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/registry/EventListenerRegistry.java b/http/base/src/main/java/org/apache/felix/http/base/internal/registry/EventListenerRegistry.java
index 3adc1f5..623c99c 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/registry/EventListenerRegistry.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/registry/EventListenerRegistry.java
@@ -21,19 +21,19 @@ import java.util.List;
 
 import org.jetbrains.annotations.Nullable;
 import org.jetbrains.annotations.NotNull;
-import javax.servlet.ServletContextAttributeEvent;
-import javax.servlet.ServletContextAttributeListener;
-import javax.servlet.ServletContextEvent;
-import javax.servlet.ServletContextListener;
-import javax.servlet.ServletRequestAttributeEvent;
-import javax.servlet.ServletRequestAttributeListener;
-import javax.servlet.ServletRequestEvent;
-import javax.servlet.ServletRequestListener;
-import javax.servlet.http.HttpSessionAttributeListener;
-import javax.servlet.http.HttpSessionBindingEvent;
-import javax.servlet.http.HttpSessionEvent;
-import javax.servlet.http.HttpSessionIdListener;
-import javax.servlet.http.HttpSessionListener;
+import jakarta.servlet.ServletContextAttributeEvent;
+import jakarta.servlet.ServletContextAttributeListener;
+import jakarta.servlet.ServletContextEvent;
+import jakarta.servlet.ServletContextListener;
+import jakarta.servlet.ServletRequestAttributeEvent;
+import jakarta.servlet.ServletRequestAttributeListener;
+import jakarta.servlet.ServletRequestEvent;
+import jakarta.servlet.ServletRequestListener;
+import jakarta.servlet.http.HttpSessionAttributeListener;
+import jakarta.servlet.http.HttpSessionBindingEvent;
+import jakarta.servlet.http.HttpSessionEvent;
+import jakarta.servlet.http.HttpSessionIdListener;
+import jakarta.servlet.http.HttpSessionListener;
 
 import org.apache.felix.http.base.internal.handler.ListenerHandler;
 import org.apache.felix.http.base.internal.logger.SystemLogger;
@@ -408,7 +408,7 @@ public final class EventListenerRegistry implements
     }
 
     /**
-     * @see javax.servlet.http.HttpSessionIdListener#sessionIdChanged(javax.servlet.http.HttpSessionEvent, java.lang.String)
+     * @see jakarta.servlet.http.HttpSessionIdListener#sessionIdChanged(jakarta.servlet.http.HttpSessionEvent, java.lang.String)
      */
     @Override
     public void sessionIdChanged(@NotNull final HttpSessionEvent event, @NotNull final String oldSessionId) {
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/registry/FilterRegistry.java b/http/base/src/main/java/org/apache/felix/http/base/internal/registry/FilterRegistry.java
index 7955435..13db6a8 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/registry/FilterRegistry.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/registry/FilterRegistry.java
@@ -24,7 +24,7 @@ import java.util.List;
 
 import org.jetbrains.annotations.Nullable;
 import org.jetbrains.annotations.NotNull;
-import javax.servlet.DispatcherType;
+import jakarta.servlet.DispatcherType;
 
 import org.apache.felix.http.base.internal.handler.FilterHandler;
 import org.apache.felix.http.base.internal.handler.ServletHandler;
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/registry/HandlerRegistry.java b/http/base/src/main/java/org/apache/felix/http/base/internal/registry/HandlerRegistry.java
index 82aa97e..2230d43 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/registry/HandlerRegistry.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/registry/HandlerRegistry.java
@@ -21,7 +21,7 @@ import java.util.Collections;
 import java.util.Iterator;
 import java.util.List;
 
-import javax.servlet.DispatcherType;
+import jakarta.servlet.DispatcherType;
 
 import org.apache.felix.http.base.internal.HttpConfig;
 import org.apache.felix.http.base.internal.handler.FilterHandler;
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/registry/PerContextHandlerRegistry.java b/http/base/src/main/java/org/apache/felix/http/base/internal/registry/PerContextHandlerRegistry.java
index 90c8b5c..04cc9c6 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/registry/PerContextHandlerRegistry.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/registry/PerContextHandlerRegistry.java
@@ -16,7 +16,7 @@
  */
 package org.apache.felix.http.base.internal.registry;
 
-import javax.servlet.DispatcherType;
+import jakarta.servlet.DispatcherType;
 
 import org.apache.felix.http.base.internal.HttpConfig;
 import org.apache.felix.http.base.internal.handler.FilterHandler;
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/AbstractInfo.java b/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/AbstractInfo.java
index 630f90b..95c2cb3 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/AbstractInfo.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/AbstractInfo.java
@@ -23,6 +23,9 @@ import java.util.Collections;
 import java.util.HashMap;
 import java.util.Map;
 
+import org.apache.felix.http.base.internal.util.ServiceUtils;
+import org.jetbrains.annotations.NotNull;
+import org.osgi.framework.BundleContext;
 import org.osgi.framework.Constants;
 import org.osgi.framework.ServiceReference;
 import org.osgi.service.http.whiteboard.HttpWhiteboardConstants;
@@ -226,4 +229,28 @@ public abstract class AbstractInfo<T> implements Comparable<AbstractInfo<T>>
         final AbstractInfo<?> other = (AbstractInfo<?>) obj;
         return serviceId == other.serviceId;
     }
+
+    /**
+     * Get a service object
+     * @param bundleContext context
+     * @return The object or {@code null}
+     */
+    public T getService(final BundleContext bundleContext) {
+        return ServiceUtils.safeGetServiceObjects(bundleContext, this.getServiceReference());
+    }
+
+    /**
+     * Unget the service object
+     * @param bundleContext The bundle context
+     * @param service The service object
+     */
+    public void ungetService(final BundleContext bundleContext, final T service) {
+        ServiceUtils.safeUngetServiceObjects(bundleContext, this.getServiceReference(), service);
+    }
+
+    /**
+     * Get the type represented by this info
+     * @return The type
+     */
+    public abstract @NotNull String getType();
 }
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/FilterInfo.java b/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/FilterInfo.java
index d08dbc0..961c3eb 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/FilterInfo.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/FilterInfo.java
@@ -22,22 +22,24 @@ import java.util.Map;
 import java.util.regex.Pattern;
 import java.util.regex.PatternSyntaxException;
 
-import javax.servlet.DispatcherType;
-import javax.servlet.Filter;
-
+import org.apache.felix.http.base.internal.jakartawrappers.FilterWrapper;
 import org.apache.felix.http.base.internal.util.PatternUtil;
+import org.jetbrains.annotations.NotNull;
 import org.osgi.dto.DTO;
 import org.osgi.framework.ServiceReference;
 import org.osgi.service.http.runtime.dto.FilterDTO;
 import org.osgi.service.http.whiteboard.HttpWhiteboardConstants;
 
+import jakarta.servlet.DispatcherType;
+import jakarta.servlet.Filter;
+
 /**
  * Provides registration information for a {@link Filter}, and is used to programmatically register {@link Filter}s.
  * <p>
  * This class only provides information used at registration time, and as such differs slightly from {@link DTO}s like, {@link FilterDTO}.
  * </p>
  */
-public final class FilterInfo extends WhiteboardServiceInfo<Filter>
+public class FilterInfo extends WhiteboardServiceInfo<Filter>
 {
     /**
      * The name of the filter.
@@ -89,6 +91,10 @@ public final class FilterInfo extends WhiteboardServiceInfo<Filter>
      */
     private final Map<String, String> initParams;
 
+    /**
+     * new filter info
+     * @param ref filter service reference
+     */
     public FilterInfo(final ServiceReference<Filter> ref)
     {
         super(ref);
@@ -202,4 +208,21 @@ public final class FilterInfo extends WhiteboardServiceInfo<Filter>
     {
         return initParams;
     }
+
+    @Override
+    public @NotNull String getType() {
+        return "Filter";
+    }
+
+    /**
+     * Get the class name of the filter
+     * @param filter The filter
+     * @return The class name
+     */
+    public @NotNull String getClassName(@NotNull final Filter filter) {
+        if (filter instanceof FilterWrapper ) {
+            return ((FilterWrapper)filter).getFilter().getClass().getName();
+        }
+        return filter.getClass().getName();
+    }
 }
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/ListenerInfo.java b/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/ListenerInfo.java
index 7611f48..851e611 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/ListenerInfo.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/ListenerInfo.java
@@ -22,19 +22,19 @@ import java.util.EventListener;
 import java.util.HashSet;
 import java.util.Set;
 
-import javax.servlet.ServletContextAttributeListener;
-import javax.servlet.ServletContextListener;
-import javax.servlet.ServletRequestAttributeListener;
-import javax.servlet.ServletRequestListener;
-import javax.servlet.http.HttpSessionAttributeListener;
-import javax.servlet.http.HttpSessionIdListener;
-import javax.servlet.http.HttpSessionListener;
-
 import org.jetbrains.annotations.NotNull;
 import org.osgi.framework.Constants;
 import org.osgi.framework.ServiceReference;
 import org.osgi.service.http.whiteboard.HttpWhiteboardConstants;
 
+import jakarta.servlet.ServletContextAttributeListener;
+import jakarta.servlet.ServletContextListener;
+import jakarta.servlet.ServletRequestAttributeListener;
+import jakarta.servlet.ServletRequestListener;
+import jakarta.servlet.http.HttpSessionAttributeListener;
+import jakarta.servlet.http.HttpSessionIdListener;
+import jakarta.servlet.http.HttpSessionListener;
+
 /**
  * Info object for registered listeners.
  */
@@ -52,18 +52,39 @@ public class ListenerInfo extends WhiteboardServiceInfo<EventListener>
         ALLOWED_INTERFACES.add(ServletRequestListener.class.getName());
     }
 
+    /** Is the listener enabled (per properties) */
     private final boolean enabled;
 
-    private final String[] types;
+    /** The service types */
+    private final Set<String> types;
+
+    /** The service types as reported through DTOs */
+    private final String[] dtoTypes;
 
     /**
-     * Constructor for http whiteboard
+     * Constructor
      * @param ref The service reference
      */
     public ListenerInfo(final ServiceReference<EventListener> ref)
     {
+        this(ref, getTypes(ref), null);
+    }
+
+    /**
+     * Constructor
+     * @param ref The service reference
+     * @param dtoTypes Optional dto types
+     * @param types The listener types
+     */
+    public ListenerInfo(final ServiceReference<EventListener> ref, final Set<String> types, final String[] dtos)
+    {
         super(ref);
         this.enabled = this.getBooleanProperty(ref, HttpWhiteboardConstants.HTTP_WHITEBOARD_LISTENER);
+        this.types = types;
+        this.dtoTypes = dtos == null ? types.toArray(new String[types.size()]) : dtos;
+    }
+
+    private static Set<String> getTypes(final ServiceReference<EventListener> ref) {
         final String[] objectClass = (String[])ref.getProperty(Constants.OBJECTCLASS);
         final Set<String> names = new HashSet<String>();
         for(final String name : objectClass)
@@ -73,7 +94,7 @@ public class ListenerInfo extends WhiteboardServiceInfo<EventListener>
                 names.add(name);
             }
         }
-        this.types = names.toArray(new String[names.size()]);
+        return names;
     }
 
     @Override
@@ -82,11 +103,20 @@ public class ListenerInfo extends WhiteboardServiceInfo<EventListener>
         return super.isValid() && this.enabled;
     }
 
-    public String[] getListenerTypes()
+    /**
+     * The types as reported through the DTOs
+     * @return Array of types
+     */
+    public @NotNull String[] getDTOListenerTypes()
     {
-        return this.types;
+        return this.dtoTypes;
     }
 
+    /**
+     * Is this listener of the required type?
+     * @param className The listener type
+     * @return {@code true} If the listener should be registered as that type
+     */
     public boolean isListenerType(@NotNull final String className)
     {
         for(final String t : this.types)
@@ -98,4 +128,17 @@ public class ListenerInfo extends WhiteboardServiceInfo<EventListener>
         }
         return false;
     }
+
+    /**
+     * Get the registered listener types
+     * @return The set of types
+     */
+    public @NotNull Set<String> getListenerTypes() {
+        return this.types;
+    }
+
+    @Override
+    public @NotNull String getType() {
+        return "Listener";
+    }
 }
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/PreprocessorInfo.java b/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/PreprocessorInfo.java
index 158eb0d..345d9ef 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/PreprocessorInfo.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/PreprocessorInfo.java
@@ -20,9 +20,11 @@ package org.apache.felix.http.base.internal.runtime;
 
 import java.util.Map;
 
+import org.apache.felix.http.base.internal.jakartawrappers.PreprocessorWrapper;
+import org.apache.felix.http.base.osgi.whiteboard.Preprocessor;
+import org.jetbrains.annotations.NotNull;
 import org.osgi.framework.ServiceReference;
 import org.osgi.service.http.whiteboard.HttpWhiteboardConstants;
-import org.osgi.service.http.whiteboard.Preprocessor;
 
 /**
  * Provides registration information for a {@link Preprocessor}.
@@ -31,7 +33,7 @@ import org.osgi.service.http.whiteboard.Preprocessor;
  * slightly from the corresponding DTO
  * </p>
  */
-public final class PreprocessorInfo extends WhiteboardServiceInfo<Preprocessor>
+public class PreprocessorInfo extends WhiteboardServiceInfo<Preprocessor>
 {
     /**
      * The preprocessor initialization parameters as provided during registration of the preprocessor.
@@ -51,4 +53,22 @@ public final class PreprocessorInfo extends WhiteboardServiceInfo<Preprocessor>
     {
         return initParams;
     }
+
+
+    @Override
+    public @NotNull String getType() {
+        return "Preprocessor";
+    }
+
+    /**
+     * Get the class name of the preprocessor
+     * @param preprocessor The preprocesor
+     * @return The class name
+     */
+    public @NotNull String getClassName(@NotNull final Preprocessor preprocessor) {
+        if (preprocessor instanceof PreprocessorWrapper ) {
+            return ((PreprocessorWrapper)preprocessor).getPreprocessor().getClass().getName();
+        }
+        return preprocessor.getClass().getName();
+    }
 }
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/ResourceInfo.java b/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/ResourceInfo.java
index abd07d9..4522daa 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/ResourceInfo.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/ResourceInfo.java
@@ -19,6 +19,7 @@
 package org.apache.felix.http.base.internal.runtime;
 
 import org.apache.felix.http.base.internal.util.PatternUtil;
+import org.jetbrains.annotations.NotNull;
 import org.osgi.framework.ServiceReference;
 import org.osgi.service.http.whiteboard.HttpWhiteboardConstants;
 
@@ -44,7 +45,7 @@ public final class ResourceInfo extends WhiteboardServiceInfo<Object>
         public ResourceServletInfo(ResourceInfo resource) {
             super(resource);
         }
-    };
+    }
 
     public ResourceInfo(final ServiceReference<Object> ref)
     {
@@ -86,4 +87,9 @@ public final class ResourceInfo extends WhiteboardServiceInfo<Object>
     {
         return this.servletInfo;
     }
+
+    @Override
+    public @NotNull String getType() {
+        return "Resource";
+    }
 }
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/ServletContextHelperInfo.java b/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/ServletContextHelperInfo.java
index 6d0de3e..17d74de 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/ServletContextHelperInfo.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/ServletContextHelperInfo.java
@@ -23,14 +23,15 @@ import java.util.Map;
 
 import org.apache.felix.http.base.internal.service.HttpServiceFactory;
 import org.apache.felix.http.base.internal.util.PatternUtil;
+import org.apache.felix.http.base.osgi.whiteboard.ServletContextHelper;
+import org.jetbrains.annotations.NotNull;
 import org.osgi.framework.ServiceReference;
-import org.osgi.service.http.context.ServletContextHelper;
 import org.osgi.service.http.whiteboard.HttpWhiteboardConstants;
 
 /**
  * Provides registration information for a {@link ServletContextHelper}
  */
-public final class ServletContextHelperInfo extends AbstractInfo<ServletContextHelper>
+public class ServletContextHelperInfo extends AbstractInfo<ServletContextHelper>
 {
 
     private final String name;
@@ -106,4 +107,17 @@ public final class ServletContextHelperInfo extends AbstractInfo<ServletContextH
     {
         return initParams;
     }
+
+    @Override
+    public @NotNull String getType() {
+        return "ServletContextHelper";
+    }
+
+    /**
+     * Get the registered service type
+     * @return The type
+     */
+    public @NotNull String getServiceType() {
+        return ServletContextHelper.class.getName();
+    }
 }
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/ServletInfo.java b/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/ServletInfo.java
index 59724db..f830ccd 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/ServletInfo.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/ServletInfo.java
@@ -21,15 +21,17 @@ package org.apache.felix.http.base.internal.runtime;
 import java.util.Collections;
 import java.util.Map;
 
-import javax.servlet.Servlet;
-
 import org.apache.felix.http.base.internal.dispatch.MultipartConfig;
+import org.apache.felix.http.base.internal.jakartawrappers.ServletWrapper;
 import org.apache.felix.http.base.internal.util.PatternUtil;
+import org.jetbrains.annotations.NotNull;
 import org.osgi.dto.DTO;
 import org.osgi.framework.ServiceReference;
 import org.osgi.service.http.runtime.dto.ServletDTO;
 import org.osgi.service.http.whiteboard.HttpWhiteboardConstants;
 
+import jakarta.servlet.Servlet;
+
 /**
  * Provides registration information for a {@link Servlet}, and is used to programmatically register {@link Servlet}s.
  * <p>
@@ -252,4 +254,21 @@ public class ServletInfo extends WhiteboardServiceInfo<Servlet>
     {
         return multipartConfig;
     }
+
+    @Override
+    public @NotNull String getType() {
+        return "Servlet";
+    }
+
+    /**
+     * Get the class name of the servlet
+     * @param servlet The servlet
+     * @return The class name
+     */
+    public @NotNull String getClassName(@NotNull final Servlet servlet) {
+        if (servlet instanceof ServletWrapper ) {
+            return ((ServletWrapper)servlet).getServlet().getClass().getName();
+        }
+        return servlet.getClass().getName();
+    }
 }
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/dto/FilterDTOBuilder.java b/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/dto/FilterDTOBuilder.java
index 7811deb..4b378e8 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/dto/FilterDTOBuilder.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/dto/FilterDTOBuilder.java
@@ -19,7 +19,7 @@
 package org.apache.felix.http.base.internal.runtime.dto;
 
 import org.jetbrains.annotations.NotNull;
-import javax.servlet.DispatcherType;
+import jakarta.servlet.DispatcherType;
 
 import org.apache.felix.http.base.internal.handler.FilterHandler;
 import org.apache.felix.http.base.internal.runtime.FilterInfo;
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/dto/ListenerDTOBuilder.java b/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/dto/ListenerDTOBuilder.java
index d76681f..bf6118c 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/dto/ListenerDTOBuilder.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/dto/ListenerDTOBuilder.java
@@ -32,7 +32,7 @@ public final class ListenerDTOBuilder
         final ListenerDTO dto = (reason == -1 ? new ListenerDTO() : new FailedListenerDTO());
 
         dto.serviceId = info.getServiceId();
-        dto.types = Arrays.copyOf(info.getListenerTypes(), info.getListenerTypes().length);
+        dto.types = Arrays.copyOf(info.getDTOListenerTypes(), info.getDTOListenerTypes().length);
 
         if ( reason != -1 )
         {
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/dto/RequestInfoDTOBuilder.java b/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/dto/RequestInfoDTOBuilder.java
index 9c15e89..a4b12c4 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/dto/RequestInfoDTOBuilder.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/dto/RequestInfoDTOBuilder.java
@@ -16,7 +16,7 @@
  */
 package org.apache.felix.http.base.internal.runtime.dto;
 
-import javax.servlet.DispatcherType;
+import jakarta.servlet.DispatcherType;
 
 import org.apache.felix.http.base.internal.handler.FilterHandler;
 import org.apache.felix.http.base.internal.registry.HandlerRegistry;
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/dto/ServletContextDTOBuilder.java b/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/dto/ServletContextDTOBuilder.java
index 0815563..c10ed5e 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/dto/ServletContextDTOBuilder.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/dto/ServletContextDTOBuilder.java
@@ -24,7 +24,7 @@ import java.util.Collections;
 import java.util.HashMap;
 import java.util.Map;
 
-import javax.servlet.ServletContext;
+import jakarta.servlet.ServletContext;
 
 import org.apache.felix.http.base.internal.runtime.ServletContextHelperInfo;
 import org.osgi.dto.DTO;
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/service/DefaultHttpContext.java b/http/base/src/main/java/org/apache/felix/http/base/internal/service/DefaultHttpContext.java
index 22a048d..e85bb08 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/service/DefaultHttpContext.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/service/DefaultHttpContext.java
@@ -16,13 +16,15 @@
  */
 package org.apache.felix.http.base.internal.service;
 
-import org.osgi.service.http.HttpContext;
-import org.osgi.framework.Bundle;
+import java.net.URL;
+
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
-import java.net.URL;
 
-public final class DefaultHttpContext 
+import org.osgi.framework.Bundle;
+import org.osgi.service.http.HttpContext;
+
+public final class DefaultHttpContext
     implements HttpContext
 {
     private Bundle bundle;
@@ -32,11 +34,13 @@ public final class DefaultHttpContext
         this.bundle = bundle;
     }
 
+    @Override
     public String getMimeType(String name)
     {
         return null;
     }
 
+    @Override
     public URL getResource(String name)
     {
         if (name.startsWith("/")) {
@@ -46,6 +50,7 @@ public final class DefaultHttpContext
         return this.bundle.getResource(name);
     }
 
+    @Override
     public boolean handleSecurity(HttpServletRequest req, HttpServletResponse res)
     {
         return true;
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/service/DefaultHttpContext.java b/http/base/src/main/java/org/apache/felix/http/base/internal/service/HttpResourceServlet.java
similarity index 54%
copy from http/base/src/main/java/org/apache/felix/http/base/internal/service/DefaultHttpContext.java
copy to http/base/src/main/java/org/apache/felix/http/base/internal/service/HttpResourceServlet.java
index 22a048d..0faccb6 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/service/DefaultHttpContext.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/service/HttpResourceServlet.java
@@ -16,38 +16,21 @@
  */
 package org.apache.felix.http.base.internal.service;
 
-import org.osgi.service.http.HttpContext;
-import org.osgi.framework.Bundle;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import java.net.URL;
+import org.apache.felix.http.base.internal.whiteboard.ResourceServlet;
 
-public final class DefaultHttpContext 
-    implements HttpContext
-{
-    private Bundle bundle;
+public class HttpResourceServlet extends ResourceServlet {
 
-    public DefaultHttpContext(Bundle bundle)
-    {
-        this.bundle = bundle;
-    }
+    private volatile javax.servlet.Servlet wrapper;
 
-    public String getMimeType(String name)
-    {
-        return null;
+    public HttpResourceServlet(String prefix) {
+        super(prefix);
     }
 
-    public URL getResource(String name)
-    {
-        if (name.startsWith("/")) {
-            name = name.substring(1);
-        }
-
-        return this.bundle.getResource(name);
+    public javax.servlet.Servlet getWrapper() {
+        return wrapper;
     }
 
-    public boolean handleSecurity(HttpServletRequest req, HttpServletResponse res)
-    {
-        return true;
+    public void setWrapper(javax.servlet.Servlet wrapper) {
+        this.wrapper = wrapper;
     }
 }
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/service/HttpServiceFactory.java b/http/base/src/main/java/org/apache/felix/http/base/internal/service/HttpServiceFactory.java
index 87f5ee0..c7ae1a5 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/service/HttpServiceFactory.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/service/HttpServiceFactory.java
@@ -18,10 +18,8 @@ package org.apache.felix.http.base.internal.service;
 
 import java.util.Hashtable;
 
-import org.jetbrains.annotations.NotNull;
-import javax.servlet.ServletContext;
-
 import org.apache.felix.http.base.internal.registry.HandlerRegistry;
+import org.jetbrains.annotations.NotNull;
 import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.Constants;
@@ -30,14 +28,20 @@ import org.osgi.framework.ServiceRegistration;
 import org.osgi.service.http.HttpService;
 import org.osgi.service.http.runtime.HttpServiceRuntimeConstants;
 
+import jakarta.servlet.ServletContext;
+
+/**
+ * The http service factory
+ */
 public final class HttpServiceFactory
     implements ServiceFactory<HttpService>
 {
+    /** The name of the context for the http service. */
     public static final String HTTP_SERVICE_CONTEXT_NAME = "org.osgi.service.http";
 
+    /** The id of the context for the http service. */
     public static final long HTTP_SERVICE_CONTEXT_SERVICE_ID = -1;
 
-
     /**
      * Name of the Framework property indicating whether the servlet context
      * attributes of the ServletContext objects created for each HttpContext
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/service/PerBundleHttpServiceImpl.java b/http/base/src/main/java/org/apache/felix/http/base/internal/service/PerBundleHttpServiceImpl.java
index a3edacd..359a8de 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/service/PerBundleHttpServiceImpl.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/service/PerBundleHttpServiceImpl.java
@@ -23,19 +23,18 @@ import java.util.HashSet;
 import java.util.Map;
 import java.util.Set;
 
-import javax.servlet.Servlet;
-import javax.servlet.ServletContext;
-import javax.servlet.ServletException;
-
 import org.apache.felix.http.base.internal.context.ExtServletContext;
 import org.apache.felix.http.base.internal.logger.SystemLogger;
 import org.apache.felix.http.base.internal.runtime.ServletInfo;
 import org.apache.felix.http.base.internal.util.PatternUtil;
+import org.jetbrains.annotations.NotNull;
 import org.osgi.framework.Bundle;
 import org.osgi.service.http.HttpContext;
 import org.osgi.service.http.HttpService;
 import org.osgi.service.http.NamespaceException;
 
+import jakarta.servlet.ServletContext;
+
 /**
  * This implementation of the {@link HttpService} implements the front end
  * used by client bundles. It performs the validity checks and passes the
@@ -44,10 +43,17 @@ import org.osgi.service.http.NamespaceException;
 public final class PerBundleHttpServiceImpl implements HttpService
 {
     private final Bundle bundle;
-    private final Set<Servlet> localServlets = new HashSet<>();
+    private final Set<javax.servlet.Servlet> localServlets = new HashSet<>();
     private final ServletContextManager contextManager;
     private final SharedHttpServiceImpl sharedHttpService;
 
+    /**
+     * Create a new http service front end
+     * @param bundle The using bundle
+     * @param sharedHttpService The shared service
+     * @param context The context
+     * @param sharedContextAttributes Shared context attributes?
+     */
     public PerBundleHttpServiceImpl(final Bundle bundle,
             final SharedHttpServiceImpl sharedHttpService,
             final ServletContext context,
@@ -77,7 +83,7 @@ public final class PerBundleHttpServiceImpl implements HttpService
     }
 
     /**
-     * No need to sync this method, syncing is done via {@link #registerServlet(String, Servlet, Dictionary, HttpContext)}
+     * No need to sync this method, syncing is done via {@link #registerServlet(String, javax.servlet.Servlet, Dictionary, HttpContext)}
      * @see org.osgi.service.http.HttpService#registerResources(java.lang.String, java.lang.String, org.osgi.service.http.HttpContext)
      */
     @Override
@@ -94,10 +100,12 @@ public final class PerBundleHttpServiceImpl implements HttpService
         }
         try
         {
-            final Servlet servlet = new ResourceServlet(name);
-            registerServlet(alias, servlet, null, context);
+            final HttpResourceServlet servlet = new HttpResourceServlet(name);
+            final javax.servlet.Servlet wrapper = new org.apache.felix.http.base.internal.javaxwrappers.ServletWrapper(servlet);
+            servlet.setWrapper(wrapper);
+            registerServlet(alias, wrapper, null, context);
         }
-        catch (ServletException e)
+        catch (javax.servlet.ServletException e)
         {
             SystemLogger.error("Failed to register resources", e);
         }
@@ -107,7 +115,8 @@ public final class PerBundleHttpServiceImpl implements HttpService
      * @see org.osgi.service.http.HttpService#registerServlet(java.lang.String, javax.servlet.Servlet, java.util.Dictionary, org.osgi.service.http.HttpContext)
      */
     @Override
-    public void registerServlet(String alias, Servlet servlet, @SuppressWarnings("rawtypes") Dictionary initParams, HttpContext context) throws ServletException, NamespaceException
+    public void registerServlet(String alias, javax.servlet.Servlet servlet, @SuppressWarnings("rawtypes") Dictionary initParams, HttpContext context)
+            throws javax.servlet.ServletException, NamespaceException
     {
         if (servlet == null)
         {
@@ -139,7 +148,7 @@ public final class PerBundleHttpServiceImpl implements HttpService
         {
             if (this.localServlets.contains(servlet))
             {
-                throw new ServletException("Servlet instance " + servlet + " already registered");
+                throw new javax.servlet.ServletException("Servlet instance " + servlet + " already registered");
             }
             this.localServlets.add(servlet);
         }
@@ -171,7 +180,7 @@ public final class PerBundleHttpServiceImpl implements HttpService
     @Override
     public void unregister(final String alias)
     {
-        final Servlet servlet = this.sharedHttpService.unregister(alias);
+        final javax.servlet.Servlet servlet = this.sharedHttpService.unregister(alias);
         if ( servlet != null )
         {
             synchronized ( this.localServlets )
@@ -181,16 +190,19 @@ public final class PerBundleHttpServiceImpl implements HttpService
         }
     }
 
+    /**
+     * Remove all registered servlets
+     */
     public void unregisterAll()
     {
-        final Set<Servlet> servlets = new HashSet<>(this.localServlets);
-        for (final Servlet servlet : servlets)
+        final Set<javax.servlet.Servlet> servlets = new HashSet<>(this.localServlets);
+        for (final javax.servlet.Servlet servlet : servlets)
         {
             unregisterServlet(servlet);
         }
     }
 
-    private void unregisterServlet(final Servlet servlet)
+    private void unregisterServlet(final javax.servlet.Servlet servlet)
     {
         if (servlet != null)
         {
@@ -202,7 +214,12 @@ public final class PerBundleHttpServiceImpl implements HttpService
         }
     }
 
-    public ExtServletContext getServletContext(HttpContext context)
+    /**
+     * Get a servlet context
+     * @param context http context
+     * @return servlet context
+     */
+    public @NotNull ExtServletContext getServletContext(HttpContext context)
     {
         if (context == null)
         {
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/service/ServletContextImpl.java b/http/base/src/main/java/org/apache/felix/http/base/internal/service/ServletContextImpl.java
index b62da50..ecec5e2 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/service/ServletContextImpl.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/service/ServletContextImpl.java
@@ -30,31 +30,13 @@ import java.util.Map;
 import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
 
-import javax.servlet.Filter;
-import javax.servlet.FilterRegistration;
-import javax.servlet.RequestDispatcher;
-import javax.servlet.Servlet;
-import javax.servlet.ServletContext;
-import javax.servlet.ServletContextAttributeEvent;
-import javax.servlet.ServletException;
-import javax.servlet.ServletRegistration;
-import javax.servlet.ServletRegistration.Dynamic;
-import javax.servlet.ServletRequestAttributeListener;
-import javax.servlet.ServletRequestListener;
-import javax.servlet.SessionCookieConfig;
-import javax.servlet.SessionTrackingMode;
-import javax.servlet.descriptor.JspConfigDescriptor;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import javax.servlet.http.HttpSessionAttributeListener;
-import javax.servlet.http.HttpSessionListener;
-import javax.servlet.http.MappingMatch;
-
 import org.apache.felix.http.base.internal.HttpConfig;
 import org.apache.felix.http.base.internal.context.ExtServletContext;
 import org.apache.felix.http.base.internal.dispatch.RequestDispatcherImpl;
 import org.apache.felix.http.base.internal.dispatch.RequestInfo;
 import org.apache.felix.http.base.internal.handler.ServletHandler;
+import org.apache.felix.http.base.internal.javaxwrappers.ServletRequestWrapper;
+import org.apache.felix.http.base.internal.javaxwrappers.ServletResponseWrapper;
 import org.apache.felix.http.base.internal.logger.SystemLogger;
 import org.apache.felix.http.base.internal.registry.PathResolution;
 import org.apache.felix.http.base.internal.registry.PerContextHandlerRegistry;
@@ -64,6 +46,25 @@ import org.apache.felix.http.base.internal.util.UriUtils;
 import org.osgi.framework.Bundle;
 import org.osgi.service.http.HttpContext;
 
+import jakarta.servlet.Filter;
+import jakarta.servlet.FilterRegistration;
+import jakarta.servlet.RequestDispatcher;
+import jakarta.servlet.Servlet;
+import jakarta.servlet.ServletContext;
+import jakarta.servlet.ServletContextAttributeEvent;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.ServletRegistration;
+import jakarta.servlet.ServletRegistration.Dynamic;
+import jakarta.servlet.ServletRequestAttributeListener;
+import jakarta.servlet.ServletRequestListener;
+import jakarta.servlet.SessionCookieConfig;
+import jakarta.servlet.SessionTrackingMode;
+import jakarta.servlet.descriptor.JspConfigDescriptor;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+import jakarta.servlet.http.HttpSessionAttributeListener;
+import jakarta.servlet.http.HttpSessionListener;
+
 @SuppressWarnings("deprecation")
 public class ServletContextImpl implements ExtServletContext
 {
@@ -73,6 +74,14 @@ public class ServletContextImpl implements ExtServletContext
     private final Map<String, Object> attributes;
     private final PerContextHandlerRegistry handlerRegistry;
 
+    /**
+     * Create a new servlet context implementation
+     * @param bundle The bundle
+     * @param context The context
+     * @param httpContext The http context
+     * @param sharedAttributes shared attribtes
+     * @param registry The registry
+     */
     public ServletContextImpl(final Bundle bundle,
             final ServletContext context,
             final HttpContext httpContext,
@@ -405,7 +414,8 @@ public class ServletContextImpl implements ExtServletContext
     @Override
     public boolean handleSecurity(HttpServletRequest req, HttpServletResponse res) throws IOException
     {
-        return this.httpContext.handleSecurity(req, res);
+        return this.httpContext.handleSecurity((javax.servlet.http.HttpServletRequest)ServletRequestWrapper.getWrapper(req),
+                (javax.servlet.http.HttpServletResponse)ServletResponseWrapper.getWrapper(res));
     }
 
     @Override
@@ -599,6 +609,47 @@ public class ServletContextImpl implements ExtServletContext
     }
 
     @Override
+    public Dynamic addJspFile(final String servletName, final String jspFile) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public int getSessionTimeout() {
+        // TODO Auto-generated method stub
+        return 0;
+    }
+
+    @Override
+    public void setSessionTimeout(final int sessionTimeout) {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public String getRequestCharacterEncoding() {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public void setRequestCharacterEncoding(final String encoding) {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public String getResponseCharacterEncoding() {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public void setResponseCharacterEncoding(final String encoding) {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
     public HttpConfig getConfig()
     {
         return this.handlerRegistry.getConfig();
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/service/ServletContextManager.java b/http/base/src/main/java/org/apache/felix/http/base/internal/service/ServletContextManager.java
index c2bf611..5114447 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/service/ServletContextManager.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/service/ServletContextManager.java
@@ -19,7 +19,7 @@ package org.apache.felix.http.base.internal.service;
 import java.util.Map;
 import java.util.WeakHashMap;
 
-import javax.servlet.ServletContext;
+import jakarta.servlet.ServletContext;
 
 import org.apache.felix.http.base.internal.context.ExtServletContext;
 import org.apache.felix.http.base.internal.registry.PerContextHandlerRegistry;
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/service/SharedHttpServiceImpl.java b/http/base/src/main/java/org/apache/felix/http/base/internal/service/SharedHttpServiceImpl.java
index 7ce664b..6dccef0 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/service/SharedHttpServiceImpl.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/service/SharedHttpServiceImpl.java
@@ -20,23 +20,29 @@ import java.util.HashMap;
 import java.util.Iterator;
 import java.util.Map;
 
-import javax.servlet.Servlet;
-import javax.servlet.ServletException;
-
 import org.apache.felix.http.base.internal.context.ExtServletContext;
 import org.apache.felix.http.base.internal.handler.HttpServiceServletHandler;
 import org.apache.felix.http.base.internal.handler.ServletHandler;
+import org.apache.felix.http.base.internal.jakartawrappers.ServletWrapper;
 import org.apache.felix.http.base.internal.registry.HandlerRegistry;
 import org.apache.felix.http.base.internal.runtime.ServletInfo;
 import org.jetbrains.annotations.NotNull;
 import org.osgi.service.http.NamespaceException;
 
+/**
+ * Shared http service implementation
+ * This implementation is shared by all bundles using the http service.
+ */
 public final class SharedHttpServiceImpl
 {
     private final HandlerRegistry handlerRegistry;
 
     private final Map<String, ServletHandler> aliasMap = new HashMap<>();
 
+    /**
+     * Create a new implementation
+     * @param handlerRegistry The handler registry
+     */
     public SharedHttpServiceImpl(final HandlerRegistry handlerRegistry)
     {
         if (handlerRegistry == null)
@@ -49,11 +55,17 @@ public final class SharedHttpServiceImpl
 
     /**
      * Register a servlet
+     * @param alias The alias
+     * @param httpContext The servlet context
+     * @param servlet The servlet
+     * @param servletInfo The info for the servlet
+     * @throws javax.servlet.ServletException If registration fails
+     * @throws NamespaceException If a servlet for the same alias already exists
      */
     public void registerServlet(@NotNull final String alias,
             @NotNull final ExtServletContext httpContext,
-            @NotNull final Servlet servlet,
-            @NotNull final ServletInfo servletInfo) throws ServletException, NamespaceException
+            @NotNull final javax.servlet.Servlet servlet,
+            @NotNull final ServletInfo servletInfo) throws javax.servlet.ServletException, NamespaceException
     {
         final ServletHandler handler = new HttpServiceServletHandler(httpContext, servletInfo, servlet);
 
@@ -70,9 +82,12 @@ public final class SharedHttpServiceImpl
     }
 
     /**
+     * Unregister a servlet
+     * @param alias The alias
+     * @return The servlet or {@code null}
      * @see org.osgi.service.http.HttpService#unregister(java.lang.String)
      */
-    public Servlet unregister(final String alias)
+    public javax.servlet.Servlet unregister(final String alias)
     {
         synchronized (this.aliasMap)
         {
@@ -82,13 +97,24 @@ public final class SharedHttpServiceImpl
                 throw new IllegalArgumentException("Nothing registered at " + alias);
             }
 
-            final Servlet s = handler.getServlet();
+            final javax.servlet.Servlet s;
+            if ( handler.getServlet() instanceof HttpResourceServlet ) {
+                final HttpResourceServlet resource = (HttpResourceServlet)handler.getServlet();
+                s = resource.getWrapper();
+                resource.setWrapper(null);
+            } else {
+                s = ((ServletWrapper)handler.getServlet()).getServlet();
+            }
             this.handlerRegistry.getRegistry(handler.getContextServiceId()).unregisterServlet(handler.getServletInfo(), true);
             return s;
         }
     }
 
-    public void unregisterServlet(final Servlet servlet)
+    /**
+     * Unregister a servlet
+     * @param servlet The servlet
+     */
+    public void unregisterServlet(final javax.servlet.Servlet servlet)
     {
         if (servlet != null)
         {
@@ -111,7 +137,11 @@ public final class SharedHttpServiceImpl
         }
     }
 
-	public HandlerRegistry getHandlerRegistry()
+    /**
+     * Get the handler registry
+     * @return The registry
+     */
+	public @NotNull HandlerRegistry getHandlerRegistry()
 	{
 		return this.handlerRegistry;
 	}
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/FailureStateHandler.java b/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/FailureStateHandler.java
index 27d8ef4..b3c306f 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/FailureStateHandler.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/FailureStateHandler.java
@@ -68,7 +68,7 @@ public class FailureStateHandler {
 
     public void addFailure(final AbstractInfo<?> info, final long contextId, final int reason, final Exception ex)
     {
-        final String type = info.getClass().getSimpleName().substring(0, info.getClass().getSimpleName().length() - 4);
+        final String type = info.getType();
         final String serviceInfo;
         final ServiceReference<?> ref = info.getServiceReference();
         if ( ref == null ) {
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/HttpServiceContextHandler.java b/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/HttpServiceContextHandler.java
index 0ed049b..aa87d64 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/HttpServiceContextHandler.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/HttpServiceContextHandler.java
@@ -21,7 +21,7 @@ import java.util.Map;
 
 import org.jetbrains.annotations.Nullable;
 import org.jetbrains.annotations.NotNull;
-import javax.servlet.ServletContext;
+import jakarta.servlet.ServletContext;
 
 import org.apache.felix.http.base.internal.context.ExtServletContext;
 import org.apache.felix.http.base.internal.registry.PerContextHandlerRegistry;
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/PerBundleServletContextImpl.java b/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/PerBundleServletContextImpl.java
index c3a4d61..de76249 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/PerBundleServletContextImpl.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/PerBundleServletContextImpl.java
@@ -24,31 +24,31 @@ import java.util.EventListener;
 import java.util.Map;
 import java.util.Set;
 
-import javax.servlet.Filter;
-import javax.servlet.FilterRegistration;
-import javax.servlet.RequestDispatcher;
-import javax.servlet.Servlet;
-import javax.servlet.ServletContext;
-import javax.servlet.ServletException;
-import javax.servlet.ServletRegistration;
-import javax.servlet.ServletRegistration.Dynamic;
-import javax.servlet.ServletRequestAttributeListener;
-import javax.servlet.ServletRequestListener;
-import javax.servlet.SessionCookieConfig;
-import javax.servlet.SessionTrackingMode;
-import javax.servlet.descriptor.JspConfigDescriptor;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import javax.servlet.http.HttpSessionAttributeListener;
-import javax.servlet.http.HttpSessionListener;
-
 import org.apache.felix.http.base.internal.HttpConfig;
 import org.apache.felix.http.base.internal.context.ExtServletContext;
 import org.apache.felix.http.base.internal.registry.PerContextHandlerRegistry;
 import org.apache.felix.http.base.internal.util.MimeTypes;
+import org.apache.felix.http.base.osgi.whiteboard.ServletContextHelper;
 import org.osgi.framework.Bundle;
 import org.osgi.framework.wiring.BundleWiring;
-import org.osgi.service.http.context.ServletContextHelper;
+
+import jakarta.servlet.Filter;
+import jakarta.servlet.FilterRegistration;
+import jakarta.servlet.RequestDispatcher;
+import jakarta.servlet.Servlet;
+import jakarta.servlet.ServletContext;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.ServletRegistration;
+import jakarta.servlet.ServletRegistration.Dynamic;
+import jakarta.servlet.ServletRequestAttributeListener;
+import jakarta.servlet.ServletRequestListener;
+import jakarta.servlet.SessionCookieConfig;
+import jakarta.servlet.SessionTrackingMode;
+import jakarta.servlet.descriptor.JspConfigDescriptor;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+import jakarta.servlet.http.HttpSessionAttributeListener;
+import jakarta.servlet.http.HttpSessionListener;
 
 /**
  * This servlet context implementation represents the per
@@ -63,6 +63,13 @@ public class PerBundleServletContextImpl implements ExtServletContext {
     private final ServletContextHelper contextHelper;
     private final PerContextHandlerRegistry handlerRegistry;
 
+    /**
+     * Create a new context implementation
+     * @param bundle The bundle
+     * @param sharedContext The shared context
+     * @param delegatee The delegatee
+     * @param handlerRegistry The handler registry
+     */
     public PerBundleServletContextImpl(final Bundle bundle,
             final ServletContext sharedContext,
             final ServletContextHelper delegatee,
@@ -125,7 +132,7 @@ public class PerBundleServletContextImpl implements ExtServletContext {
     }
 
     /**
-     * @see javax.servlet.ServletContext#getResource(java.lang.String)
+     * @see jakarta.servlet.ServletContext#getResource(java.lang.String)
      */
     @Override
     public URL getResource(final String path)
@@ -355,21 +362,21 @@ public class PerBundleServletContextImpl implements ExtServletContext {
     }
 
     @Override
-    public javax.servlet.FilterRegistration.Dynamic addFilter(
+    public jakarta.servlet.FilterRegistration.Dynamic addFilter(
             String filterName, String className)
     {
         return delegatee.addFilter(filterName, className);
     }
 
     @Override
-    public javax.servlet.FilterRegistration.Dynamic addFilter(
+    public jakarta.servlet.FilterRegistration.Dynamic addFilter(
             String filterName, Filter filter)
     {
         return delegatee.addFilter(filterName, filter);
     }
 
     @Override
-    public javax.servlet.FilterRegistration.Dynamic addFilter(
+    public jakarta.servlet.FilterRegistration.Dynamic addFilter(
             String filterName, Class<? extends Filter> filterClass)
     {
         return delegatee.addFilter(filterName, filterClass);
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/RegistrationFailureException.java b/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/RegistrationFailureException.java
index 46a60e8..f17a97b 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/RegistrationFailureException.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/RegistrationFailureException.java
@@ -16,7 +16,7 @@
  */
 package org.apache.felix.http.base.internal.whiteboard;
 
-import javax.servlet.ServletException;
+import jakarta.servlet.ServletException;
 
 import org.apache.felix.http.base.internal.runtime.WhiteboardServiceInfo;
 
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/service/ResourceServlet.java b/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/ResourceServlet.java
similarity index 77%
rename from http/base/src/main/java/org/apache/felix/http/base/internal/service/ResourceServlet.java
rename to http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/ResourceServlet.java
index 19f459d..3a4d143 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/service/ResourceServlet.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/ResourceServlet.java
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.felix.http.base.internal.service;
+package org.apache.felix.http.base.internal.whiteboard;
 
 import java.io.File;
 import java.io.IOException;
@@ -23,93 +23,79 @@ import java.io.OutputStream;
 import java.net.URL;
 import java.net.URLConnection;
 
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.http.HttpServlet;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
 
 /**
  * The resource servlet
  */
-public final class ResourceServlet extends HttpServlet
-{
+public class ResourceServlet extends HttpServlet {
+
     private static final long serialVersionUID = 1L;
 
     /** The path of the resource registration. */
     private final String prefix;
 
-    public ResourceServlet(final String prefix)
-    {
+    /**
+     * The prefix for the resource
+     * @param prefix The prefix
+     */
+    public ResourceServlet(final String prefix) {
         this.prefix = prefix;
     }
 
     @Override
     protected void doGet(final HttpServletRequest req, final HttpServletResponse res)
-            throws ServletException, IOException
-    {
+            throws ServletException, IOException {
         final String target = req.getPathInfo();
         final String resName = (target == null ? this.prefix : this.prefix + target);
 
         final URL url = getServletContext().getResource(resName);
 
-        if (url == null)
-        {
+        if (url == null) {
             res.sendError(HttpServletResponse.SC_NOT_FOUND);
-        }
-        else
-        {
+        } else {
             handle(req, res, url, resName);
         }
     }
 
     private void handle(final HttpServletRequest req,
             final HttpServletResponse res, final URL url, final String resName)
-    throws IOException
-    {
+    throws IOException {
         final String contentType = getServletContext().getMimeType(resName);
-        if (contentType != null)
-        {
+        if (contentType != null) {
             res.setContentType(contentType);
         }
 
         final long lastModified = getLastModified(url);
-        if (lastModified != 0)
-        {
+        if (lastModified != 0) {
             res.setDateHeader("Last-Modified", lastModified);
         }
 
-        if (!resourceModified(lastModified, req.getDateHeader("If-Modified-Since")))
-        {
+        if (!resourceModified(lastModified, req.getDateHeader("If-Modified-Since"))) {
             res.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
-        }
-        else
-        {
+        } else {
             copyResource(url, res);
         }
     }
 
-    private long getLastModified(final URL url)
-    {
+    private long getLastModified(final URL url) {
         long lastModified = 0;
 
-        try
-        {
+        try {
             final URLConnection conn = url.openConnection();
             lastModified = conn.getLastModified();
-        }
-        catch (final Exception e)
-        {
+        } catch (final Exception e) {
             // Do nothing
         }
 
-        if (lastModified == 0)
-        {
+        if (lastModified == 0) {
             final String filepath = url.getPath();
-            if (filepath != null)
-            {
+            if (filepath != null) {
                 final File f = new File(filepath);
-                if (f.exists())
-                {
+                if (f.exists()) {
                     lastModified = f.lastModified();
                 }
             }
@@ -118,22 +104,19 @@ public final class ResourceServlet extends HttpServlet
         return lastModified;
     }
 
-    private boolean resourceModified(long resTimestamp, long modSince)
-    {
+    private boolean resourceModified(long resTimestamp, long modSince) {
         modSince /= 1000;
         resTimestamp /= 1000;
 
         return resTimestamp == 0 || modSince == -1 || resTimestamp > modSince;
     }
 
-    private void copyResource(final URL url, final HttpServletResponse res) throws IOException
-    {
+    private void copyResource(final URL url, final HttpServletResponse res) throws IOException {
         URLConnection conn = null;
         OutputStream os = null;
         InputStream is = null;
 
-        try
-        {
+        try {
             conn = url.openConnection();
 
             is = conn.getInputStream();
@@ -141,28 +124,22 @@ public final class ResourceServlet extends HttpServlet
             // FELIX-3987 content length should be set *before* any streaming is done
             // as headers should be written before the content is actually written...
             int len = getContentLength(conn);
-            if (len >= 0)
-            {
+            if (len >= 0) {
                 res.setContentLength(len);
             }
 
             byte[] buf = new byte[1024];
             int n;
 
-            while ((n = is.read(buf, 0, buf.length)) >= 0)
-            {
+            while ((n = is.read(buf, 0, buf.length)) >= 0) {
                 os.write(buf, 0, n);
             }
-        }
-        finally
-        {
-            if (is != null)
-            {
+        } finally {
+            if (is != null) {
                 is.close();
             }
 
-            if (os != null)
-            {
+            if (os != null) {
                 os.close();
             }
         }
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/SharedServletContextImpl.java b/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/SharedServletContextImpl.java
index 3ec5ce4..7e74c04 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/SharedServletContextImpl.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/SharedServletContextImpl.java
@@ -29,21 +29,6 @@ import java.util.Map;
 import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
 
-import javax.servlet.Filter;
-import javax.servlet.FilterRegistration;
-import javax.servlet.RequestDispatcher;
-import javax.servlet.Servlet;
-import javax.servlet.ServletContext;
-import javax.servlet.ServletContextAttributeEvent;
-import javax.servlet.ServletContextAttributeListener;
-import javax.servlet.ServletException;
-import javax.servlet.ServletRegistration;
-import javax.servlet.ServletRegistration.Dynamic;
-import javax.servlet.SessionCookieConfig;
-import javax.servlet.SessionTrackingMode;
-import javax.servlet.descriptor.JspConfigDescriptor;
-import javax.servlet.http.MappingMatch;
-
 import org.apache.felix.http.base.internal.dispatch.RequestDispatcherImpl;
 import org.apache.felix.http.base.internal.dispatch.RequestInfo;
 import org.apache.felix.http.base.internal.handler.ServletHandler;
@@ -53,6 +38,20 @@ import org.apache.felix.http.base.internal.registry.PerContextHandlerRegistry;
 import org.apache.felix.http.base.internal.registry.ServletResolution;
 import org.apache.felix.http.base.internal.util.UriUtils;
 
+import jakarta.servlet.Filter;
+import jakarta.servlet.FilterRegistration;
+import jakarta.servlet.RequestDispatcher;
+import jakarta.servlet.Servlet;
+import jakarta.servlet.ServletContext;
+import jakarta.servlet.ServletContextAttributeEvent;
+import jakarta.servlet.ServletContextAttributeListener;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.ServletRegistration;
+import jakarta.servlet.ServletRegistration.Dynamic;
+import jakarta.servlet.SessionCookieConfig;
+import jakarta.servlet.SessionTrackingMode;
+import jakarta.servlet.descriptor.JspConfigDescriptor;
+
 /**
  * This servlet context implementation represents the shared
  * part for a servlet context backed by a servlet context helper.
@@ -102,7 +101,7 @@ public class SharedServletContextImpl implements ServletContext
     }
 
     /**
-     * @see javax.servlet.ServletContext#getResource(java.lang.String)
+     * @see jakarta.servlet.ServletContext#getResource(java.lang.String)
      */
     @Override
     public URL getResource(String path)
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/WhiteboardContextHandler.java b/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/WhiteboardContextHandler.java
index 3cb96d7..1502ab0 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/WhiteboardContextHandler.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/WhiteboardContextHandler.java
@@ -19,18 +19,17 @@ package org.apache.felix.http.base.internal.whiteboard;
 import java.util.HashMap;
 import java.util.Map;
 
-import javax.servlet.ServletContext;
-
 import org.apache.felix.http.base.internal.context.ExtServletContext;
 import org.apache.felix.http.base.internal.registry.HandlerRegistry;
 import org.apache.felix.http.base.internal.registry.PerContextHandlerRegistry;
 import org.apache.felix.http.base.internal.runtime.ServletContextHelperInfo;
-import org.apache.felix.http.base.internal.util.ServiceUtils;
+import org.apache.felix.http.base.osgi.whiteboard.ServletContextHelper;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleContext;
-import org.osgi.service.http.context.ServletContextHelper;
+
+import jakarta.servlet.ServletContext;
 
 /**
  * The whiteboard context handler provides some information and functionality for
@@ -83,6 +82,7 @@ public class WhiteboardContextHandler implements Comparable<WhiteboardContextHan
 
     /**
      * Activate this context.
+     * @param registry The handler registry
      * @return {@code true} if it succeeded.
      */
     public boolean activate(@NotNull final HandlerRegistry registry)
@@ -136,7 +136,7 @@ public class WhiteboardContextHandler implements Comparable<WhiteboardContextHan
             if ( holder == null )
             {
 
-                final ServletContextHelper service = ServiceUtils.safeGetServiceObjects(bundle.getBundleContext(), this.info.getServiceReference());
+                final ServletContextHelper service = this.info.getService(bundle.getBundleContext());
                 if ( service != null )
                 {
                     holder = new ContextHolder();
@@ -173,7 +173,7 @@ public class WhiteboardContextHandler implements Comparable<WhiteboardContextHan
                     if ( holder.servletContextHelper != null )
                     {
                         final BundleContext ctx = bundle.getBundleContext();
-                        ServiceUtils.safeUngetServiceObjects(ctx, this.info.getServiceReference(), holder.servletContextHelper);
+                        this.info.ungetService(ctx, holder.servletContextHelper);
                     }
                 }
             }
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/WhiteboardManager.java b/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/WhiteboardManager.java
index 6832efb..3e06ee3 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/WhiteboardManager.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/WhiteboardManager.java
@@ -33,18 +33,6 @@ import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
-import javax.servlet.FilterChain;
-import javax.servlet.ServletContext;
-import javax.servlet.ServletContextEvent;
-import javax.servlet.ServletContextListener;
-import javax.servlet.ServletException;
-import javax.servlet.ServletRequest;
-import javax.servlet.ServletResponse;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import javax.servlet.http.HttpSession;
-import javax.servlet.http.HttpSessionEvent;
-
 import org.apache.felix.http.base.internal.console.HttpServicePlugin;
 import org.apache.felix.http.base.internal.context.ExtServletContext;
 import org.apache.felix.http.base.internal.handler.FilterHandler;
@@ -71,13 +59,15 @@ import org.apache.felix.http.base.internal.runtime.dto.RegistryRuntime;
 import org.apache.felix.http.base.internal.runtime.dto.ServletContextDTOBuilder;
 import org.apache.felix.http.base.internal.service.HttpServiceFactory;
 import org.apache.felix.http.base.internal.service.HttpServiceRuntimeImpl;
-import org.apache.felix.http.base.internal.service.ResourceServlet;
-import org.apache.felix.http.base.internal.whiteboard.tracker.FilterTracker;
-import org.apache.felix.http.base.internal.whiteboard.tracker.ListenersTracker;
-import org.apache.felix.http.base.internal.whiteboard.tracker.PreprocessorTracker;
+import org.apache.felix.http.base.internal.whiteboard.tracker.JavaxFilterTracker;
+import org.apache.felix.http.base.internal.whiteboard.tracker.JavaxListenersTracker;
+import org.apache.felix.http.base.internal.whiteboard.tracker.JavaxPreprocessorTracker;
+import org.apache.felix.http.base.internal.whiteboard.tracker.JavaxServletContextHelperTracker;
+import org.apache.felix.http.base.internal.whiteboard.tracker.JavaxServletTracker;
 import org.apache.felix.http.base.internal.whiteboard.tracker.ResourceTracker;
 import org.apache.felix.http.base.internal.whiteboard.tracker.ServletContextHelperTracker;
-import org.apache.felix.http.base.internal.whiteboard.tracker.ServletTracker;
+import org.apache.felix.http.base.osgi.whiteboard.Preprocessor;
+import org.apache.felix.http.base.osgi.whiteboard.ServletContextHelper;
 import org.jetbrains.annotations.NotNull;
 import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleContext;
@@ -87,15 +77,25 @@ import org.osgi.framework.InvalidSyntaxException;
 import org.osgi.framework.ServiceFactory;
 import org.osgi.framework.ServiceReference;
 import org.osgi.framework.ServiceRegistration;
-import org.osgi.service.http.context.ServletContextHelper;
 import org.osgi.service.http.runtime.HttpServiceRuntimeConstants;
 import org.osgi.service.http.runtime.dto.DTOConstants;
 import org.osgi.service.http.runtime.dto.PreprocessorDTO;
 import org.osgi.service.http.runtime.dto.ServletContextDTO;
 import org.osgi.service.http.whiteboard.HttpWhiteboardConstants;
-import org.osgi.service.http.whiteboard.Preprocessor;
 import org.osgi.util.tracker.ServiceTracker;
 
+import jakarta.servlet.FilterChain;
+import jakarta.servlet.ServletContext;
+import jakarta.servlet.ServletContextEvent;
+import jakarta.servlet.ServletContextListener;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.ServletRequest;
+import jakarta.servlet.ServletResponse;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+import jakarta.servlet.http.HttpSession;
+import jakarta.servlet.http.HttpSessionEvent;
+
 public final class WhiteboardManager
 {
     /** The bundle context of the http bundle. */
@@ -199,12 +199,17 @@ public final class WhiteboardManager
                         // nothing to do
                     }
                 }, props);
-        addTracker(new FilterTracker(this.httpBundleContext, this));
-        addTracker(new ListenersTracker(this.httpBundleContext, this));
-        addTracker(new PreprocessorTracker(this.httpBundleContext, this));
+//        addTracker(new FilterTracker(this.httpBundleContext, this));
+//        addTracker(new ListenersTracker(this.httpBundleContext, this));
+//        addTracker(new PreprocessorTracker(this.httpBundleContext, this));
         addTracker(new ResourceTracker(this.httpBundleContext, this));
         addTracker(new ServletContextHelperTracker(this.httpBundleContext, this));
-        addTracker(new ServletTracker(this.httpBundleContext, this));
+//        addTracker(new ServletTracker(this.httpBundleContext, this));
+        addTracker(new JavaxServletContextHelperTracker(httpBundleContext, this));
+        addTracker(new JavaxFilterTracker(httpBundleContext, this));
+        addTracker(new JavaxServletTracker(httpBundleContext, this));
+        addTracker(new JavaxListenersTracker(httpBundleContext, this));
+        addTracker(new JavaxPreprocessorTracker(httpBundleContext, this));
 
         this.plugin.register();
     }
@@ -525,8 +530,8 @@ public final class WhiteboardManager
                 final String filterString = "(" + Constants.SERVICE_ID + "=" + String.valueOf(h.getContextInfo().getServiceId()) + ")";
                 try
                 {
-                    final Collection<ServiceReference<ServletContextHelper>> col = info.getServiceReference().getBundle().getBundleContext().getServiceReferences(ServletContextHelper.class, filterString);
-                    if ( !col.isEmpty() )
+                    final ServiceReference<?>[] col = info.getServiceReference().getBundle().getBundleContext().getServiceReferences(h.getContextInfo().getServiceType(), filterString);
+                    if ( col !=null && col.length > 0 )
                     {
                         visible = true;
                     }
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/FilterTracker.java b/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/FilterTracker.java
index 3a10f33..0b73c8b 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/FilterTracker.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/FilterTracker.java
@@ -16,8 +16,6 @@
  */
 package org.apache.felix.http.base.internal.whiteboard.tracker;
 
-import javax.servlet.Filter;
-
 import org.apache.felix.http.base.internal.runtime.FilterInfo;
 import org.apache.felix.http.base.internal.runtime.WhiteboardServiceInfo;
 import org.apache.felix.http.base.internal.whiteboard.WhiteboardManager;
@@ -25,6 +23,8 @@ import org.osgi.framework.BundleContext;
 import org.osgi.framework.ServiceReference;
 import org.osgi.service.http.whiteboard.HttpWhiteboardConstants;
 
+import jakarta.servlet.Filter;
+
 public final class FilterTracker extends WhiteboardServiceTracker<Filter>
 {
     public FilterTracker(final BundleContext context, final WhiteboardManager manager)
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/JavaxFilterTracker.java b/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/JavaxFilterTracker.java
new file mode 100644
index 0000000..bd4bd70
--- /dev/null
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/JavaxFilterTracker.java
@@ -0,0 +1,88 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.felix.http.base.internal.whiteboard.tracker;
+
+import org.apache.felix.http.base.internal.jakartawrappers.FilterWrapper;
+import org.apache.felix.http.base.internal.runtime.FilterInfo;
+import org.apache.felix.http.base.internal.runtime.WhiteboardServiceInfo;
+import org.apache.felix.http.base.internal.util.ServiceUtils;
+import org.apache.felix.http.base.internal.whiteboard.WhiteboardManager;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.http.whiteboard.HttpWhiteboardConstants;
+
+import jakarta.servlet.Filter;
+
+
+/**
+ * Tracker for http whiteboard filters
+ */
+public final class JavaxFilterTracker extends WhiteboardServiceTracker<Filter> {
+
+    /**
+     * Create new tracker
+     * @param context bundle context
+     * @param manager whiteboard manager
+     */
+    public JavaxFilterTracker(final BundleContext context, final WhiteboardManager manager) {
+        super(manager, context, String.format("(&(objectClass=%s)(|(%s=*)(%s=*)(%s=*)))",
+                javax.servlet.Filter.class.getName(),
+                HttpWhiteboardConstants.HTTP_WHITEBOARD_FILTER_PATTERN,
+                HttpWhiteboardConstants.HTTP_WHITEBOARD_FILTER_REGEX,
+                HttpWhiteboardConstants.HTTP_WHITEBOARD_FILTER_SERVLET));
+    }
+
+    @Override
+    protected WhiteboardServiceInfo<Filter> getServiceInfo(final ServiceReference<Filter> ref) {
+        return new JavaxFilterInfo(ref);
+    }
+
+    /**
+     * Filter info for javax filters
+     */
+    private static final class JavaxFilterInfo extends FilterInfo {
+
+        private final ServiceReference<javax.servlet.Filter> reference;
+
+        /**
+         * Create new filter
+         * @param ref Reference to the filter
+         */
+        @SuppressWarnings({ "rawtypes", "unchecked" })
+        public JavaxFilterInfo(final ServiceReference<Filter> ref) {
+            super(ref);
+            this.reference = (ServiceReference)ref;
+        }
+
+        @Override
+        public Filter getService(final BundleContext bundleContext) {
+            final javax.servlet.Filter filter = ServiceUtils.safeGetServiceObjects(bundleContext, this.reference);
+            if ( filter == null ) {
+                return null;
+            }
+            return new FilterWrapper(filter);
+        }
+
+        @Override
+        public void ungetService(final BundleContext bundleContext, final Filter service) {
+            if ( service instanceof FilterWrapper ) {
+                final javax.servlet.Filter filter = ((FilterWrapper)service).getFilter();
+                ServiceUtils.safeUngetServiceObjects(bundleContext, this.reference, filter);
+            }
+        }
+    }
+}
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/JavaxListenersTracker.java b/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/JavaxListenersTracker.java
new file mode 100644
index 0000000..cddd7da
--- /dev/null
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/JavaxListenersTracker.java
@@ -0,0 +1,169 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.felix.http.base.internal.whiteboard.tracker;
+
+import java.util.EventListener;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.apache.felix.http.base.internal.jakartawrappers.EventListenerWrapper;
+import org.apache.felix.http.base.internal.runtime.ListenerInfo;
+import org.apache.felix.http.base.internal.runtime.WhiteboardServiceInfo;
+import org.apache.felix.http.base.internal.util.ServiceUtils;
+import org.apache.felix.http.base.internal.whiteboard.WhiteboardManager;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.http.whiteboard.HttpWhiteboardConstants;
+
+import jakarta.servlet.ServletContextAttributeListener;
+import jakarta.servlet.ServletContextListener;
+import jakarta.servlet.ServletRequestAttributeListener;
+import jakarta.servlet.ServletRequestListener;
+import jakarta.servlet.http.HttpSessionAttributeListener;
+import jakarta.servlet.http.HttpSessionIdListener;
+import jakarta.servlet.http.HttpSessionListener;
+
+/**
+ * Tracker for http whiteboard listeners
+ */
+public final class JavaxListenersTracker extends WhiteboardServiceTracker<EventListener>
+{
+    /**
+     * Create a filter expression for all supported listener.
+     */
+    private static String createListenersFilterExpression()
+    {
+        return String.format("(&" +
+                             "(|(objectClass=%s)(objectClass=%s)(objectClass=%s)(objectClass=%s)(objectClass=%s)(objectClass=%s)(objectClass=%s))" +
+                             "(%s=*)(!(%s~=false)))",
+                javax.servlet.http.HttpSessionAttributeListener.class.getName(),
+                javax.servlet.http.HttpSessionIdListener.class.getName(),
+                javax.servlet.http.HttpSessionListener.class.getName(),
+                javax.servlet.ServletContextListener.class.getName(),
+                javax.servlet.ServletContextAttributeListener.class.getName(),
+                javax.servlet.ServletRequestListener.class.getName(),
+                javax.servlet.ServletRequestAttributeListener.class.getName(),
+                HttpWhiteboardConstants.HTTP_WHITEBOARD_LISTENER,
+                HttpWhiteboardConstants.HTTP_WHITEBOARD_LISTENER);
+    }
+
+    /**
+     * Create new tracker
+     * @param context bundle context
+     * @param manager whiteboard manager
+     */
+    public JavaxListenersTracker(final BundleContext context, final WhiteboardManager manager)
+    {
+        super(manager, context, createListenersFilterExpression());
+    }
+
+    @Override
+    protected WhiteboardServiceInfo<EventListener> getServiceInfo(final ServiceReference<EventListener> ref) {
+        return new JavaxListenerInfo(ref);
+    }
+
+    /**
+     * Info for javax listeners
+     */
+    private static final class JavaxListenerInfo extends ListenerInfo {
+
+        /**
+         * Create new info
+         * @param ref Reference to the listener
+         */
+        public JavaxListenerInfo(final ServiceReference<EventListener> ref) {
+            super(ref, getListenerTypes(ref), getDTOListenerTypes(ref));
+        }
+
+        @Override
+        public EventListener getService(final BundleContext bundleContext) {
+            final EventListener listener = ServiceUtils.safeGetServiceObjects(bundleContext, this.getServiceReference());
+            if ( listener == null ) {
+                return null;
+            }
+            return new EventListenerWrapper(listener, this.getListenerTypes());
+        }
+
+        @Override
+        public void ungetService(final BundleContext bundleContext, final EventListener service) {
+            if ( service instanceof EventListenerWrapper ) {
+                final EventListener listener = ((EventListenerWrapper)service).getListener();
+                ServiceUtils.safeUngetServiceObjects(bundleContext, this.getServiceReference(), listener);
+            }
+        }
+
+        private static String[] getDTOListenerTypes(final ServiceReference<EventListener> ref) {
+            final Set<String> services = new HashSet<>();
+            final String[] objectClass = (String[])ref.getProperty(Constants.OBJECTCLASS);
+            for(final String v : objectClass) {
+                if (javax.servlet.http.HttpSessionAttributeListener.class.getName().equals(v)) {
+                    services.add(javax.servlet.http.HttpSessionAttributeListener.class.getName());
+
+                } else if (javax.servlet.http.HttpSessionIdListener.class.getName().equals(v)) {
+                    services.add(javax.servlet.http.HttpSessionIdListener.class.getName());
+
+                } else if (javax.servlet.http.HttpSessionListener.class.getName().equals(v)) {
+                    services.add(javax.servlet.http.HttpSessionListener.class.getName());
+
+                } else if (javax.servlet.ServletContextListener.class.getName().equals(v)) {
+                    services.add(javax.servlet.ServletContextListener.class.getName());
+
+                } else if (javax.servlet.ServletContextAttributeListener.class.getName().equals(v)) {
+                    services.add(javax.servlet.ServletContextAttributeListener.class.getName());
+
+                } else if (javax.servlet.ServletRequestListener.class.getName().equals(v)) {
+                    services.add(javax.servlet.ServletRequestListener.class.getName());
+
+                } else if (javax.servlet.ServletRequestAttributeListener.class.getName().equals(v)) {
+                    services.add(javax.servlet.ServletRequestAttributeListener.class.getName());
+                }
+            }
+            return services.toArray(new String[services.size()]);
+        }
+
+        private static Set<String> getListenerTypes(final ServiceReference<EventListener> ref) {
+            final Set<String> services = new HashSet<>();
+            final String[] objectClass = (String[])ref.getProperty(Constants.OBJECTCLASS);
+            for(final String v : objectClass) {
+                if (javax.servlet.http.HttpSessionAttributeListener.class.getName().equals(v)) {
+                    services.add(HttpSessionAttributeListener.class.getName());
+
+                } else if (javax.servlet.http.HttpSessionIdListener.class.getName().equals(v)) {
+                    services.add(HttpSessionIdListener.class.getName());
+
+                } else if (javax.servlet.http.HttpSessionListener.class.getName().equals(v)) {
+                    services.add(HttpSessionListener.class.getName());
+
+                } else if (javax.servlet.ServletContextListener.class.getName().equals(v)) {
+                    services.add(ServletContextListener.class.getName());
+
+                } else if (javax.servlet.ServletContextAttributeListener.class.getName().equals(v)) {
+                    services.add(ServletContextAttributeListener.class.getName());
+
+                } else if (javax.servlet.ServletRequestListener.class.getName().equals(v)) {
+                    services.add(ServletRequestListener.class.getName());
+
+                } else if (javax.servlet.ServletRequestAttributeListener.class.getName().equals(v)) {
+                    services.add(ServletRequestAttributeListener.class.getName());
+                }
+            }
+            return services;
+        }
+    }
+}
+
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/JavaxPreprocessorTracker.java b/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/JavaxPreprocessorTracker.java
new file mode 100644
index 0000000..293241d
--- /dev/null
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/JavaxPreprocessorTracker.java
@@ -0,0 +1,82 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.felix.http.base.internal.whiteboard.tracker;
+
+import org.apache.felix.http.base.internal.jakartawrappers.PreprocessorWrapper;
+import org.apache.felix.http.base.internal.runtime.PreprocessorInfo;
+import org.apache.felix.http.base.internal.runtime.WhiteboardServiceInfo;
+import org.apache.felix.http.base.internal.util.ServiceUtils;
+import org.apache.felix.http.base.internal.whiteboard.WhiteboardManager;
+import org.apache.felix.http.base.osgi.whiteboard.Preprocessor;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+
+public final class JavaxPreprocessorTracker extends WhiteboardServiceTracker<Preprocessor>
+{
+
+   /**
+     * Create a new tracker
+     * @param bundleContext The bundle context.
+     * @param contextManager The context manager
+     */
+    public JavaxPreprocessorTracker(final BundleContext bundleContext, final WhiteboardManager contextManager)
+    {
+        super(contextManager, bundleContext,
+        		String.format("(objectClass=%s)", org.osgi.service.http.whiteboard.Preprocessor.class.getName()));
+    }
+
+    @Override
+    protected WhiteboardServiceInfo<Preprocessor> getServiceInfo(final ServiceReference<Preprocessor> ref)
+    {
+        return new JavaxPreprocessorInfo(ref);
+    }
+
+    /**
+     * Info for javax listeners
+     */
+    private static final class JavaxPreprocessorInfo extends PreprocessorInfo {
+
+        private final ServiceReference<org.osgi.service.http.whiteboard.Preprocessor> reference;
+
+        /**
+         * Create new info
+         * @param ref Reference to the preprocessor
+         */
+        @SuppressWarnings({ "rawtypes", "unchecked" })
+        public JavaxPreprocessorInfo(final ServiceReference<Preprocessor> ref) {
+            super(ref);
+            this.reference = (ServiceReference)ref;
+        }
+
+        @Override
+        public Preprocessor getService(final BundleContext bundleContext) {
+            final org.osgi.service.http.whiteboard.Preprocessor p = ServiceUtils.safeGetServiceObjects(bundleContext, this.reference);
+            if ( p == null ) {
+                return null;
+            }
+            return new PreprocessorWrapper(p);
+        }
+
+        @Override
+        public void ungetService(final BundleContext bundleContext, final Preprocessor service) {
+            if ( service instanceof PreprocessorWrapper ) {
+                final org.osgi.service.http.whiteboard.Preprocessor p = ((PreprocessorWrapper)service).getPreprocessor();
+                ServiceUtils.safeUngetServiceObjects(bundleContext, this.reference, p);
+            }
+        }
+    }
+}
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/ServletContextHelperTracker.java b/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/JavaxServletContextHelperTracker.java
similarity index 58%
copy from http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/ServletContextHelperTracker.java
copy to http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/JavaxServletContextHelperTracker.java
index 913c46f..316e994 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/ServletContextHelperTracker.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/JavaxServletContextHelperTracker.java
@@ -19,21 +19,23 @@ package org.apache.felix.http.base.internal.whiteboard.tracker;
 import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
 
-import org.jetbrains.annotations.NotNull;
-
+import org.apache.felix.http.base.internal.jakartawrappers.ServletContextHelperWrapper;
 import org.apache.felix.http.base.internal.runtime.ServletContextHelperInfo;
+import org.apache.felix.http.base.internal.util.ServiceUtils;
 import org.apache.felix.http.base.internal.whiteboard.WhiteboardManager;
+import org.apache.felix.http.base.osgi.whiteboard.ServletContextHelper;
+import org.jetbrains.annotations.NotNull;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.Constants;
 import org.osgi.framework.InvalidSyntaxException;
 import org.osgi.framework.ServiceReference;
-import org.osgi.service.http.context.ServletContextHelper;
 import org.osgi.util.tracker.ServiceTracker;
 
 /**
- * Tracks all {@link ServletContextHelper} services.
+ * Tracks all {@link org.osgi.service.http.context.ServletContextHelper} services for
+ * the http whiteboard
  */
-public final class ServletContextHelperTracker extends ServiceTracker<ServletContextHelper, ServiceReference<ServletContextHelper>>
+public final class JavaxServletContextHelperTracker extends ServiceTracker<ServletContextHelper, ServiceReference<ServletContextHelper>>
 {
     private final WhiteboardManager contextManager;
 
@@ -45,7 +47,7 @@ public final class ServletContextHelperTracker extends ServiceTracker<ServletCon
         try
         {
             return btx.createFilter(String.format("(objectClass=%s)",
-                    ServletContextHelper.class.getName()));
+                    org.osgi.service.http.context.ServletContextHelper.class.getName()));
         }
         catch ( final InvalidSyntaxException ise)
         {
@@ -54,7 +56,12 @@ public final class ServletContextHelperTracker extends ServiceTracker<ServletCon
         return null; // we never get here - and if we get an NPE which is fine
     }
 
-    public ServletContextHelperTracker(@NotNull final BundleContext context, @NotNull final WhiteboardManager manager)
+    /**
+     * Create a new tracker
+     * @param context bundle context
+     * @param manager whiteboard manager
+     */
+    public JavaxServletContextHelperTracker(@NotNull final BundleContext context, @NotNull final WhiteboardManager manager)
     {
         super(context, createFilter(context), null);
         this.contextManager = manager;
@@ -88,7 +95,7 @@ public final class ServletContextHelperTracker extends ServiceTracker<ServletCon
 
     private void added(@NotNull final ServiceReference<ServletContextHelper> ref)
     {
-        final ServletContextHelperInfo info = new ServletContextHelperInfo(ref);
+        final ServletContextHelperInfo info = new JavaxServletContextHelperInfo(ref);
         if ( this.contextManager.addContextHelper(info) )
         {
             this.allInfos.put((Long)ref.getProperty(Constants.SERVICE_ID), info);
@@ -103,4 +110,45 @@ public final class ServletContextHelperTracker extends ServiceTracker<ServletCon
             this.contextManager.removeContextHelper(info);
         }
     }
+
+    /**
+     * Filter info for javax filters
+     */
+    private static final class JavaxServletContextHelperInfo extends ServletContextHelperInfo {
+
+        private final ServiceReference<org.osgi.service.http.context.ServletContextHelper> reference;
+
+        /**
+         * Create new info
+         * @param ref Reference to the service
+         */
+        @SuppressWarnings({ "rawtypes", "unchecked" })
+        public JavaxServletContextHelperInfo(final ServiceReference<ServletContextHelper> ref) {
+            super(ref);
+            this.reference = (ServiceReference)ref;
+        }
+
+        @Override
+        public ServletContextHelper getService(final BundleContext bundleContext) {
+            final org.osgi.service.http.context.ServletContextHelper helper = ServiceUtils.safeGetServiceObjects(bundleContext, this.reference);
+            if ( helper == null ) {
+                return null;
+            }
+            return new ServletContextHelperWrapper(helper);
+        }
+
+        @Override
+        public void ungetService(final BundleContext bundleContext, final ServletContextHelper service) {
+            if ( service instanceof ServletContextHelperWrapper ) {
+                final org.osgi.service.http.context.ServletContextHelper helper = ((ServletContextHelperWrapper)service).getHelper();
+                ServiceUtils.safeUngetServiceObjects(bundleContext, this.reference, helper);
+            }
+        }
+
+        @Override
+        public @NotNull String getServiceType() {
+            return org.osgi.service.http.context.ServletContextHelper.class.getName();
+        }
+    }
+
 }
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/JavaxServletTracker.java b/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/JavaxServletTracker.java
new file mode 100644
index 0000000..73c20b2
--- /dev/null
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/JavaxServletTracker.java
@@ -0,0 +1,88 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.felix.http.base.internal.whiteboard.tracker;
+
+import org.apache.felix.http.base.internal.jakartawrappers.ServletWrapper;
+import org.apache.felix.http.base.internal.runtime.ServletInfo;
+import org.apache.felix.http.base.internal.runtime.WhiteboardServiceInfo;
+import org.apache.felix.http.base.internal.util.ServiceUtils;
+import org.apache.felix.http.base.internal.whiteboard.WhiteboardManager;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.http.whiteboard.HttpWhiteboardConstants;
+
+import jakarta.servlet.Servlet;
+
+
+/**
+ * Tracker for http whiteboard servlets
+ */
+public final class JavaxServletTracker extends WhiteboardServiceTracker<Servlet> {
+
+    /**
+     * Create new tracker
+     * @param context bundle context
+     * @param manager whiteboard manager
+     */
+    public JavaxServletTracker(final BundleContext context, final WhiteboardManager manager) {
+        super(manager, context, String.format("(&(objectClass=%s)(|(%s=*)(%s=*)(%s=*)))",
+                javax.servlet.Servlet.class.getName(),
+                HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_NAME,
+                HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_PATTERN,
+                HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_ERROR_PAGE));
+    }
+
+    @Override
+    protected WhiteboardServiceInfo<Servlet> getServiceInfo(final ServiceReference<Servlet> ref) {
+        return new JavaxServletInfo(ref);
+    }
+
+    /**
+     * Servlet info for javax servlets
+     */
+    private static final class JavaxServletInfo extends ServletInfo {
+
+        private final ServiceReference<javax.servlet.Servlet> reference;
+
+        /**
+         * Create new info
+         * @param ref Reference to the servlet
+         */
+        @SuppressWarnings({ "rawtypes", "unchecked" })
+        public JavaxServletInfo(final ServiceReference<Servlet> ref) {
+            super(ref);
+            this.reference = (ServiceReference)ref;
+        }
+
+        @Override
+        public Servlet getService(final BundleContext bundleContext) {
+            final javax.servlet.Servlet servlet = ServiceUtils.safeGetServiceObjects(bundleContext, this.reference);
+            if ( servlet == null ) {
+                return null;
+            }
+            return new ServletWrapper(servlet);
+        }
+
+        @Override
+        public void ungetService(final BundleContext bundleContext, final Servlet service) {
+            if ( service instanceof ServletWrapper ) {
+                final javax.servlet.Servlet servlet = ((ServletWrapper)service).getServlet();
+                ServiceUtils.safeUngetServiceObjects(bundleContext, this.reference, servlet);
+            }
+        }
+    }
+}
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/ListenersTracker.java b/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/ListenersTracker.java
index e758f7b..6ac04ee 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/ListenersTracker.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/ListenersTracker.java
@@ -18,14 +18,6 @@ package org.apache.felix.http.base.internal.whiteboard.tracker;
 
 import java.util.EventListener;
 
-import javax.servlet.ServletContextAttributeListener;
-import javax.servlet.ServletContextListener;
-import javax.servlet.ServletRequestAttributeListener;
-import javax.servlet.ServletRequestListener;
-import javax.servlet.http.HttpSessionAttributeListener;
-import javax.servlet.http.HttpSessionIdListener;
-import javax.servlet.http.HttpSessionListener;
-
 import org.apache.felix.http.base.internal.runtime.ListenerInfo;
 import org.apache.felix.http.base.internal.runtime.WhiteboardServiceInfo;
 import org.apache.felix.http.base.internal.whiteboard.WhiteboardManager;
@@ -33,6 +25,14 @@ import org.osgi.framework.BundleContext;
 import org.osgi.framework.ServiceReference;
 import org.osgi.service.http.whiteboard.HttpWhiteboardConstants;
 
+import jakarta.servlet.ServletContextAttributeListener;
+import jakarta.servlet.ServletContextListener;
+import jakarta.servlet.ServletRequestAttributeListener;
+import jakarta.servlet.ServletRequestListener;
+import jakarta.servlet.http.HttpSessionAttributeListener;
+import jakarta.servlet.http.HttpSessionIdListener;
+import jakarta.servlet.http.HttpSessionListener;
+
 public final class ListenersTracker extends WhiteboardServiceTracker<EventListener>
 {
     /**
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/PreprocessorTracker.java b/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/PreprocessorTracker.java
index 3df5166..ddbd094 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/PreprocessorTracker.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/PreprocessorTracker.java
@@ -19,9 +19,9 @@ package org.apache.felix.http.base.internal.whiteboard.tracker;
 import org.apache.felix.http.base.internal.runtime.PreprocessorInfo;
 import org.apache.felix.http.base.internal.runtime.WhiteboardServiceInfo;
 import org.apache.felix.http.base.internal.whiteboard.WhiteboardManager;
+import org.apache.felix.http.base.osgi.whiteboard.Preprocessor;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.ServiceReference;
-import org.osgi.service.http.whiteboard.Preprocessor;
 
 public final class PreprocessorTracker extends WhiteboardServiceTracker<Preprocessor>
 {
@@ -33,12 +33,12 @@ public final class PreprocessorTracker extends WhiteboardServiceTracker<Preproce
      */
     public PreprocessorTracker(final BundleContext bundleContext, final WhiteboardManager contextManager)
     {
-        super(contextManager, bundleContext, 
+        super(contextManager, bundleContext,
         		String.format("(objectClass=%s)", Preprocessor.class.getName()));
     }
 
     @Override
-    protected WhiteboardServiceInfo<Preprocessor> getServiceInfo(final ServiceReference<Preprocessor> ref) 
+    protected WhiteboardServiceInfo<Preprocessor> getServiceInfo(final ServiceReference<Preprocessor> ref)
     {
         return new PreprocessorInfo(ref);
     }
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/ServletContextHelperTracker.java b/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/ServletContextHelperTracker.java
index 913c46f..93f7665 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/ServletContextHelperTracker.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/ServletContextHelperTracker.java
@@ -19,15 +19,14 @@ package org.apache.felix.http.base.internal.whiteboard.tracker;
 import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
 
-import org.jetbrains.annotations.NotNull;
-
 import org.apache.felix.http.base.internal.runtime.ServletContextHelperInfo;
 import org.apache.felix.http.base.internal.whiteboard.WhiteboardManager;
+import org.apache.felix.http.base.osgi.whiteboard.ServletContextHelper;
+import org.jetbrains.annotations.NotNull;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.Constants;
 import org.osgi.framework.InvalidSyntaxException;
 import org.osgi.framework.ServiceReference;
-import org.osgi.service.http.context.ServletContextHelper;
 import org.osgi.util.tracker.ServiceTracker;
 
 /**
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/ServletTracker.java b/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/ServletTracker.java
index 800fa35..0dccd55 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/ServletTracker.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/ServletTracker.java
@@ -16,8 +16,6 @@
... 881 lines suppressed ...