Updating to new Jax RS concept vs JSON servlet
diff --git a/org.apache.sling.servlets.json/.editorconfig b/org.apache.sling.jaxrs/.editorconfig
similarity index 100%
rename from org.apache.sling.servlets.json/.editorconfig
rename to org.apache.sling.jaxrs/.editorconfig
diff --git a/org.apache.sling.jaxrs/README.md b/org.apache.sling.jaxrs/README.md
new file mode 100644
index 0000000..2c8f167
--- /dev/null
+++ b/org.apache.sling.jaxrs/README.md
@@ -0,0 +1,25 @@
+# Apache Sling JaxRs Json Support
+
+Sling excels at delivering content and experiences, however creating APIs isn't as smooth of an experience.
+
+This is a POC based on the [aries-jax-rs-whiteboard](../aries-jax-rs-whiteboard/) showing how Aries Jax Rs Whiteboard can be incorporated into any modern Sling application and be used to create RESTful applications.
+
+This implementation includes features to support serializing and deserialzing responses from JSON and JSON Problem support including the ability to map ThrowableProblems into responses.
+
+## Use
+
+Run:
+
+    mvn clean install
+
+This will build the code and run the IT which installs the feature models and additional bundles into the local Apache Sling instance and then verifies that the service is responding as expected.
+
+If you want to change the default client configuration, provide following the properties:
+
+ - sling.it.host
+ - sling.it.username
+ - sling.it.password
+
+E.g.:
+
+    mvn clean install -Dsling.it.host=http://localhost:4502
\ No newline at end of file
diff --git a/org.apache.sling.servlets.json/pom.xml b/org.apache.sling.jaxrs/bundle/pom.xml
similarity index 80%
rename from org.apache.sling.servlets.json/pom.xml
rename to org.apache.sling.jaxrs/bundle/pom.xml
index 7c5b214..8de993e 100644
--- a/org.apache.sling.servlets.json/pom.xml
+++ b/org.apache.sling.jaxrs/bundle/pom.xml
@@ -22,14 +22,13 @@
 
     <parent>
         <groupId>org.apache.sling</groupId>
-        <artifactId>sling-bundle-parent</artifactId>
-        <version>48</version>
-        <relativePath />
+        <artifactId>org.apache.sling.jaxrs</artifactId>
+        <version>1.0.0-SNAPSHOT</version>
+        <relativePath>..</relativePath>
     </parent>
 
-    <artifactId>org.apache.sling.servlets.json</artifactId>
-    <version>1.0.0-SNAPSHOT</version>
-    <name>Apache Sling - JSON Servlet</name>
+    <artifactId>org.apache.sling.jaxrs.bundle</artifactId>
+    <name>Apache Sling - Jax-Rs Whiteboard Support</name>
 
     <properties>
         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
@@ -44,12 +43,10 @@
             <plugin>
                 <groupId>biz.aQute.bnd</groupId>
                 <artifactId>bnd-maven-plugin</artifactId>
+
                 <configuration>
                     <bnd>
-                        <![CDATA[
-                        -fixupmessages "Classes found in the wrong directory"; restrict:=error; is:=warning
-                        -includeresource: glob-[0-9\.]*.jar;lib:=true
-                    ]]>
+                      Export-Package: org.apache.sling.jaxrs.json.problem
                     </bnd>
                 </configuration>
             </plugin>
@@ -116,6 +113,25 @@
     </build>
 
     <dependencies>
+
+        <dependency>
+            <groupId>org.apache.aries.spec</groupId>
+            <artifactId>org.apache.aries.javax.jax.rs-api</artifactId>
+            <version>1.0.4</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.aries.jax.rs</groupId>
+            <artifactId>org.apache.aries.jax.rs.whiteboard</artifactId>
+            <version>2.0.1</version>
+            <scope>provided</scope>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.apache.geronimo.specs</groupId>
+                    <artifactId>geronimo-jaxrs_2.1_spec</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
         <dependency>
             <groupId>javax.jcr</groupId>
             <artifactId>jcr</artifactId>
@@ -140,6 +156,18 @@
         </dependency>
         <dependency>
             <groupId>org.osgi</groupId>
+            <artifactId>osgi.core</artifactId>
+            <version>7.0.0</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.osgi</groupId>
+            <artifactId>osgi.cmpn</artifactId>
+            <version>7.0.0</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.osgi</groupId>
             <artifactId>org.osgi.annotation.versioning</artifactId>
             <version>1.0.0</version>
             <scope>provided</scope>
@@ -167,14 +195,10 @@
             <artifactId>slf4j-api</artifactId>
         </dependency>
         <dependency>
-            <groupId>org.osgi</groupId>
-            <artifactId>org.osgi.annotation.versioning</artifactId>
-        </dependency>
-
-        <dependency>
-            <groupId>com.hrakaroo</groupId>
-            <artifactId>glob</artifactId>
-            <version>0.9.0</version>
+            <groupId>org.apache.sling</groupId>
+            <artifactId>org.apache.sling.commons.mime</artifactId>
+            <version>2.2.2</version>
+            <scope>provided</scope>
         </dependency>
 
         <dependency>
