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

sseifert pushed a commit to branch master
in repository 
https://gitbox.apache.org/repos/asf/sling-org-apache-sling-models-jacksonexporter.git


The following commit(s) were added to refs/heads/master by this push:
     new 9e70224  SLING-13079 Include Integration Tests (#17)
9e70224 is described below

commit 9e70224a2aac0b27f0bad972f63d76f8c11eb0dd
Author: Stefan Seifert <[email protected]>
AuthorDate: Thu Jan 29 20:33:30 2026 +0100

    SLING-13079 Include Integration Tests (#17)
---
 pom.xml                                            | 338 +++++++++++++++++-
 src/test/it-features/it-launcher-repoinit.txt      |  23 ++
 src/test/it-features/it-launcher.json              |  34 ++
 .../customizers/SM_TeleporterCustomizer.java       |  61 ++++
 .../jacksonexporter/it/GenerateTestBundle.java     |  92 +++++
 .../it/testbundle/exporter/BaseComponent.java      |  59 ++++
 .../testbundle/exporter/BaseRequestComponent.java  | 105 ++++++
 .../it/testbundle/exporter/Component.java          |  26 ++
 .../it/testbundle/exporter/ComponentImpl.java      |  50 +++
 .../testbundle/exporter/DoubledFirstComponent.java |  34 ++
 .../exporter/DoubledSecondComponent.java           |  34 ++
 .../it/testbundle/exporter/ExtendedComponent.java  |  53 +++
 .../exporter/ExtendedRequestComponent.java         |  62 ++++
 .../exporter/JakartaBaseRequestComponent.java      | 105 ++++++
 .../exporter/JakartaExtendedRequestComponent.java  |  62 ++++
 .../exporter/JakartaRequestComponentImpl.java      |  59 ++++
 .../testbundle/exporter/RequestComponentImpl.java  |  59 ++++
 .../AnotherTestBindingsValuesProvider.java         |  36 ++
 .../services/TestBindingsValuesProvider.java       |  36 ++
 .../it/testing/exporter/ExporterIT.java            | 393 +++++++++++++++++++++
 20 files changed, 1717 insertions(+), 4 deletions(-)

diff --git a/pom.xml b/pom.xml
index 25e4e77..f3ff686 100644
--- a/pom.xml
+++ b/pom.xml
@@ -39,9 +39,16 @@
     </scm>
 
     <properties>
-        <sling.java.version>11</sling.java.version>
         
<project.build.outputTimestamp>2025-06-25T07:05:44Z</project.build.outputTimestamp>
+        <sling.java.version>11</sling.java.version>
+        <models.api.version>1.3.0</models.api.version>
+        <models.impl.version>2.0.1-SNAPSHOT</models.impl.version>
         <version.jackson>2.15.0</version.jackson>
+        <!-- integration tests -->
+        <sling.starter.version>14-SNAPSHOT</sling.starter.version>
+        <starter.min.bundles.count>200</starter.min.bundles.count>
+        <it.startTimeoutSeconds>60</it.startTimeoutSeconds>
+        <it.models.log.level>debug</it.models.log.level>
     </properties>
 
     <dependencies>
@@ -71,13 +78,12 @@
         <dependency>
             <groupId>org.apache.sling</groupId>
             <artifactId>org.apache.sling.models.api</artifactId>
-            <version>1.3.0</version>
+            <version>${models.api.version}</version>
             <scope>provided</scope>
         </dependency>
         <dependency>
             <groupId>org.slf4j</groupId>
             <artifactId>slf4j-api</artifactId>
-            <version>2.0.17</version>
             <scope>provided</scope>
         </dependency>
 
@@ -160,7 +166,7 @@
         <dependency>
             <groupId>org.apache.sling</groupId>
             <artifactId>org.apache.sling.testing.sling-mock.junit5</artifactId>
-            <version>3.5.6</version>
+            <version>4.0.2</version>
             <scope>test</scope>
         </dependency>
         <dependency>
@@ -170,6 +176,330 @@
             <scope>test</scope>
         </dependency>
 
+        <!-- Integration test dependencies -->
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.sling</groupId>
+            <artifactId>org.apache.sling.junit.core</artifactId>
+            <version>1.2.0</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.sling</groupId>
+            <artifactId>org.apache.sling.testing.rules</artifactId>
+            <version>2.0.2</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.sling</groupId>
+            <artifactId>org.apache.sling.testing.clients</artifactId>
+            <version>3.1.0</version>
+            <scope>test</scope>
+            <exclusions>
+                <exclusion>
+                    <groupId>javax.servlet</groupId>
+                    <artifactId>servlet-api</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.sling</groupId>
+            <artifactId>org.apache.sling.junit.teleporter</artifactId>
+            <version>1.1.0</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>jakarta.json</groupId>
+            <artifactId>jakarta.json-api</artifactId>
+            <version>2.1.1</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.johnzon</groupId>
+            <artifactId>johnzon-core</artifactId>
+            <version>2.0.2</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.sling</groupId>
+            <artifactId>org.apache.sling.engine</artifactId>
+            <version>3.0.0</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>io.github.classgraph</groupId>
+            <artifactId>classgraph</artifactId>
+            <version>4.8.184</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.sling</groupId>
+            <artifactId>org.apache.sling.models.impl</artifactId>
+            <version>${models.impl.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.sling</groupId>
+            <artifactId>org.apache.sling.models.impl</artifactId>
+            <version>${models.impl.version}</version>
+            <classifier>tests</classifier>
+            <scope>test</scope>
+        </dependency>
+
     </dependencies>
 
+    <build>
+        <plugins>
+
+            <!-- Generate IT Test Bundle on the fly via TinyBundles -->
+            <plugin>
+                <groupId>org.codehaus.mojo</groupId>
+                <artifactId>exec-maven-plugin</artifactId>
+                <version>3.6.3</version>
+                <executions>
+                    <execution>
+                        <id>generate-it-testbundle</id>
+                        <goals>
+                            <goal>java</goal>
+                        </goals>
+                        <phase>prepare-package</phase>
+                        <configuration>
+                            <classpathScope>test</classpathScope>
+                            
<mainClass>org.apache.sling.models.jacksonexporter.it.GenerateTestBundle</mainClass>
+                            <arguments>
+                                
<argument>${project.build.directory}/it-testbundle.jar</argument>
+                            </arguments>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+
+            <plugin>
+                <groupId>org.codehaus.mojo</groupId>
+                <artifactId>build-helper-maven-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <id>reserve-network-port</id>
+                        <goals>
+                            <goal>reserve-network-port</goal>
+                        </goals>
+                        <phase>initialize</phase>
+                        <configuration>
+                            <portNames>
+                                <portName>http.port</portName>
+                                <portName>jacoco.port</portName>
+                            </portNames>
+                        </configuration>
+                    </execution>
+                    <execution>
+                        <id>attach-it-testbundle</id>
+                        <goals>
+                            <goal>attach-artifact</goal>
+                        </goals>
+                        <configuration>
+                            <artifacts>
+                                <artifact>
+                                    
<file>${project.build.directory}/it-testbundle.jar</file>
+                                    <type>jar</type>
+                                    <classifier>it-testbundle</classifier>
+                                </artifact>
+                            </artifacts>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+
+            <plugin>
+                <groupId>org.jacoco</groupId>
+                <artifactId>jacoco-maven-plugin</artifactId>
+                <executions>
+                    <!--
+                    Record integration test code coverage via jacoco, using 
TCP server
+                    We cannot rely on the default file-based approach as the 
sling JVM is stopped forcefully, preventing proper file write on shutdown.
+                    -->
+                    <execution>
+                        <id>prepare-agent-integration-launcher</id>
+                        <goals>
+                            <goal>prepare-agent-integration</goal>
+                        </goals>
+                        <configuration>
+                            
<propertyName>jacoco.launcher.command</propertyName>
+                            <output>tcpserver</output>
+                            <address>localhost</address>
+                            <port>${jacoco.port}</port>
+                        </configuration>
+                    </execution>
+                    <execution>
+                        <id>dump-coverage-launcher</id>
+                        <goals>
+                            <goal>dump</goal>
+                        </goals>
+                        <phase>post-integration-test</phase>
+                        <configuration>
+                            <address>localhost</address>
+                            <port>${jacoco.port}</port>
+                            
<destFile>${project.build.directory}/jacoco-it.exec</destFile>
+                            <append>true</append>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+
+            <plugin>
+                <groupId>org.apache.sling</groupId>
+                <artifactId>slingfeature-maven-plugin</artifactId>
+                <version>1.9.2</version>
+                <extensions>true</extensions>
+                <configuration>
+                    <features>src/test/it-features</features>
+                    
<replacePropertyVariables>models.api.version,models.impl.version,it.models.log.level</replacePropertyVariables>
+                    
<skipAddFeatureDependencies>true</skipAddFeatureDependencies>
+                    <aggregates>
+                        <aggregate>
+                            <classifier>it-app</classifier>
+                            <filesInclude>*.json</filesInclude>
+                            <variablesOverrides>
+                                <http.port>${http.port}</http.port>
+                            </variablesOverrides>
+                            <artifactsOverrides>
+                                
<artifactsOverride>org.apache.sling:org.apache.sling.models.api:HIGHEST</artifactsOverride>
+                                
<artifactsOverride>org.apache.sling:org.apache.sling.models.impl:HIGHEST</artifactsOverride>
+                                
<artifactsOverride>org.apache.sling:org.apache.sling.models.jacksonexporter:HIGHEST</artifactsOverride>
+                            </artifactsOverrides>
+                            <includeArtifact>
+                                <groupId>org.apache.sling</groupId>
+                                
<artifactId>org.apache.sling.starter</artifactId>
+                                <classifier>nosample_base</classifier>
+                                <version>${sling.starter.version}</version>
+                                <type>slingosgifeature</type>
+                            </includeArtifact>
+                            <includeArtifact>
+                                <groupId>org.apache.sling</groupId>
+                                
<artifactId>org.apache.sling.starter</artifactId>
+                                <classifier>oak_persistence_sns</classifier>
+                                <version>${sling.starter.version}</version>
+                                <type>slingosgifeature</type>
+                            </includeArtifact>
+                            <includeArtifact>
+                                <groupId>org.apache.sling</groupId>
+                                
<artifactId>org.apache.sling.starter</artifactId>
+                                <classifier>junit</classifier>
+                                <version>${sling.starter.version}</version>
+                                <type>slingosgifeature</type>
+                            </includeArtifact>
+                        </aggregate>
+                    </aggregates>
+                    <scans>
+                        <scan>
+                            <includeClassifier>it-app</includeClassifier>
+                        </scan>
+                    </scans>
+                </configuration>
+                <executions>
+                    <execution>
+                        <id>prepare-features</id>
+                        <goals>
+                            <goal>aggregate-features</goal>
+                            <goal>analyse-features</goal>
+                            <goal>attach-features</goal>
+                        </goals>
+                        <phase>pre-integration-test</phase>
+                    </execution>
+                </executions>
+            </plugin>
+
+            <plugin>
+                <groupId>org.apache.sling</groupId>
+                <artifactId>feature-launcher-maven-plugin</artifactId>
+                <version>1.0.3-SNAPSHOT</version>
+                <configuration>
+                    <launches>
+                        <launch>
+                            <id>sling-starter-oak-tar</id>
+                            <feature>
+                                <groupId>org.apache.sling</groupId>
+                                
<artifactId>org.apache.sling.models.jacksonexporter</artifactId>
+                                <version>${project.version}</version>
+                                <classifier>it-app</classifier>
+                                <type>slingosgifeature</type>
+                            </feature>
+                            <launcherArguments>
+                                <vmOptions>
+                                    <value>--add-opens 
java.base/java.lang=ALL-UNNAMED</value>
+                                    <value>${jacoco.launcher.command}</value>
+                                </vmOptions>
+                                <frameworkProperties>
+                                    
<org.osgi.service.http.port>${http.port}</org.osgi.service.http.port>
+                                    
<org.apache.felix.http.jetty.responseBufferSize>5000000</org.apache.felix.http.jetty.responseBufferSize>
+                                </frameworkProperties>
+                            </launcherArguments>
+                            
<startTimeoutSeconds>${it.startTimeoutSeconds}</startTimeoutSeconds>
+                        </launch>
+                    </launches>
+                </configuration>
+                <executions>
+                    <execution>
+                        <id>launcher-start</id>
+                        <goals>
+                            <goal>start</goal>
+                            <goal>stop</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+
+            <plugin>
+                <artifactId>maven-failsafe-plugin</artifactId>
+                <configuration>
+                    <systemPropertyVariables>
+                        
<launchpad.http.server.url>http://localhost:${http.port}</launchpad.http.server.url>
+                        
<starter.http.test.ports>false:${http.port}</starter.http.test.ports>
+                        
<starter.min.bundles.count>${starter.min.bundles.count}</starter.min.bundles.count>
+                        <!-- Comma-separated list of paths to check for 200 
status -->
+                        
<starter.check.paths>/system/console/bundles,</starter.check.paths>
+                    </systemPropertyVariables>
+                </configuration>
+                <dependencies>
+                    <!-- Uss JUnit 4 for integration tests -->
+                    <dependency>
+                        <groupId>org.apache.maven.surefire</groupId>
+                        <artifactId>surefire-junit47</artifactId>
+                        <version>3.5.4</version>
+                    </dependency>
+                </dependencies>
+                <executions>
+                    <execution>
+                        <id>integration-test</id>
+                        <goals>
+                            <goal>integration-test</goal>
+                            <goal>verify</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+
+        </plugins>
+    </build>
+
+    <profiles>
+        <!--
+          Debugging profile:
+          - Run on port 8080 (not random port)
+          - Waits for user input after tests are completed to allow inspection 
before shutting down the Sling instance
+          - Sets log level for Sling Models to DEBUG
+         -->
+        <profile>
+            <id>it-debug</id>
+            <properties>
+                <http.port>8080</http.port>
+                
<feature-launcher.waitForInput>true</feature-launcher.waitForInput>
+                <it.models.log.level>debug</it.models.log.level>
+            </properties>
+        </profile>
+    </profiles>
+
 </project>
diff --git a/src/test/it-features/it-launcher-repoinit.txt 
b/src/test/it-features/it-launcher-repoinit.txt
new file mode 100644
index 0000000..7d36118
--- /dev/null
+++ b/src/test/it-features/it-launcher-repoinit.txt
@@ -0,0 +1,23 @@
+#
+#  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.
+#
+
+create service user models-it
+set ACL for models-it
+    allow   jcr:all    on /
+end
\ No newline at end of file
diff --git a/src/test/it-features/it-launcher.json 
b/src/test/it-features/it-launcher.json
new file mode 100644
index 0000000..ff9bbb8
--- /dev/null
+++ b/src/test/it-features/it-launcher.json
@@ -0,0 +1,34 @@
+{
+    "bundles": [
+        {
+            "id": 
"org.apache.sling/org.apache.sling.models.api/${models.api.version}",
+            "start-order": 20
+        },
+        {
+            "id": 
"org.apache.sling/org.apache.sling.models.impl/${models.impl.version}",
+            "start-order": 20
+        },
+        {
+            "id": 
"org.apache.sling/org.apache.sling.models.jacksonexporter/${project.version}",
+            "start-order": 20
+        },
+        {
+            "id": 
"org.apache.sling/org.apache.sling.models.jacksonexporter/${project.version}//it-testbundle",
+            "start-order": 20
+        }
+    ],
+    "configurations": {
+        
"org.apache.sling.serviceusermapping.impl.ServiceUserMapperImpl.amended~integration-tests":
 {
+            "user.mapping": [
+                "org.apache.sling.junit.core=models-it"
+            ]
+        },
+        
"org.apache.sling.commons.log.LogManager.factory.config~integration-tests": {
+            "org.apache.sling.commons.log.names": [
+                "org.apache.sling.models"
+            ],
+            "org.apache.sling.commons.log.level": "${it.models.log.level}"
+        }
+    },
+    "repoinit:TEXT|true": "@file"
+}
\ No newline at end of file
diff --git 
a/src/test/java/org/apache/sling/junit/teleporter/customizers/SM_TeleporterCustomizer.java
 
b/src/test/java/org/apache/sling/junit/teleporter/customizers/SM_TeleporterCustomizer.java
new file mode 100644
index 0000000..b506364
--- /dev/null
+++ 
b/src/test/java/org/apache/sling/junit/teleporter/customizers/SM_TeleporterCustomizer.java
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.sling.junit.teleporter.customizers;
+
+import java.io.IOException;
+import java.net.URI;
+import java.util.concurrent.TimeoutException;
+
+import org.apache.sling.junit.rules.TeleporterRule;
+import org.apache.sling.models.impl.ModelAdapterFactory;
+import org.apache.sling.models.jacksonexporter.impl.JacksonExporter;
+import org.apache.sling.testing.clients.ClientException;
+import org.apache.sling.testing.clients.osgi.OsgiConsoleClient;
+import org.apache.sling.testing.serversetup.instance.SlingTestBase;
+import org.apache.sling.testing.teleporter.client.ClientSideTeleporter;
+import org.apache.sling.testing.timeouts.TimeoutsProvider;
+
+/** This is required by the TeleporterRule, to setup the client-side
+ *  teleporter with (at least) the test server URL.
+ */
+public class SM_TeleporterCustomizer implements TeleporterRule.Customizer {
+
+    private static final SlingTestBase S = new SlingTestBase();
+
+    private static final Class[] EXPECTED_COMPONENTS = new Class[] 
{ModelAdapterFactory.class, JacksonExporter.class};
+
+    @Override
+    public void customize(TeleporterRule t, String options) {
+        final ClientSideTeleporter cst = (ClientSideTeleporter) t;
+        cst.setBaseUrl(S.getServerBaseUrl());
+        cst.setServerCredentials(S.getServerUsername(), S.getServerPassword());
+        
cst.setTestReadyTimeoutSeconds(TimeoutsProvider.getInstance().getTimeout(5));
+        cst.includeDependencyPrefix("org.apache.sling.models.it.testing");
+
+        // additionally check for the registration of mandatory sling models 
components
+        try (OsgiConsoleClient osgiClient =
+                new OsgiConsoleClient(URI.create(S.getServerBaseUrl()), 
S.getServerUsername(), S.getServerPassword())) {
+            for (Class clazz : EXPECTED_COMPONENTS) {
+                osgiClient.waitComponentRegistered(clazz.getName(), 20000, 
200);
+            }
+        } catch (ClientException | TimeoutException | InterruptedException | 
IOException ex) {
+            throw new RuntimeException("Error waiting for expected 
components.", ex);
+        }
+    }
+}
diff --git 
a/src/test/java/org/apache/sling/models/jacksonexporter/it/GenerateTestBundle.java
 
b/src/test/java/org/apache/sling/models/jacksonexporter/it/GenerateTestBundle.java
new file mode 100644
index 0000000..b6cf45d
--- /dev/null
+++ 
b/src/test/java/org/apache/sling/models/jacksonexporter/it/GenerateTestBundle.java
@@ -0,0 +1,92 @@
+/*
+ * 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.models.jacksonexporter.it;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.List;
+import java.util.Set;
+import java.util.TreeSet;
+import java.util.stream.Collectors;
+
+import io.github.classgraph.ClassGraph;
+import io.github.classgraph.ClassInfo;
+import io.github.classgraph.ScanResult;
+import org.apache.sling.models.annotations.Model;
+import org.ops4j.pax.tinybundles.TinyBundle;
+import org.ops4j.pax.tinybundles.TinyBundles;
+import org.osgi.framework.Constants;
+
+/**
+ * This uses tinybundles to create a test bundle that is deployed to sling
+ * starter. The test bundle contains all classes from the packages
+ * org.apache.sling.models.it.testbundle.*
+ */
+public class GenerateTestBundle {
+
+    private static final String DUMMY_TEXT = "Dummy file for Integration Test 
bundle.";
+
+    public static void main(String[] args) throws Exception {
+        Path outputFile = Paths.get(args[0]);
+        try (InputStream bundleStream = 
createBundle().build(TinyBundles.bndBuilder())) {
+            Files.copy(bundleStream, outputFile);
+        }
+        System.out.println("Test bundle created at " + 
outputFile.toAbsolutePath());
+    }
+
+    static TinyBundle createBundle() {
+        TinyBundle bundle = TinyBundles.bundle()
+                .setHeader(Constants.BUNDLE_NAME, "Apache Sling Models Jackson 
Exporter - IT Test Bundle")
+                .setHeader(Constants.BUNDLE_VERSION, "1.0.0-SNAPSHOT")
+                .setHeader(Constants.EXPORT_PACKAGE, 
"org.apache.sling.models.jacksonexporter.it.testbundle.*")
+                // add dummy files to please verify-legal-files check
+                .addResource("META-INF/LICENSE", new 
ByteArrayInputStream(DUMMY_TEXT.getBytes(StandardCharsets.UTF_8)))
+                .addResource("META-INF/NOTICE", new 
ByteArrayInputStream(DUMMY_TEXT.getBytes(StandardCharsets.UTF_8)));
+
+        // add all testbundle classes
+        Set<String> modelClassNames = new TreeSet<>();
+        getAllClasses().forEach(clazz -> {
+            bundle.addClass(clazz);
+            if (clazz.isAnnotationPresent(Model.class)) {
+                modelClassNames.add(clazz.getName());
+            }
+        });
+
+        // register sling models
+        bundle.setHeader("Sling-Model-Classes", 
modelClassNames.stream().collect(Collectors.joining(",")));
+
+        return bundle;
+    }
+
+    /**
+     * Dynamically find all classes in classpath under package(s) 
org.apache.sling.models.it.testbundle.*
+     */
+    static List<Class<?>> getAllClasses() {
+        try (ScanResult scanResult = new ClassGraph()
+                .enableClassInfo()
+                
.acceptPackages("org.apache.sling.models.jacksonexporter.it.testbundle")
+                .scan()) {
+            return 
scanResult.getAllClasses().stream().map(ClassInfo::loadClass).collect(Collectors.toList());
+        }
+    }
+}
diff --git 
a/src/test/java/org/apache/sling/models/jacksonexporter/it/testbundle/exporter/BaseComponent.java
 
b/src/test/java/org/apache/sling/models/jacksonexporter/it/testbundle/exporter/BaseComponent.java
new file mode 100644
index 0000000..f6b7bbd
--- /dev/null
+++ 
b/src/test/java/org/apache/sling/models/jacksonexporter/it/testbundle/exporter/BaseComponent.java
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.sling.models.jacksonexporter.it.testbundle.exporter;
+
+import javax.inject.Inject;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.models.annotations.Exporter;
+import org.apache.sling.models.annotations.Model;
+
+@Model(
+        adaptables = {Resource.class},
+        resourceType = "sling/exp/base")
+@Exporter(name = "jackson", extensions = "json")
+public class BaseComponent {
+
+    private final Resource resource;
+
+    @Inject
+    private String sampleValue;
+
+    public BaseComponent(Resource resource) {
+        this.resource = resource;
+    }
+
+    public String getId() {
+        return this.resource.getPath();
+    }
+
+    public String getSampleValue() {
+        return sampleValue;
+    }
+
+    @JsonProperty(value = "UPPER")
+    public String getSampleValueToUpperCase() {
+        return sampleValue.toUpperCase();
+    }
+
+    public Resource getResource() {
+        return resource;
+    }
+}
diff --git 
a/src/test/java/org/apache/sling/models/jacksonexporter/it/testbundle/exporter/BaseRequestComponent.java
 
b/src/test/java/org/apache/sling/models/jacksonexporter/it/testbundle/exporter/BaseRequestComponent.java
new file mode 100644
index 0000000..1775f71
--- /dev/null
+++ 
b/src/test/java/org/apache/sling/models/jacksonexporter/it/testbundle/exporter/BaseRequestComponent.java
@@ -0,0 +1,105 @@
+/*
+ * 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.models.jacksonexporter.it.testbundle.exporter;
+
+import javax.inject.Inject;
+import javax.servlet.ServletRequest;
+import javax.servlet.http.HttpServletRequest;
+
+import java.util.Map;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import org.apache.sling.api.SlingHttpServletRequest;
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.models.annotations.Exporter;
+import org.apache.sling.models.annotations.ExporterOption;
+import org.apache.sling.models.annotations.Model;
+import org.apache.sling.models.annotations.Via;
+import org.apache.sling.models.annotations.injectorspecific.SlingObject;
+
+@Model(
+        adaptables = {SlingHttpServletRequest.class},
+        resourceType = "sling/exp-request/base")
+@Exporter(
+        name = "jackson",
+        extensions = "json",
+        options = {@ExporterOption(name = 
"MapperFeature.SORT_PROPERTIES_ALPHABETICALLY", value = "true")})
+public class BaseRequestComponent {
+
+    @Inject
+    @SlingObject
+    private Resource resource;
+
+    @Inject
+    @Via("resource")
+    private String sampleValue;
+
+    @Inject
+    private Map<String, Object> testBindingsObject;
+
+    @Inject
+    private Map<String, Object> testBindingsObject2;
+
+    private final SlingHttpServletRequest request;
+
+    public BaseRequestComponent(SlingHttpServletRequest request) {
+        this.request = request;
+    }
+
+    public String getId() {
+        return this.resource.getPath();
+    }
+
+    public String getSampleValue() {
+        return sampleValue;
+    }
+
+    @JsonProperty(value = "UPPER")
+    public String getSampleValueToUpperCase() {
+        return sampleValue.toUpperCase();
+    }
+
+    public Resource getResource() {
+        return resource;
+    }
+
+    public Map<String, Object> getTestBindingsObject() {
+        return testBindingsObject;
+    }
+
+    public Map<String, Object> getTestBindingsObject2() {
+        return testBindingsObject2;
+    }
+
+    @JsonIgnore
+    public SlingHttpServletRequest getSlingHttpServletRequest() {
+        return request;
+    }
+
+    @JsonIgnore
+    public HttpServletRequest getHttpServletRequest() {
+        return request;
+    }
+
+    @JsonIgnore
+    public ServletRequest getServletRequest() {
+        return request;
+    }
+}
diff --git 
a/src/test/java/org/apache/sling/models/jacksonexporter/it/testbundle/exporter/Component.java
 
b/src/test/java/org/apache/sling/models/jacksonexporter/it/testbundle/exporter/Component.java
new file mode 100644
index 0000000..d83af0b
--- /dev/null
+++ 
b/src/test/java/org/apache/sling/models/jacksonexporter/it/testbundle/exporter/Component.java
@@ -0,0 +1,26 @@
+/*
+ * 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.models.jacksonexporter.it.testbundle.exporter;
+
+public interface Component {
+
+    String getId();
+
+    String getSampleValue();
+}
diff --git 
a/src/test/java/org/apache/sling/models/jacksonexporter/it/testbundle/exporter/ComponentImpl.java
 
b/src/test/java/org/apache/sling/models/jacksonexporter/it/testbundle/exporter/ComponentImpl.java
new file mode 100644
index 0000000..1e8773f
--- /dev/null
+++ 
b/src/test/java/org/apache/sling/models/jacksonexporter/it/testbundle/exporter/ComponentImpl.java
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.sling.models.jacksonexporter.it.testbundle.exporter;
+
+import javax.inject.Inject;
+
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.models.annotations.Exporter;
+import org.apache.sling.models.annotations.Model;
+
+@Model(
+        adaptables = {Resource.class},
+        adapters = Component.class,
+        resourceType = "sling/exp/interface")
+@Exporter(name = "jackson", extensions = "json")
+public class ComponentImpl implements Component {
+
+    private final Resource resource;
+
+    @Inject
+    private String sampleValue;
+
+    public ComponentImpl(Resource resource) {
+        this.resource = resource;
+    }
+
+    public String getId() {
+        return this.resource.getPath();
+    }
+
+    public String getSampleValue() {
+        return sampleValue;
+    }
+}
diff --git 
a/src/test/java/org/apache/sling/models/jacksonexporter/it/testbundle/exporter/DoubledFirstComponent.java
 
b/src/test/java/org/apache/sling/models/jacksonexporter/it/testbundle/exporter/DoubledFirstComponent.java
new file mode 100644
index 0000000..3d76e37
--- /dev/null
+++ 
b/src/test/java/org/apache/sling/models/jacksonexporter/it/testbundle/exporter/DoubledFirstComponent.java
@@ -0,0 +1,34 @@
+/*
+ * 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.models.jacksonexporter.it.testbundle.exporter;
+
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.models.annotations.Exporter;
+import org.apache.sling.models.annotations.Model;
+
+@Model(
+        adaptables = {Resource.class},
+        resourceType = "sling/exp/doubled")
+@Exporter(name = "jackson", extensions = "json", selector = "firstmodel")
+public class DoubledFirstComponent {
+
+    public String getValue() {
+        return "first";
+    }
+}
diff --git 
a/src/test/java/org/apache/sling/models/jacksonexporter/it/testbundle/exporter/DoubledSecondComponent.java
 
b/src/test/java/org/apache/sling/models/jacksonexporter/it/testbundle/exporter/DoubledSecondComponent.java
new file mode 100644
index 0000000..d79ab33
--- /dev/null
+++ 
b/src/test/java/org/apache/sling/models/jacksonexporter/it/testbundle/exporter/DoubledSecondComponent.java
@@ -0,0 +1,34 @@
+/*
+ * 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.models.jacksonexporter.it.testbundle.exporter;
+
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.models.annotations.Exporter;
+import org.apache.sling.models.annotations.Model;
+
+@Model(
+        adaptables = {Resource.class},
+        resourceType = "sling/exp/doubled")
+@Exporter(name = "jackson", extensions = "json", selector = "secondmodel")
+public class DoubledSecondComponent {
+
+    public String getValue() {
+        return "second";
+    }
+}
diff --git 
a/src/test/java/org/apache/sling/models/jacksonexporter/it/testbundle/exporter/ExtendedComponent.java
 
b/src/test/java/org/apache/sling/models/jacksonexporter/it/testbundle/exporter/ExtendedComponent.java
new file mode 100644
index 0000000..ecb11e6
--- /dev/null
+++ 
b/src/test/java/org/apache/sling/models/jacksonexporter/it/testbundle/exporter/ExtendedComponent.java
@@ -0,0 +1,53 @@
+/*
+ * 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.models.jacksonexporter.it.testbundle.exporter;
+
+import javax.inject.Inject;
+
+import java.util.Calendar;
+import java.util.Date;
+import java.util.GregorianCalendar;
+
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.models.annotations.Exporter;
+import org.apache.sling.models.annotations.Model;
+
+@Model(
+        adaptables = {Resource.class},
+        resourceType = "sling/exp/extended")
+@Exporter(name = "jackson", extensions = "json")
+public class ExtendedComponent extends BaseComponent {
+
+    @Inject
+    private Date date;
+
+    public ExtendedComponent(Resource resource) {
+        super(resource);
+    }
+
+    public Calendar getDateByCalendar() {
+        Calendar cal = new GregorianCalendar();
+        cal.setTime(date);
+        return cal;
+    }
+
+    public Date getDate() {
+        return date;
+    }
+}
diff --git 
a/src/test/java/org/apache/sling/models/jacksonexporter/it/testbundle/exporter/ExtendedRequestComponent.java
 
b/src/test/java/org/apache/sling/models/jacksonexporter/it/testbundle/exporter/ExtendedRequestComponent.java
new file mode 100644
index 0000000..df3ec1b
--- /dev/null
+++ 
b/src/test/java/org/apache/sling/models/jacksonexporter/it/testbundle/exporter/ExtendedRequestComponent.java
@@ -0,0 +1,62 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.sling.models.jacksonexporter.it.testbundle.exporter;
+
+import javax.inject.Inject;
+
+import java.util.Calendar;
+import java.util.Date;
+import java.util.GregorianCalendar;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import org.apache.sling.api.SlingHttpServletRequest;
+import org.apache.sling.models.annotations.Exporter;
+import org.apache.sling.models.annotations.ExporterOption;
+import org.apache.sling.models.annotations.Model;
+import org.apache.sling.models.annotations.Via;
+
+@Model(
+        adaptables = {SlingHttpServletRequest.class},
+        resourceType = "sling/exp-request/extended")
+@Exporter(
+        name = "jackson",
+        extensions = "json",
+        options = {@ExporterOption(name = 
"SerializationFeature.WRITE_DATES_AS_TIMESTAMPS", value = "false")})
+public class ExtendedRequestComponent extends BaseRequestComponent {
+
+    @Inject
+    @Via("resource")
+    private Date date;
+
+    public ExtendedRequestComponent(SlingHttpServletRequest request) {
+        super(request);
+    }
+
+    @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = 
"yyyy-MM-dd'T'HH:mm:ss.SSSZ", timezone = "UTC")
+    public Calendar getDateByCalendar() {
+        Calendar cal = new GregorianCalendar();
+        cal.setTime(date);
+        return cal;
+    }
+
+    @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = 
"yyyy-MM-dd'T'HH:mm:ss.SSSZ", timezone = "UTC")
+    public Date getDate() {
+        return date;
+    }
+}
diff --git 
a/src/test/java/org/apache/sling/models/jacksonexporter/it/testbundle/exporter/JakartaBaseRequestComponent.java
 
b/src/test/java/org/apache/sling/models/jacksonexporter/it/testbundle/exporter/JakartaBaseRequestComponent.java
new file mode 100644
index 0000000..a9e1178
--- /dev/null
+++ 
b/src/test/java/org/apache/sling/models/jacksonexporter/it/testbundle/exporter/JakartaBaseRequestComponent.java
@@ -0,0 +1,105 @@
+/*
+ * 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.models.jacksonexporter.it.testbundle.exporter;
+
+import javax.inject.Inject;
+
+import java.util.Map;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import jakarta.servlet.ServletRequest;
+import jakarta.servlet.http.HttpServletRequest;
+import org.apache.sling.api.SlingJakartaHttpServletRequest;
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.models.annotations.Exporter;
+import org.apache.sling.models.annotations.ExporterOption;
+import org.apache.sling.models.annotations.Model;
+import org.apache.sling.models.annotations.Via;
+import org.apache.sling.models.annotations.injectorspecific.SlingObject;
+
+@Model(
+        adaptables = {SlingJakartaHttpServletRequest.class},
+        resourceType = "sling/exp-request/baseJakarta")
+@Exporter(
+        name = "jackson",
+        extensions = "json",
+        options = {@ExporterOption(name = 
"MapperFeature.SORT_PROPERTIES_ALPHABETICALLY", value = "true")})
+public class JakartaBaseRequestComponent {
+
+    @Inject
+    @SlingObject
+    private Resource resource;
+
+    @Inject
+    @Via("resource")
+    private String sampleValue;
+
+    @Inject
+    private Map<String, Object> testBindingsObject;
+
+    @Inject
+    private Map<String, Object> testBindingsObject2;
+
+    private final SlingJakartaHttpServletRequest request;
+
+    public JakartaBaseRequestComponent(SlingJakartaHttpServletRequest request) 
{
+        this.request = request;
+    }
+
+    public String getId() {
+        return this.resource.getPath();
+    }
+
+    public String getSampleValue() {
+        return sampleValue;
+    }
+
+    @JsonProperty(value = "UPPER")
+    public String getSampleValueToUpperCase() {
+        return sampleValue.toUpperCase();
+    }
+
+    public Resource getResource() {
+        return resource;
+    }
+
+    public Map<String, Object> getTestBindingsObject() {
+        return testBindingsObject;
+    }
+
+    public Map<String, Object> getTestBindingsObject2() {
+        return testBindingsObject2;
+    }
+
+    @JsonIgnore
+    public SlingJakartaHttpServletRequest getSlingHttpServletRequest() {
+        return request;
+    }
+
+    @JsonIgnore
+    public HttpServletRequest getHttpServletRequest() {
+        return request;
+    }
+
+    @JsonIgnore
+    public ServletRequest getServletRequest() {
+        return request;
+    }
+}
diff --git 
a/src/test/java/org/apache/sling/models/jacksonexporter/it/testbundle/exporter/JakartaExtendedRequestComponent.java
 
b/src/test/java/org/apache/sling/models/jacksonexporter/it/testbundle/exporter/JakartaExtendedRequestComponent.java
new file mode 100644
index 0000000..c2edd58
--- /dev/null
+++ 
b/src/test/java/org/apache/sling/models/jacksonexporter/it/testbundle/exporter/JakartaExtendedRequestComponent.java
@@ -0,0 +1,62 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.sling.models.jacksonexporter.it.testbundle.exporter;
+
+import javax.inject.Inject;
+
+import java.util.Calendar;
+import java.util.Date;
+import java.util.GregorianCalendar;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import org.apache.sling.api.SlingJakartaHttpServletRequest;
+import org.apache.sling.models.annotations.Exporter;
+import org.apache.sling.models.annotations.ExporterOption;
+import org.apache.sling.models.annotations.Model;
+import org.apache.sling.models.annotations.Via;
+
+@Model(
+        adaptables = {SlingJakartaHttpServletRequest.class},
+        resourceType = "sling/exp-request/extendedJakarta")
+@Exporter(
+        name = "jackson",
+        extensions = "json",
+        options = {@ExporterOption(name = 
"SerializationFeature.WRITE_DATES_AS_TIMESTAMPS", value = "false")})
+public class JakartaExtendedRequestComponent extends 
JakartaBaseRequestComponent {
+
+    @Inject
+    @Via("resource")
+    private Date date;
+
+    public JakartaExtendedRequestComponent(SlingJakartaHttpServletRequest 
request) {
+        super(request);
+    }
+
+    @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = 
"yyyy-MM-dd'T'HH:mm:ss.SSSZ", timezone = "UTC")
+    public Calendar getDateByCalendar() {
+        Calendar cal = new GregorianCalendar();
+        cal.setTime(date);
+        return cal;
+    }
+
+    @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = 
"yyyy-MM-dd'T'HH:mm:ss.SSSZ", timezone = "UTC")
+    public Date getDate() {
+        return date;
+    }
+}
diff --git 
a/src/test/java/org/apache/sling/models/jacksonexporter/it/testbundle/exporter/JakartaRequestComponentImpl.java
 
b/src/test/java/org/apache/sling/models/jacksonexporter/it/testbundle/exporter/JakartaRequestComponentImpl.java
new file mode 100644
index 0000000..3522422
--- /dev/null
+++ 
b/src/test/java/org/apache/sling/models/jacksonexporter/it/testbundle/exporter/JakartaRequestComponentImpl.java
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.sling.models.jacksonexporter.it.testbundle.exporter;
+
+import javax.inject.Inject;
+
+import org.apache.sling.api.SlingJakartaHttpServletRequest;
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.models.annotations.Exporter;
+import org.apache.sling.models.annotations.Model;
+import org.apache.sling.models.annotations.Via;
+import org.apache.sling.models.annotations.injectorspecific.SlingObject;
+
+@Model(
+        adaptables = {SlingJakartaHttpServletRequest.class},
+        adapters = Component.class,
+        resourceType = "sling/exp-request/interfaceJakarta")
+@Exporter(name = "jackson", extensions = "json")
+public class JakartaRequestComponentImpl implements Component {
+
+    @Inject
+    @SlingObject
+    private Resource resource;
+
+    @Inject
+    @Via("resource")
+    private String sampleValue;
+
+    @SuppressWarnings("unused")
+    private final SlingJakartaHttpServletRequest request;
+
+    public JakartaRequestComponentImpl(SlingJakartaHttpServletRequest request) 
{
+        this.request = request;
+    }
+
+    public String getId() {
+        return this.resource.getPath();
+    }
+
+    public String getSampleValue() {
+        return sampleValue;
+    }
+}
diff --git 
a/src/test/java/org/apache/sling/models/jacksonexporter/it/testbundle/exporter/RequestComponentImpl.java
 
b/src/test/java/org/apache/sling/models/jacksonexporter/it/testbundle/exporter/RequestComponentImpl.java
new file mode 100644
index 0000000..7fa3687
--- /dev/null
+++ 
b/src/test/java/org/apache/sling/models/jacksonexporter/it/testbundle/exporter/RequestComponentImpl.java
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.sling.models.jacksonexporter.it.testbundle.exporter;
+
+import javax.inject.Inject;
+
+import org.apache.sling.api.SlingHttpServletRequest;
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.models.annotations.Exporter;
+import org.apache.sling.models.annotations.Model;
+import org.apache.sling.models.annotations.Via;
+import org.apache.sling.models.annotations.injectorspecific.SlingObject;
+
+@Model(
+        adaptables = {SlingHttpServletRequest.class},
+        adapters = Component.class,
+        resourceType = "sling/exp-request/interface")
+@Exporter(name = "jackson", extensions = "json")
+public class RequestComponentImpl implements Component {
+
+    @Inject
+    @SlingObject
+    private Resource resource;
+
+    @Inject
+    @Via("resource")
+    private String sampleValue;
+
+    @SuppressWarnings("unused")
+    private final SlingHttpServletRequest request;
+
+    public RequestComponentImpl(SlingHttpServletRequest request) {
+        this.request = request;
+    }
+
+    public String getId() {
+        return this.resource.getPath();
+    }
+
+    public String getSampleValue() {
+        return sampleValue;
+    }
+}
diff --git 
a/src/test/java/org/apache/sling/models/jacksonexporter/it/testbundle/services/AnotherTestBindingsValuesProvider.java
 
b/src/test/java/org/apache/sling/models/jacksonexporter/it/testbundle/services/AnotherTestBindingsValuesProvider.java
new file mode 100644
index 0000000..39bee94
--- /dev/null
+++ 
b/src/test/java/org/apache/sling/models/jacksonexporter/it/testbundle/services/AnotherTestBindingsValuesProvider.java
@@ -0,0 +1,36 @@
+/*
+ * 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.models.jacksonexporter.it.testbundle.services;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.osgi.service.component.annotations.Component;
+
+@Component(
+        service = Map.class,
+        property = {"javax.script.name=sling-models-exporter"})
+public class AnotherTestBindingsValuesProvider extends HashMap<String, Object> 
{
+    private static final long serialVersionUID = 1L;
+
+    public AnotherTestBindingsValuesProvider() {
+        super.put("testBindingsObject2", Collections.singletonMap("name2", 
"value2"));
+    }
+}
diff --git 
a/src/test/java/org/apache/sling/models/jacksonexporter/it/testbundle/services/TestBindingsValuesProvider.java
 
b/src/test/java/org/apache/sling/models/jacksonexporter/it/testbundle/services/TestBindingsValuesProvider.java
new file mode 100644
index 0000000..cae26bd
--- /dev/null
+++ 
b/src/test/java/org/apache/sling/models/jacksonexporter/it/testbundle/services/TestBindingsValuesProvider.java
@@ -0,0 +1,36 @@
+/*
+ * 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.models.jacksonexporter.it.testbundle.services;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.osgi.service.component.annotations.Component;
+
+@Component(
+        service = Map.class,
+        property = {"javax.script.name=*"})
+public class TestBindingsValuesProvider extends HashMap<String, Object> {
+    private static final long serialVersionUID = -5029445376678233701L;
+
+    public TestBindingsValuesProvider() {
+        super.put("testBindingsObject", Collections.singletonMap("name", 
"value"));
+    }
+}
diff --git 
a/src/test/java/org/apache/sling/models/jacksonexporter/it/testing/exporter/ExporterIT.java
 
b/src/test/java/org/apache/sling/models/jacksonexporter/it/testing/exporter/ExporterIT.java
new file mode 100644
index 0000000..900016f
--- /dev/null
+++ 
b/src/test/java/org/apache/sling/models/jacksonexporter/it/testing/exporter/ExporterIT.java
@@ -0,0 +1,393 @@
+/*
+ * 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.models.jacksonexporter.it.testing.exporter;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.io.StringReader;
+import java.text.Format;
+import java.util.Calendar;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.TimeZone;
+
+import jakarta.json.Json;
+import jakarta.json.JsonObject;
+import org.apache.commons.lang3.Strings;
+import org.apache.commons.lang3.time.FastDateFormat;
+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.api.resource.ResourceUtil;
+import org.apache.sling.engine.SlingRequestProcessor;
+import org.apache.sling.junit.rules.TeleporterRule;
+import org.apache.sling.models.factory.MissingExporterException;
+import org.apache.sling.models.factory.ModelFactory;
+import org.apache.sling.models.it.testing.helper.FakeRequest;
+import org.apache.sling.models.it.testing.helper.FakeResponse;
+import org.apache.sling.models.it.testing.helper.JakartaFakeRequest;
+import org.apache.sling.models.it.testing.helper.JakartaFakeResponse;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Rule;
+import org.junit.Test;
+
+import static 
org.apache.sling.api.resource.ResourceResolver.PROPERTY_RESOURCE_SUPER_TYPE;
+import static 
org.apache.sling.api.resource.ResourceResolver.PROPERTY_RESOURCE_TYPE;
+
+public class ExporterIT {
+
+    @Rule
+    public final TeleporterRule teleporter = 
TeleporterRule.forClass(getClass(), "SM_Teleporter");
+
+    private ResourceResolverFactory rrFactory;
+
+    private ModelFactory modelFactory;
+
+    private SlingRequestProcessor slingRequestProcessor;
+
+    private final String baseComponentPath = "/content/exp/baseComponent";
+    private final String doubledComponentPath = 
"/content/exp/doubledComponent";
+    private final String childComponentPath = "/content/exp/childComponent";
+    private final String extendedComponentPath = 
"/content/exp/extendedComponent";
+    private final String interfaceComponentPath = 
"/content/exp/interfaceComponent";
+    private final String baseRequestComponentPath = 
"/content/exp-request/baseComponent";
+    private final String extendedRequestComponentPath = 
"/content/exp-request/extendedComponent";
+    private final String interfaceRequestComponentPath = 
"/content/exp-request/interfaceComponent";
+    private final String jakartaBaseRequestComponentPath = 
"/content/exp-request/baseComponentJakarta";
+    private final String jakartaExtendedRequestComponentPath = 
"/content/exp-request/extendedComponentJakarta";
+    private final String jakartaInterfaceRequestComponentPath = 
"/content/exp-request/interfaceComponentJakarta";
+    private Calendar testDate;
+
+    private Format dateFormat = 
FastDateFormat.getInstance("yyyy-MM-dd'T'HH:mm:ss.SSSZ", 
TimeZone.getTimeZone("UTC"));
+
+    @Before
+    public void setup() throws Exception {
+        rrFactory = teleporter.getService(ResourceResolverFactory.class);
+        modelFactory = teleporter.getService(ModelFactory.class);
+        slingRequestProcessor = 
teleporter.getService(SlingRequestProcessor.class);
+
+        try (ResourceResolver adminResolver = 
rrFactory.getServiceResourceResolver(null); ) {
+            Map<String, Object> properties = new HashMap<String, Object>();
+            properties.put("sampleValue", "baseTESTValue");
+            properties.put("sampleBooleanValue", true);
+            properties.put("sampleLongValue", 1l);
+            properties.put("sampleDoubleValue", 1d);
+            properties.put("sampleArray", new String[] {"a", "b", "c"});
+            properties.put("sampleEmptyArray", new String[0]);
+            properties.put("sampleBinary", new 
ByteArrayInputStream("abc".getBytes("UTF-8")));
+            properties.put("sampleBinaryArray", new InputStream[] {
+                new ByteArrayInputStream("abc".getBytes("UTF-8")), new 
ByteArrayInputStream("def".getBytes("UTF-8"))
+            });
+            properties.put(PROPERTY_RESOURCE_TYPE, "sling/exp/base");
+            ResourceUtil.getOrCreateResource(adminResolver, baseComponentPath, 
properties, null, false);
+
+            ResourceUtil.getOrCreateResource(
+                    adminResolver, baseComponentPath + "/child", 
Collections.<String, Object>emptyMap(), null, false);
+
+            properties.put(PROPERTY_RESOURCE_TYPE, "sling/exp-request/base");
+            ResourceUtil.getOrCreateResource(adminResolver, 
baseRequestComponentPath, properties, null, false);
+
+            properties.put(PROPERTY_RESOURCE_TYPE, 
"sling/exp-request/baseJakarta");
+            ResourceUtil.getOrCreateResource(adminResolver, 
jakartaBaseRequestComponentPath, properties, null, false);
+            properties.clear();
+
+            properties.put("sampleValue", "childTESTValue");
+            properties.put(PROPERTY_RESOURCE_TYPE, "sling/exp/child");
+            properties.put(PROPERTY_RESOURCE_SUPER_TYPE, "sling/exp/base");
+            ResourceUtil.getOrCreateResource(adminResolver, 
childComponentPath, properties, null, false);
+            properties.clear();
+
+            properties.put("sampleValue", "extendedTESTValue");
+            properties.put(PROPERTY_RESOURCE_TYPE, "sling/exp/extended");
+            testDate = Calendar.getInstance();
+            testDate.setTimeZone(TimeZone.getTimeZone("UTC"));
+            testDate.setTimeInMillis(0);
+            testDate.set(2015, 6, 29);
+            properties.put("date", testDate);
+            ResourceUtil.getOrCreateResource(adminResolver, 
extendedComponentPath, properties, null, false);
+
+            properties.put(PROPERTY_RESOURCE_TYPE, 
"sling/exp-request/extended");
+            ResourceUtil.getOrCreateResource(adminResolver, 
extendedRequestComponentPath, properties, null, false);
+
+            properties.put(PROPERTY_RESOURCE_TYPE, 
"sling/exp-request/extendedJakarta");
+            ResourceUtil.getOrCreateResource(
+                    adminResolver, jakartaExtendedRequestComponentPath, 
properties, null, false);
+            properties.clear();
+
+            properties.put("sampleValue", "interfaceTESTValue");
+            properties.put(PROPERTY_RESOURCE_TYPE, "sling/exp/interface");
+            ResourceUtil.getOrCreateResource(adminResolver, 
interfaceComponentPath, properties, null, false);
+
+            properties.put(PROPERTY_RESOURCE_TYPE, 
"sling/exp-request/interface");
+            ResourceUtil.getOrCreateResource(adminResolver, 
interfaceRequestComponentPath, properties, null, false);
+
+            properties.put(PROPERTY_RESOURCE_TYPE, 
"sling/exp-request/interfaceJakarta");
+            ResourceUtil.getOrCreateResource(
+                    adminResolver, jakartaInterfaceRequestComponentPath, 
properties, null, false);
+            properties.clear();
+
+            properties.put(PROPERTY_RESOURCE_TYPE, "sling/exp/doubled");
+            ResourceUtil.getOrCreateResource(adminResolver, 
doubledComponentPath, properties, null, false);
+
+            adminResolver.commit();
+        }
+    }
+
+    @Test
+    public void testExportToJSON() throws Exception {
+        try (ResourceResolver resolver = 
rrFactory.getServiceResourceResolver(null); ) {
+            final Resource baseComponentResource = 
resolver.getResource(baseComponentPath);
+            Assert.assertNotNull(baseComponentResource);
+            String jsonData = modelFactory.exportModelForResource(
+                    baseComponentResource, "jackson", String.class, 
Collections.<String, String>emptyMap());
+            Assert.assertTrue(
+                    "JSON Data should contain the property value", 
Strings.CS.contains(jsonData, "baseTESTValue"));
+
+            JsonObject parsed = Json.createReader(new 
StringReader(jsonData)).readObject();
+            JsonObject resource = parsed.getJsonObject("resource");
+            Assert.assertEquals(3, 
resource.getJsonArray("sampleArray").size());
+            Assert.assertEquals(
+                    1.0d, 
resource.getJsonNumber("sampleDoubleValue").doubleValue(), .1);
+            Assert.assertEquals(2, 
resource.getJsonArray(":sampleBinaryArray").size());
+            Assert.assertTrue(resource.getBoolean("sampleBooleanValue"));
+            Assert.assertEquals(1, resource.getInt("sampleLongValue"));
+            Assert.assertEquals(3, resource.getInt(":sampleBinary"));
+            Assert.assertEquals(0, 
resource.getJsonArray("sampleEmptyArray").size());
+
+            final Resource extendedComponentResource = 
resolver.getResource(extendedComponentPath);
+            Assert.assertNotNull(extendedComponentResource);
+            jsonData = modelFactory.exportModelForResource(
+                    extendedComponentResource, "jackson", String.class, 
Collections.<String, String>emptyMap());
+            Assert.assertTrue(
+                    "JSON Data should contain the property value", 
Strings.CS.contains(jsonData, "extendedTESTValue"));
+
+            final Resource interfaceComponentResource = 
resolver.getResource(interfaceComponentPath);
+            Assert.assertNotNull(baseComponentResource);
+            jsonData = modelFactory.exportModelForResource(
+                    interfaceComponentResource, "jackson", String.class, 
Collections.<String, String>emptyMap());
+            Assert.assertTrue(
+                    "JSON Data should contain the property value", 
Strings.CS.contains(jsonData, "interfaceTESTValue"));
+        }
+    }
+
+    @Test
+    public void testExportToTidyJSON() throws Exception {
+        try (ResourceResolver resolver = 
rrFactory.getServiceResourceResolver(null); ) {
+            final Resource baseComponentResource = 
resolver.getResource(baseComponentPath);
+            Assert.assertNotNull(baseComponentResource);
+            String jsonData = modelFactory.exportModelForResource(
+                    baseComponentResource, "jackson", String.class, 
Collections.<String, String>emptyMap());
+            Assert.assertFalse(jsonData.contains(System.lineSeparator()));
+
+            jsonData = modelFactory.exportModelForResource(
+                    baseComponentResource,
+                    "jackson",
+                    String.class,
+                    Collections.<String, String>singletonMap("tidy", "true"));
+            Assert.assertTrue(jsonData.contains(System.lineSeparator()));
+        }
+    }
+
+    @SuppressWarnings("unchecked")
+    @Test
+    public void testExportToMap() throws Exception {
+        try (ResourceResolver resolver = 
rrFactory.getServiceResourceResolver(null); ) {
+            final Resource baseComponentResource = 
resolver.getResource(baseComponentPath);
+            Assert.assertNotNull(baseComponentResource);
+            Map<String, Object> data = modelFactory.exportModelForResource(
+                    baseComponentResource, "jackson", Map.class, 
Collections.<String, String>emptyMap());
+            Assert.assertEquals("Should have resource value", "baseTESTValue", 
data.get("sampleValue"));
+            Assert.assertEquals("Should have resource value", "BASETESTVALUE", 
data.get("UPPER"));
+        }
+    }
+
+    @Test
+    public void testResourceServlets() throws Exception {
+        try (ResourceResolver resolver = 
rrFactory.getServiceResourceResolver(null); ) {
+            FakeResponse response = new FakeResponse();
+            slingRequestProcessor.processRequest(
+                    new FakeRequest(baseComponentPath + ".model.json"), 
response, resolver);
+            JsonObject obj = Json.createReader(
+                            new 
StringReader((response.getStringWriter().toString())))
+                    .readObject();
+            Assert.assertEquals("application/json", response.getContentType());
+            Assert.assertEquals("UTF-8", response.getCharacterEncoding());
+            Assert.assertEquals("BASETESTVALUE", obj.getString("UPPER"));
+            Assert.assertEquals(baseComponentPath, obj.getString("id"));
+
+            response = new FakeResponse();
+            slingRequestProcessor.processRequest(
+                    new FakeRequest(extendedComponentPath + ".model.json"), 
response, resolver);
+            obj = Json.createReader(new 
StringReader((response.getStringWriter().toString())))
+                    .readObject();
+            Assert.assertEquals("application/json", response.getContentType());
+            Assert.assertEquals("UTF-8", response.getCharacterEncoding());
+            Assert.assertEquals(extendedComponentPath, obj.getString("id"));
+            Assert.assertEquals(
+                    testDate.getTimeInMillis(), 
obj.getJsonNumber("date").longValue());
+
+            response = new FakeResponse();
+            slingRequestProcessor.processRequest(
+                    new FakeRequest(interfaceComponentPath + ".model.json"), 
response, resolver);
+            obj = Json.createReader(new 
StringReader((response.getStringWriter().toString())))
+                    .readObject();
+            Assert.assertEquals("application/json", response.getContentType());
+            Assert.assertEquals("UTF-8", response.getCharacterEncoding());
+            Assert.assertEquals(interfaceComponentPath, obj.getString("id"));
+            Assert.assertEquals("interfaceTESTValue", 
obj.getString("sampleValue"));
+        }
+    }
+
+    @Test
+    @Ignore("TODO: enable when problem with Jakarta Servlet API -> Javax 
Servlet API is solved")
+    public void testRequestServlets() throws Exception {
+        try (ResourceResolver resolver = 
rrFactory.getServiceResourceResolver(null); ) {
+            FakeResponse response = new FakeResponse();
+            slingRequestProcessor.processRequest(
+                    new FakeRequest(baseRequestComponentPath + ".model.json"), 
response, resolver);
+            String stringOutput = response.getStringWriter().toString();
+
+            Assert.assertTrue(
+                    "String does not start with '{\"UPPER\":': '" + 
stringOutput + "'",
+                    stringOutput.startsWith("{\"UPPER\":"));
+
+            JsonObject obj = Json.createReader(new 
StringReader(stringOutput)).readObject();
+            Assert.assertEquals("application/json", response.getContentType());
+            Assert.assertEquals("UTF-8", response.getCharacterEncoding());
+            Assert.assertEquals("BASETESTVALUE", obj.getString("UPPER"));
+            Assert.assertTrue(obj.containsKey("testBindingsObject"));
+            JsonObject testBindingsObject = 
obj.getJsonObject("testBindingsObject");
+            Assert.assertEquals("value", testBindingsObject.getString("name"));
+            Assert.assertTrue(obj.containsKey("testBindingsObject2"));
+            JsonObject testBindingsObject2 = 
obj.getJsonObject("testBindingsObject2");
+            Assert.assertEquals("value2", 
testBindingsObject2.getString("name2"));
+            Assert.assertEquals(baseRequestComponentPath, obj.getString("id"));
+
+            response = new FakeResponse();
+            slingRequestProcessor.processRequest(
+                    new FakeRequest(extendedRequestComponentPath + 
".model.json"), response, resolver);
+            obj = Json.createReader(new 
StringReader((response.getStringWriter().toString())))
+                    .readObject();
+            Assert.assertEquals("application/json", response.getContentType());
+            Assert.assertEquals("UTF-8", response.getCharacterEncoding());
+            Assert.assertEquals(extendedRequestComponentPath, 
obj.getString("id"));
+            Assert.assertEquals(dateFormat.format(testDate), 
obj.getString("date"));
+
+            response = new FakeResponse();
+            slingRequestProcessor.processRequest(
+                    new FakeRequest(interfaceRequestComponentPath + 
".model.json"), response, resolver);
+            obj = Json.createReader(new 
StringReader((response.getStringWriter().toString())))
+                    .readObject();
+            Assert.assertEquals("application/json", response.getContentType());
+            Assert.assertEquals("UTF-8", response.getCharacterEncoding());
+            Assert.assertEquals(interfaceRequestComponentPath, 
obj.getString("id"));
+            Assert.assertEquals("interfaceTESTValue", 
obj.getString("sampleValue"));
+        }
+    }
+
+    @Test
+    public void testRequestServlets_Jakarta() throws Exception {
+        try (ResourceResolver resolver = 
rrFactory.getServiceResourceResolver(null); ) {
+            JakartaFakeResponse response = new JakartaFakeResponse();
+            slingRequestProcessor.processRequest(
+                    new JakartaFakeRequest(jakartaBaseRequestComponentPath + 
".model.json"), response, resolver);
+            String stringOutput = response.getStringWriter().toString();
+
+            Assert.assertTrue(
+                    "String does not start with '{\"UPPER\":': '" + 
stringOutput + "'",
+                    stringOutput.startsWith("{\"UPPER\":"));
+
+            JsonObject obj = Json.createReader(new 
StringReader(stringOutput)).readObject();
+            Assert.assertEquals("application/json", response.getContentType());
+            Assert.assertEquals("UTF-8", response.getCharacterEncoding());
+            Assert.assertEquals("BASETESTVALUE", obj.getString("UPPER"));
+            Assert.assertTrue(obj.containsKey("testBindingsObject"));
+            JsonObject testBindingsObject = 
obj.getJsonObject("testBindingsObject");
+            Assert.assertEquals("value", testBindingsObject.getString("name"));
+            Assert.assertTrue(obj.containsKey("testBindingsObject2"));
+            JsonObject testBindingsObject2 = 
obj.getJsonObject("testBindingsObject2");
+            Assert.assertEquals("value2", 
testBindingsObject2.getString("name2"));
+            Assert.assertEquals(jakartaBaseRequestComponentPath, 
obj.getString("id"));
+
+            response = new JakartaFakeResponse();
+            slingRequestProcessor.processRequest(
+                    new JakartaFakeRequest(jakartaExtendedRequestComponentPath 
+ ".model.json"), response, resolver);
+            obj = Json.createReader(new 
StringReader((response.getStringWriter().toString())))
+                    .readObject();
+            Assert.assertEquals("application/json", response.getContentType());
+            Assert.assertEquals("UTF-8", response.getCharacterEncoding());
+            Assert.assertEquals(jakartaExtendedRequestComponentPath, 
obj.getString("id"));
+            Assert.assertEquals(dateFormat.format(testDate), 
obj.getString("date"));
+
+            response = new JakartaFakeResponse();
+            slingRequestProcessor.processRequest(
+                    new 
JakartaFakeRequest(jakartaInterfaceRequestComponentPath + ".model.json"), 
response, resolver);
+            obj = Json.createReader(new 
StringReader((response.getStringWriter().toString())))
+                    .readObject();
+            Assert.assertEquals("application/json", response.getContentType());
+            Assert.assertEquals("UTF-8", response.getCharacterEncoding());
+            Assert.assertEquals(jakartaInterfaceRequestComponentPath, 
obj.getString("id"));
+            Assert.assertEquals("interfaceTESTValue", 
obj.getString("sampleValue"));
+        }
+    }
+
+    @Test
+    public void testDoubledServlets() throws Exception {
+        try (ResourceResolver resolver = 
rrFactory.getServiceResourceResolver(null); ) {
+            FakeResponse response = new FakeResponse();
+            slingRequestProcessor.processRequest(
+                    new FakeRequest(doubledComponentPath + 
".firstmodel.json"), response, resolver);
+
+            JsonObject obj = Json.createReader(
+                            new 
StringReader((response.getStringWriter().toString())))
+                    .readObject();
+            Assert.assertEquals("application/json", response.getContentType());
+            Assert.assertEquals("first", obj.getString("value"));
+
+            response = new FakeResponse();
+            slingRequestProcessor.processRequest(
+                    new FakeRequest(doubledComponentPath + 
".secondmodel.json"), response, resolver);
+            obj = Json.createReader(new 
StringReader((response.getStringWriter().toString())))
+                    .readObject();
+            Assert.assertEquals("application/json", response.getContentType());
+            Assert.assertEquals("second", obj.getString("value"));
+        }
+    }
+
+    @Test
+    public void testFailedExport() throws Exception {
+        boolean thrown = false;
+        try {
+            try (ResourceResolver resolver = 
rrFactory.getServiceResourceResolver(null); ) {
+                final Resource baseComponentResource = 
resolver.getResource(baseComponentPath);
+                Assert.assertNotNull(baseComponentResource);
+                modelFactory.exportModelForResource(
+                        baseComponentResource, "jaxb", String.class, 
Collections.<String, String>emptyMap());
+                Assert.fail("Should have thrown missing serializer error.");
+            }
+        } catch (MissingExporterException e) {
+            thrown = true;
+            Assert.assertEquals("No exporter named jaxb supports 
java.lang.String.", e.getMessage());
+        }
+        Assert.assertTrue(thrown);
+    }
+}

Reply via email to