diff --git a/org.apache.sling.jaxrs/bundle/src/main/java/org/apache/sling/jaxrs/json/JsonMessageBodyReader.java b/org.apache.sling.jaxrs/bundle/src/main/java/org/apache/sling/jaxrs/json/JsonMessageBodyReader.java
new file mode 100644
index 0000000..9d1d5e3
--- /dev/null
+++ b/org.apache.sling.jaxrs/bundle/src/main/java/org/apache/sling/jaxrs/json/JsonMessageBodyReader.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.sling.jaxrs.json;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.ext.MessageBodyReader;
+import javax.ws.rs.ext.Provider;
+
+import org.osgi.service.component.annotations.Component;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.ObjectReader;
+
+@Component(service = MessageBodyReader.class, property = { "osgi.jaxrs.extension=true" })
+@Provider
+public class JsonMessageBodyReader<T extends Object> implements MessageBodyReader<T> {
+
+    private final ObjectReader reader = new ObjectMapper().reader();
+
+    @Override
+    public boolean isReadable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
+        return mediaType.isCompatible(MediaType.APPLICATION_JSON_TYPE)
+                || mediaType.getType().equals("application") && mediaType.getSubtype().endsWith("json");
+    }
+
+    @Override
+    public T readFrom(Class<T> type, Type genericType, Annotation[] annotations, MediaType mediaType,
+            MultivaluedMap<String, String> httpHeaders, InputStream entityStream)
+            throws IOException, WebApplicationException {
+        return reader.readValue(entityStream, type);
+    }
+
+}
diff --git a/org.apache.sling.jaxrs/bundle/src/main/java/org/apache/sling/jaxrs/json/JsonMessageBodyWriter.java b/org.apache.sling.jaxrs/bundle/src/main/java/org/apache/sling/jaxrs/json/JsonMessageBodyWriter.java
new file mode 100644
index 0000000..6a4d86b
--- /dev/null
+++ b/org.apache.sling.jaxrs/bundle/src/main/java/org/apache/sling/jaxrs/json/JsonMessageBodyWriter.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.sling.jaxrs.json;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.ext.MessageBodyWriter;
+import javax.ws.rs.ext.Provider;
+
+import org.osgi.service.component.annotations.Component;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.ObjectWriter;
+
+@Component(service = MessageBodyWriter.class, property = { "osgi.jaxrs.extension=true" })
+@Provider
+public class JsonMessageBodyWriter implements MessageBodyWriter<Object> {
+
+    private final ObjectWriter writer = new ObjectMapper().writer();
+
+    @Override
+    public boolean isWriteable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
+        return mediaType.isCompatible(MediaType.APPLICATION_JSON_TYPE)
+                || mediaType.getType().equals("application") && mediaType.getSubtype().endsWith("json");
+    }
+
+    @Override
+    public void writeTo(Object t, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType,
+            MultivaluedMap<String, Object> httpHeaders, OutputStream entityStream)
+            throws IOException, WebApplicationException {
+        writer.writeValue(entityStream, t);
+    }
+
+}
diff --git a/org.apache.sling.jaxrs/bundle/src/main/java/org/apache/sling/jaxrs/json/ProblemExceptionMapper.java b/org.apache.sling.jaxrs/bundle/src/main/java/org/apache/sling/jaxrs/json/ProblemExceptionMapper.java
new file mode 100644
index 0000000..5cd3e48
--- /dev/null
+++ b/org.apache.sling.jaxrs/bundle/src/main/java/org/apache/sling/jaxrs/json/ProblemExceptionMapper.java
@@ -0,0 +1,39 @@
+/*
+ * 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.sling.jaxrs.json;
+
+import javax.ws.rs.core.Response;
+import javax.ws.rs.ext.ExceptionMapper;
+import javax.ws.rs.ext.Provider;
+
+import org.apache.sling.jaxrs.json.problem.Problem;
+import org.apache.sling.jaxrs.json.problem.ProblemBuilder;
+import org.apache.sling.jaxrs.json.problem.ThrowableProblem;
+import org.osgi.service.component.annotations.Component;
+
+@Component(service = ExceptionMapper.class, property = { "osgi.jaxrs.extension=true" })
+@Provider
+public class ProblemExceptionMapper implements ExceptionMapper<ThrowableProblem> {
+
+    @Override
+    public Response toResponse(ThrowableProblem exception) {
+        Problem problem = exception.getProblem();
+        return Response.status(problem.getStatus()).header("Content-Type", ProblemBuilder.RESPONSE_CONTENT_TYPE)
+                .entity(problem).build();
+    }
+
+}
diff --git a/org.apache.sling.servlets.json/src/main/java/org/apache/sling/servlets/json/problem/Problem.java b/org.apache.sling.jaxrs/bundle/src/main/java/org/apache/sling/jaxrs/json/problem/Problem.java
similarity index 98%
rename from org.apache.sling.servlets.json/src/main/java/org/apache/sling/servlets/json/problem/Problem.java
rename to org.apache.sling.jaxrs/bundle/src/main/java/org/apache/sling/jaxrs/json/problem/Problem.java
index fbb0b94..feef9a3 100644
--- a/org.apache.sling.servlets.json/src/main/java/org/apache/sling/servlets/json/problem/Problem.java
+++ b/org.apache.sling.jaxrs/bundle/src/main/java/org/apache/sling/jaxrs/json/problem/Problem.java
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.sling.servlets.json.problem;
+package org.apache.sling.jaxrs.json.problem;
 
 import java.net.URI;
 import java.util.HashMap;
diff --git a/org.apache.sling.servlets.json/src/main/java/org/apache/sling/servlets/json/problem/ProblemBuilder.java b/org.apache.sling.jaxrs/bundle/src/main/java/org/apache/sling/jaxrs/json/problem/ProblemBuilder.java
similarity index 99%
rename from org.apache.sling.servlets.json/src/main/java/org/apache/sling/servlets/json/problem/ProblemBuilder.java
rename to org.apache.sling.jaxrs/bundle/src/main/java/org/apache/sling/jaxrs/json/problem/ProblemBuilder.java
index 8ad02e2..d0bff45 100644
--- a/org.apache.sling.servlets.json/src/main/java/org/apache/sling/servlets/json/problem/ProblemBuilder.java
+++ b/org.apache.sling.jaxrs/bundle/src/main/java/org/apache/sling/jaxrs/json/problem/ProblemBuilder.java
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.sling.servlets.json.problem;
+package org.apache.sling.jaxrs.json.problem;
 
 import java.net.URI;
 import java.util.HashMap;
diff --git a/org.apache.sling.servlets.json/src/main/java/org/apache/sling/servlets/json/problem/Problematic.java b/org.apache.sling.jaxrs/bundle/src/main/java/org/apache/sling/jaxrs/json/problem/Problematic.java
similarity index 94%
rename from org.apache.sling.servlets.json/src/main/java/org/apache/sling/servlets/json/problem/Problematic.java
rename to org.apache.sling.jaxrs/bundle/src/main/java/org/apache/sling/jaxrs/json/problem/Problematic.java
index 4988587..0bfc302 100644
--- a/org.apache.sling.servlets.json/src/main/java/org/apache/sling/servlets/json/problem/Problematic.java
+++ b/org.apache.sling.jaxrs/bundle/src/main/java/org/apache/sling/jaxrs/json/problem/Problematic.java
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.sling.servlets.json.problem;
+package org.apache.sling.jaxrs.json.problem;
 
 import org.osgi.annotation.versioning.ConsumerType;
 
diff --git a/org.apache.sling.servlets.json/src/main/java/org/apache/sling/servlets/json/problem/ThrowableProblem.java b/org.apache.sling.jaxrs/bundle/src/main/java/org/apache/sling/jaxrs/json/problem/ThrowableProblem.java
similarity index 95%
rename from org.apache.sling.servlets.json/src/main/java/org/apache/sling/servlets/json/problem/ThrowableProblem.java
rename to org.apache.sling.jaxrs/bundle/src/main/java/org/apache/sling/jaxrs/json/problem/ThrowableProblem.java
index 0f1fdb2..fd26c5d 100644
--- a/org.apache.sling.servlets.json/src/main/java/org/apache/sling/servlets/json/problem/ThrowableProblem.java
+++ b/org.apache.sling.jaxrs/bundle/src/main/java/org/apache/sling/jaxrs/json/problem/ThrowableProblem.java
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.sling.servlets.json.problem;
+package org.apache.sling.jaxrs.json.problem;
 
 import org.osgi.annotation.versioning.ConsumerType;
 
diff --git a/org.apache.sling.jaxrs/bundle/src/main/java/org/apache/sling/jaxrs/json/problem/package-info.java b/org.apache.sling.jaxrs/bundle/src/main/java/org/apache/sling/jaxrs/json/problem/package-info.java
new file mode 100644
index 0000000..9530887
--- /dev/null
+++ b/org.apache.sling.jaxrs/bundle/src/main/java/org/apache/sling/jaxrs/json/problem/package-info.java
@@ -0,0 +1,22 @@
+
+/*
+ * 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.
+ */
+
+@org.osgi.annotation.versioning.Version("1.0.0")
+package org.apache.sling.jaxrs.json.problem;
diff --git a/org.apache.sling.jaxrs/bundle/src/test/java/org/apache/sling/jaxrs/json/JsonMessageBodyReaderTest.java b/org.apache.sling.jaxrs/bundle/src/test/java/org/apache/sling/jaxrs/json/JsonMessageBodyReaderTest.java
new file mode 100644
index 0000000..4eaa8a7
--- /dev/null
+++ b/org.apache.sling.jaxrs/bundle/src/test/java/org/apache/sling/jaxrs/json/JsonMessageBodyReaderTest.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.sling.jaxrs.json;
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.lang.annotation.Annotation;
+import java.util.Map;
+
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.MediaType;
+
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.CsvSource;
+
+class JsonMessageBodyReaderTest {
+
+    private JsonMessageBodyReader<Map> reader = new JsonMessageBodyReader<>();
+
+    @ParameterizedTest
+    @CsvSource(value = {
+            "application/json,true",
+            "application/problem+json,true",
+            "application/xml,false"
+    })
+    void testIsReadable(String mediaType, boolean expected) {
+        assertEquals(expected,
+                reader.isReadable(null, null, new Annotation[0], MediaType.valueOf(mediaType)));
+    }
+
+    @Test
+    void testReadFrom() throws WebApplicationException, IOException {
+        Map read = reader.readFrom(Map.class, getClass(), null, null, null,
+                new ByteArrayInputStream("{\"Hello\":\"World\"}".getBytes()));
+        assertEquals("World", read.get("Hello"));
+    }
+
+}
diff --git a/org.apache.sling.jaxrs/bundle/src/test/java/org/apache/sling/jaxrs/json/JsonMessageBodyWriterTest.java b/org.apache.sling.jaxrs/bundle/src/test/java/org/apache/sling/jaxrs/json/JsonMessageBodyWriterTest.java
new file mode 100644
index 0000000..fb26b39
--- /dev/null
+++ b/org.apache.sling.jaxrs/bundle/src/test/java/org/apache/sling/jaxrs/json/JsonMessageBodyWriterTest.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.sling.jaxrs.json;
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.util.Map;
+
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.MediaType;
+
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.CsvSource;
+
+class JsonMessageBodyWriterTest {
+
+    private JsonMessageBodyWriter writer = new JsonMessageBodyWriter();
+
+    @ParameterizedTest
+    @CsvSource(value = {
+            "application/json,true",
+            "application/problem+json,true",
+            "application/xml,false"
+    })
+    void testIsWriteable(String mediaType, boolean expected) {
+        assertEquals(expected,
+                writer.isWriteable(getClass(), getClass(), null, MediaType.valueOf(mediaType)));
+    }
+
+    @Test
+    void testWriteTo() throws WebApplicationException, IOException {
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        writer.writeTo(Map.of("Hello", "World"), getClass(), getClass(), null, null, null, baos);
+        assertEquals("{\"Hello\":\"World\"}", new String(baos.toByteArray()));
+    }
+
+}
diff --git a/org.apache.sling.jaxrs/bundle/src/test/java/org/apache/sling/jaxrs/json/ProblemExceptionMapperTest.java b/org.apache.sling.jaxrs/bundle/src/test/java/org/apache/sling/jaxrs/json/ProblemExceptionMapperTest.java
new file mode 100644
index 0000000..ef4eeed
--- /dev/null
+++ b/org.apache.sling.jaxrs/bundle/src/test/java/org/apache/sling/jaxrs/json/ProblemExceptionMapperTest.java
@@ -0,0 +1,39 @@
+/*
+ * 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.sling.jaxrs.json;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import javax.ws.rs.core.Response;
+
+import org.apache.sling.jaxrs.json.problem.ProblemBuilder;
+import org.apache.sling.jaxrs.json.problem.ThrowableProblem;
+import org.junit.jupiter.api.Test;
+
+class ProblemExceptionMapperTest {
+
+    @Test
+    void mapsProblem() {
+        ProblemExceptionMapper mapper = new ProblemExceptionMapper();
+        ThrowableProblem throwable = ProblemBuilder.get().withStatus(400).buildThrowable();
+        Response response = mapper.toResponse(throwable);
+        assertEquals(400, response.getStatus());
+        assertEquals("application/problem+json", response.getHeaderString("Content-Type"));
+        assertEquals(throwable.getProblem(), response.getEntity());
+    }
+
+}
diff --git a/org.apache.sling.servlets.json/src/test/java/org/apache/sling/servlets/json/problem/ProblemBuilderTest.java b/org.apache.sling.jaxrs/bundle/src/test/java/org/apache/sling/jaxrs/json/problem/ProblemBuilderTest.java
similarity index 99%
rename from org.apache.sling.servlets.json/src/test/java/org/apache/sling/servlets/json/problem/ProblemBuilderTest.java
rename to org.apache.sling.jaxrs/bundle/src/test/java/org/apache/sling/jaxrs/json/problem/ProblemBuilderTest.java
index 4bea61d..b7002fa 100644
--- a/org.apache.sling.servlets.json/src/test/java/org/apache/sling/servlets/json/problem/ProblemBuilderTest.java
+++ b/org.apache.sling.jaxrs/bundle/src/test/java/org/apache/sling/jaxrs/json/problem/ProblemBuilderTest.java
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.sling.servlets.json.problem;
+package org.apache.sling.jaxrs.json.problem;
 
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertNotNull;
diff --git a/org.apache.sling.jaxrs/it/pom.xml b/org.apache.sling.jaxrs/it/pom.xml
new file mode 100644
index 0000000..1ba58e9
--- /dev/null
+++ b/org.apache.sling.jaxrs/it/pom.xml
@@ -0,0 +1,116 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!--
+  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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <groupId>org.apache.sling</groupId>
+        <artifactId>org.apache.sling.jaxrs</artifactId>
+        <version>1.0.0-SNAPSHOT</version>
+        <relativePath>..</relativePath>
+    </parent>
+
+    <artifactId>org.apache.sling.jaxrs.it</artifactId>
+    <name>Apache Sling - Jax-RS IT</name>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-dependency-plugin</artifactId>
+                <version>3.3.0</version>
+                <executions>
+                    <execution>
+                        <id>download-feature-installer</id>
+                        <phase>generate-sources</phase>
+                        <goals>
+                            <goal>copy</goal>
+                        </goals>
+                        <configuration>
+                            <stripVersion>true</stripVersion>
+                            <artifactItems>
+                                <artifactItem>
+                                    <groupId>org.apache.sling</groupId>
+                                    <artifactId>org.apache.sling.installer.factory.feature</artifactId>
+                                    <version>0.7.0</version>
+                                    <type>jar</type>
+                                </artifactItem>
+                                <artifactItem>
+                                    <groupId>org.apache.sling</groupId>
+                                    <artifactId>org.apache.sling.jaxrs.bundle</artifactId>
+                                    <version>${project.version}</version>
+                                    <type>jar</type>
+                                </artifactItem>
+                                <artifactItem>
+                                    <groupId>org.apache.sling</groupId>
+                                    <artifactId>org.apache.sling.jaxrs.sample</artifactId>
+                                    <version>${project.version}</version>
+                                    <type>jar</type>
+                                </artifactItem>
+                            </artifactItems>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <artifactId>maven-failsafe-plugin</artifactId>
+                <version>2.22.0</version>
+                <executions>
+                    <execution>
+                        <goals>
+                            <goal>integration-test</goal>
+                            <goal>verify</goal>
+                        </goals>
+                    </execution>
+                </executions>
+                <configuration>
+                    <useFile>false</useFile>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+    <dependencies>
+        <dependency>
+            <groupId>com.fasterxml.jackson.core</groupId>
+            <artifactId>jackson-databind</artifactId>
+            <version>2.13.3</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.sling</groupId>
+            <artifactId>org.apache.sling.testing.clients</artifactId>
+            <version>3.0.12</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.junit.jupiter</groupId>
+            <artifactId>junit-jupiter</artifactId>
+            <version>5.8.2</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-simple</artifactId>
+            <version>1.7.36</version>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+</project>
\ No newline at end of file
diff --git a/org.apache.sling.jaxrs/it/src/test/java/org/apache/sling/jaxrs/JaxRsIT.java b/org.apache.sling.jaxrs/it/src/test/java/org/apache/sling/jaxrs/JaxRsIT.java
new file mode 100644
index 0000000..bb81139
--- /dev/null
+++ b/org.apache.sling.jaxrs/it/src/test/java/org/apache/sling/jaxrs/JaxRsIT.java
@@ -0,0 +1,172 @@
+/*
+ * 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.sling.jaxrs;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URI;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.http.NameValuePair;
+import org.apache.http.entity.StringEntity;
+import org.apache.http.message.BasicHeader;
+import org.apache.http.message.BasicNameValuePair;
+import org.apache.sling.testing.clients.ClientException;
+import org.apache.sling.testing.clients.SlingClient;
+import org.apache.sling.testing.clients.SlingHttpResponse;
+import org.apache.sling.testing.clients.osgi.OsgiConsoleClient;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+class JaxRsIT {
+
+    private static final Logger log = LoggerFactory.getLogger(JaxRsIT.class);
+
+    static SlingClient adminClient;
+    private static final ObjectMapper objectMapper = new ObjectMapper();
+
+    @BeforeAll
+    static void beforeAll() throws ClientException, IOException, InterruptedException {
+
+        URI uri = URI.create(System.getProperty("sling.it.host", "http://localhost:8080"));
+        String username = System.getProperty("sling.it.username", "admin");
+        String password = System.getProperty("sling.it.password", "admin");
+
+        log.info("Initializing Sling client with host: {} and user: {}", uri, username);
+        adminClient = new SlingClient(uri, username, password);
+        OsgiConsoleClient osgiConsoleClient = adminClient.adaptTo(OsgiConsoleClient.class);
+
+        if (!adminClient.exists("/apps/system/install/jaxrs.json")) {
+            log.info("Running first time setup...");
+
+            log.info("Installing Feature Installer...");
+            osgiConsoleClient.installBundle(
+                    new File("target/dependency/org.apache.sling.installer.factory.feature.jar"), true);
+            ensureLoaded(osgiConsoleClient);
+        }
+
+        log.info("Updating features...");
+        adminClient.upload(new File("src/test/resources/jaxrs.json"), "application/json",
+                "/apps/system/install/jaxrs.json", true, 200, 201);
+        adminClient.upload(new File("src/test/resources/sample.json"), "application/json",
+                "/apps/system/install/sample.json", true, 200, 201);
+        ensureLoaded(osgiConsoleClient);
+
+        log.info("Updating bundles...");
+        osgiConsoleClient.installBundle(new File("target/dependency/org.apache.sling.jaxrs.bundle.jar"), true);
+        osgiConsoleClient.installBundle(new File("target/dependency/org.apache.sling.jaxrs.sample.jar"), true);
+        ensureLoaded(osgiConsoleClient);
+
+    }
+
+    private static void ensureLoaded(OsgiConsoleClient osgiConsoleClient)
+            throws IOException, InterruptedException, ClientException {
+        boolean featureLoaded = false;
+        for (int i = 0; i < 120 && !featureLoaded; i++) {
+            try {
+                TimeUnit.SECONDS.sleep(1);
+                osgiConsoleClient.getOSGiConfiguration("org.apache.aries.jax.rs.whiteboard~test", 200);
+                Map<String, Object> bundleStatus = getJsonBody("/system/console/bundles.json", Collections.emptyList());
+                String statusString = bundleStatus.get("status").toString();
+                if (!statusString.matches("Bundle information: \\d* bundles in total - all \\d* bundles active.")) {
+                    throw new ClientException("Invalid bundle status: " + statusString);
+                }
+                featureLoaded = true;
+            } catch (ClientException ce) {
+                log.warn("Features not installed: {}", ce.toString());
+                osgiConsoleClient.startBundle("org.apache.sling.jaxrs.sample");
+                osgiConsoleClient.startBundle("org.apache.sling.jaxrs.bundle");
+                TimeUnit.SECONDS.sleep(1);
+            }
+        }
+        if (!featureLoaded) {
+            throw new IOException("Features not loaded after 120 seconds");
+        }
+    }
+
+    private static Map<String, Object> readJsonBody(SlingHttpResponse response) throws IOException {
+        return objectMapper.readValue(response.getContent(),
+                new TypeReference<Map<String, Object>>() {
+                });
+    }
+
+    private static Map<String, Object> getJsonBody(String path, List<NameValuePair> params)
+            throws ClientException, IOException {
+        SlingHttpResponse response = adminClient.doGet(path,
+                params, Collections.emptyList(), 200);
+        return readJsonBody(response);
+    }
+
+    @Test
+    void canGetResource() throws ClientException, IOException {
+        Map<String, Object> properties = getJsonBody("/test/sling/resource",
+                List.of(new BasicNameValuePair("path", "/content")));
+        assertEquals("/content", properties.get("path"));
+        assertNotNull(properties.get("type"));
+    }
+
+    @Test
+    void canHandleProblems() throws ClientException, IOException {
+        SlingHttpResponse response = adminClient.doGet("/test/sling/resource", List.of(), List.of(), 404);
+        assertEquals("application/problem+json", response.getLastHeader("Content-Type").getValue());
+        Map<String, Object> properties = readJsonBody(response);
+        assertEquals("Not Found", properties.get("title"));
+        assertEquals(404, properties.get("status"));
+        assertEquals("Resource null not found", properties.get("detail"));
+    }
+
+    @Test
+    void canGetUserInfo() throws ClientException, IOException {
+        Map<String, Object> properties = getJsonBody("/test/userinfo",
+                List.of());
+        assertEquals("admin", properties.get("userId"));
+    }
+
+    @Test
+    void canGetSinglePath() throws ClientException, IOException {
+        Map<String, Object> properties = getJsonBody("/test/bob",
+                List.of());
+        assertEquals("The single input was bob (3 characters)", properties.get("message"));
+    }
+
+    @Test
+    void canGetTwoPaths() throws ClientException, IOException {
+        Map<String, Object> properties = getJsonBody("/test/bob/sal",
+                List.of());
+        assertEquals("The dual input was bob and sal", properties.get("message"));
+    }
+
+    @Test
+    void canPostBody() throws ClientException, IOException {
+        SlingHttpResponse response = adminClient.doPost("/test/name",
+                new StringEntity(objectMapper.writeValueAsString(Map.of("name", "Sling"))),
+                List.of(new BasicHeader("Content-Type", "application/json")), 200);
+        Map<String, Object> properties = readJsonBody(response);
+        assertEquals("Hello Sling!", properties.get("message"));
+    }
+}
diff --git a/org.apache.sling.jaxrs/it/src/test/resources/jaxrs.json b/org.apache.sling.jaxrs/it/src/test/resources/jaxrs.json
new file mode 100644
index 0000000..c6be125
--- /dev/null
+++ b/org.apache.sling.jaxrs/it/src/test/resources/jaxrs.json
@@ -0,0 +1,79 @@
+{
+    "id": "org.apache.sling:org.apache.sling.jaxrs.feature:1.0.0",
+    "bundles": [
+      {
+        "id": "org.osgi:org.osgi.service.jaxrs:1.0.0",
+        "start-order": 20
+      },
+      {
+        "id": "org.apache.aries.spec:org.apache.aries.javax.jax.rs-api:1.0.4",
+        "start-order": 20
+      },
+      {
+        "id": "org.apache.aries.jax.rs:org.apache.aries.jax.rs.whiteboard:2.0.1",
+        "start-order": 20
+      },
+      {
+        "id": "org.apache.aries.component-dsl:org.apache.aries.component-dsl.component-dsl:1.2.2",
+        "start-order": 20
+      },
+      {
+        "id": "org.apache.cxf:cxf-core:3.4.3",
+        "start-order": 20
+      },
+      {
+        "id": "org.apache.cxf:cxf-rt-rs-client:3.4.3",
+        "start-order": 20
+      },
+      {
+        "id": "org.apache.cxf:cxf-rt-frontend-jaxrs:3.4.3",
+        "start-order": 20
+      },
+      {
+        "id": "org.apache.cxf:cxf-rt-rs-sse:3.4.3",
+        "start-order": 20
+      },
+      {
+        "id": "com.fasterxml.woodstox:woodstox-core:6.2.4",
+        "start-order": 20
+      },
+      {
+        "id": "org.glassfish.jaxb:jaxb-runtime:2.3.3",
+        "start-order": 20
+      },
+      {
+        "id": "org.apache.cxf:cxf-rt-transports-http:3.4.3",
+        "start-order": 20
+      },
+      {
+        "id": "org.apache.ws.xmlschema:xmlschema-core:2.2.5",
+        "start-order": 20
+      },
+      {
+        "id": "org.codehaus.woodstox:stax2-api:4.2.1",
+        "start-order": 20
+      },
+      {
+        "id": "jakarta.xml.bind:jakarta.xml.bind-api:2.3.3",
+        "start-order": 20
+      },
+      {
+        "id": "com.sun.xml.bind:jaxb-osgi:2.3.3",
+        "start-order": 20
+      },
+      {
+        "id": "org.apache.cxf:cxf-rt-security:3.4.3",
+        "start-order": 20
+      },
+      {
+        "id": "org.apache.aries.spifly:org.apache.aries.spifly.dynamic.framework.extension:1.3.3",
+        "start-order": 20
+      }
+    ],
+    "configurations": {
+      "org.apache.aries.jax.rs.whiteboard.default": {
+        "default.application.base": "/api/jaxrs",
+        "osgi.http.whiteboard.context.select": "(osgi.http.whiteboard.context.name=org.apache.sling)"
+      }
+    }
+  }
diff --git a/org.apache.sling.jaxrs/it/src/test/resources/sample.json b/org.apache.sling.jaxrs/it/src/test/resources/sample.json
new file mode 100644
index 0000000..730a32d
--- /dev/null
+++ b/org.apache.sling.jaxrs/it/src/test/resources/sample.json
@@ -0,0 +1,11 @@
+{
+    "id": "org.apache.sling:org.apache.sling.jaxrs-sample.feature:1.0.0",
+    "configurations": {
+      "org.apache.aries.jax.rs.whiteboard~test": {
+        "enabled": true,
+        "jax.rs.whiteboard.name": "test",
+        "default.application.base": "/",
+        "osgi.http.whiteboard.context.select": "(osgi.http.whiteboard.context.name=org.apache.sling.test)"
+      }
+    }
+  }
diff --git a/org.apache.sling.jaxrs/pom.xml b/org.apache.sling.jaxrs/pom.xml
new file mode 100644
index 0000000..0954c47
--- /dev/null
+++ b/org.apache.sling.jaxrs/pom.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!--
+  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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <groupId>org.apache.sling</groupId>
+        <artifactId>sling-bundle-parent</artifactId>
+        <version>48</version>
+        <relativePath />
+    </parent>
+
+    <artifactId>org.apache.sling.jaxrs</artifactId>
+    <version>1.0.0-SNAPSHOT</version>
+    <name>Apache Sling - Jax-RS Whiteboard Support</name>
+    <packaging>pom</packaging>
+
+    <properties>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+        <sling.java.version>11</sling.java.version>
+        <bnd.baseline.fail.on.missing>false</bnd.baseline.fail.on.missing>
+    </properties>
+
+    <modules>
+        <module>bundle</module>
+        <module>sample</module>
+        <module>it</module>
+    </modules>
+</project>
\ No newline at end of file
diff --git a/org.apache.sling.servlets.json/pom.xml b/org.apache.sling.jaxrs/sample/pom.xml
similarity index 63%
copy from org.apache.sling.servlets.json/pom.xml
copy to org.apache.sling.jaxrs/sample/pom.xml
index 7c5b214..360e017 100644
--- a/org.apache.sling.servlets.json/pom.xml
+++ b/org.apache.sling.jaxrs/sample/pom.xml
@@ -22,21 +22,18 @@
 
     <parent>
         <groupId>org.apache.sling</groupId>
-        <artifactId>sling-bundle-parent</artifactId>
-        <version>48</version>
-        <relativePath />
+        <artifactId>org.apache.sling.jaxrs</artifactId>
+        <version>1.0.0-SNAPSHOT</version>
+        <relativePath>..</relativePath>
     </parent>
 
-    <artifactId>org.apache.sling.servlets.json</artifactId>
-    <version>1.0.0-SNAPSHOT</version>
-    <name>Apache Sling - JSON Servlet</name>
+    <artifactId>org.apache.sling.jaxrs.sample</artifactId>
+    <name>Apache Sling - Jax-RS Sample</name>
 
     <properties>
         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
         <sling.java.version>11</sling.java.version>
         <bnd.baseline.fail.on.missing>false</bnd.baseline.fail.on.missing>
-
-        <required.coverage>0.85</required.coverage>
     </properties>
 
     <build>
@@ -44,53 +41,6 @@
             <plugin>
                 <groupId>biz.aQute.bnd</groupId>
                 <artifactId>bnd-maven-plugin</artifactId>
-                <configuration>
-                    <bnd>
-                        <![CDATA[
-                        -fixupmessages "Classes found in the wrong directory"; restrict:=error; is:=warning
-                        -includeresource: glob-[0-9\.]*.jar;lib:=true
-                    ]]>
-                    </bnd>
-                </configuration>
-            </plugin>
-            <plugin>
-                <groupId>org.jacoco</groupId>
-                <artifactId>jacoco-maven-plugin</artifactId>
-                <version>0.8.7</version>
-                <executions>
-                    <execution>
-                        <goals>
-                            <goal>prepare-agent</goal>
-                        </goals>
-                    </execution>
-                    <execution>
-                        <id>report</id>
-                        <phase>prepare-package</phase>
-                        <goals>
-                            <goal>report</goal>
-                        </goals>
-                    </execution>
-                    <execution>
-                        <id>jacoco-check</id>
-                        <goals>
-                            <goal>check</goal>
-                        </goals>
-                        <configuration>
-                            <rules>
-                                <rule>
-                                    <element>PACKAGE</element>
-                                    <limits>
-                                        <limit>
-                                            <counter>LINE</counter>
-                                            <value>COVEREDRATIO</value>
-                                            <minimum>${required.coverage}</minimum>
-                                        </limit>
-                                    </limits>
-                                </rule>
-                            </rules>
-                        </configuration>
-                    </execution>
-                </executions>
             </plugin>
 
             <plugin>
@@ -117,6 +67,37 @@
 
     <dependencies>
         <dependency>
+            <groupId>org.apache.sling</groupId>
+            <artifactId>org.apache.sling.jaxrs.bundle</artifactId>
+            <version>1.0.0-SNAPSHOT</version>
+            <scope>provided</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.aries.spec</groupId>
+            <artifactId>org.apache.aries.javax.jax.rs-api</artifactId>
+            <version>1.0.4</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.sling</groupId>
+            <artifactId>org.apache.sling.auth.core</artifactId>
+            <version>1.5.6</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.aries.jax.rs</groupId>
+            <artifactId>org.apache.aries.jax.rs.whiteboard</artifactId>
+            <version>2.0.1</version>
+            <scope>provided</scope>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.apache.geronimo.specs</groupId>
+                    <artifactId>geronimo-jaxrs_2.1_spec</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
             <groupId>javax.jcr</groupId>
             <artifactId>jcr</artifactId>
         </dependency>
@@ -127,12 +108,6 @@
             <scope>provided</scope>
         </dependency>
         <dependency>
-            <groupId>org.apache.sling</groupId>
-            <artifactId>org.apache.sling.auth.core</artifactId>
-            <version>1.5.6</version>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
             <groupId>javax.servlet</groupId>
             <artifactId>servlet-api</artifactId>
             <version>2.5</version>
@@ -140,6 +115,18 @@
         </dependency>
         <dependency>
             <groupId>org.osgi</groupId>
+            <artifactId>osgi.core</artifactId>
+            <version>7.0.0</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.osgi</groupId>
+            <artifactId>osgi.cmpn</artifactId>
+            <version>7.0.0</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.osgi</groupId>
             <artifactId>org.osgi.annotation.versioning</artifactId>
             <version>1.0.0</version>
             <scope>provided</scope>
@@ -157,24 +144,14 @@
             <scope>provided</scope>
         </dependency>
         <dependency>
-            <groupId>com.fasterxml.jackson.core</groupId>
-            <artifactId>jackson-databind</artifactId>
-            <version>2.13.3</version>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
             <groupId>org.slf4j</groupId>
             <artifactId>slf4j-api</artifactId>
         </dependency>
         <dependency>
-            <groupId>org.osgi</groupId>
-            <artifactId>org.osgi.annotation.versioning</artifactId>
-        </dependency>
-
-        <dependency>
-            <groupId>com.hrakaroo</groupId>
-            <artifactId>glob</artifactId>
-            <version>0.9.0</version>
+            <groupId>org.apache.sling</groupId>
+            <artifactId>org.apache.sling.commons.mime</artifactId>
+            <version>2.2.2</version>
+            <scope>provided</scope>
         </dependency>
 
         <dependency>
diff --git a/org.apache.sling.jaxrs/sample/src/main/features/jaxrs-sample.json b/org.apache.sling.jaxrs/sample/src/main/features/jaxrs-sample.json
new file mode 100644
index 0000000..65f0b94
--- /dev/null
+++ b/org.apache.sling.jaxrs/sample/src/main/features/jaxrs-sample.json
@@ -0,0 +1,11 @@
+{
+    "id": "org.apache.sling:jaxrs-sample:1.0",
+    "configurations": {
+      "org.apache.aries.jax.rs.whiteboard~test": {
+        "enabled": true,
+        "jax.rs.whiteboard.name": "test",
+        "default.application.base": "/",
+        "osgi.http.whiteboard.context.select": "(osgi.http.whiteboard.context.name=org.apache.sling.test)"
+      }
+    }
+  }
diff --git a/org.apache.sling.jaxrs/sample/src/main/java/org/apache/sling/jaxrs/sample/JaxRsServlet.java b/org.apache.sling.jaxrs/sample/src/main/java/org/apache/sling/jaxrs/sample/JaxRsServlet.java
new file mode 100644
index 0000000..d272e89
--- /dev/null
+++ b/org.apache.sling.jaxrs/sample/src/main/java/org/apache/sling/jaxrs/sample/JaxRsServlet.java
@@ -0,0 +1,114 @@
+/*
+ * 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.sling.jaxrs.sample;
+
+import java.util.Map;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.MediaType;
+
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.api.resource.ResourceResolver;
+import org.apache.sling.api.resource.ResourceResolverFactory;
+import org.apache.sling.jaxrs.json.problem.ProblemBuilder;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Reference;
+import org.osgi.service.jaxrs.whiteboard.propertytypes.JaxrsApplicationSelect;
+import org.osgi.service.jaxrs.whiteboard.propertytypes.JaxrsResource;
+
+@Path("/")
+@Produces(MediaType.APPLICATION_JSON)
+@Component(service = JaxRsServlet.class)
+@JaxrsResource
+@JaxrsApplicationSelect(value = "(jax.rs.whiteboard.name=test)")
+public class JaxRsServlet {
+
+    static int counter;
+
+    @Reference
+    private ResourceResolverFactory factory;
+
+    ResourceResolver getResourceResolver(HttpServletRequest request) {
+        ResourceResolver rr = factory.getThreadResourceResolver();
+        if (rr != null) {
+            return rr;
+        }
+        throw new IllegalStateException("Request does not provide a ResourceResolver");
+    }
+
+    @GET
+    @Path("/sling/resource")
+    public Map<String, Object> getResource(@Context HttpServletRequest request, @QueryParam("path") String path) {
+        try (ResourceResolver rr = getResourceResolver(request)) {
+            final Resource r = rr.getResource(path);
+            if (r == null) {
+                throw ProblemBuilder.get().withStatus(404).withDetail(String.format("Resource %s not found", path))
+                        .buildThrowable();
+            }
+            return Map.of("path", r.getPath(), "type", r.getResourceType());
+        }
+    }
+
+    @GET
+    @Path("/userinfo")
+    public Map<String, Object> getUserInfo(@Context HttpServletRequest request) throws Exception {
+        try (ResourceResolver rr = getResourceResolver(request)) {
+            return Map.of("userId", rr.getUserID());
+        }
+    }
+
+    @GET
+    @Path("/{one}")
+    public Map<String, Object> getOne(@PathParam("one") String one) {
+        return Map.of("message", String.format(
+                "The single input was %s (%d characters)",
+                one, one.length(), counter));
+    }
+
+    @GET
+    @Path("/{one}/{two}")
+    public Map<String, Object> getTwo(@PathParam("one") String one, @PathParam("two") String two) {
+        return Map.of("message", String.format(
+                "The dual input was %s and %s",
+                one, two, counter));
+    }
+
+    @POST
+    @Path("/name")
+    @Consumes(MediaType.APPLICATION_JSON)
+    public static Map<String, Object> echoName(Map<String, Object> params) {
+        return Map.of("message", "Hello " + params.get("name") + "!");
+    }
+
+    @POST
+    @Path("/increment/{howMuch}")
+    @Consumes(MediaType.WILDCARD)
+    public static Map<String, Object> incrementCounter(@PathParam("howMuch") int howMuch) {
+        counter += howMuch;
+        return Map.of("message", String.format(
+                "The counter has been incremented by %d and is now %d%n",
+                howMuch, counter));
+    }
+}
diff --git a/org.apache.sling.jaxrs/sample/src/main/java/org/apache/sling/jaxrs/sample/TestHttpContext.java b/org.apache.sling.jaxrs/sample/src/main/java/org/apache/sling/jaxrs/sample/TestHttpContext.java
new file mode 100644
index 0000000..70dc48d
--- /dev/null
+++ b/org.apache.sling.jaxrs/sample/src/main/java/org/apache/sling/jaxrs/sample/TestHttpContext.java
@@ -0,0 +1,142 @@
+/*
+ * 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.sling.jaxrs.sample;
+
+import java.io.IOException;
+import java.net.URL;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletRequestWrapper;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.sling.auth.core.AuthenticationSupport;
+import org.apache.sling.commons.mime.MimeTypeService;
+import org.osgi.service.component.annotations.Activate;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Reference;
+import org.osgi.service.http.context.ServletContextHelper;
+import org.osgi.service.http.whiteboard.HttpWhiteboardConstants;
+
+/**
+ * Context that registers an HTTP whiteboard for "/test".
+ */
+@Component(service = ServletContextHelper.class, property = {
+        HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_NAME + "=" + TestHttpContext.CONTEXT_NAME,
+        HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_PATH + "=" + TestHttpContext.CONTEXT_PATH
+})
+public class TestHttpContext extends ServletContextHelper {
+
+    public static final String CONTEXT_NAME = "org.apache.sling.test";
+    public static final String CONTEXT_PATH = "/test";
+
+    private final MimeTypeService mimeTypeService;
+
+    private final AuthenticationSupport authenticationSupport;
+
+    /**
+     * Constructs a new context that will use the given dependencies.
+     *
+     * @param mimeTypeService       Used when providing mime type of requests.
+     * @param authenticationSupport Used to authenticate requests with sling.
+     */
+    @Activate
+    public TestHttpContext(@Reference final MimeTypeService mimeTypeService,
+            @Reference final AuthenticationSupport authenticationSupport) {
+        this.mimeTypeService = mimeTypeService;
+        this.authenticationSupport = authenticationSupport;
+    }
+
+    // ---------- HttpContext interface ----------------------------------------
+    /**
+     * Returns the MIME type as resolved by the <code>MimeTypeService</code> or
+     * <code>null</code> if the service is not available.
+     */
+    @Override
+    public String getMimeType(String name) {
+        MimeTypeService mtservice = mimeTypeService;
+        if (mtservice != null) {
+            return mtservice.getMimeType(name);
+        }
+        return null;
+    }
+
+    /**
+     * Returns the real context path that is used to mount this context.
+     *
+     * @param req servlet request
+     * @return the context path
+     */
+    public static String getRealContextPath(HttpServletRequest req) {
+        final String path = req.getContextPath();
+        if (path.equals(CONTEXT_PATH)) {
+            return "";
+        }
+        return path.substring(CONTEXT_PATH.length());
+    }
+
+    /**
+     * Returns a request wrapper that transforms the context path back to the
+     * original one
+     *
+     * @param req request
+     * @return the request wrapper
+     */
+    public static HttpServletRequest createContextPathAdapterRequest(HttpServletRequest req) {
+        return new HttpServletRequestWrapper(req) {
+
+            @Override
+            public String getContextPath() {
+                return getRealContextPath((HttpServletRequest) getRequest());
+            }
+
+        };
+
+    }
+
+    /**
+     * Always returns <code>null</code> because resources are all provided
+     * through individual endpoint implementations.
+     */
+    @Override
+    public URL getResource(String name) {
+        return null;
+    }
+
+    /**
+     * Tries to authenticate the request using the
+     * <code>SlingAuthenticator</code>. If the authenticator or the Repository
+     * is missing this method returns <code>false</code> and sends a 503/SERVICE
+     * UNAVAILABLE status back to the client.
+     */
+    @Override
+    public boolean handleSecurity(HttpServletRequest request,
+            HttpServletResponse response) throws IOException {
+
+        final AuthenticationSupport authenticator = this.authenticationSupport;
+        if (authenticator != null) {
+            return authenticator.handleSecurity(createContextPathAdapterRequest(request), response);
+        }
+
+        // send 503/SERVICE UNAVAILABLE, flush to ensure delivery
+        response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE,
+                "AuthenticationSupport service missing. Cannot authenticate request.");
+        response.flushBuffer();
+
+        // terminate this request now
+        return false;
+    }
+}
diff --git a/org.apache.sling.servlets.json/README.md b/org.apache.sling.servlets.json/README.md
deleted file mode 100644
index d3b265a..0000000
--- a/org.apache.sling.servlets.json/README.md
+++ /dev/null
@@ -1,34 +0,0 @@
-# Apache Sling JSON Servlet Support
-
-Sling excels at delivering content and experiences, however creating APIs isn't as smooth of an experience.
-
-Apache Sling JSON Servlet support enables developers to easily create REST API's on top of Apache Sling. This library includes:
-
- - Implementation of non-Resource-based Servlets for creating OSGi Whiteboard APIs
- - Built-in methods for deserializing requests and serializing responses to JSON
- - Built-in support for [RFC-7807 JSON Problem](https://datatracker.ietf.org/doc/html/rfc7807) responses
- - Extensions of Java's default HttpServlet which ensures exceptions are returned as JSON Problem responses with reasonable HTTP codes
-
-## Use
-
-After installing the bundle, you can create Servlets using the OSGi HTTP whiteboard context:
-
-    @Component(service = { Servlet.class })
-    @HttpWhiteboardContextSelect("(" + HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_NAME + "=com.company.restapi)")
-    @HttpWhiteboardServletPattern("/myapi/*")
-    public class MyApiServlet extends JacksonJsonServlet {
-
-        protected void doPost(@NotNull HttpServletRequest request, @NotNull HttpServletResponse response)
-                throws ServletException, IOException {
-            Map<String, Object> properties = super.readRequestBody(request, new TypeReference<Map<String, Object>>() {
-            });
-            String name = properties.get("name");
-            if (StringUtils.isBlank(name)) {
-                super.sendProblemResponse(response, ProblemBuilder.get().withStatus(400).withDetails("Please provide a name").build());
-            } else {
-                Map responseBody = Map.of("message", "Greetings " + name);
-                super.sendJsonResponse(response, responseBody);
-            }
-        }
-    }
-
diff --git a/org.apache.sling.servlets.json/src/main/java/org/apache/sling/servlets/json/BaseJsonServlet.java b/org.apache.sling.servlets.json/src/main/java/org/apache/sling/servlets/json/BaseJsonServlet.java
deleted file mode 100644
index e63c12f..0000000
--- a/org.apache.sling.servlets.json/src/main/java/org/apache/sling/servlets/json/BaseJsonServlet.java
+++ /dev/null
@@ -1,156 +0,0 @@
-/*
- * 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.sling.servlets.json;
-
-import java.io.IOException;
-import java.util.Optional;
-import java.util.Set;
-
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.apache.sling.api.resource.LoginException;
-import org.apache.sling.api.resource.ResourceResolver;
-import org.apache.sling.auth.core.AuthenticationSupport;
-import org.apache.sling.servlets.json.problem.Problem;
-import org.apache.sling.servlets.json.problem.ProblemBuilder;
-import org.jetbrains.annotations.NotNull;
-import org.osgi.annotation.versioning.ConsumerType;
-
-import com.fasterxml.jackson.core.type.TypeReference;
-
-/**
- * An extension of the SlingAllMethodsServlet tailored to producing JSON APIs.
- * <p>
- * This class adds support for PATCH requests and adds several different useful
- * base methods for reading the response body as JSON, writing an object as JSON
- * and sending problems as RFC 7807-compliant JSON+Problem responses
- * <p>
- * This class also catches ServletException, IOException and
- * RuntimeExceptions thrown from the called methods and sends a JSON
- * Problem response based on the thrown exception
- */
-@ConsumerType
-public interface BaseJsonServlet {
-
-    static final String RESPONSE_CONTENT_TYPE = "application/json";
-
-    static final Set<String> SERVLET_SUPPORTED_METHODS = Set.of("GET", "HEAD", "POST", "PUT", "DELETE",
-            "OPTIONS", "TRACE");
-
-    /**
-     * Retrieves a <code>ResourceResolver</code> that can be used to perform various
-     * operations against the underlying repository.
-     *
-     * @return Resolver for performing operations. Will not be null.
-     * @throws LoginException unable to find resource resolver in request
-     */
-    default @NotNull ResourceResolver getResourceResolver(@NotNull HttpServletRequest request) throws LoginException {
-        return Optional.ofNullable(request.getAttribute(AuthenticationSupport.REQUEST_ATTRIBUTE_RESOLVER))
-                .map(ResourceResolver.class::cast)
-                .orElseThrow(() -> new LoginException("Could not get ResourceResolver from request"));
-    }
-
-    /**
-     * Read an object from the request, handing invalid or missing request bodies
-     * and returning a 400 response.
-     *
-     * @param <T>     the type of object to be read from the request
-     * @param request the request from which to read the object
-     * @param type    the class of the type to read
-     * @return the object read from the request
-     */
-    <T> T readRequestBody(HttpServletRequest request, Class<T> type);
-
-    /**
-     * Read an object from the request, handing invalid or missing request bodies
-     * and returning a 400 response.
-     *
-     * @param <T>     the type of object to be read from the request
-     * @param request the request from which to read the object
-     * @param type    the class of the type to read
-     * @return the object read from the request
-     */
-    <T> T readRequestBody(HttpServletRequest request, TypeReference<T> type);
-
-    /**
-     * Sends a JSON response with the content type application/json and a 200 status
-     * code.
-     *
-     * @param response     the response to which to write
-     * @param responseBody the object to write to the response
-     * @throws IOException an exception occurs writing the object to the response
-     */
-    default void sendJsonResponse(HttpServletResponse response, Object responseBody)
-            throws IOException {
-        sendJsonResponse(response, HttpServletResponse.SC_OK, responseBody);
-    }
-
-    /**
-     * Sends a JSON response with the content type application/json
-     *
-     * @param response     the response to which to write
-     * @param statusCode   the status code to send for the response
-     * @param responseBody the object to write to the response
-     * @throws IOException an exception occurs writing the object to the response
-     */
-    default void sendJsonResponse(HttpServletResponse response, int statusCode, Object responseBody)
-            throws IOException {
-        sendJsonResponse(response, statusCode, RESPONSE_CONTENT_TYPE, responseBody);
-    }
-
-    /**
-     * Sends a JSON response by serializing the responseBody object into JSON
-     *
-     * @param response     the response to which to write
-     * @param statusCode   the status code to send for the response
-     * @param contentType  the content type to send for the response
-     * @param responseBody the object to write to the response
-     * @throws IOException an exception occurs writing the object to the response
-     */
-    void sendJsonResponse(HttpServletResponse response, int statusCode, String contentType,
-            Object responseBody) throws IOException;
-
-    /**
-     * Sends a problem response, setting the status based on the status of the
-     * ProblemBuilder, the content type application/problem+json and the body being
-     * the the problem JSON
-     *
-     * @param response       the response to which to write the problem
-     * @param problemBuilder the problem to write
-     * @throws IOException Thrown if the problem cannot be written to the response
-     */
-    default void sendProblemResponse(HttpServletResponse response, Problem problem)
-            throws IOException {
-        sendJsonResponse(response, problem.getStatus(), ProblemBuilder.RESPONSE_CONTENT_TYPE,
-                problem);
-    }
-
-    /**
-     * Helper method which causes an method not allowed HTTP and JSON problem
-     * response to be sent for an unhandled HTTP request method.
-     *
-     * @param request  Required for method override
-     * @param response The HTTP response to which the error status is sent.
-     * @throws IOException Thrown if the status cannot be sent to the client.
-     */
-    default void handleMethodNotImplemented(@NotNull HttpServletRequest request,
-            @NotNull HttpServletResponse response) throws IOException {
-        sendProblemResponse(response,
-                ProblemBuilder.get().withStatus(HttpServletResponse.SC_METHOD_NOT_ALLOWED).build());
-    }
-}
diff --git a/org.apache.sling.servlets.json/src/main/java/org/apache/sling/servlets/json/DynamicRequestServlet.java b/org.apache.sling.servlets.json/src/main/java/org/apache/sling/servlets/json/DynamicRequestServlet.java
deleted file mode 100644
index 55d7f9f..0000000
--- a/org.apache.sling.servlets.json/src/main/java/org/apache/sling/servlets/json/DynamicRequestServlet.java
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * 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.sling.servlets.json;
-
-import java.io.IOException;
-
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.apache.sling.servlets.json.dynamicrequest.DynamicRequestMapper;
-import org.apache.sling.servlets.json.problem.ProblemBuilder;
-import org.apache.sling.servlets.json.problem.Problematic;
-import org.jetbrains.annotations.NotNull;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class DynamicRequestServlet extends JacksonJsonServlet {
-
-    private static final Logger log = LoggerFactory.getLogger(DynamicRequestServlet.class);
-
-    private final DynamicRequestMapper mapper;
-
-    public DynamicRequestServlet() {
-        mapper = new DynamicRequestMapper(this);
-    }
-
-    /**
-     * Tries to handle the request by calling a Java method implemented for the
-     * respective HTTP request method.
-     * <p>
-     * This implementation first attempts to resolve handling methods by
-     * identifying methods with the @RequestHandler annotation which
-     * apply to the provided request. Any such request handler
-     * <p>
-     * In addition, this method catches ServletException, IOException and
-     * RuntimeExceptions thrown from the called methods and sends a JSON
-     * Problem response based on the thrown exception
-     *
-     * @param request  The HTTP request
-     * @param response The HTTP response
-     * @return <code>true</code> if the requested method
-     *         (<code>request.getMethod()</code>)
-     *         is known. Otherwise <code>false</code> is returned.
-     * @throws ServletException Forwarded from any of the dispatched methods
-     * @throws IOException      Forwarded from any of the dispatched methods
-     */
-    @Override
-    protected void service(@NotNull HttpServletRequest request,
-            @NotNull HttpServletResponse response) throws ServletException,
-            IOException {
-        boolean serviced = false;
-        try {
-            serviced = mapper.mayService(request, response);
-            if (!serviced) {
-                super.service(request, response);
-            }
-        } catch (IOException | ServletException | RuntimeException e) {
-            if (e instanceof Problematic) {
-                sendProblemResponse(response, ((Problematic) e).getProblem());
-            } else {
-                log.error("Handing uncaught exception", e);
-                sendProblemResponse(response, ProblemBuilder.get().fromException(e).build());
-            }
-        }
-    }
-
-}
diff --git a/org.apache.sling.servlets.json/src/main/java/org/apache/sling/servlets/json/JacksonJsonServlet.java b/org.apache.sling.servlets.json/src/main/java/org/apache/sling/servlets/json/JacksonJsonServlet.java
deleted file mode 100644
index a220f9a..0000000
--- a/org.apache.sling.servlets.json/src/main/java/org/apache/sling/servlets/json/JacksonJsonServlet.java
+++ /dev/null
@@ -1,297 +0,0 @@
-/*
- * 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.sling.servlets.json;
-
-import java.io.IOException;
-import java.nio.charset.StandardCharsets;
-
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.apache.sling.servlets.json.problem.ProblemBuilder;
-import org.apache.sling.servlets.json.problem.Problematic;
-import org.jetbrains.annotations.NotNull;
-import org.osgi.annotation.versioning.ConsumerType;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.fasterxml.jackson.core.type.TypeReference;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.databind.ObjectReader;
-import com.fasterxml.jackson.databind.ObjectWriter;
-
-/**
- * An extension of the BaseJsonServlet using Jackson for serialization.
- */
-@ConsumerType
-public abstract class JacksonJsonServlet extends HttpServlet implements BaseJsonServlet {
-
-    private static final Logger log = LoggerFactory.getLogger(JacksonJsonServlet.class);
-
-    private static final ObjectMapper objectMapper = new ObjectMapper();
-    private static final ObjectWriter objectWriter = objectMapper.writer();
-    private static final ObjectReader objectReader = objectMapper.reader();
-
-    /**
-     * Called by the
-     * {@link #service(HttpServletRequest, HttpServletResponse)} method
-     * to handle an HTTP <em>GET</em> request.
-     * <p>
-     * This default implementation reports back to the client that the method is
-     * not supported.
-     * <p>
-     * Implementations of this class should overwrite this method with their
-     * implementation for the HTTP <em>PATCH</em> method support.
-     *
-     * @param request  The HTTP request
-     * @param response The HTTP response
-     * @throws ServletException Not thrown by this implementation.
-     * @throws IOException      If the error status cannot be reported back to the
-     *                          client.
-     */
-    @Override
-    protected void doGet(final HttpServletRequest req, final HttpServletResponse resp)
-            throws ServletException, IOException {
-        sendProblemResponse(resp, ProblemBuilder.get().withStatus(HttpServletResponse.SC_METHOD_NOT_ALLOWED).build());
-    }
-
-    /**
-     * Called by the
-     * {@link #service(HttpServletRequest, HttpServletResponse)} method
-     * to handle an HTTP <em>POST</em> request.
-     * <p>
-     * This default implementation reports back to the client that the method is
-     * not supported.
-     * <p>
-     * Implementations of this class should overwrite this method with their
-     * implementation for the HTTP <em>PATCH</em> method support.
-     *
-     * @param request  The HTTP request
-     * @param response The HTTP response
-     * @throws ServletException Not thrown by this implementation.
-     * @throws IOException      If the error status cannot be reported back to the
-     *                          client.
-     */
-    @Override
-    protected void doPost(final HttpServletRequest req, final HttpServletResponse resp)
-            throws ServletException, IOException {
-        sendProblemResponse(resp, ProblemBuilder.get().withStatus(HttpServletResponse.SC_METHOD_NOT_ALLOWED).build());
-    }
-
-    /**
-     * Called by the
-     * {@link #service(HttpServletRequest, HttpServletResponse)} method
-     * to handle an HTTP <em>PUT</em> request.
-     * <p>
-     * This default implementation reports back to the client that the method is
-     * not supported.
-     * <p>
-     * Implementations of this class should overwrite this method with their
-     * implementation for the HTTP <em>PATCH</em> method support.
-     *
-     * @param request  The HTTP request
-     * @param response The HTTP response
-     * @throws ServletException Not thrown by this implementation.
-     * @throws IOException      If the error status cannot be reported back to the
-     *                          client.
-     */
-    @Override
-    protected void doPut(final HttpServletRequest req, final HttpServletResponse resp)
-            throws ServletException, IOException {
-        sendProblemResponse(resp, ProblemBuilder.get().withStatus(HttpServletResponse.SC_METHOD_NOT_ALLOWED).build());
-    }
-
-    /**
-     * Called by the
-     * {@link #service(HttpServletRequest, HttpServletResponse)} method
-     * to handle an HTTP <em>DELETE</em> request.
-     * <p>
-     * This default implementation reports back to the client that the method is
-     * not supported.
-     * <p>
-     * Implementations of this class should overwrite this method with their
-     * implementation for the HTTP <em>PATCH</em> method support.
-     *
-     * @param request  The HTTP request
-     * @param response The HTTP response
-     * @throws ServletException Not thrown by this implementation.
-     * @throws IOException      If the error status cannot be reported back to the
-     *                          client.
-     */
-    @Override
-    protected void doDelete(final HttpServletRequest req, final HttpServletResponse resp)
-            throws ServletException, IOException {
-        sendProblemResponse(resp, ProblemBuilder.get().withStatus(HttpServletResponse.SC_METHOD_NOT_ALLOWED).build());
-    }
-
-    /**
-     * Called by the
-     * {@link #service(HttpServletRequest, HttpServletResponse)} method
-     * to handle an HTTP <em>PATCH</em> request.
-     * <p>
-     * This default implementation reports back to the client that the method is
-     * not supported.
-     * <p>
-     * Implementations of this class should overwrite this method with their
-     * implementation for the HTTP <em>PATCH</em> method support.
-     *
-     * @param request  The HTTP request
-     * @param response The HTTP response
-     * @throws ServletException Not thrown by this implementation.
-     * @throws IOException      If the error status cannot be reported back to the
-     *                          client.
-     */
-    protected void doPatch(@NotNull HttpServletRequest request, @NotNull HttpServletResponse response)
-            throws ServletException, IOException {
-        handleMethodNotImplemented(request, response);
-    }
-
-    /**
-     * Tries to handle the request by calling a Java method implemented for the
-     * respective HTTP request method.
-     * <p>
-     * This implementation first calls the base class implementation and only if
-     * the base class cannot dispatch will try to dispatch the supported methods
-     * <em>PATCH</em>
-     * <p>
-     * In addition, this method catches ServletException, IOException and
-     * RuntimeExceptions thrown from the called methods and sends a JSON
-     * Problem response based on the thrown exception
-     *
-     * @param request  The HTTP request
-     * @param response The HTTP response
-     * @return <code>true</code> if the requested method
-     *         (<code>request.getMethod()</code>)
-     *         is known. Otherwise <code>false</code> is returned.
-     * @throws ServletException Forwarded from any of the dispatched methods
-     * @throws IOException      Forwarded from any of the dispatched methods
-     */
-    @Override
-    protected void service(@NotNull HttpServletRequest request,
-            @NotNull HttpServletResponse response) throws ServletException,
-            IOException {
-        final String method = request.getMethod();
-        try {
-            // assume the method is known for now
-            if (SERVLET_SUPPORTED_METHODS.contains(method)) {
-                super.service(request, response);
-            } else if ("PATCH".equals(method)) {
-                doPatch(request, response);
-            } else {
-                handleMethodNotImplemented(request, response);
-            }
-        } catch (IOException | ServletException | RuntimeException e) {
-            if (e instanceof Problematic) {
-                sendProblemResponse(response, ((Problematic) e).getProblem());
-            } else {
-                log.error("Handing uncaught exception", e);
-                sendProblemResponse(response, ProblemBuilder.get().fromException(e).build());
-            }
-        }
-    }
-
-    /**
-     * Provides the Jackson ObjectWriter instance to use for writing objects to the
-     * response.
-     * <p>
-     * Implementations of this class can overwrite this method to customize the
-     * behavior of the ObjectWiter
-     *
-     * @return the ObjectWriter
-     */
-    public ObjectWriter getObjectWriter() {
-        return objectWriter;
-    }
-
-    /**
-     * Provides the Jackson ObjectReader instance to use for reading objects from
-     * the request.
-     * <p>
-     * Implementations of this class can overwrite this method to customize the
-     * behavior of the ObjectReader
-     *
-     * @return the ObjectReader
-     */
-    public ObjectReader getObjectReader() {
-        return objectReader;
-    }
-
-    /**
-     * Read an object from the request, handing invalid or missing request bodies
-     * and returning a 400 response.
-     *
-     * @param <T>     the type of object to be read from the request
-     * @param request the request from which to read the object
-     * @param type    the class of the type to read
-     * @return the object read from the request
-     */
-    @Override
-    public <T> T readRequestBody(HttpServletRequest request, Class<T> type) {
-        try {
-            return getObjectReader().readValue(request.getReader(), type);
-        } catch (IOException e) {
-            throw ProblemBuilder.get().withStatus(HttpServletResponse.SC_BAD_REQUEST)
-                    .withDetail("Unable to parse request as JSON: " + e.getMessage()).buildThrowable();
-        }
-    }
-
-    /**
-     * Read an object from the request, handing invalid or missing request bodies
-     * and returning a 400 response.
-     *
-     * @param <T>     the type of object to be read from the request
-     * @param request the request from which to read the object
-     * @param type    the class of the type to read
-     * @return the object read from the request
-     */
-    @Override
-    public <T> T readRequestBody(HttpServletRequest request, TypeReference<T> type) {
-        try {
-            return getObjectReader().forType(type).readValue(request.getReader());
-        } catch (IOException e) {
-            throw ProblemBuilder.get().withStatus(HttpServletResponse.SC_BAD_REQUEST)
-                    .withDetail("Unable to parse request as JSON: " + e.getMessage()).buildThrowable();
-        }
-    }
-
-    /**
-     * Sends a JSON response
-     *
-     * @param response     the response to which to write
-     * @param statusCode   the status code to send for the response
-     * @param contentType  the content type to send for the response
-     * @param responseBody the object to write to the response
-     * @throws IOException an exception occurs writing the object to the response
-     */
-    @Override
-    public void sendJsonResponse(HttpServletResponse response, int statusCode, String contentType,
-            Object responseBody) throws IOException {
-        if (!response.isCommitted()) {
-            response.reset();
-            response.setStatus(statusCode);
-            response.setContentType(contentType);
-            response.setCharacterEncoding(StandardCharsets.UTF_8.toString());
-        } else {
-            // Response already committed: don't change status
-            log.warn("Response already committed, unable to change status, output might not be well formed");
-        }
-        response.getWriter().write(getObjectWriter().writeValueAsString(responseBody));
-    }
-
-}
diff --git a/org.apache.sling.servlets.json/src/main/java/org/apache/sling/servlets/json/annotations/RequestBody.java b/org.apache.sling.servlets.json/src/main/java/org/apache/sling/servlets/json/annotations/RequestBody.java
deleted file mode 100644
index 2f6980a..0000000
--- a/org.apache.sling.servlets.json/src/main/java/org/apache/sling/servlets/json/annotations/RequestBody.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * 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.sling.servlets.json.annotations;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-@Retention(RetentionPolicy.RUNTIME)
-@Target(ElementType.PARAMETER)
-public @interface RequestBody {
-
-}
diff --git a/org.apache.sling.servlets.json/src/main/java/org/apache/sling/servlets/json/annotations/RequestHandler.java b/org.apache.sling.servlets.json/src/main/java/org/apache/sling/servlets/json/annotations/RequestHandler.java
deleted file mode 100644
index 36335b7..0000000
--- a/org.apache.sling.servlets.json/src/main/java/org/apache/sling/servlets/json/annotations/RequestHandler.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * 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.sling.servlets.json.annotations;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-@Retention(RetentionPolicy.RUNTIME)
-@Target(ElementType.METHOD)
-public @interface RequestHandler {
-
-    String[] methods();
-
-    String path();
-
-}
diff --git a/org.apache.sling.servlets.json/src/main/java/org/apache/sling/servlets/json/annotations/RequestParameter.java b/org.apache.sling.servlets.json/src/main/java/org/apache/sling/servlets/json/annotations/RequestParameter.java
deleted file mode 100644
index 78eb5b9..0000000
--- a/org.apache.sling.servlets.json/src/main/java/org/apache/sling/servlets/json/annotations/RequestParameter.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * 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.sling.servlets.json.annotations;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-@Retention(RetentionPolicy.RUNTIME)
-@Target(ElementType.PARAMETER)
-public @interface RequestParameter {
-
-    String name();
-
-}
diff --git a/org.apache.sling.servlets.json/src/main/java/org/apache/sling/servlets/json/dynamicrequest/DynamicRequestMapper.java b/org.apache.sling.servlets.json/src/main/java/org/apache/sling/servlets/json/dynamicrequest/DynamicRequestMapper.java
deleted file mode 100644
index b5f4e3b..0000000
--- a/org.apache.sling.servlets.json/src/main/java/org/apache/sling/servlets/json/dynamicrequest/DynamicRequestMapper.java
+++ /dev/null
@@ -1,183 +0,0 @@
-/*
- * 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.sling.servlets.json.dynamicrequest;
-
-import java.io.IOException;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.lang.reflect.Parameter;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Optional;
-import java.util.Set;
-import java.util.stream.Collectors;
-
-import javax.servlet.ServletException;
-import javax.servlet.ServletRequest;
-import javax.servlet.ServletResponse;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.apache.sling.api.resource.ValueMap;
-import org.apache.sling.api.wrappers.ValueMapDecorator;
-import org.apache.sling.servlets.json.DynamicRequestServlet;
-import org.apache.sling.servlets.json.annotations.RequestBody;
-import org.apache.sling.servlets.json.annotations.RequestHandler;
-import org.apache.sling.servlets.json.annotations.RequestParameter;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class DynamicRequestMapper {
-
-    private static final Logger log = LoggerFactory.getLogger(DynamicRequestMapper.class);
-
-    private final Set<String> mappingKeys = new HashSet<>();
-    private final Map<String, List<DynamicRequestMapping>> mappings = new HashMap<>();
-    private final DynamicRequestServlet instance;
-
-    public DynamicRequestMapper(DynamicRequestServlet instance) {
-        readRequestHandlers(instance);
-        this.instance = instance;
-    }
-
-    public boolean mayService(HttpServletRequest request, HttpServletResponse response)
-            throws IOException, ServletException {
-        final String method = request.getMethod();
-        final String path = request.getRequestURI();
-        Optional<DynamicRequestMapping> mappingOp = Optional.ofNullable(mappings.get(method))
-                .orElse(Collections.emptyList()).stream().filter(drm -> drm.matches(path)).findFirst();
-        if (mappingOp.isPresent()) {
-            callMethod(request, response, mappingOp.get());
-            return true;
-        } else {
-            return false;
-        }
-    }
-
-    private void callMethod(final HttpServletRequest request, final HttpServletResponse response,
-            final DynamicRequestMapping dynamicRequestMapping) throws IOException, ServletException {
-        final Method method = dynamicRequestMapping.getMethod();
-        final List<Object> values = new ArrayList<>();
-        final ValueMap parameters = new ValueMapDecorator(request.getParameterMap());
-        for (Parameter param : method.getParameters()) {
-            if (ServletRequest.class.isAssignableFrom(param.getType())) {
-                log.trace("Adding request for param: {}", param);
-                values.add(request);
-            } else if (ServletResponse.class.isAssignableFrom(param.getType())) {
-                log.trace("Adding response for param: {}", param);
-                values.add(response);
-            } else if (param.isAnnotationPresent(RequestBody.class)) {
-                log.debug("Adding response body as {} for param: {}", param.getType(), param);
-                values.add(instance.readRequestBody(request, param.getType()));
-            } else if (param.isAnnotationPresent(RequestParameter.class)) {
-                RequestParameter rp = param.getAnnotation(RequestParameter.class);
-                log.debug("Adding response parameter {} as {} for param: {}", rp.name(), param.getType(), param);
-                values.add(parameters.get(rp.name(), param.getType()));
-            } else {
-                throw new RequestMappingException("Failed to call : " + dynamicRequestMapping
-                        + " parameter " + param.getName()
-                        + " must either be a ServletRequest, ServletResponse or be annotated with request value mappings");
-            }
-        }
-
-        try {
-            log.trace("Invoking method {} with parameters {}", method, values);
-            Object value = method.invoke(instance, values.toArray());
-            if (value != null) {
-                log.trace("Recieved response {}", value);
-                instance.sendJsonResponse(response, value);
-            }
-        } catch (IllegalAccessException | IllegalArgumentException e) {
-            throw new RequestMappingException("Unexpected exception invoking method " + method.toGenericString(), e);
-        } catch (InvocationTargetException e) {
-            Throwable cause = e.getCause();
-            if (cause instanceof RuntimeException) {
-                throw (RuntimeException) cause;
-            }
-            if (cause instanceof IOException) {
-                throw (IOException) cause;
-            }
-            if (cause instanceof ServletException) {
-                throw (ServletException) cause;
-            }
-            throw new RequestMappingException("Unexpected exception invoking method " + method.toGenericString(), e);
-        }
-    }
-
-    private void readRequestHandlers(HttpServlet instance) {
-        log.debug("Loading request handlers from: {}", instance.getClass());
-        for (Method method : instance.getClass().getDeclaredMethods()) {
-            log.trace("Evaluating method: {}", method);
-            RequestHandler handler = method.getAnnotation(RequestHandler.class);
-            if (handler != null) {
-                readRequestHandler(handler, method);
-            }
-        }
-    }
-
-    private void readRequestHandler(RequestHandler handler, Method method) {
-        log.trace("Found request handler {} in method: {}", handler, method);
-        DynamicRequestMapping mapping = new DynamicRequestMapping(handler, method);
-        validateMapping(mapping);
-        Arrays.stream(handler.methods()).forEach(m -> {
-
-            log.trace("Adding request handler {} for method: {}", mapping, m);
-            mappings.computeIfAbsent(m, k -> new ArrayList<>());
-            mappings.get(m).add(mapping);
-        });
-    }
-
-    private Collection<String> getMappingKeys(RequestHandler handler) {
-        return Arrays.stream(handler.methods()).map(m -> '[' + m + "] " + handler.path()).collect(Collectors.toList());
-    }
-
-    private void validateMapping(DynamicRequestMapping mapping) {
-        // validate that there aren't duplicate request handlers
-        log.trace("Validing that requst handler is duplicate");
-        getMappingKeys(mapping.getHandler()).forEach(kp -> {
-            if (mappingKeys.contains(kp)) {
-                throw new RequestMappingException("Validation failed for method: " + mapping.getMethod()
-                        + " a request handler is already registred for " + kp);
-            }
-            mappingKeys.add(kp);
-        });
-
-        log.trace("Validing request handler can be injecteds");
-        validateCanInject(mapping.getMethod());
-    }
-
-    private void validateCanInject(Method method) {
-        for (Parameter param : method.getParameters()) {
-            if (!ServletRequest.class.isAssignableFrom(param.getType())
-                    && !ServletResponse.class.isAssignableFrom(param.getType())
-                    && !param.isAnnotationPresent(RequestBody.class)
-                    && !param.isAnnotationPresent(RequestParameter.class)) {
-                throw new RequestMappingException("Validation failed for method: " + method
-                        + " parameter " + param.getName()
-                        + " must either be a ServletRequest, ServletResponse or be annotated with request value mappings");
-            }
-        }
-    }
-
-}
diff --git a/org.apache.sling.servlets.json/src/main/java/org/apache/sling/servlets/json/dynamicrequest/DynamicRequestMapping.java b/org.apache.sling.servlets.json/src/main/java/org/apache/sling/servlets/json/dynamicrequest/DynamicRequestMapping.java
deleted file mode 100644
index 7c521c8..0000000
--- a/org.apache.sling.servlets.json/src/main/java/org/apache/sling/servlets/json/dynamicrequest/DynamicRequestMapping.java
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * 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.sling.servlets.json.dynamicrequest;
-
-import java.lang.reflect.Method;
-
-import org.apache.sling.servlets.json.annotations.RequestHandler;
-
-import com.hrakaroo.glob.GlobPattern;
-import com.hrakaroo.glob.MatchingEngine;
-
-public class DynamicRequestMapping {
-
-    private final RequestHandler handler;
-    private final Method method;
-    private final MatchingEngine matcher;
-
-    /**
-     * @param handler
-     * @param method
-     */
-    public DynamicRequestMapping(RequestHandler handler, Method method) {
-        this.handler = handler;
-        this.method = method;
-        matcher = GlobPattern.compile(handler.path());
-    }
-
-    /**
-     * @return the handler
-     */
-    public RequestHandler getHandler() {
-        return handler;
-    }
-
-    /**
-     * @return the method
-     */
-    public Method getMethod() {
-        return method;
-    }
-
-    /**
-     * If true, this DynamicRequestMapping instance matches the request path
-     *
-     * @param requestPath the request path for this request
-     * @return whether or not the request path matches
-     */
-    public boolean matches(String requestPath) {
-        return matcher.matches(requestPath);
-    }
-
-    /*
-     * (non-Javadoc)
-     *
-     * @see java.lang.Object#toString()
-     */
-    @Override
-    public String toString() {
-        return "DynamicRequestMapping [handler=" + handler + ", method=" + method + "]";
-    }
-
-}
diff --git a/org.apache.sling.servlets.json/src/main/java/org/apache/sling/servlets/json/dynamicrequest/RequestMappingException.java b/org.apache.sling.servlets.json/src/main/java/org/apache/sling/servlets/json/dynamicrequest/RequestMappingException.java
deleted file mode 100644
index 3d9bdce..0000000
--- a/org.apache.sling.servlets.json/src/main/java/org/apache/sling/servlets/json/dynamicrequest/RequestMappingException.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * 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.sling.servlets.json.dynamicrequest;
-
-import org.apache.sling.api.SlingException;
-
-public class RequestMappingException extends SlingException {
-
-    /**
-     * Constructs a new RequestMappingException
-     */
-    protected RequestMappingException() {
-        super();
-    }
-
-    /**
-     * Constructs a new RequestMappingException with the given text
-     *
-     * @param text the exception text
-     */
-    protected RequestMappingException(String text) {
-        super(text);
-    }
-
-    /**
-     * Constructs a new RequestMappingException with a cause
-     *
-     * @param text  the exception text
-     * @param cause the root cause
-     */
-    public RequestMappingException(String text, Throwable cause) {
-        super(text, cause);
-    }
-
-    /**
-     * Constructs a new RequestMappingException with only a cause
-     *
-     * @param cause the root cause
-     */
-    protected RequestMappingException(Throwable cause) {
-        super(cause);
-    }
-}
diff --git a/org.apache.sling.servlets.json/src/test/java/org/apache/sling/servlets/json/DynamicRequestServletTest.java b/org.apache.sling.servlets.json/src/test/java/org/apache/sling/servlets/json/DynamicRequestServletTest.java
deleted file mode 100644
index 5d9e2b8..0000000
--- a/org.apache.sling.servlets.json/src/test/java/org/apache/sling/servlets/json/DynamicRequestServletTest.java
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
- * 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.sling.servlets.json;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertThrows;
-
-import java.io.IOException;
-
-import javax.servlet.ServletException;
-
-import org.apache.sling.servlets.json.dynamicrequest.DuplicateHandlersServlet;
-import org.apache.sling.servlets.json.dynamicrequest.InvalidArgumentsServlet;
-import org.apache.sling.servlets.json.dynamicrequest.RequestMappingException;
-import org.apache.sling.servlets.json.dynamicrequest.SampleDynamicRequestServlet;
-import org.apache.sling.testing.mock.sling.junit5.SlingContext;
-import org.apache.sling.testing.mock.sling.junit5.SlingContextExtension;
-import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.extension.ExtendWith;
-import org.junit.jupiter.params.ParameterizedTest;
-import org.junit.jupiter.params.provider.CsvSource;
-
-@ExtendWith(SlingContextExtension.class)
-class DynamicRequestServletTest {
-
-    private final SampleDynamicRequestServlet servlet = new SampleDynamicRequestServlet();
-
-    private final SlingContext context = new SlingContext();
-
-    @Test
-    void testSimple() throws ServletException, IOException {
-        context.request().setServletPath("/simple");
-        context.request().setMethod("GET");
-        servlet.service(context.request(), context.response());
-
-        assertEquals(200, context.response().getStatus());
-        assertEquals("application/json;charset=UTF-8", context.response().getContentType());
-        assertEquals("{\"Hello\":\"World\"}", context.response().getOutputAsString());
-    }
-
-    @ParameterizedTest
-    @CsvSource(value = {
-            "/simple/bob,200",
-            "/simple/bob/sal,200",
-            "/simple/bob.png,200",
-            "/simple2/glob,405"
-    })
-    void testGlob(String path, int status) throws ServletException, IOException {
-        context.request().setServletPath(path);
-        context.request().setMethod("GET");
-        servlet.service(context.request(), context.response());
-        assertEquals(status, context.response().getStatus());
-    }
-
-    @Test
-    void testOrdering() throws ServletException, IOException {
-        context.request().setServletPath("/simple/glob");
-        context.request().setMethod("GET");
-        servlet.service(context.request(), context.response());
-        assertEquals(200, context.response().getStatus());
-        assertEquals("{\"Hello\":\"World2\"}", context.response().getOutputAsString());
-    }
-
-    @Test
-    void testNoResponse() throws ServletException, IOException {
-        context.request().setServletPath("/no-response");
-        context.request().setMethod("POST");
-        servlet.service(context.request(), context.response());
-        assertEquals(202, context.response().getStatus());
-        assertEquals("", context.response().getOutputAsString());
-    }
-
-    @Test
-    void supportsParameters() throws ServletException, IOException {
-        context.request().setServletPath("/with-param");
-        context.request().setMethod("GET");
-        context.request().addRequestParameter("name", "Sling");
-        servlet.service(context.request(), context.response());
-        assertEquals(200, context.response().getStatus());
-        assertEquals("{\"Hello\":\"Sling\"}", context.response().getOutputAsString());
-    }
-
-    @Test
-    void supportsMissingParams() throws ServletException, IOException {
-        context.request().setServletPath("/with-param");
-        context.request().setMethod("GET");
-        servlet.service(context.request(), context.response());
-        assertEquals(200, context.response().getStatus());
-        assertEquals("{\"Hello\":null}", context.response().getOutputAsString());
-    }
-
-    @Test
-    void handlesThrownExceptions() throws ServletException, IOException {
-        context.request().setServletPath("/npe");
-        context.request().setMethod("GET");
-        servlet.service(context.request(), context.response());
-        assertEquals(500, context.response().getStatus());
-        assertEquals("application/problem+json;charset=UTF-8", context.response().getContentType());
-        assertEquals(
-                "{\"title\":\"Internal Server Error\",\"status\":500,\"detail\":\"java.lang.NullPointerException\"}",
-                context.response().getOutputAsString());
-    }
-
-    @Test
-    void wontConstructWithDuplicateHandlers() {
-        assertThrows(RequestMappingException.class, () -> new DuplicateHandlersServlet());
-    }
-
-    @Test
-    void wontConstructWithInvalidArguments() {
-        assertThrows(Exception.class, () -> new InvalidArgumentsServlet());
-    }
-}
diff --git a/org.apache.sling.servlets.json/src/test/java/org/apache/sling/servlets/json/JacksonJsonServletTest.java b/org.apache.sling.servlets.json/src/test/java/org/apache/sling/servlets/json/JacksonJsonServletTest.java
deleted file mode 100644
index d2697ab..0000000
--- a/org.apache.sling.servlets.json/src/test/java/org/apache/sling/servlets/json/JacksonJsonServletTest.java
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
- * 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.sling.servlets.json;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.fail;
-
-import java.io.IOException;
-import java.util.stream.Stream;
-
-import javax.jcr.PathNotFoundException;
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.apache.sling.testing.mock.sling.junit5.SlingContext;
-import org.apache.sling.testing.mock.sling.junit5.SlingContextExtension;
-import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.extension.ExtendWith;
-import org.junit.jupiter.params.ParameterizedTest;
-import org.junit.jupiter.params.provider.Arguments;
-import org.junit.jupiter.params.provider.MethodSource;
-import org.junit.jupiter.params.provider.ValueSource;
-
-@ExtendWith(SlingContextExtension.class)
-class JacksonJsonServletTest {
-
-    private final SlingContext context = new SlingContext();
-
-    @ParameterizedTest
-    @ValueSource(strings = { "GET", "PATCH", "POST" })
-    void testBasicServlet(String method) throws ServletException, IOException {
-        String body = "{\"Hello\":\"World\"}";
-
-        context.request().setContent(body.getBytes());
-        context.request().setMethod(method);
-
-        TestJacksonJsonServlet testServlet = new TestJacksonJsonServlet();
-        testServlet.service(context.request(), context.response());
-
-        assertEquals(200, context.response().getStatus());
-        assertEquals("application/json;charset=UTF-8", context.response().getContentType());
-        assertEquals(body, context.response().getOutputAsString());
-    }
-
-    @ParameterizedTest
-    @ValueSource(strings = { "PUT", "DELEEETE" })
-    void testUnsupported(String method) throws ServletException, IOException {
-        context.request().setMethod(method);
-
-        TestJacksonJsonServlet testServlet = new TestJacksonJsonServlet();
-        testServlet.service(context.request(), context.response());
-
-        assertEquals(405, context.response().getStatus());
-        assertEquals("application/problem+json;charset=UTF-8", context.response().getContentType());
-        assertEquals("{\"title\":\"Method Not Allowed\",\"status\":405}", context.response().getOutputAsString());
-    }
-
-    @ParameterizedTest
-    @ValueSource(strings = { "GET", "PATCH", "POST", "PUT", "DELETE" })
-    void sendsNotAllowedByDefault(String method) throws ServletException, IOException {
-
-        context.request().setMethod(method);
-
-        JacksonJsonServlet defaultServlet = new JacksonJsonServlet() {
-        };
-        defaultServlet.service(context.request(), context.response());
-
-        assertEquals(405, context.response().getStatus());
-        assertEquals("application/problem+json;charset=UTF-8", context.response().getContentType());
-        assertEquals("{\"title\":\"Method Not Allowed\",\"status\":405}", context.response().getOutputAsString());
-    }
-
-    @Test
-    void canDeserializeObject() throws ServletException, IOException {
-
-        JacksonJsonServlet defaultServlet = new JacksonJsonServlet() {
-            @Override
-            protected void doPost(HttpServletRequest req, HttpServletResponse resp)
-                    throws ServletException, IOException {
-                SamplePojo model = super.readRequestBody(req, SamplePojo.class);
-                assertEquals("Sling", model.getTitle());
-            }
-        };
-
-        context.request().setMethod("POST");
-        context.request().setContent("{\"title\":\"Sling\"}".getBytes());
-        defaultServlet.service(context.request(), context.response());
-
-        assertEquals(200, context.response().getStatus());
-    }
-
-    @Test
-    void returns400OnInvalidJsonBody() throws ServletException, IOException {
-
-        JacksonJsonServlet defaultServlet = new JacksonJsonServlet() {
-            @Override
-            protected void doPost(HttpServletRequest req, HttpServletResponse resp)
-                    throws ServletException, IOException {
-                SamplePojo model = super.readRequestBody(req, SamplePojo.class);
-                assertEquals("Sling", model.getTitle());
-            }
-        };
-
-        context.request().setMethod("POST");
-        context.request().setContent("{\"title\",\"Sling\"}".getBytes());
-        defaultServlet.service(context.request(), context.response());
-
-        assertEquals(400, context.response().getStatus());
-        assertEquals("application/problem+json;charset=UTF-8", context.response().getContentType());
-
-        assertEquals(
-                "{\"title\":\"Bad Request\",\"status\":400,\"detail\":\"Unable to parse request as JSON: Unexpected character (',' (code 44)): was expecting a colon to separate field name and value\\n at [Source: (BufferedReader); line: 1, column: 10]\"}",
-                context.response().getOutputAsString());
-    }
-
-    @ParameterizedTest
-    @MethodSource("provideExceptions")
-    void catchesExceptions(Exception ex, int statusCode) throws ServletException, IOException {
-        context.request().setMethod("GET");
-
-        JacksonJsonServlet throwyServlet = new JacksonJsonServlet() {
-            @Override
-            protected void doGet(HttpServletRequest req, HttpServletResponse resp)
-                    throws ServletException, IOException {
-                if (ex instanceof RuntimeException) {
-                    throw (RuntimeException) ex;
-                }
-                if (ex instanceof ServletException) {
-                    throw (ServletException) ex;
-                }
-                if (ex instanceof IOException) {
-                    throw (IOException) ex;
-                }
-                fail("Unexpected exception type");
-            }
-        };
-        throwyServlet.service(context.request(), context.response());
-
-        assertEquals(statusCode, context.response().getStatus());
-        assertEquals("application/problem+json;charset=UTF-8", context.response().getContentType());
-    }
-
-    static Stream<Arguments> provideExceptions() throws Exception {
-        return Stream.of(
-                Arguments.of(new RuntimeException(), 500),
-                Arguments.of(new RuntimeException("Bad", new PathNotFoundException()), 404));
-    }
-
-}
diff --git a/org.apache.sling.servlets.json/src/test/java/org/apache/sling/servlets/json/SamplePojo.java b/org.apache.sling.servlets.json/src/test/java/org/apache/sling/servlets/json/SamplePojo.java
deleted file mode 100644
index a56b717..0000000
--- a/org.apache.sling.servlets.json/src/test/java/org/apache/sling/servlets/json/SamplePojo.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * 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.sling.servlets.json;
-
-public class SamplePojo {
-
-    private String title;
-
-    public String getTitle() {
-        return title;
-    }
-}
diff --git a/org.apache.sling.servlets.json/src/test/java/org/apache/sling/servlets/json/TestJacksonJsonServlet.java b/org.apache.sling.servlets.json/src/test/java/org/apache/sling/servlets/json/TestJacksonJsonServlet.java
deleted file mode 100644
index 3c550c9..0000000
--- a/org.apache.sling.servlets.json/src/test/java/org/apache/sling/servlets/json/TestJacksonJsonServlet.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * 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.sling.servlets.json;
-
-import java.io.IOException;
-import java.util.Map;
-
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.jetbrains.annotations.NotNull;
-
-import com.fasterxml.jackson.core.type.TypeReference;
-
-public class TestJacksonJsonServlet extends JacksonJsonServlet {
-
-    private void echo(@NotNull HttpServletRequest request, @NotNull HttpServletResponse response)
-            throws ServletException, IOException {
-
-        Map<String, Object> properties = super.readRequestBody(request, new TypeReference<Map<String, Object>>() {
-        });
-        super.sendJsonResponse(response, properties);
-    }
-
-    protected void doGet(@NotNull HttpServletRequest request, @NotNull HttpServletResponse response)
-            throws ServletException, IOException {
-        echo(request, response);
-    }
-
-    protected void doPatch(@NotNull HttpServletRequest request, @NotNull HttpServletResponse response)
-            throws ServletException, IOException {
-        echo(request, response);
-    }
-
-    protected void doPost(@NotNull HttpServletRequest request, @NotNull HttpServletResponse response)
-            throws ServletException, IOException {
-        echo(request, response);
-    }
-
-}
diff --git a/org.apache.sling.servlets.json/src/test/java/org/apache/sling/servlets/json/dynamicrequest/DuplicateHandlersServlet.java b/org.apache.sling.servlets.json/src/test/java/org/apache/sling/servlets/json/dynamicrequest/DuplicateHandlersServlet.java
deleted file mode 100644
index dccfbfb..0000000
--- a/org.apache.sling.servlets.json/src/test/java/org/apache/sling/servlets/json/dynamicrequest/DuplicateHandlersServlet.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * 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.sling.servlets.json.dynamicrequest;
-
-import org.apache.sling.servlets.json.DynamicRequestServlet;
-import org.apache.sling.servlets.json.annotations.RequestHandler;
-
-public class DuplicateHandlersServlet extends DynamicRequestServlet {
-
-    @RequestHandler(methods = { "GET" }, path = "/simple")
-    public void simpleHandler() {
-    }
-
-    @RequestHandler(methods = { "GET" }, path = "/simple")
-    public void duplicateHandler() {
-    }
-
-}
diff --git a/org.apache.sling.servlets.json/src/test/java/org/apache/sling/servlets/json/dynamicrequest/InvalidArgumentsServlet.java b/org.apache.sling.servlets.json/src/test/java/org/apache/sling/servlets/json/dynamicrequest/InvalidArgumentsServlet.java
deleted file mode 100644
index 058e90e..0000000
--- a/org.apache.sling.servlets.json/src/test/java/org/apache/sling/servlets/json/dynamicrequest/InvalidArgumentsServlet.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * 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.sling.servlets.json.dynamicrequest;
-
-import org.apache.sling.servlets.json.DynamicRequestServlet;
-import org.apache.sling.servlets.json.annotations.RequestHandler;
-
-public class InvalidArgumentsServlet extends DynamicRequestServlet {
-
-    @RequestHandler(methods = { "GET" }, path = "/simple")
-    public void duplicateHandler(String name) {
-    }
-
-}
diff --git a/org.apache.sling.servlets.json/src/test/java/org/apache/sling/servlets/json/dynamicrequest/SampleDynamicRequestServlet.java b/org.apache.sling.servlets.json/src/test/java/org/apache/sling/servlets/json/dynamicrequest/SampleDynamicRequestServlet.java
deleted file mode 100644
index 31d91fa..0000000
--- a/org.apache.sling.servlets.json/src/test/java/org/apache/sling/servlets/json/dynamicrequest/SampleDynamicRequestServlet.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * 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.sling.servlets.json.dynamicrequest;
-
-import java.util.HashMap;
-import java.util.Map;
-
-import javax.servlet.http.HttpServletResponse;
-
-import org.apache.sling.servlets.json.DynamicRequestServlet;
-import org.apache.sling.servlets.json.annotations.RequestHandler;
-import org.apache.sling.servlets.json.annotations.RequestParameter;
-
-public class SampleDynamicRequestServlet extends DynamicRequestServlet {
-
-    @RequestHandler(methods = { "GET" }, path = "/simple")
-    public Map<String, Object> simpleHandler() {
-        return Map.of("Hello", "World");
-    }
-
-    @RequestHandler(methods = { "GET" }, path = "/simple/**")
-    public Map<String, Object> globHandler() {
-        return Map.of("Hello", "World2");
-    }
-
-    @RequestHandler(methods = { "POST" }, path = "/no-response")
-    public void noResponse(HttpServletResponse response) {
-        response.setStatus(HttpServletResponse.SC_ACCEPTED);
-    }
-
-    @RequestHandler(methods = { "GET" }, path = "/with-param")
-    public Map<String, Object> withParameter(HttpServletResponse response,
-            @RequestParameter(name = "name") String name) {
-        Map<String, Object> resp = new HashMap<>();
-        resp.put("Hello", name);
-        return resp;
-    }
-
-    @RequestHandler(methods = { "GET" }, path = "/npe")
-    public void npe(HttpServletResponse response,
-            @RequestParameter(name = "name") String name) {
-        name.length();
-    }
-
-}