You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by ss...@apache.org on 2026/01/09 16:38:24 UTC

(sling-org-apache-sling-models-impl) 02/05: add integration tests from https://github.com/apache/sling-org-apache-sling-models-integration-tests

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

sseifert pushed a commit to branch feature/SLING-13050-integration-tests
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-models-impl.git

commit cf02ee6473e14758b4b25cd5cf8c61d9db767dfd
Author: Stefan Seifert <st...@users.noreply.github.com>
AuthorDate: Fri Jan 9 15:37:54 2026 +0100

    add integration tests from https://github.com/apache/sling-org-apache-sling-models-integration-tests
---
 impl/pom.xml                                       |   6 +-
 it/bnd.bnd                                         |   7 +
 it/pom.xml                                         | 244 ++++++++++
 .../it/delegate/request/DelegateBaseModel.java     |  50 +++
 .../it/delegate/request/DelegateExtendedModel.java |  46 ++
 .../it/delegate/request/DelegateInterface.java     |  26 ++
 .../models/it/delegate/request/package-info.java   |  21 +
 .../it/delegate/resource/DelegateBaseModel.java    |  44 ++
 .../delegate/resource/DelegateExtendedModel.java   |  43 ++
 .../it/delegate/resource/DelegateInterface.java    |  26 ++
 .../models/it/delegate/resource/package-info.java  |  21 +
 .../models/it/delegate/viaoriginalresource/A.java  |  21 +
 .../models/it/delegate/viaoriginalresource/A1.java |  21 +
 .../models/it/delegate/viaoriginalresource/B.java  |  21 +
 .../models/it/delegate/viaoriginalresource/B1.java |  21 +
 .../viaoriginalresource/models/A1Impl.java         |  43 ++
 .../delegate/viaoriginalresource/models/AImpl.java |  39 ++
 .../viaoriginalresource/models/B1Impl.java         |  40 ++
 .../delegate/viaoriginalresource/models/BImpl.java |  31 ++
 .../viaoriginalresource/models/package-info.java   |  21 +
 .../delegate/viaoriginalresource/package-info.java |  21 +
 .../sling/models/it/exporter/BaseComponent.java    |  59 +++
 .../models/it/exporter/BaseRequestComponent.java   | 101 +++++
 .../apache/sling/models/it/exporter/Component.java |  26 ++
 .../sling/models/it/exporter/ComponentImpl.java    |  50 +++
 .../models/it/exporter/DoubledFirstComponent.java  |  34 ++
 .../models/it/exporter/DoubledSecondComponent.java |  34 ++
 .../models/it/exporter/ExtendedComponent.java      |  53 +++
 .../it/exporter/ExtendedRequestComponent.java      |  59 +++
 .../models/it/exporter/RequestComponentImpl.java   |  59 +++
 .../sling/models/it/exporter/package-info.java     |  21 +
 .../implpicker/CustomLastImplementationPicker.java |  44 ++
 .../sling/models/it/implpicker/package-info.java   |  21 +
 .../it/models/ConstructorInjectionTestModel.java   |  59 +++
 .../models/it/models/FieldInjectionTestModel.java  |  66 +++
 .../it/models/InterfaceInjectionTestModel.java     |  41 ++
 .../models/it/models/ModelWithOptionalImport.java  |  32 ++
 .../sling/models/it/models/RequestSelfModel.java   |  26 ++
 .../models/it/models/RequestSelfModelImpl.java     |  34 ++
 .../apache/sling/models/it/models/SelfModel.java   |  34 ++
 .../it/models/ServiceInjectionTestModel.java       |  49 ++
 .../models/SlingPropertyAnnotationTestModel.java   |  34 ++
 .../sling/models/it/models/SourceObject.java       |  34 ++
 .../apache/sling/models/it/models/ViaModel.java    |  36 ++
 .../implextend/ExtendsClassPropertyModel.java      |  37 ++
 .../ImplementsInterfacePropertyModel.java          |  53 +++
 .../ImplementsInterfacePropertyModel2.java         |  52 +++
 .../InvalidImplementsInterfacePropertyModel.java   |  52 +++
 .../implextend/InvalidSampleServiceInterface.java  |  30 ++
 .../models/implextend/SampleServiceInterface.java  |  30 ++
 .../it/models/implextend/SimplePropertyModel.java  |  47 ++
 .../models/it/models/implextend/package-info.java  |  21 +
 .../sling/models/it/models/package-info.java       |  21 +
 .../sling/models/it/rtbound/BaseComponent.java     |  51 +++
 .../sling/models/it/rtbound/ExtendedComponent.java |  48 ++
 .../models/it/rtbound/FromRequestComponent.java    |  27 ++
 .../sling/models/it/rtbound/package-info.java      |  21 +
 .../models/it/rtboundpicker/BaseComponent.java     |  31 ++
 .../models/it/rtboundpicker/SubRTComponent.java    |  31 ++
 .../models/it/rtboundpicker/TestComponent.java     |  24 +
 .../models/it/rtboundpicker/package-info.java      |  21 +
 .../AnotherTestBindingsValuesProvider.java         |  36 ++
 .../sling/models/it/services/SimpleService.java    |  23 +
 .../services/SimpleServiceWithCustomRanking.java   |  32 ++
 .../it/services/TestBindingsValuesProvider.java    |  36 ++
 .../models/it/services/TestResourceDecorator.java  |  66 +++
 .../sling/models/it/services/package-info.java     |  21 +
 .../sling/models/it/servlets/PathBoundServlet.java |  46 ++
 .../org/apache/sling/models/it/noclasses/foo.txt   |   1 +
 .../customizers/SM_TeleporterCustomizer.java       |  61 +++
 .../apache/sling/models/testing/DecoratedIT.java   |  96 ++++
 .../sling/models/testing/ImplementsExtendsIT.java  | 150 +++++++
 .../testing/InjectorSpecificAnnotationIT.java      |  72 +++
 .../sling/models/testing/ModelFactorySimpleIT.java | 130 ++++++
 .../sling/models/testing/PathBoundServletIT.java   |  56 +++
 .../ServiceInjectionWithDifferentRankingIT.java    | 147 ++++++
 .../org/apache/sling/models/testing/SimpleIT.java  | 111 +++++
 .../org/apache/sling/models/testing/ViaIT.java     |  77 ++++
 .../models/testing/delegate/DelegateRequestIT.java | 114 +++++
 .../testing/delegate/DelegateResourceIT.java       | 105 +++++
 .../ViaOriginalResourceDelegationIT.java           | 139 ++++++
 .../sling/models/testing/exporter/ExporterIT.java  | 344 ++++++++++++++
 .../sling/models/testing/helper/FakeRequest.java   | 400 +++++++++++++++++
 .../sling/models/testing/helper/FakeResponse.java  | 191 ++++++++
 .../sling/models/testing/rtbound/FakeRequest.java  | 498 +++++++++++++++++++++
 .../testing/rtbound/ResourceTypeBindingIT.java     | 146 ++++++
 .../rtboundpicker/ResourceTypePickerIT.java        |  91 ++++
 .../provisioning/sling-models-jacksonexporter.txt  |  24 +
 it/src/test/provisioning/sling.txt                 |  50 +++
 pom.xml                                            |   1 +
 90 files changed, 5677 insertions(+), 3 deletions(-)

diff --git a/impl/pom.xml b/impl/pom.xml
index 951d7d3..a5b3f73 100644
--- a/impl/pom.xml
+++ b/impl/pom.xml
@@ -22,9 +22,9 @@
 
     <parent>
         <groupId>org.apache.sling</groupId>
-        <artifactId>sling-bundle-parent</artifactId>
-        <version>62</version>
-        <relativePath />
+        <artifactId>org.apache.sling.models.impl.parent</artifactId>
+        <version>2.0.1-SNAPSHOT</version>
+        <relativePath>../parent/pom.xml</relativePath>
     </parent>
 
     <artifactId>org.apache.sling.models.impl</artifactId>
diff --git a/it/bnd.bnd b/it/bnd.bnd
new file mode 100644
index 0000000..1aef1d3
--- /dev/null
+++ b/it/bnd.bnd
@@ -0,0 +1,7 @@
+Sling-Test-Regexp: .*Test
+
+Import-Package:\
+  org.apache.commons.beanutils;resolution:=optional,\
+  *
+
+-plugin: org.apache.sling.bnd.models.ModelsScannerPlugin
diff --git a/it/pom.xml b/it/pom.xml
new file mode 100644
index 0000000..7e209ec
--- /dev/null
+++ b/it/pom.xml
@@ -0,0 +1,244 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+    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.models.impl.parent</artifactId>
+        <version>2.0.1-SNAPSHOT</version>
+        <relativePath>../parent/pom.xml</relativePath>
+    </parent>
+
+    <artifactId>org.apache.sling.models.impl.it</artifactId>
+
+    <name>Apache Sling Models Implementation - Integration Tests</name>
+    <description>Apache Sling Models Integration Tests - builds a bundle
+        with Sling server-side tests, and executes them via a
+        remote test proxy that runs in the integration-tests phase.</description>
+
+    <properties>
+        <sling.java.version>8</sling.java.version>
+        <!-- start with -DkeepITServerRunning=true to allow to rerun ITs or inspect the server after the ITs have been executed there -->
+        <keepITServerRunning>false</keepITServerRunning>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.osgi</groupId>
+            <artifactId>org.osgi.framework</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.osgi</groupId>
+            <artifactId>org.osgi.service.component</artifactId>
+            <scope>provided</scope>
+        </dependency>
+
+        <!-- OSGi annotations -->
+        <dependency>
+            <groupId>org.osgi</groupId>
+            <artifactId>org.osgi.annotation.versioning</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.osgi</groupId>
+            <artifactId>org.osgi.service.component.annotations</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.osgi</groupId>
+            <artifactId>org.osgi.service.metatype.annotations</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.sling</groupId>
+            <artifactId>org.apache.sling.servlets.annotations</artifactId>
+            <scope>provided</scope>
+        </dependency>
+
+        <!-- Additional bundles needed by the Sling instance under test -->
+        <dependency>
+            <groupId>org.apache.sling</groupId>
+            <artifactId>org.apache.sling.junit.core</artifactId>
+            <version>1.0.28</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.sling</groupId>
+            <artifactId>org.apache.sling.testing.rules</artifactId>
+            <version>1.0.8</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.sling</groupId>
+            <artifactId>org.apache.sling.testing.clients</artifactId>
+            <version>2.0.12</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.0.20</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.sling</groupId>
+            <artifactId>org.apache.sling.engine</artifactId>
+            <version>2.6.14</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.sling</groupId>
+            <artifactId>org.apache.sling.models.api</artifactId>
+            <version>1.5.5-SNAPSHOT</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.sling</groupId>
+            <artifactId>org.apache.sling.models.impl</artifactId>
+            <version>1.7.3-SNAPSHOT</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.sling</groupId>
+            <artifactId>org.apache.sling.models.jacksonexporter</artifactId>
+            <version>1.1.5-SNAPSHOT</version>
+            <scope>provided</scope>
+        </dependency>
+
+        <!-- actual dependencies -->
+        <dependency>
+            <groupId>javax.servlet</groupId>
+            <artifactId>javax.servlet-api</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>javax.jcr</groupId>
+            <artifactId>jcr</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.sling</groupId>
+            <artifactId>org.apache.sling.api</artifactId>
+            <version>2.18.4</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-lang3</artifactId>
+            <version>3.8.1</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>com.fasterxml.jackson.core</groupId>
+            <artifactId>jackson-annotations</artifactId>
+            <version>2.9.7</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.geronimo.specs</groupId>
+            <artifactId>geronimo-atinject_1.0_spec</artifactId>
+            <version>1.0</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-api</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.jetbrains</groupId>
+            <artifactId>annotations</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-simple</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <!-- This dependency is not actually used within Sling. It's used for ModelWithOptionalImport test case to test a model with a class that is not resolved. -->
+        <dependency>
+            <groupId>commons-beanutils</groupId>
+            <artifactId>commons-beanutils</artifactId>
+            <version>1.9.4</version>
+            <scope>provided</scope>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>biz.aQute.bnd</groupId>
+                <artifactId>bnd-maven-plugin</artifactId>
+                <dependencies>
+                    <dependency>
+                        <groupId>org.apache.sling</groupId>
+                        <artifactId>org.apache.sling.bnd.models</artifactId>
+                        <version>1.0.0</version>
+                    </dependency>
+                </dependencies>
+            </plugin>
+            <plugin>
+                <groupId>biz.aQute.bnd</groupId>
+                <artifactId>bnd-baseline-maven-plugin</artifactId>
+                <configuration>
+                    <skip>true</skip>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.rat</groupId>
+                <artifactId>apache-rat-plugin</artifactId>
+                <configuration>
+                    <excludes>
+                        <exclude>src/main/resources/org/apache/sling/models/it/noclasses/foo.txt</exclude>
+                    </excludes>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+    <profiles>
+        <profile>
+            <id>debug-remote-process</id>
+            <properties>
+                <sling.vm.options>-Xmx512m -Xdebug -Xrunjdwp:server=y,transport=dt_socket,address=38080,suspend=n</sling.vm.options>
+            </properties>
+        </profile>
+        <profile>
+            <id>debug-remote-process-suspend</id>
+            <properties>
+                <sling.vm.options>-Xmx512m -Xdebug -Xrunjdwp:server=y,transport=dt_socket,address=38080,suspend=y</sling.vm.options>
+            </properties>
+        </profile>
+    </profiles>
+
+</project>
diff --git a/it/src/main/java/org/apache/sling/models/it/delegate/request/DelegateBaseModel.java b/it/src/main/java/org/apache/sling/models/it/delegate/request/DelegateBaseModel.java
new file mode 100644
index 0000000..1e4369e
--- /dev/null
+++ b/it/src/main/java/org/apache/sling/models/it/delegate/request/DelegateBaseModel.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.it.delegate.request;
+
+import javax.inject.Inject;
+
+import org.apache.sling.api.SlingHttpServletRequest;
+import org.apache.sling.models.annotations.Model;
+import org.apache.sling.models.annotations.Via;
+
+@Model(
+        adaptables = SlingHttpServletRequest.class,
+        adapters = DelegateInterface.class,
+        resourceType = "sling/delegate/base")
+public class DelegateBaseModel implements DelegateInterface {
+
+    @Inject
+    @Via("resource")
+    private String text;
+
+    @Inject
+    @Via("resource")
+    private String other;
+
+    @Override
+    public String getText() {
+        return text;
+    }
+
+    @Override
+    public String getOther() {
+        return other;
+    }
+}
diff --git a/it/src/main/java/org/apache/sling/models/it/delegate/request/DelegateExtendedModel.java b/it/src/main/java/org/apache/sling/models/it/delegate/request/DelegateExtendedModel.java
new file mode 100644
index 0000000..c2a01a7
--- /dev/null
+++ b/it/src/main/java/org/apache/sling/models/it/delegate/request/DelegateExtendedModel.java
@@ -0,0 +1,46 @@
+/*
+ * 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.it.delegate.request;
+
+import org.apache.sling.api.SlingHttpServletRequest;
+import org.apache.sling.models.annotations.Model;
+import org.apache.sling.models.annotations.Via;
+import org.apache.sling.models.annotations.injectorspecific.Self;
+import org.apache.sling.models.annotations.via.ResourceSuperType;
+
+@Model(
+        adaptables = SlingHttpServletRequest.class,
+        adapters = DelegateInterface.class,
+        resourceType = "sling/delegate/extended")
+public class DelegateExtendedModel implements DelegateInterface {
+
+    @Self
+    @Via(type = ResourceSuperType.class)
+    private DelegateInterface delegate;
+
+    @Override
+    public String getOther() {
+        return delegate.getOther();
+    }
+
+    @Override
+    public String getText() {
+        return delegate.getText().toUpperCase();
+    }
+}
diff --git a/it/src/main/java/org/apache/sling/models/it/delegate/request/DelegateInterface.java b/it/src/main/java/org/apache/sling/models/it/delegate/request/DelegateInterface.java
new file mode 100644
index 0000000..9826052
--- /dev/null
+++ b/it/src/main/java/org/apache/sling/models/it/delegate/request/DelegateInterface.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.it.delegate.request;
+
+public interface DelegateInterface {
+
+    String getText();
+
+    String getOther();
+}
diff --git a/it/src/main/java/org/apache/sling/models/it/delegate/request/package-info.java b/it/src/main/java/org/apache/sling/models/it/delegate/request/package-info.java
new file mode 100644
index 0000000..3e7e701
--- /dev/null
+++ b/it/src/main/java/org/apache/sling/models/it/delegate/request/package-info.java
@@ -0,0 +1,21 @@
+/*
+ * 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.
+ */
+
+@Version("1.0")
+package org.apache.sling.models.it.delegate.request;
+
+import org.osgi.annotation.versioning.Version;
diff --git a/it/src/main/java/org/apache/sling/models/it/delegate/resource/DelegateBaseModel.java b/it/src/main/java/org/apache/sling/models/it/delegate/resource/DelegateBaseModel.java
new file mode 100644
index 0000000..0b2031b
--- /dev/null
+++ b/it/src/main/java/org/apache/sling/models/it/delegate/resource/DelegateBaseModel.java
@@ -0,0 +1,44 @@
+/*
+ * 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.it.delegate.resource;
+
+import javax.inject.Inject;
+
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.models.annotations.Model;
+
+@Model(adaptables = Resource.class, adapters = DelegateInterface.class, resourceType = "sling/delegate/base")
+public class DelegateBaseModel implements DelegateInterface {
+
+    @Inject
+    private String text;
+
+    @Inject
+    private String other;
+
+    @Override
+    public String getText() {
+        return text;
+    }
+
+    @Override
+    public String getOther() {
+        return other;
+    }
+}
diff --git a/it/src/main/java/org/apache/sling/models/it/delegate/resource/DelegateExtendedModel.java b/it/src/main/java/org/apache/sling/models/it/delegate/resource/DelegateExtendedModel.java
new file mode 100644
index 0000000..df901f5
--- /dev/null
+++ b/it/src/main/java/org/apache/sling/models/it/delegate/resource/DelegateExtendedModel.java
@@ -0,0 +1,43 @@
+/*
+ * 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.it.delegate.resource;
+
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.models.annotations.Model;
+import org.apache.sling.models.annotations.Via;
+import org.apache.sling.models.annotations.injectorspecific.Self;
+import org.apache.sling.models.annotations.via.ResourceSuperType;
+
+@Model(adaptables = Resource.class, adapters = DelegateInterface.class, resourceType = "sling/delegate/extended")
+public class DelegateExtendedModel implements DelegateInterface {
+
+    @Self
+    @Via(type = ResourceSuperType.class)
+    private DelegateInterface delegate;
+
+    @Override
+    public String getOther() {
+        return delegate.getOther();
+    }
+
+    @Override
+    public String getText() {
+        return delegate.getText().toUpperCase();
+    }
+}
diff --git a/it/src/main/java/org/apache/sling/models/it/delegate/resource/DelegateInterface.java b/it/src/main/java/org/apache/sling/models/it/delegate/resource/DelegateInterface.java
new file mode 100644
index 0000000..2b208e2
--- /dev/null
+++ b/it/src/main/java/org/apache/sling/models/it/delegate/resource/DelegateInterface.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.it.delegate.resource;
+
+public interface DelegateInterface {
+
+    String getText();
+
+    String getOther();
+}
diff --git a/it/src/main/java/org/apache/sling/models/it/delegate/resource/package-info.java b/it/src/main/java/org/apache/sling/models/it/delegate/resource/package-info.java
new file mode 100644
index 0000000..a0f5c5b
--- /dev/null
+++ b/it/src/main/java/org/apache/sling/models/it/delegate/resource/package-info.java
@@ -0,0 +1,21 @@
+/*
+ * 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.
+ */
+
+@Version("1.0")
+package org.apache.sling.models.it.delegate.resource;
+
+import org.osgi.annotation.versioning.Version;
diff --git a/it/src/main/java/org/apache/sling/models/it/delegate/viaoriginalresource/A.java b/it/src/main/java/org/apache/sling/models/it/delegate/viaoriginalresource/A.java
new file mode 100644
index 0000000..7581fea
--- /dev/null
+++ b/it/src/main/java/org/apache/sling/models/it/delegate/viaoriginalresource/A.java
@@ -0,0 +1,21 @@
+/*
+ * 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.it.delegate.viaoriginalresource;
+
+public interface A {}
diff --git a/it/src/main/java/org/apache/sling/models/it/delegate/viaoriginalresource/A1.java b/it/src/main/java/org/apache/sling/models/it/delegate/viaoriginalresource/A1.java
new file mode 100644
index 0000000..6d3048b
--- /dev/null
+++ b/it/src/main/java/org/apache/sling/models/it/delegate/viaoriginalresource/A1.java
@@ -0,0 +1,21 @@
+/*
+ * 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.it.delegate.viaoriginalresource;
+
+public interface A1 extends A {}
diff --git a/it/src/main/java/org/apache/sling/models/it/delegate/viaoriginalresource/B.java b/it/src/main/java/org/apache/sling/models/it/delegate/viaoriginalresource/B.java
new file mode 100644
index 0000000..8fbbdab
--- /dev/null
+++ b/it/src/main/java/org/apache/sling/models/it/delegate/viaoriginalresource/B.java
@@ -0,0 +1,21 @@
+/*
+ * 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.it.delegate.viaoriginalresource;
+
+public interface B {}
diff --git a/it/src/main/java/org/apache/sling/models/it/delegate/viaoriginalresource/B1.java b/it/src/main/java/org/apache/sling/models/it/delegate/viaoriginalresource/B1.java
new file mode 100644
index 0000000..50fb27c
--- /dev/null
+++ b/it/src/main/java/org/apache/sling/models/it/delegate/viaoriginalresource/B1.java
@@ -0,0 +1,21 @@
+/*
+ * 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.it.delegate.viaoriginalresource;
+
+public interface B1 extends B {}
diff --git a/it/src/main/java/org/apache/sling/models/it/delegate/viaoriginalresource/models/A1Impl.java b/it/src/main/java/org/apache/sling/models/it/delegate/viaoriginalresource/models/A1Impl.java
new file mode 100644
index 0000000..62e4b63
--- /dev/null
+++ b/it/src/main/java/org/apache/sling/models/it/delegate/viaoriginalresource/models/A1Impl.java
@@ -0,0 +1,43 @@
+/*
+ * 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.it.delegate.viaoriginalresource.models;
+
+import org.apache.sling.api.SlingHttpServletRequest;
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.models.annotations.Model;
+import org.apache.sling.models.annotations.Via;
+import org.apache.sling.models.annotations.injectorspecific.Self;
+import org.apache.sling.models.annotations.via.ResourceSuperType;
+import org.apache.sling.models.it.delegate.viaoriginalresource.A;
+import org.apache.sling.models.it.delegate.viaoriginalresource.A1;
+import org.apache.sling.models.it.delegate.viaoriginalresource.B1;
+
+@Model(
+        adaptables = {SlingHttpServletRequest.class, Resource.class},
+        adapters = {A1.class, A.class},
+        resourceType = "delegate/nestedrtbound/specific")
+public class A1Impl implements A1 {
+
+    @Self
+    @Via(type = ResourceSuperType.class)
+    public A delegate;
+
+    @Self
+    public B1 other;
+}
diff --git a/it/src/main/java/org/apache/sling/models/it/delegate/viaoriginalresource/models/AImpl.java b/it/src/main/java/org/apache/sling/models/it/delegate/viaoriginalresource/models/AImpl.java
new file mode 100644
index 0000000..9622bdb
--- /dev/null
+++ b/it/src/main/java/org/apache/sling/models/it/delegate/viaoriginalresource/models/AImpl.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.models.it.delegate.viaoriginalresource.models;
+
+import org.apache.sling.api.SlingHttpServletRequest;
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.models.annotations.Model;
+import org.apache.sling.models.annotations.Via;
+import org.apache.sling.models.annotations.injectorspecific.Self;
+import org.apache.sling.models.annotations.via.OriginalResourceType;
+import org.apache.sling.models.it.delegate.viaoriginalresource.A;
+import org.apache.sling.models.it.delegate.viaoriginalresource.B;
+
+@Model(
+        adaptables = {SlingHttpServletRequest.class, Resource.class},
+        adapters = {A.class},
+        resourceType = "delegate/nestedrtbound/generic")
+public class AImpl implements A {
+
+    @Self
+    @Via(type = OriginalResourceType.class)
+    public B other;
+}
diff --git a/it/src/main/java/org/apache/sling/models/it/delegate/viaoriginalresource/models/B1Impl.java b/it/src/main/java/org/apache/sling/models/it/delegate/viaoriginalresource/models/B1Impl.java
new file mode 100644
index 0000000..85e744f
--- /dev/null
+++ b/it/src/main/java/org/apache/sling/models/it/delegate/viaoriginalresource/models/B1Impl.java
@@ -0,0 +1,40 @@
+/*
+ * 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.it.delegate.viaoriginalresource.models;
+
+import org.apache.sling.api.SlingHttpServletRequest;
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.models.annotations.Model;
+import org.apache.sling.models.annotations.Via;
+import org.apache.sling.models.annotations.injectorspecific.Self;
+import org.apache.sling.models.annotations.via.ResourceSuperType;
+import org.apache.sling.models.it.delegate.viaoriginalresource.B;
+import org.apache.sling.models.it.delegate.viaoriginalresource.B1;
+
+@Model(
+        adaptables = {SlingHttpServletRequest.class, Resource.class},
+        adapters = {B1.class, B.class},
+        resourceType = "delegate/nestedrtbound/specific",
+        cache = true)
+public class B1Impl implements B1 {
+
+    @Self
+    @Via(type = ResourceSuperType.class)
+    public B delegate;
+}
diff --git a/it/src/main/java/org/apache/sling/models/it/delegate/viaoriginalresource/models/BImpl.java b/it/src/main/java/org/apache/sling/models/it/delegate/viaoriginalresource/models/BImpl.java
new file mode 100644
index 0000000..e3b8569
--- /dev/null
+++ b/it/src/main/java/org/apache/sling/models/it/delegate/viaoriginalresource/models/BImpl.java
@@ -0,0 +1,31 @@
+/*
+ * 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.it.delegate.viaoriginalresource.models;
+
+import org.apache.sling.api.SlingHttpServletRequest;
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.models.annotations.Model;
+import org.apache.sling.models.it.delegate.viaoriginalresource.B;
+
+@Model(
+        adaptables = {SlingHttpServletRequest.class, Resource.class},
+        adapters = {B.class},
+        resourceType = "delegate/nestedrtbound/generic",
+        cache = true)
+public class BImpl implements B {}
diff --git a/it/src/main/java/org/apache/sling/models/it/delegate/viaoriginalresource/models/package-info.java b/it/src/main/java/org/apache/sling/models/it/delegate/viaoriginalresource/models/package-info.java
new file mode 100644
index 0000000..88f82b0
--- /dev/null
+++ b/it/src/main/java/org/apache/sling/models/it/delegate/viaoriginalresource/models/package-info.java
@@ -0,0 +1,21 @@
+/*
+ * 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.
+ */
+
+@Version("1.0")
+package org.apache.sling.models.it.delegate.viaoriginalresource.models;
+
+import org.osgi.annotation.versioning.Version;
diff --git a/it/src/main/java/org/apache/sling/models/it/delegate/viaoriginalresource/package-info.java b/it/src/main/java/org/apache/sling/models/it/delegate/viaoriginalresource/package-info.java
new file mode 100644
index 0000000..fa049a5
--- /dev/null
+++ b/it/src/main/java/org/apache/sling/models/it/delegate/viaoriginalresource/package-info.java
@@ -0,0 +1,21 @@
+/*
+ * 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.
+ */
+
+@Version("1.0")
+package org.apache.sling.models.it.delegate.viaoriginalresource;
+
+import org.osgi.annotation.versioning.Version;
diff --git a/it/src/main/java/org/apache/sling/models/it/exporter/BaseComponent.java b/it/src/main/java/org/apache/sling/models/it/exporter/BaseComponent.java
new file mode 100644
index 0000000..c772d96
--- /dev/null
+++ b/it/src/main/java/org/apache/sling/models/it/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.it.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/it/src/main/java/org/apache/sling/models/it/exporter/BaseRequestComponent.java b/it/src/main/java/org/apache/sling/models/it/exporter/BaseRequestComponent.java
new file mode 100644
index 0000000..6aa5405
--- /dev/null
+++ b/it/src/main/java/org/apache/sling/models/it/exporter/BaseRequestComponent.java
@@ -0,0 +1,101 @@
+/*
+ * 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.it.exporter;
+
+import javax.inject.Inject;
+import javax.servlet.ServletRequest;
+import javax.servlet.http.HttpServletRequest;
+
+import java.util.Map;
+
+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;
+    }
+
+    public SlingHttpServletRequest getSlingHttpServletRequest() {
+        return request;
+    }
+
+    public HttpServletRequest getHttpServletRequest() {
+        return request;
+    }
+
+    public ServletRequest getServletRequest() {
+        return request;
+    }
+}
diff --git a/it/src/main/java/org/apache/sling/models/it/exporter/Component.java b/it/src/main/java/org/apache/sling/models/it/exporter/Component.java
new file mode 100644
index 0000000..d90f5a2
--- /dev/null
+++ b/it/src/main/java/org/apache/sling/models/it/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.it.exporter;
+
+public interface Component {
+
+    String getId();
+
+    String getSampleValue();
+}
diff --git a/it/src/main/java/org/apache/sling/models/it/exporter/ComponentImpl.java b/it/src/main/java/org/apache/sling/models/it/exporter/ComponentImpl.java
new file mode 100644
index 0000000..4d0deb9
--- /dev/null
+++ b/it/src/main/java/org/apache/sling/models/it/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.it.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/it/src/main/java/org/apache/sling/models/it/exporter/DoubledFirstComponent.java b/it/src/main/java/org/apache/sling/models/it/exporter/DoubledFirstComponent.java
new file mode 100644
index 0000000..84b0289
--- /dev/null
+++ b/it/src/main/java/org/apache/sling/models/it/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.it.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/it/src/main/java/org/apache/sling/models/it/exporter/DoubledSecondComponent.java b/it/src/main/java/org/apache/sling/models/it/exporter/DoubledSecondComponent.java
new file mode 100644
index 0000000..bbc118c
--- /dev/null
+++ b/it/src/main/java/org/apache/sling/models/it/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.it.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/it/src/main/java/org/apache/sling/models/it/exporter/ExtendedComponent.java b/it/src/main/java/org/apache/sling/models/it/exporter/ExtendedComponent.java
new file mode 100644
index 0000000..ff0bd7f
--- /dev/null
+++ b/it/src/main/java/org/apache/sling/models/it/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.it.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/it/src/main/java/org/apache/sling/models/it/exporter/ExtendedRequestComponent.java b/it/src/main/java/org/apache/sling/models/it/exporter/ExtendedRequestComponent.java
new file mode 100644
index 0000000..492486d
--- /dev/null
+++ b/it/src/main/java/org/apache/sling/models/it/exporter/ExtendedRequestComponent.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.it.exporter;
+
+import javax.inject.Inject;
+
+import java.util.Calendar;
+import java.util.Date;
+import java.util.GregorianCalendar;
+
+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);
+    }
+
+    public Calendar getDateByCalendar() {
+        Calendar cal = new GregorianCalendar();
+        cal.setTime(date);
+        return cal;
+    }
+
+    public Date getDate() {
+        return date;
+    }
+}
diff --git a/it/src/main/java/org/apache/sling/models/it/exporter/RequestComponentImpl.java b/it/src/main/java/org/apache/sling/models/it/exporter/RequestComponentImpl.java
new file mode 100644
index 0000000..2ffe7e6
--- /dev/null
+++ b/it/src/main/java/org/apache/sling/models/it/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.it.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/it/src/main/java/org/apache/sling/models/it/exporter/package-info.java b/it/src/main/java/org/apache/sling/models/it/exporter/package-info.java
new file mode 100644
index 0000000..d6273ab
--- /dev/null
+++ b/it/src/main/java/org/apache/sling/models/it/exporter/package-info.java
@@ -0,0 +1,21 @@
+/*
+ * 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.
+ */
+
+@Version("1.0")
+package org.apache.sling.models.it.exporter;
+
+import org.osgi.annotation.versioning.Version;
diff --git a/it/src/main/java/org/apache/sling/models/it/implpicker/CustomLastImplementationPicker.java b/it/src/main/java/org/apache/sling/models/it/implpicker/CustomLastImplementationPicker.java
new file mode 100644
index 0000000..5979847
--- /dev/null
+++ b/it/src/main/java/org/apache/sling/models/it/implpicker/CustomLastImplementationPicker.java
@@ -0,0 +1,44 @@
+/*
+ * 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.it.implpicker;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.models.spi.ImplementationPicker;
+import org.jetbrains.annotations.NotNull;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.propertytypes.ServiceRanking;
+
+/**
+ * This is a curious {@link ImplementationPicker} implementation for integration test
+ * that picks the last implementation if the resource has the name "custom";
+ */
+@Component(service = ImplementationPicker.class)
+@ServiceRanking(100)
+public class CustomLastImplementationPicker implements ImplementationPicker {
+
+    public static final String CUSTOM_NAME = "custom";
+
+    public Class<?> pick(@NotNull Class<?> adapterType, Class<?>[] implementationsTypes, @NotNull Object adaptable) {
+        if (adaptable instanceof Resource && StringUtils.equals(((Resource) adaptable).getName(), CUSTOM_NAME)) {
+            return implementationsTypes[implementationsTypes.length - 1];
+        }
+        return null;
+    }
+}
diff --git a/it/src/main/java/org/apache/sling/models/it/implpicker/package-info.java b/it/src/main/java/org/apache/sling/models/it/implpicker/package-info.java
new file mode 100644
index 0000000..c8a5b3e
--- /dev/null
+++ b/it/src/main/java/org/apache/sling/models/it/implpicker/package-info.java
@@ -0,0 +1,21 @@
+/*
+ * 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.
+ */
+
+@Version("1.0")
+package org.apache.sling.models.it.implpicker;
+
+import org.osgi.annotation.versioning.Version;
diff --git a/it/src/main/java/org/apache/sling/models/it/models/ConstructorInjectionTestModel.java b/it/src/main/java/org/apache/sling/models/it/models/ConstructorInjectionTestModel.java
new file mode 100644
index 0000000..c80b1c5
--- /dev/null
+++ b/it/src/main/java/org/apache/sling/models/it/models/ConstructorInjectionTestModel.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.it.models;
+
+import javax.inject.Inject;
+import javax.inject.Named;
+import javax.servlet.Filter;
+
+import java.util.List;
+
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.models.annotations.Model;
+import org.apache.sling.models.annotations.injectorspecific.Self;
+
+@Model(adaptables = Resource.class)
+public class ConstructorInjectionTestModel {
+
+    private final String testProperty;
+    private final List<Filter> filters;
+    private final Resource resource;
+
+    @Inject
+    public ConstructorInjectionTestModel(
+            @Named("testProperty") String testProperty,
+            @Named("filters") List<Filter> filters,
+            @Self Resource resource) {
+        this.testProperty = testProperty;
+        this.filters = filters;
+        this.resource = resource;
+    }
+
+    public String getTestProperty() {
+        return testProperty;
+    }
+
+    public List<Filter> getFilters() {
+        return filters;
+    }
+
+    public Resource getResource() {
+        return resource;
+    }
+}
diff --git a/it/src/main/java/org/apache/sling/models/it/models/FieldInjectionTestModel.java b/it/src/main/java/org/apache/sling/models/it/models/FieldInjectionTestModel.java
new file mode 100644
index 0000000..f8ed3a8
--- /dev/null
+++ b/it/src/main/java/org/apache/sling/models/it/models/FieldInjectionTestModel.java
@@ -0,0 +1,66 @@
+/*
+ * 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.it.models;
+
+import javax.inject.Inject;
+import javax.inject.Named;
+import javax.servlet.Filter;
+
+import java.util.List;
+
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.models.annotations.Model;
+import org.apache.sling.models.annotations.Optional;
+
+@Model(adaptables = Resource.class)
+public class FieldInjectionTestModel {
+
+    @Inject
+    private String testProperty;
+
+    @Inject
+    @Optional
+    @Named("child/childProperty")
+    private String childProperty;
+
+    @Inject
+    private List<Filter> filters;
+
+    private final Resource resource;
+
+    public FieldInjectionTestModel(Resource pResource) {
+        this.resource = pResource;
+    }
+
+    public String getTestProperty() {
+        return testProperty;
+    }
+
+    public String getChildProperty() {
+        return childProperty;
+    }
+
+    public List<Filter> getFilters() {
+        return filters;
+    }
+
+    public Resource getResource() {
+        return resource;
+    }
+}
diff --git a/it/src/main/java/org/apache/sling/models/it/models/InterfaceInjectionTestModel.java b/it/src/main/java/org/apache/sling/models/it/models/InterfaceInjectionTestModel.java
new file mode 100644
index 0000000..52e2e40
--- /dev/null
+++ b/it/src/main/java/org/apache/sling/models/it/models/InterfaceInjectionTestModel.java
@@ -0,0 +1,41 @@
+/*
+ * 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.it.models;
+
+import javax.inject.Inject;
+import javax.servlet.Filter;
+
+import java.util.List;
+
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.models.annotations.Model;
+import org.apache.sling.models.annotations.injectorspecific.Self;
+
+@Model(adaptables = Resource.class)
+public interface InterfaceInjectionTestModel {
+
+    @Inject
+    String getTestProperty();
+
+    @Inject
+    List<Filter> getFilters();
+
+    @Self
+    Resource getResource();
+}
diff --git a/it/src/main/java/org/apache/sling/models/it/models/ModelWithOptionalImport.java b/it/src/main/java/org/apache/sling/models/it/models/ModelWithOptionalImport.java
new file mode 100644
index 0000000..d33b05b
--- /dev/null
+++ b/it/src/main/java/org/apache/sling/models/it/models/ModelWithOptionalImport.java
@@ -0,0 +1,32 @@
+/*
+ * 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.it.models;
+
+import org.apache.commons.beanutils.BeanUtils;
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.models.annotations.Model;
+
+@Model(adaptables = Resource.class)
+public class ModelWithOptionalImport {
+
+    // this class is not available at runtime. The containing package has an optional import so the bundle
+    // still resolves
+    @SuppressWarnings("unused")
+    private BeanUtils beanUtils = new BeanUtils();
+}
diff --git a/it/src/main/java/org/apache/sling/models/it/models/RequestSelfModel.java b/it/src/main/java/org/apache/sling/models/it/models/RequestSelfModel.java
new file mode 100644
index 0000000..b711431
--- /dev/null
+++ b/it/src/main/java/org/apache/sling/models/it/models/RequestSelfModel.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.it.models;
+
+import org.apache.sling.api.SlingHttpServletRequest;
+
+public interface RequestSelfModel {
+
+    SlingHttpServletRequest getRequest();
+}
diff --git a/it/src/main/java/org/apache/sling/models/it/models/RequestSelfModelImpl.java b/it/src/main/java/org/apache/sling/models/it/models/RequestSelfModelImpl.java
new file mode 100644
index 0000000..de9e83f
--- /dev/null
+++ b/it/src/main/java/org/apache/sling/models/it/models/RequestSelfModelImpl.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.it.models;
+
+import org.apache.sling.api.SlingHttpServletRequest;
+import org.apache.sling.models.annotations.Model;
+import org.apache.sling.models.annotations.injectorspecific.Self;
+
+@Model(adaptables = SlingHttpServletRequest.class, adapters = RequestSelfModel.class)
+public class RequestSelfModelImpl implements RequestSelfModel {
+
+    @Self
+    private SlingHttpServletRequest request;
+
+    public SlingHttpServletRequest getRequest() {
+        return request;
+    }
+}
diff --git a/it/src/main/java/org/apache/sling/models/it/models/SelfModel.java b/it/src/main/java/org/apache/sling/models/it/models/SelfModel.java
new file mode 100644
index 0000000..c635c4e
--- /dev/null
+++ b/it/src/main/java/org/apache/sling/models/it/models/SelfModel.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.it.models;
+
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.models.annotations.Model;
+import org.apache.sling.models.annotations.injectorspecific.Self;
+
+@Model(adaptables = Resource.class)
+public class SelfModel {
+
+    @Self
+    private Resource resource;
+
+    public Resource getResource() {
+        return resource;
+    }
+}
diff --git a/it/src/main/java/org/apache/sling/models/it/models/ServiceInjectionTestModel.java b/it/src/main/java/org/apache/sling/models/it/models/ServiceInjectionTestModel.java
new file mode 100644
index 0000000..c9f2cf3
--- /dev/null
+++ b/it/src/main/java/org/apache/sling/models/it/models/ServiceInjectionTestModel.java
@@ -0,0 +1,49 @@
+/*
+ * 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.it.models;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.models.annotations.Model;
+import org.apache.sling.models.annotations.injectorspecific.OSGiService;
+import org.apache.sling.models.it.services.SimpleService;
+
+@Model(adaptables = Resource.class)
+public class ServiceInjectionTestModel {
+
+    @OSGiService
+    private SimpleService simpleService; // must return the service impl with the highest ranking
+
+    @OSGiService
+    private List<SimpleService> simpleServices;
+
+    public SimpleService getSimpleService() {
+        return simpleService;
+    }
+
+    public Integer[] getSimpleServicesRankings() {
+        List<Integer> serviceRankings = new ArrayList<Integer>();
+        for (SimpleService service : simpleServices) {
+            serviceRankings.add(service.getRanking());
+        }
+        return serviceRankings.toArray(new Integer[serviceRankings.size()]);
+    }
+}
diff --git a/it/src/main/java/org/apache/sling/models/it/models/SlingPropertyAnnotationTestModel.java b/it/src/main/java/org/apache/sling/models/it/models/SlingPropertyAnnotationTestModel.java
new file mode 100644
index 0000000..abda77a
--- /dev/null
+++ b/it/src/main/java/org/apache/sling/models/it/models/SlingPropertyAnnotationTestModel.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.it.models;
+
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.models.annotations.Model;
+import org.apache.sling.models.annotations.injectorspecific.ValueMapValue;
+
+@Model(adaptables = Resource.class)
+public class SlingPropertyAnnotationTestModel {
+
+    @ValueMapValue
+    private String testProperty;
+
+    public String getTestProperty() {
+        return testProperty;
+    }
+}
diff --git a/it/src/main/java/org/apache/sling/models/it/models/SourceObject.java b/it/src/main/java/org/apache/sling/models/it/models/SourceObject.java
new file mode 100644
index 0000000..d31d57f
--- /dev/null
+++ b/it/src/main/java/org/apache/sling/models/it/models/SourceObject.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.it.models;
+
+import org.apache.sling.api.resource.Resource;
+
+public class SourceObject {
+
+    public SourceObject(Resource resource) {
+        this.resource = resource;
+    }
+
+    private Resource resource;
+
+    public Resource getResource() {
+        return resource;
+    }
+}
diff --git a/it/src/main/java/org/apache/sling/models/it/models/ViaModel.java b/it/src/main/java/org/apache/sling/models/it/models/ViaModel.java
new file mode 100644
index 0000000..a33c24e
--- /dev/null
+++ b/it/src/main/java/org/apache/sling/models/it/models/ViaModel.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.it.models;
+
+import javax.inject.Inject;
+
+import org.apache.sling.models.annotations.Model;
+import org.apache.sling.models.annotations.Via;
+
+@Model(adaptables = SourceObject.class)
+public class ViaModel {
+
+    @Inject
+    @Via("resource")
+    private String testProperty;
+
+    public String getTestProperty() {
+        return testProperty;
+    }
+}
diff --git a/it/src/main/java/org/apache/sling/models/it/models/implextend/ExtendsClassPropertyModel.java b/it/src/main/java/org/apache/sling/models/it/models/implextend/ExtendsClassPropertyModel.java
new file mode 100644
index 0000000..4dbb0dc
--- /dev/null
+++ b/it/src/main/java/org/apache/sling/models/it/models/implextend/ExtendsClassPropertyModel.java
@@ -0,0 +1,37 @@
+/*
+ * 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.it.models.implextend;
+
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.models.annotations.Model;
+
+/**
+ * This is an example for a model that can not be adapted itself, but only
+ * to a superclass it extends. This superclass is defined as "adapters".
+ */
+@Model(
+        adaptables = Resource.class,
+        adapters = {SimplePropertyModel.class})
+public class ExtendsClassPropertyModel extends SimplePropertyModel {
+
+    @Override
+    public String getAllProperties() {
+        return "!" + super.getAllProperties() + "!";
+    }
+}
diff --git a/it/src/main/java/org/apache/sling/models/it/models/implextend/ImplementsInterfacePropertyModel.java b/it/src/main/java/org/apache/sling/models/it/models/implextend/ImplementsInterfacePropertyModel.java
new file mode 100644
index 0000000..033d184
--- /dev/null
+++ b/it/src/main/java/org/apache/sling/models/it/models/implextend/ImplementsInterfacePropertyModel.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.it.models.implextend;
+
+import javax.inject.Inject;
+import javax.inject.Named;
+
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.models.annotations.Model;
+import org.apache.sling.models.annotations.Optional;
+
+/**
+ * This is an example for a model that can not be adapted itself, but only
+ * to an interface it implements. This interfaces is defined as "adapters".
+ */
+@Model(
+        adaptables = Resource.class,
+        adapters = {SampleServiceInterface.class})
+public class ImplementsInterfacePropertyModel implements SampleServiceInterface {
+
+    @Inject
+    private String first;
+
+    @Inject
+    @Optional
+    private String second;
+
+    @Inject
+    @Named("third")
+    private String thirdProperty;
+
+    public String getAllProperties() {
+        StringBuilder sb = new StringBuilder();
+        sb.append(first).append("|").append(second).append("|").append(thirdProperty);
+        return sb.toString();
+    }
+}
diff --git a/it/src/main/java/org/apache/sling/models/it/models/implextend/ImplementsInterfacePropertyModel2.java b/it/src/main/java/org/apache/sling/models/it/models/implextend/ImplementsInterfacePropertyModel2.java
new file mode 100644
index 0000000..40d05ec
--- /dev/null
+++ b/it/src/main/java/org/apache/sling/models/it/models/implextend/ImplementsInterfacePropertyModel2.java
@@ -0,0 +1,52 @@
+/*
+ * 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.it.models.implextend;
+
+import javax.inject.Inject;
+import javax.inject.Named;
+
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.models.annotations.Model;
+import org.apache.sling.models.annotations.Optional;
+
+/**
+ * Additional model class that implements the same interface as {@link ImplementsInterfacePropertyModel}.
+ */
+@Model(
+        adaptables = Resource.class,
+        adapters = {SampleServiceInterface.class})
+public class ImplementsInterfacePropertyModel2 implements SampleServiceInterface {
+
+    @Inject
+    private String first;
+
+    @Inject
+    @Optional
+    private String second;
+
+    @Inject
+    @Named("third")
+    private String thirdProperty;
+
+    public String getAllProperties() {
+        StringBuilder sb = new StringBuilder();
+        sb.append(first).append("|").append(second).append("|").append(thirdProperty);
+        return sb.toString();
+    }
+}
diff --git a/it/src/main/java/org/apache/sling/models/it/models/implextend/InvalidImplementsInterfacePropertyModel.java b/it/src/main/java/org/apache/sling/models/it/models/implextend/InvalidImplementsInterfacePropertyModel.java
new file mode 100644
index 0000000..6f0dfdf
--- /dev/null
+++ b/it/src/main/java/org/apache/sling/models/it/models/implextend/InvalidImplementsInterfacePropertyModel.java
@@ -0,0 +1,52 @@
+/*
+ * 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.it.models.implextend;
+
+import javax.inject.Inject;
+import javax.inject.Named;
+
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.models.annotations.Model;
+import org.apache.sling.models.annotations.Optional;
+
+/**
+ * This model defines an invalid adapters property containing an interface it does not implement.
+ */
+@Model(
+        adaptables = Resource.class,
+        adapters = {InvalidSampleServiceInterface.class})
+public class InvalidImplementsInterfacePropertyModel implements SampleServiceInterface {
+
+    @Inject
+    private String first;
+
+    @Inject
+    @Optional
+    private String second;
+
+    @Inject
+    @Named("third")
+    private String thirdProperty;
+
+    public String getAllProperties() {
+        StringBuilder sb = new StringBuilder();
+        sb.append(first).append("|").append(second).append("|").append(thirdProperty);
+        return sb.toString();
+    }
+}
diff --git a/it/src/main/java/org/apache/sling/models/it/models/implextend/InvalidSampleServiceInterface.java b/it/src/main/java/org/apache/sling/models/it/models/implextend/InvalidSampleServiceInterface.java
new file mode 100644
index 0000000..18f26cb
--- /dev/null
+++ b/it/src/main/java/org/apache/sling/models/it/models/implextend/InvalidSampleServiceInterface.java
@@ -0,0 +1,30 @@
+/*
+ * 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.it.models.implextend;
+
+/**
+ * Example "service" interface to which sling models can adapt.
+ */
+public interface InvalidSampleServiceInterface {
+
+    /**
+     * @return concanated string with all properties
+     */
+    String getAllProperties();
+}
diff --git a/it/src/main/java/org/apache/sling/models/it/models/implextend/SampleServiceInterface.java b/it/src/main/java/org/apache/sling/models/it/models/implextend/SampleServiceInterface.java
new file mode 100644
index 0000000..84f1155
--- /dev/null
+++ b/it/src/main/java/org/apache/sling/models/it/models/implextend/SampleServiceInterface.java
@@ -0,0 +1,30 @@
+/*
+ * 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.it.models.implextend;
+
+/**
+ * Example "service" interface to which sling models can adapt.
+ */
+public interface SampleServiceInterface {
+
+    /**
+     * @return concatenated string with all properties
+     */
+    String getAllProperties();
+}
diff --git a/it/src/main/java/org/apache/sling/models/it/models/implextend/SimplePropertyModel.java b/it/src/main/java/org/apache/sling/models/it/models/implextend/SimplePropertyModel.java
new file mode 100644
index 0000000..a942c08
--- /dev/null
+++ b/it/src/main/java/org/apache/sling/models/it/models/implextend/SimplePropertyModel.java
@@ -0,0 +1,47 @@
+/*
+ * 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.it.models.implextend;
+
+import javax.inject.Inject;
+import javax.inject.Named;
+
+import org.apache.sling.models.annotations.Optional;
+
+/**
+ * Base class without @Model annotation.
+ */
+public class SimplePropertyModel {
+
+    @Inject
+    private String first;
+
+    @Inject
+    @Optional
+    private String second;
+
+    @Inject
+    @Named("third")
+    private String thirdProperty;
+
+    public String getAllProperties() {
+        StringBuilder sb = new StringBuilder();
+        sb.append(first).append("|").append(second).append("|").append(thirdProperty);
+        return sb.toString();
+    }
+}
diff --git a/it/src/main/java/org/apache/sling/models/it/models/implextend/package-info.java b/it/src/main/java/org/apache/sling/models/it/models/implextend/package-info.java
new file mode 100644
index 0000000..3d4840c
--- /dev/null
+++ b/it/src/main/java/org/apache/sling/models/it/models/implextend/package-info.java
@@ -0,0 +1,21 @@
+/*
+ * 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.
+ */
+
+@Version("1.0")
+package org.apache.sling.models.it.models.implextend;
+
+import org.osgi.annotation.versioning.Version;
diff --git a/it/src/main/java/org/apache/sling/models/it/models/package-info.java b/it/src/main/java/org/apache/sling/models/it/models/package-info.java
new file mode 100644
index 0000000..d387b59
--- /dev/null
+++ b/it/src/main/java/org/apache/sling/models/it/models/package-info.java
@@ -0,0 +1,21 @@
+/*
+ * 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.
+ */
+
+@Version("1.0")
+package org.apache.sling.models.it.models;
+
+import org.osgi.annotation.versioning.Version;
diff --git a/it/src/main/java/org/apache/sling/models/it/rtbound/BaseComponent.java b/it/src/main/java/org/apache/sling/models/it/rtbound/BaseComponent.java
new file mode 100644
index 0000000..b15f9f3
--- /dev/null
+++ b/it/src/main/java/org/apache/sling/models/it/rtbound/BaseComponent.java
@@ -0,0 +1,51 @@
+/*
+ * 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.it.rtbound;
+
+import javax.inject.Inject;
+
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.models.annotations.Model;
+
+@Model(
+        adaptables = {Resource.class},
+        resourceType = "sling/rt/base")
+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;
+    }
+
+    public String getSampleValueToUpperCase() {
+        return sampleValue.toUpperCase();
+    }
+}
diff --git a/it/src/main/java/org/apache/sling/models/it/rtbound/ExtendedComponent.java b/it/src/main/java/org/apache/sling/models/it/rtbound/ExtendedComponent.java
new file mode 100644
index 0000000..43cbed7
--- /dev/null
+++ b/it/src/main/java/org/apache/sling/models/it/rtbound/ExtendedComponent.java
@@ -0,0 +1,48 @@
+/*
+ * 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.it.rtbound;
+
+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.Model;
+
+@Model(
+        adaptables = {Resource.class},
+        resourceType = "sling/rt/extended")
+public class ExtendedComponent extends BaseComponent {
+
+    private final Date d = new Date();
+
+    public ExtendedComponent(Resource resource) {
+        super(resource);
+    }
+
+    public Calendar getDateByCalendar() {
+        Calendar cal = new GregorianCalendar();
+        cal.setTime(d);
+        return cal;
+    }
+
+    public Date getDate() {
+        return d;
+    }
+}
diff --git a/it/src/main/java/org/apache/sling/models/it/rtbound/FromRequestComponent.java b/it/src/main/java/org/apache/sling/models/it/rtbound/FromRequestComponent.java
new file mode 100644
index 0000000..c39b754
--- /dev/null
+++ b/it/src/main/java/org/apache/sling/models/it/rtbound/FromRequestComponent.java
@@ -0,0 +1,27 @@
+/*
+ * 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.it.rtbound;
+
+import org.apache.sling.api.SlingHttpServletRequest;
+import org.apache.sling.models.annotations.Model;
+
+@Model(
+        adaptables = {SlingHttpServletRequest.class},
+        resourceType = "sling/rt/fromRequest")
+public class FromRequestComponent {}
diff --git a/it/src/main/java/org/apache/sling/models/it/rtbound/package-info.java b/it/src/main/java/org/apache/sling/models/it/rtbound/package-info.java
new file mode 100644
index 0000000..19332e3
--- /dev/null
+++ b/it/src/main/java/org/apache/sling/models/it/rtbound/package-info.java
@@ -0,0 +1,21 @@
+/*
+ * 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.
+ */
+
+@Version("1.0")
+package org.apache.sling.models.it.rtbound;
+
+import org.osgi.annotation.versioning.Version;
diff --git a/it/src/main/java/org/apache/sling/models/it/rtboundpicker/BaseComponent.java b/it/src/main/java/org/apache/sling/models/it/rtboundpicker/BaseComponent.java
new file mode 100644
index 0000000..292cef0
--- /dev/null
+++ b/it/src/main/java/org/apache/sling/models/it/rtboundpicker/BaseComponent.java
@@ -0,0 +1,31 @@
+/*
+ * 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.it.rtboundpicker;
+
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.models.annotations.Model;
+
+@Model(adaptables = Resource.class, adapters = TestComponent.class, resourceType = "sling/rtpicker/base")
+public class BaseComponent implements TestComponent {
+
+    @Override
+    public String getSampleValue() {
+        return "base";
+    }
+}
diff --git a/it/src/main/java/org/apache/sling/models/it/rtboundpicker/SubRTComponent.java b/it/src/main/java/org/apache/sling/models/it/rtboundpicker/SubRTComponent.java
new file mode 100644
index 0000000..32011b2
--- /dev/null
+++ b/it/src/main/java/org/apache/sling/models/it/rtboundpicker/SubRTComponent.java
@@ -0,0 +1,31 @@
+/*
+ * 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.it.rtboundpicker;
+
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.models.annotations.Model;
+
+@Model(adaptables = Resource.class, adapters = TestComponent.class, resourceType = "sling/rtpicker/sub")
+public class SubRTComponent implements TestComponent {
+
+    @Override
+    public String getSampleValue() {
+        return "sub";
+    }
+}
diff --git a/it/src/main/java/org/apache/sling/models/it/rtboundpicker/TestComponent.java b/it/src/main/java/org/apache/sling/models/it/rtboundpicker/TestComponent.java
new file mode 100644
index 0000000..3d97aea
--- /dev/null
+++ b/it/src/main/java/org/apache/sling/models/it/rtboundpicker/TestComponent.java
@@ -0,0 +1,24 @@
+/*
+ * 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.it.rtboundpicker;
+
+public interface TestComponent {
+
+    String getSampleValue();
+}
diff --git a/it/src/main/java/org/apache/sling/models/it/rtboundpicker/package-info.java b/it/src/main/java/org/apache/sling/models/it/rtboundpicker/package-info.java
new file mode 100644
index 0000000..950815c
--- /dev/null
+++ b/it/src/main/java/org/apache/sling/models/it/rtboundpicker/package-info.java
@@ -0,0 +1,21 @@
+/*
+ * 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.
+ */
+
+@Version("1.0")
+package org.apache.sling.models.it.rtboundpicker;
+
+import org.osgi.annotation.versioning.Version;
diff --git a/it/src/main/java/org/apache/sling/models/it/services/AnotherTestBindingsValuesProvider.java b/it/src/main/java/org/apache/sling/models/it/services/AnotherTestBindingsValuesProvider.java
new file mode 100644
index 0000000..9dcce31
--- /dev/null
+++ b/it/src/main/java/org/apache/sling/models/it/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.it.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/it/src/main/java/org/apache/sling/models/it/services/SimpleService.java b/it/src/main/java/org/apache/sling/models/it/services/SimpleService.java
new file mode 100644
index 0000000..aeb4ee1
--- /dev/null
+++ b/it/src/main/java/org/apache/sling/models/it/services/SimpleService.java
@@ -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.
+ */
+package org.apache.sling.models.it.services;
+
+public interface SimpleService {
+    int getRanking();
+}
diff --git a/it/src/main/java/org/apache/sling/models/it/services/SimpleServiceWithCustomRanking.java b/it/src/main/java/org/apache/sling/models/it/services/SimpleServiceWithCustomRanking.java
new file mode 100644
index 0000000..33a8068
--- /dev/null
+++ b/it/src/main/java/org/apache/sling/models/it/services/SimpleServiceWithCustomRanking.java
@@ -0,0 +1,32 @@
+/*
+ * 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.it.services;
+
+public class SimpleServiceWithCustomRanking implements SimpleService {
+
+    private final int ranking;
+
+    public SimpleServiceWithCustomRanking(int ranking) {
+        this.ranking = ranking;
+    }
+
+    public int getRanking() {
+        return ranking;
+    }
+}
diff --git a/it/src/main/java/org/apache/sling/models/it/services/TestBindingsValuesProvider.java b/it/src/main/java/org/apache/sling/models/it/services/TestBindingsValuesProvider.java
new file mode 100644
index 0000000..a7dcb68
--- /dev/null
+++ b/it/src/main/java/org/apache/sling/models/it/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.it.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/it/src/main/java/org/apache/sling/models/it/services/TestResourceDecorator.java b/it/src/main/java/org/apache/sling/models/it/services/TestResourceDecorator.java
new file mode 100644
index 0000000..8d2a0a1
--- /dev/null
+++ b/it/src/main/java/org/apache/sling/models/it/services/TestResourceDecorator.java
@@ -0,0 +1,66 @@
+/*
+ * 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.it.services;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.apache.sling.api.adapter.AdapterManager;
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.api.resource.ResourceDecorator;
+import org.apache.sling.api.resource.ResourceWrapper;
+import org.apache.sling.api.resource.ValueMap;
+import org.jetbrains.annotations.NotNull;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Reference;
+
+@Component(service = ResourceDecorator.class)
+public class TestResourceDecorator implements ResourceDecorator {
+
+    @Reference
+    private AdapterManager adapterManager;
+
+    @Override
+    @SuppressWarnings("null")
+    public Resource decorate(@NotNull Resource resource) {
+        ValueMap map = resource.adaptTo(ValueMap.class);
+        if (map != null && map.containsKey("decorate")) {
+            if (map.get("decorate", "default").equals("customAdaptTo")) {
+                return new ResourceWrapper(resource) {
+                    @Override
+                    public <AdapterType> AdapterType adaptTo(Class<AdapterType> type) {
+                        AdapterType adapter = adapterManager.getAdapter(this, type);
+                        if (adapter != null) {
+                            return adapter;
+                        } else {
+                            return super.adaptTo(type);
+                        }
+                    }
+                };
+            } else {
+                return new ResourceWrapper(resource);
+            }
+        }
+        return null;
+    }
+
+    @Override
+    public Resource decorate(@NotNull Resource resource, @NotNull HttpServletRequest request) {
+        return decorate(resource);
+    }
+}
diff --git a/it/src/main/java/org/apache/sling/models/it/services/package-info.java b/it/src/main/java/org/apache/sling/models/it/services/package-info.java
new file mode 100644
index 0000000..1f5740a
--- /dev/null
+++ b/it/src/main/java/org/apache/sling/models/it/services/package-info.java
@@ -0,0 +1,21 @@
+/*
+ * 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.
+ */
+
+@Version("1.0")
+package org.apache.sling.models.it.services;
+
+import org.osgi.annotation.versioning.Version;
diff --git a/it/src/main/java/org/apache/sling/models/it/servlets/PathBoundServlet.java b/it/src/main/java/org/apache/sling/models/it/servlets/PathBoundServlet.java
new file mode 100644
index 0000000..7657275
--- /dev/null
+++ b/it/src/main/java/org/apache/sling/models/it/servlets/PathBoundServlet.java
@@ -0,0 +1,46 @@
+/*
+ * 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.it.servlets;
+
+import javax.servlet.Servlet;
+import javax.servlet.ServletException;
+
+import java.io.IOException;
+
+import org.apache.sling.api.SlingHttpServletRequest;
+import org.apache.sling.api.SlingHttpServletResponse;
+import org.apache.sling.api.servlets.SlingSafeMethodsServlet;
+import org.apache.sling.models.it.models.RequestSelfModel;
+import org.apache.sling.servlets.annotations.SlingServletPaths;
+import org.jetbrains.annotations.NotNull;
+import org.osgi.service.component.annotations.Component;
+
+@Component(service = Servlet.class)
+@SlingServletPaths("/apps/rtpickerrequest")
+public class PathBoundServlet extends SlingSafeMethodsServlet {
+    private static final long serialVersionUID = 1L;
+
+    @Override
+    @SuppressWarnings("unused")
+    protected void doGet(@NotNull SlingHttpServletRequest request, @NotNull SlingHttpServletResponse response)
+            throws ServletException, IOException {
+        RequestSelfModel model = request.adaptTo(RequestSelfModel.class);
+        response.setStatus(200);
+    }
+}
diff --git a/it/src/main/resources/org/apache/sling/models/it/noclasses/foo.txt b/it/src/main/resources/org/apache/sling/models/it/noclasses/foo.txt
new file mode 100644
index 0000000..dd50685
--- /dev/null
+++ b/it/src/main/resources/org/apache/sling/models/it/noclasses/foo.txt
@@ -0,0 +1 @@
+text file to ensure the package gets created, but without class files
\ No newline at end of file
diff --git a/it/src/test/java/org/apache/sling/junit/teleporter/customizers/SM_TeleporterCustomizer.java b/it/src/test/java/org/apache/sling/junit/teleporter/customizers/SM_TeleporterCustomizer.java
new file mode 100644
index 0000000..22efc01
--- /dev/null
+++ b/it/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.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.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 ex) {
+            throw new RuntimeException("Error waiting for expected components.", ex);
+        }
+    }
+}
diff --git a/it/src/test/java/org/apache/sling/models/testing/DecoratedIT.java b/it/src/test/java/org/apache/sling/models/testing/DecoratedIT.java
new file mode 100644
index 0000000..8c0a39b
--- /dev/null
+++ b/it/src/test/java/org/apache/sling/models/testing/DecoratedIT.java
@@ -0,0 +1,96 @@
+/*
+ * 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.testing;
+
+import javax.jcr.Node;
+import javax.jcr.Session;
+
+import org.apache.commons.lang3.RandomStringUtils;
+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.ResourceWrapper;
+import org.apache.sling.junit.rules.TeleporterRule;
+import org.apache.sling.models.factory.ModelFactory;
+import org.apache.sling.models.it.models.SelfModel;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+public class DecoratedIT {
+
+    @Rule
+    public final TeleporterRule teleporter = TeleporterRule.forClass(getClass(), "SM_Teleporter");
+
+    private ModelFactory modelFactory;
+
+    private ResourceResolver resolver;
+    private Resource resourceWithDefaultWrapperBehavior;
+    private Resource resourceWithCustomAdaptToWrapper;
+
+    @Before
+    @SuppressWarnings("null")
+    public void setUp() throws Exception {
+        ResourceResolverFactory rrFactory = teleporter.getService(ResourceResolverFactory.class);
+        modelFactory = teleporter.getService(ModelFactory.class);
+        resolver = rrFactory.getServiceResourceResolver(null);
+        Session session = resolver.adaptTo(Session.class);
+        Node rootNode = session.getRootNode();
+        Node createdNode = rootNode.addNode("test_" + RandomStringUtils.randomAlphanumeric(10));
+        createdNode.setProperty("decorate", true);
+        session.save();
+
+        resourceWithDefaultWrapperBehavior = resolver.getResource(createdNode.getPath());
+
+        createdNode = rootNode.addNode("test_" + RandomStringUtils.randomAlphanumeric(10));
+        createdNode.setProperty("decorate", "customAdaptTo");
+        session.save();
+
+        resourceWithCustomAdaptToWrapper = resolver.getResource(createdNode.getPath());
+    }
+
+    @After
+    public void tearDown() throws Exception {
+        resolver.delete(resourceWithDefaultWrapperBehavior);
+        resolver.delete(resourceWithCustomAdaptToWrapper);
+        resolver.close();
+    }
+
+    @Test
+    public void testInjectDecoratedResourceUsingCreateModel() {
+        assertTrue("Resource is not wrapped", resourceWithDefaultWrapperBehavior instanceof ResourceWrapper);
+        SelfModel model = modelFactory.createModel(resourceWithDefaultWrapperBehavior, SelfModel.class);
+
+        assertNotNull("Model is null", model);
+        assertTrue("Model is not wrapped", model.getResource() instanceof ResourceWrapper);
+    }
+
+    @Test
+    public void testInjectDecoratedResourceUsingAdaptTo() {
+        assertTrue("Resource is not wrapped", resourceWithCustomAdaptToWrapper instanceof ResourceWrapper);
+        SelfModel model = resourceWithCustomAdaptToWrapper.adaptTo(SelfModel.class);
+
+        assertNotNull("Model is null", model);
+        assertTrue("Model is not wrapped", model.getResource() instanceof ResourceWrapper);
+    }
+}
diff --git a/it/src/test/java/org/apache/sling/models/testing/ImplementsExtendsIT.java b/it/src/test/java/org/apache/sling/models/testing/ImplementsExtendsIT.java
new file mode 100644
index 0000000..cc42661
--- /dev/null
+++ b/it/src/test/java/org/apache/sling/models/testing/ImplementsExtendsIT.java
@@ -0,0 +1,150 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.sling.models.testing;
+
+import javax.jcr.Node;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+
+import org.apache.commons.lang3.RandomStringUtils;
+import org.apache.sling.api.adapter.AdapterManager;
+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.junit.rules.TeleporterRule;
+import org.apache.sling.models.it.implpicker.CustomLastImplementationPicker;
+import org.apache.sling.models.it.models.implextend.ImplementsInterfacePropertyModel;
+import org.apache.sling.models.it.models.implextend.ImplementsInterfacePropertyModel2;
+import org.apache.sling.models.it.models.implextend.InvalidSampleServiceInterface;
+import org.apache.sling.models.it.models.implextend.SampleServiceInterface;
+import org.apache.sling.models.it.models.implextend.SimplePropertyModel;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+
+public class ImplementsExtendsIT {
+
+    @Rule
+    public final TeleporterRule teleporter = TeleporterRule.forClass(getClass(), "SM_Teleporter");
+
+    private AdapterManager adapterManager;
+
+    private String firstValue;
+    private String secondValue;
+    private String thirdValue;
+    private ResourceResolver resolver;
+    private Resource resource;
+    private Node createdNode;
+
+    @Before
+    @SuppressWarnings("null")
+    public void setUp() throws Exception {
+        ResourceResolverFactory rrFactory = teleporter.getService(ResourceResolverFactory.class);
+        adapterManager = teleporter.getService(AdapterManager.class);
+        firstValue = RandomStringUtils.randomAlphanumeric(10);
+        thirdValue = RandomStringUtils.randomAlphanumeric(10);
+
+        resolver = rrFactory.getServiceResourceResolver(null);
+        Session session = resolver.adaptTo(Session.class);
+        Node rootNode = session.getRootNode();
+        createdNode = rootNode.addNode("test_" + RandomStringUtils.randomAlphanumeric(10));
+        createdNode.setProperty("first", firstValue);
+        createdNode.setProperty("third", thirdValue);
+        session.save();
+
+        resource = resolver.getResource(createdNode.getPath());
+    }
+
+    @After
+    public void after() throws Exception {
+        if (resolver != null) {
+            resolver.close();
+        }
+    }
+
+    /**
+     * Try to adapt to interface, with an different implementation class that has the @Model annotation
+     */
+    @Test
+    public void testImplementsInterfaceModel() {
+        SampleServiceInterface model = adapterManager.getAdapter(resource, SampleServiceInterface.class);
+        assertNotNull(model);
+        assertEquals(ImplementsInterfacePropertyModel.class, model.getClass());
+        assertEquals(firstValue + "|" + secondValue + "|" + thirdValue, model.getAllProperties());
+    }
+
+    /**
+     * Ensure that the implementation class itself can be adapted to, even if it is not part of the "adapter" property in the annotation.
+     */
+    @Test
+    public void testImplementsInterfaceModel_ImplClassImplicitlyMapped() {
+        ImplementsInterfacePropertyModel model =
+                adapterManager.getAdapter(resource, ImplementsInterfacePropertyModel.class);
+        assertNotNull(model);
+    }
+
+    /**
+     * Test implementation class with a mapping that is not valid (an interface that is not implemented).
+     */
+    @Test
+    public void testInvalidImplementsInterfaceModel() {
+        InvalidSampleServiceInterface model = adapterManager.getAdapter(resource, InvalidSampleServiceInterface.class);
+        assertNull(model);
+    }
+
+    /**
+     * Test to adapt to a superclass of the implementation class with the appropriate mapping in the @Model annotation.
+     */
+    @Test
+    public void testExtendsClassModel() {
+        SimplePropertyModel model = adapterManager.getAdapter(resource, SimplePropertyModel.class);
+        assertNotNull(model);
+        assertEquals("!" + firstValue + "|" + secondValue + "|" + thirdValue + "!", model.getAllProperties());
+    }
+
+    /**
+     * Try to adapt to interface, with an different implementation class that has the @Model annotation
+     */
+    @Test
+    @SuppressWarnings("null")
+    public void testImplementsInterfaceModelWithPickLastImplementationPicker() throws RepositoryException {
+
+        Session session = resolver.adaptTo(Session.class);
+        Node node = resource.adaptTo(Node.class);
+        Node childNode = node.addNode(CustomLastImplementationPicker.CUSTOM_NAME);
+        childNode.setProperty("first", firstValue);
+        childNode.setProperty("third", thirdValue);
+        session.save();
+
+        Resource childResource = resolver.getResource(childNode.getPath());
+
+        SampleServiceInterface model = adapterManager.getAdapter(childResource, SampleServiceInterface.class);
+        assertNotNull(model);
+        assertEquals(ImplementsInterfacePropertyModel2.class, model.getClass());
+        assertEquals(firstValue + "|" + secondValue + "|" + thirdValue, model.getAllProperties());
+
+        childNode.remove();
+        session.save();
+    }
+}
diff --git a/it/src/test/java/org/apache/sling/models/testing/InjectorSpecificAnnotationIT.java b/it/src/test/java/org/apache/sling/models/testing/InjectorSpecificAnnotationIT.java
new file mode 100644
index 0000000..3764dbc
--- /dev/null
+++ b/it/src/test/java/org/apache/sling/models/testing/InjectorSpecificAnnotationIT.java
@@ -0,0 +1,72 @@
+/*
+ * 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.testing;
+
+import javax.jcr.Node;
+import javax.jcr.Session;
+
+import org.apache.commons.lang3.RandomStringUtils;
+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.junit.rules.TeleporterRule;
+import org.apache.sling.models.it.models.SlingPropertyAnnotationTestModel;
+import org.junit.Rule;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+public class InjectorSpecificAnnotationIT {
+
+    @Rule
+    public final TeleporterRule teleporter = TeleporterRule.forClass(getClass(), "SM_Teleporter");
+
+    @Test
+    @SuppressWarnings("null")
+    public void test() throws Exception {
+        ResourceResolverFactory rrFactory = teleporter.getService(ResourceResolverFactory.class);
+        String value = RandomStringUtils.randomAlphanumeric(10);
+
+        ResourceResolver resolver = null;
+        Node createdNode = null;
+        try {
+            resolver = rrFactory.getServiceResourceResolver(null);
+            Session session = resolver.adaptTo(Session.class);
+            Node rootNode = session.getRootNode();
+            createdNode = rootNode.addNode("test_" + RandomStringUtils.randomAlphanumeric(10));
+            createdNode.setProperty("testProperty", value);
+            session.save();
+
+            Resource resource = resolver.getResource(createdNode.getPath());
+
+            SlingPropertyAnnotationTestModel model = resource.adaptTo(SlingPropertyAnnotationTestModel.class);
+
+            assertNotNull("Model is null", model);
+            assertEquals("Test Property is not set correctly", value, model.getTestProperty());
+        } finally {
+            if (createdNode != null) {
+                createdNode.remove();
+            }
+            if (resolver != null) {
+                resolver.close();
+            }
+        }
+    }
+}
diff --git a/it/src/test/java/org/apache/sling/models/testing/ModelFactorySimpleIT.java b/it/src/test/java/org/apache/sling/models/testing/ModelFactorySimpleIT.java
new file mode 100644
index 0000000..5468113
--- /dev/null
+++ b/it/src/test/java/org/apache/sling/models/testing/ModelFactorySimpleIT.java
@@ -0,0 +1,130 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.sling.models.testing;
+
+import javax.jcr.Node;
+import javax.jcr.Session;
+
+import org.apache.commons.lang3.RandomStringUtils;
+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.junit.rules.TeleporterRule;
+import org.apache.sling.models.factory.ModelFactory;
+import org.apache.sling.models.it.models.ConstructorInjectionTestModel;
+import org.apache.sling.models.it.models.FieldInjectionTestModel;
+import org.apache.sling.models.it.models.implextend.InvalidImplementsInterfacePropertyModel;
+import org.apache.sling.models.it.models.implextend.SampleServiceInterface;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Rule;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
+
+public class ModelFactorySimpleIT {
+
+    @Rule
+    public final TeleporterRule teleporter = TeleporterRule.forClass(getClass(), "SM_Teleporter");
+
+    private ModelFactory modelFactory;
+
+    private String value;
+    private ResourceResolver resolver;
+    private Resource resource;
+    private Node createdNode;
+
+    @Before
+    @SuppressWarnings("null")
+    public void setUp() throws Exception {
+        ResourceResolverFactory rrFactory = teleporter.getService(ResourceResolverFactory.class);
+        modelFactory = teleporter.getService(ModelFactory.class);
+        value = RandomStringUtils.randomAlphanumeric(10);
+
+        resolver = rrFactory.getServiceResourceResolver(null);
+        Session session = resolver.adaptTo(Session.class);
+        Node rootNode = session.getRootNode();
+        createdNode = rootNode.addNode("test_" + RandomStringUtils.randomAlphanumeric(10));
+        createdNode.setProperty("testProperty", value);
+        session.save();
+
+        resource = resolver.getResource(createdNode.getPath());
+    }
+
+    @After
+    public void tearDown() throws Exception {
+        if (createdNode != null) {
+            createdNode.remove();
+        }
+        if (resolver != null) {
+            resolver.close();
+        }
+    }
+
+    @Test
+    public void testCreateModel() {
+        FieldInjectionTestModel model = modelFactory.createModel(resource, FieldInjectionTestModel.class);
+
+        assertNotNull("Model is null", model);
+        assertEquals("Test Property is not set correctly", value, model.getTestProperty());
+        assertNotNull("Filters is null", model.getFilters());
+        assertSame("Adaptable is not injected", resource, model.getResource());
+    }
+
+    @Ignore
+    private static final class DummyClass {}
+
+    @Test
+    public void testIsModelClass() {
+        assertTrue("Model is not detected as such", modelFactory.isModelClass(ConstructorInjectionTestModel.class));
+        assertFalse("Dummy class incorrectly detected as model class", modelFactory.isModelClass(DummyClass.class));
+        assertFalse(
+                "Model with invalid adaptable incorrectly detected as model class",
+                modelFactory.isModelClass(InvalidImplementsInterfacePropertyModel.class));
+        assertTrue(
+                "Model is not detected as such",
+                modelFactory.isModelClass(SampleServiceInterface.class)); // being provided by two adapters
+    }
+
+    @Test
+    public void testCanCreateFromAdaptable() {
+        assertTrue(
+                "Model is not detected as such",
+                modelFactory.canCreateFromAdaptable(resource, ConstructorInjectionTestModel.class));
+        assertTrue(
+                "Model is not detected as such",
+                modelFactory.canCreateFromAdaptable(resource, SampleServiceInterface.class));
+        assertFalse(
+                "Model is incorrectly detected",
+                modelFactory.canCreateFromAdaptable(
+                        new String(), ConstructorInjectionTestModel.class)); // invalid adaptable
+    }
+
+    @Test()
+    public void testCanCreateFromAdaptableWithModelExceptin() {
+        assertFalse(
+                "Model is incorrectly detected",
+                modelFactory.canCreateFromAdaptable(resource, DummyClass.class)); // no model class
+    }
+}
diff --git a/it/src/test/java/org/apache/sling/models/testing/PathBoundServletIT.java b/it/src/test/java/org/apache/sling/models/testing/PathBoundServletIT.java
new file mode 100644
index 0000000..1bd4ad1
--- /dev/null
+++ b/it/src/test/java/org/apache/sling/models/testing/PathBoundServletIT.java
@@ -0,0 +1,56 @@
+/*
+ * 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.testing;
+
+import org.apache.sling.api.resource.ResourceResolver;
+import org.apache.sling.api.resource.ResourceResolverFactory;
+import org.apache.sling.engine.SlingRequestProcessor;
+import org.apache.sling.junit.rules.TeleporterRule;
+import org.apache.sling.models.testing.helper.FakeRequest;
+import org.apache.sling.models.testing.helper.FakeResponse;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+
+public class PathBoundServletIT {
+
+    @Rule
+    public final TeleporterRule teleporter = TeleporterRule.forClass(getClass(), "SM_Teleporter");
+
+    private ResourceResolverFactory rrFactory;
+    private SlingRequestProcessor slingRequestProcessor;
+
+    @Before
+    @SuppressWarnings("null")
+    public void setup() {
+        rrFactory = teleporter.getService(ResourceResolverFactory.class);
+        slingRequestProcessor = teleporter.getService(SlingRequestProcessor.class);
+    }
+
+    @Test
+    public void testDoubledServlets() throws Exception {
+        try (ResourceResolver resolver = rrFactory.getServiceResourceResolver(null); ) {
+            FakeResponse response = new FakeResponse();
+            slingRequestProcessor.processRequest(new FakeRequest("/apps/rtpickerrequest"), response, resolver);
+
+            Assert.assertEquals(200, response.getStatus());
+        }
+    }
+}
diff --git a/it/src/test/java/org/apache/sling/models/testing/ServiceInjectionWithDifferentRankingIT.java b/it/src/test/java/org/apache/sling/models/testing/ServiceInjectionWithDifferentRankingIT.java
new file mode 100644
index 0000000..7a9b1a0
--- /dev/null
+++ b/it/src/test/java/org/apache/sling/models/testing/ServiceInjectionWithDifferentRankingIT.java
@@ -0,0 +1,147 @@
+/*
+ * 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.testing;
+
+import javax.jcr.Node;
+import javax.jcr.Session;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Dictionary;
+import java.util.Hashtable;
+
+import org.apache.commons.lang3.RandomStringUtils;
+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.junit.Activator;
+import org.apache.sling.junit.rules.TeleporterRule;
+import org.apache.sling.models.factory.ModelFactory;
+import org.apache.sling.models.it.models.ServiceInjectionTestModel;
+import org.apache.sling.models.it.services.SimpleService;
+import org.apache.sling.models.it.services.SimpleServiceWithCustomRanking;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
+import org.osgi.framework.ServiceRegistration;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+public class ServiceInjectionWithDifferentRankingIT {
+
+    @Rule
+    public final TeleporterRule teleporter = TeleporterRule.forClass(getClass(), "SM_Teleporter");
+
+    private ModelFactory modelFactory;
+
+    private String value;
+    private ResourceResolver resolver;
+    private Resource resource;
+    private Node createdNode;
+    private BundleContext bundleContext;
+    private Collection<ServiceRegistration> serviceRegistrations;
+
+    @Before
+    @SuppressWarnings("null")
+    public void setUp() throws Exception {
+        ResourceResolverFactory rrFactory = teleporter.getService(ResourceResolverFactory.class);
+        modelFactory = teleporter.getService(ModelFactory.class);
+        value = RandomStringUtils.randomAlphanumeric(10);
+
+        resolver = rrFactory.getServiceResourceResolver(null);
+        Session session = resolver.adaptTo(Session.class);
+        Node rootNode = session.getRootNode();
+        createdNode = rootNode.addNode("test_" + RandomStringUtils.randomAlphanumeric(10));
+        createdNode.setProperty("testProperty", value);
+        session.save();
+
+        resource = resolver.getResource(createdNode.getPath());
+
+        bundleContext = Activator.getBundleContext();
+        serviceRegistrations = new ArrayList<ServiceRegistration>();
+    }
+
+    @After
+    public void tearDown() throws Exception {
+        if (createdNode != null) {
+            createdNode.remove();
+        }
+        if (resolver != null) {
+            resolver.close();
+        }
+
+        for (ServiceRegistration serviceRegistration : serviceRegistrations) {
+            serviceRegistration.unregister();
+        }
+    }
+
+    @SuppressWarnings("unchecked")
+    private void registerSimpleService(int ranking) {
+        @SuppressWarnings("rawtypes")
+        Dictionary serviceProps = new Hashtable();
+        serviceProps.put(Constants.SERVICE_RANKING, new Integer(ranking));
+        ServiceRegistration serviceRegistration = bundleContext.registerService(
+                SimpleService.class.getName(), new SimpleServiceWithCustomRanking(ranking), serviceProps);
+        serviceRegistrations.add(serviceRegistration);
+    }
+
+    @Test
+    public void testServiceInjectionConsideringRankingWithResource() throws IOException {
+
+        registerSimpleService(0);
+        // cannot use adaptTo due to adaptersCache
+        ServiceInjectionTestModel model = modelFactory.createModel(resource, ServiceInjectionTestModel.class);
+        assertNotNull("Model is null", model);
+        // only the default service with ranking 0 is known
+        assertEquals(
+                "The service with the highest ranking was not returned",
+                0,
+                model.getSimpleService().getRanking());
+        assertArrayEquals("Order on injected services is wrong", model.getSimpleServicesRankings(), new Integer[] {0});
+
+        registerSimpleService(-1000);
+        model = modelFactory.createModel(resource, ServiceInjectionTestModel.class);
+        assertNotNull("Model is null", model);
+        // ranking 0 is still the highest one
+        assertEquals(
+                "The service with the highest ranking was not returned",
+                0,
+                model.getSimpleService().getRanking());
+        assertArrayEquals(
+                "Order on injected services is wrong", model.getSimpleServicesRankings(), new Integer[] {0, -1000});
+
+        registerSimpleService(1000);
+        model = modelFactory.createModel(resource, ServiceInjectionTestModel.class);
+        assertNotNull("Model is null", model);
+        // now ranking 1000 is the highest
+        assertEquals(
+                "The service with the highest ranking was not returned",
+                1000,
+                model.getSimpleService().getRanking());
+        assertArrayEquals(
+                "Order on injected services is wrong", model.getSimpleServicesRankings(), new Integer[] {1000, 0, -1000
+                });
+    }
+}
diff --git a/it/src/test/java/org/apache/sling/models/testing/SimpleIT.java b/it/src/test/java/org/apache/sling/models/testing/SimpleIT.java
new file mode 100644
index 0000000..7ab3c7f
--- /dev/null
+++ b/it/src/test/java/org/apache/sling/models/testing/SimpleIT.java
@@ -0,0 +1,111 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.sling.models.testing;
+
+import javax.jcr.Node;
+import javax.jcr.Session;
+
+import org.apache.commons.lang3.RandomStringUtils;
+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.junit.rules.TeleporterRule;
+import org.apache.sling.models.it.models.ConstructorInjectionTestModel;
+import org.apache.sling.models.it.models.FieldInjectionTestModel;
+import org.apache.sling.models.it.models.InterfaceInjectionTestModel;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertSame;
+
+public class SimpleIT {
+
+    @Rule
+    public final TeleporterRule teleporter = TeleporterRule.forClass(getClass(), "SM_Teleporter");
+
+    private String value;
+    private String childValue;
+    private ResourceResolver resolver;
+    private Resource resource;
+    private Node createdNode;
+
+    @Before
+    @SuppressWarnings("null")
+    public void setUp() throws Exception {
+        ResourceResolverFactory rrFactory = teleporter.getService(ResourceResolverFactory.class);
+        value = RandomStringUtils.randomAlphanumeric(10);
+        childValue = RandomStringUtils.randomAlphanumeric(10);
+
+        resolver = rrFactory.getServiceResourceResolver(null);
+        Session session = resolver.adaptTo(Session.class);
+        Node rootNode = session.getRootNode();
+        createdNode = rootNode.addNode("test_" + RandomStringUtils.randomAlphanumeric(10));
+        createdNode.setProperty("testProperty", value);
+        Node child = createdNode.addNode("child");
+        child.setProperty("childProperty", childValue);
+        session.save();
+
+        resource = resolver.getResource(createdNode.getPath());
+    }
+
+    @After
+    public void tearDown() throws Exception {
+        if (createdNode != null) {
+            createdNode.remove();
+        }
+        if (resolver != null) {
+            resolver.close();
+        }
+    }
+
+    @Test
+    public void testFieldInjection() {
+        FieldInjectionTestModel model = resource.adaptTo(FieldInjectionTestModel.class);
+
+        assertNotNull("Model is null", model);
+        assertEquals("Test Property is not set correctly", value, model.getTestProperty());
+        assertEquals("Child Test Property is not set correctly", childValue, model.getChildProperty());
+        assertNotNull("Filters is null", model.getFilters());
+        assertSame("Adaptable is not injected", resource, model.getResource());
+    }
+
+    @Test
+    public void testInterfaceInjection() {
+        InterfaceInjectionTestModel model = resource.adaptTo(InterfaceInjectionTestModel.class);
+
+        assertNotNull("Model is null", model);
+        assertEquals("Test Property is not set correctly", value, model.getTestProperty());
+        assertNotNull("Filters is null", model.getFilters());
+        assertSame("Adaptable is not injected", resource, model.getResource());
+    }
+
+    @Test
+    public void testConstructorInjection() {
+        ConstructorInjectionTestModel model = resource.adaptTo(ConstructorInjectionTestModel.class);
+
+        assertNotNull("Model is null", model);
+        assertEquals("Test Property is not set correctly", value, model.getTestProperty());
+        assertNotNull("Filters is null", model.getFilters());
+        assertSame("Adaptable is not injected", resource, model.getResource());
+    }
+}
diff --git a/it/src/test/java/org/apache/sling/models/testing/ViaIT.java b/it/src/test/java/org/apache/sling/models/testing/ViaIT.java
new file mode 100644
index 0000000..07f973e
--- /dev/null
+++ b/it/src/test/java/org/apache/sling/models/testing/ViaIT.java
@@ -0,0 +1,77 @@
+/*
+ * 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.testing;
+
+import javax.jcr.Node;
+import javax.jcr.Session;
+
+import org.apache.commons.lang3.RandomStringUtils;
+import org.apache.sling.api.adapter.AdapterManager;
+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.junit.rules.TeleporterRule;
+import org.apache.sling.models.it.models.SourceObject;
+import org.apache.sling.models.it.models.ViaModel;
+import org.junit.Rule;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+public class ViaIT {
+
+    @Rule
+    public final TeleporterRule teleporter = TeleporterRule.forClass(getClass(), "SM_Teleporter");
+
+    @Test
+    @SuppressWarnings("null")
+    public void test() throws Exception {
+        ResourceResolverFactory rrFactory = teleporter.getService(ResourceResolverFactory.class);
+        AdapterManager adapterManager = teleporter.getService(AdapterManager.class);
+
+        String value = RandomStringUtils.randomAlphanumeric(10);
+
+        ResourceResolver resolver = null;
+        Node createdNode = null;
+        try {
+            resolver = rrFactory.getServiceResourceResolver(null);
+            Session session = resolver.adaptTo(Session.class);
+            Node rootNode = session.getRootNode();
+            createdNode = rootNode.addNode("test_" + RandomStringUtils.randomAlphanumeric(10));
+            createdNode.setProperty("testProperty", value);
+            session.save();
+
+            Resource resource = resolver.getResource(createdNode.getPath());
+            SourceObject obj = new SourceObject(resource);
+
+            ViaModel model = adapterManager.getAdapter(obj, ViaModel.class);
+
+            assertNotNull("Model is null", model);
+            assertEquals("Test Property is not set correctly", value, model.getTestProperty());
+        } finally {
+            if (createdNode != null) {
+                createdNode.remove();
+            }
+            if (resolver != null) {
+                resolver.close();
+            }
+        }
+    }
+}
diff --git a/it/src/test/java/org/apache/sling/models/testing/delegate/DelegateRequestIT.java b/it/src/test/java/org/apache/sling/models/testing/delegate/DelegateRequestIT.java
new file mode 100644
index 0000000..a6b494a
--- /dev/null
+++ b/it/src/test/java/org/apache/sling/models/testing/delegate/DelegateRequestIT.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.models.testing.delegate;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.sling.api.SlingConstants;
+import org.apache.sling.api.resource.LoginException;
+import org.apache.sling.api.resource.PersistenceException;
+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.junit.rules.TeleporterRule;
+import org.apache.sling.models.factory.ModelFactory;
+import org.apache.sling.models.it.delegate.request.DelegateBaseModel;
+import org.apache.sling.models.it.delegate.request.DelegateExtendedModel;
+import org.apache.sling.models.it.delegate.request.DelegateInterface;
+import org.apache.sling.models.testing.rtbound.FakeRequest;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+public class DelegateRequestIT {
+
+    @Rule
+    public final TeleporterRule teleporter = TeleporterRule.forClass(getClass(), "SM_Teleporter");
+
+    private ResourceResolverFactory rrFactory;
+
+    private ModelFactory modelFactory;
+
+    private final String baseComponentPath = "/content/delegate/baseComponent";
+    private final String extendedComponentPath = "/content/delegate/extendedComponent";
+
+    @Before
+    @SuppressWarnings("null")
+    public void setup() throws LoginException, PersistenceException {
+        rrFactory = teleporter.getService(ResourceResolverFactory.class);
+        modelFactory = teleporter.getService(ModelFactory.class);
+        try (ResourceResolver adminResolver = rrFactory.getServiceResourceResolver(null); ) {
+
+            Map<String, Object> properties = new HashMap<String, Object>();
+            properties.put("text", "baseTESTValue");
+            properties.put("other", "baseOther");
+            properties.put(
+                    SlingConstants.NAMESPACE_PREFIX + ":" + SlingConstants.PROPERTY_RESOURCE_TYPE,
+                    "sling/delegate/base");
+            ResourceUtil.getOrCreateResource(adminResolver, baseComponentPath, properties, null, false);
+            properties.clear();
+
+            properties.put("text", "extendedTESTValue");
+            properties.put("other", "extendedOther");
+            properties.put(
+                    SlingConstants.NAMESPACE_PREFIX + ":" + SlingConstants.PROPERTY_RESOURCE_TYPE,
+                    "sling/delegate/extended");
+            ResourceUtil.getOrCreateResource(adminResolver, extendedComponentPath, properties, null, false);
+            properties.clear();
+
+            properties.put(
+                    SlingConstants.NAMESPACE_PREFIX + ":" + SlingConstants.PROPERTY_RESOURCE_SUPER_TYPE,
+                    "sling/delegate/base");
+            ResourceUtil.getOrCreateResource(adminResolver, "/apps/sling/delegate/extended", properties, null, false);
+            properties.clear();
+
+            adminResolver.commit();
+        }
+    }
+
+    @Test
+    public void testCreateDelegateModel() throws LoginException {
+        try (ResourceResolver resolver = rrFactory.getServiceResourceResolver(null); ) {
+            final Resource baseComponentResource = resolver.getResource(baseComponentPath);
+            assertNotNull(baseComponentResource);
+            final FakeRequest baseRequest = new FakeRequest(baseComponentResource);
+            final DelegateInterface modelFromBase = modelFactory.createModel(baseRequest, DelegateInterface.class);
+            assertNotNull("Base Model should not be null", modelFromBase);
+            assertTrue("Model should be DelegateBaseModel", modelFromBase instanceof DelegateBaseModel);
+            assertEquals("baseTESTValue", modelFromBase.getText());
+            assertEquals("baseOther", modelFromBase.getOther());
+
+            final Resource extendedComponentResource = resolver.getResource(extendedComponentPath);
+            assertNotNull(extendedComponentResource);
+            final FakeRequest extendedRequest = new FakeRequest(extendedComponentResource);
+            final DelegateInterface modelFromExtended =
+                    modelFactory.createModel(extendedRequest, DelegateInterface.class);
+            assertNotNull("Extended Model should not be null", modelFromExtended);
+            assertTrue("Model should be DelegateExtendedModel", modelFromExtended instanceof DelegateExtendedModel);
+            assertEquals("EXTENDEDTESTVALUE", modelFromExtended.getText());
+            assertEquals("extendedOther", modelFromExtended.getOther());
+        }
+    }
+}
diff --git a/it/src/test/java/org/apache/sling/models/testing/delegate/DelegateResourceIT.java b/it/src/test/java/org/apache/sling/models/testing/delegate/DelegateResourceIT.java
new file mode 100644
index 0000000..97f8094
--- /dev/null
+++ b/it/src/test/java/org/apache/sling/models/testing/delegate/DelegateResourceIT.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.testing.delegate;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.sling.api.SlingConstants;
+import org.apache.sling.api.resource.LoginException;
+import org.apache.sling.api.resource.PersistenceException;
+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.junit.rules.TeleporterRule;
+import org.apache.sling.models.it.delegate.resource.DelegateBaseModel;
+import org.apache.sling.models.it.delegate.resource.DelegateExtendedModel;
+import org.apache.sling.models.it.delegate.resource.DelegateInterface;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+public class DelegateResourceIT {
+
+    @Rule
+    public final TeleporterRule teleporter = TeleporterRule.forClass(getClass(), "SM_Teleporter");
+
+    private ResourceResolverFactory rrFactory;
+
+    private final String baseComponentPath = "/content/delegate/baseComponent";
+    private final String extendedComponentPath = "/content/delegate/extendedComponent";
+
+    @Before
+    @SuppressWarnings("null")
+    public void setup() throws LoginException, PersistenceException {
+        rrFactory = teleporter.getService(ResourceResolverFactory.class);
+        try (ResourceResolver adminResolver = rrFactory.getServiceResourceResolver(null); ) {
+            Map<String, Object> properties = new HashMap<String, Object>();
+            properties.put("text", "baseTESTValue");
+            properties.put("other", "baseOther");
+            properties.put(
+                    SlingConstants.NAMESPACE_PREFIX + ":" + SlingConstants.PROPERTY_RESOURCE_TYPE,
+                    "sling/delegate/base");
+            ResourceUtil.getOrCreateResource(adminResolver, baseComponentPath, properties, null, false);
+            properties.clear();
+
+            properties.put("text", "extendedTESTValue");
+            properties.put("other", "extendedOther");
+            properties.put(
+                    SlingConstants.NAMESPACE_PREFIX + ":" + SlingConstants.PROPERTY_RESOURCE_TYPE,
+                    "sling/delegate/extended");
+            ResourceUtil.getOrCreateResource(adminResolver, extendedComponentPath, properties, null, false);
+            properties.clear();
+
+            properties.put(
+                    SlingConstants.NAMESPACE_PREFIX + ":" + SlingConstants.PROPERTY_RESOURCE_SUPER_TYPE,
+                    "sling/delegate/base");
+            ResourceUtil.getOrCreateResource(adminResolver, "/apps/sling/delegate/extended", properties, null, false);
+            properties.clear();
+
+            adminResolver.commit();
+        }
+    }
+
+    @Test
+    public void testCreateDelegateModel() throws LoginException {
+        try (ResourceResolver resolver = rrFactory.getServiceResourceResolver(null); ) {
+            final Resource baseComponentResource = resolver.getResource(baseComponentPath);
+            assertNotNull(baseComponentResource);
+            final DelegateInterface modelFromBase = baseComponentResource.adaptTo(DelegateInterface.class);
+            assertNotNull("Model should not be null", modelFromBase);
+            assertTrue("Model should be DelegateBaseModel", modelFromBase instanceof DelegateBaseModel);
+            assertEquals("baseTESTValue", modelFromBase.getText());
+            assertEquals("baseOther", modelFromBase.getOther());
+
+            final Resource extendedComponentResource = resolver.getResource(extendedComponentPath);
+            assertNotNull(extendedComponentResource);
+            final DelegateInterface modelFromExtended = extendedComponentResource.adaptTo(DelegateInterface.class);
+            assertNotNull("Model should not be null", modelFromExtended);
+            assertTrue("Model should be DelegateExtendedModel", modelFromExtended instanceof DelegateExtendedModel);
+            assertEquals("EXTENDEDTESTVALUE", modelFromExtended.getText());
+            assertEquals("extendedOther", modelFromExtended.getOther());
+        }
+    }
+}
diff --git a/it/src/test/java/org/apache/sling/models/testing/delegate/viaoriginalresource/ViaOriginalResourceDelegationIT.java b/it/src/test/java/org/apache/sling/models/testing/delegate/viaoriginalresource/ViaOriginalResourceDelegationIT.java
new file mode 100644
index 0000000..ee119b7
--- /dev/null
+++ b/it/src/test/java/org/apache/sling/models/testing/delegate/viaoriginalresource/ViaOriginalResourceDelegationIT.java
@@ -0,0 +1,139 @@
+/*
+ * 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.testing.delegate.viaoriginalresource;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.sling.api.resource.LoginException;
+import org.apache.sling.api.resource.PersistenceException;
+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.junit.rules.TeleporterRule;
+import org.apache.sling.models.factory.ModelFactory;
+import org.apache.sling.models.it.delegate.viaoriginalresource.A;
+import org.apache.sling.models.it.delegate.viaoriginalresource.models.A1Impl;
+import org.apache.sling.models.it.delegate.viaoriginalresource.models.AImpl;
+import org.apache.sling.models.it.delegate.viaoriginalresource.models.B1Impl;
+import org.apache.sling.models.it.delegate.viaoriginalresource.models.BImpl;
+import org.apache.sling.models.testing.rtbound.FakeRequest;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
+
+public class ViaOriginalResourceDelegationIT {
+
+    @Rule
+    public final TeleporterRule teleporter = TeleporterRule.forClass(getClass(), "SM_Teleporter");
+
+    private ResourceResolverFactory rrFactory;
+
+    private ModelFactory modelFactory;
+
+    private final String genericComponent = "/apps/delegate/nestedrtbound/generic";
+    private final String specificComponent = "/apps/delegate/nestedrtbound/specific";
+    private final String genericContent = "/content/delegate/nestedrtbound/generic";
+    private final String specificContent = "/content/delegate/nestedrtbound/specific";
+
+    @Before
+    @SuppressWarnings("null")
+    public void setup() throws LoginException, PersistenceException {
+        rrFactory = teleporter.getService(ResourceResolverFactory.class);
+        modelFactory = teleporter.getService(ModelFactory.class);
+        try (ResourceResolver adminResolver = rrFactory.getServiceResourceResolver(null); ) {
+
+            Map<String, Object> properties = new HashMap<String, Object>();
+            ResourceUtil.getOrCreateResource(adminResolver, genericComponent, properties, null, false);
+            properties.clear();
+
+            properties.put("sling:resourceSuperType", "delegate/nestedrtbound/generic");
+            ResourceUtil.getOrCreateResource(adminResolver, specificComponent, properties, null, false);
+            properties.clear();
+
+            properties.put("sling:resourceType", "delegate/nestedrtbound/generic");
+            ResourceUtil.getOrCreateResource(adminResolver, genericContent, properties, null, false);
+            properties.clear();
+
+            properties.put("sling:resourceType", "delegate/nestedrtbound/specific");
+            ResourceUtil.getOrCreateResource(adminResolver, specificContent, properties, null, false);
+            properties.clear();
+
+            adminResolver.commit();
+        }
+    }
+
+    @Test
+    public void testGenericModelFromRequest() throws LoginException {
+        try (ResourceResolver resolver = rrFactory.getServiceResourceResolver(null); ) {
+            final Resource content = resolver.getResource(genericContent);
+            final FakeRequest baseRequest = new FakeRequest(content);
+
+            final A model = modelFactory.createModel(baseRequest, A.class);
+            assertTrue(model instanceof AImpl);
+            assertTrue(((AImpl) model).other instanceof BImpl);
+        }
+    }
+
+    @Test
+    public void testSpecificModelFromRequest() throws LoginException {
+        try (ResourceResolver resolver = rrFactory.getServiceResourceResolver(null); ) {
+            final Resource content = resolver.getResource(specificContent);
+            final FakeRequest baseRequest = new FakeRequest(content);
+
+            final A model = modelFactory.createModel(baseRequest, A.class);
+            assertTrue(model instanceof A1Impl);
+            assertTrue(((A1Impl) model).other instanceof B1Impl);
+            assertTrue(((A1Impl) model).delegate instanceof AImpl);
+            assertTrue(((AImpl) ((A1Impl) model).delegate).other instanceof B1Impl);
+            // Since SLING-11133 and cache = true
+            assertSame(((A1Impl) model).other, ((AImpl) ((A1Impl) model).delegate).other);
+        }
+    }
+
+    @Test
+    public void testGenericModelFromResource() throws LoginException {
+        try (ResourceResolver resolver = rrFactory.getServiceResourceResolver(null); ) {
+            final Resource content = resolver.getResource(genericContent);
+
+            final A model = modelFactory.createModel(content, A.class);
+            assertTrue(model instanceof AImpl);
+            assertTrue(((AImpl) model).other instanceof BImpl);
+        }
+    }
+
+    @Test
+    public void testSpecificModelFromResource() throws LoginException {
+        try (ResourceResolver resolver = rrFactory.getServiceResourceResolver(null); ) {
+            final Resource content = resolver.getResource(specificContent);
+
+            final A model = modelFactory.createModel(content, A.class);
+            assertTrue(model instanceof A1Impl);
+            assertTrue(((A1Impl) model).other instanceof B1Impl);
+            assertTrue(((A1Impl) model).delegate instanceof AImpl);
+            assertTrue(((AImpl) ((A1Impl) model).delegate).other instanceof B1Impl);
+            // Since SLING-11133 and cache = true
+            assertSame(((A1Impl) model).other, ((AImpl) ((A1Impl) model).delegate).other);
+        }
+    }
+}
diff --git a/it/src/test/java/org/apache/sling/models/testing/exporter/ExporterIT.java b/it/src/test/java/org/apache/sling/models/testing/exporter/ExporterIT.java
new file mode 100644
index 0000000..4dae276
--- /dev/null
+++ b/it/src/test/java/org/apache/sling/models/testing/exporter/ExporterIT.java
@@ -0,0 +1,344 @@
+/*
+ * 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.testing.exporter;
+
+import javax.json.Json;
+import javax.json.JsonObject;
+
+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 org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.time.FastDateFormat;
+import org.apache.sling.api.SlingConstants;
+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.testing.helper.FakeRequest;
+import org.apache.sling.models.testing.helper.FakeResponse;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+
+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 Calendar testDate;
+
+    private Format dateFormat = FastDateFormat.getInstance("yyyy-MM-dd'T'HH:mm:ss.SSSZ", TimeZone.getTimeZone("UTC"));
+
+    @Before
+    @SuppressWarnings("null")
+    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(
+                    SlingConstants.NAMESPACE_PREFIX + ":" + SlingConstants.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(
+                    SlingConstants.NAMESPACE_PREFIX + ":" + SlingConstants.PROPERTY_RESOURCE_TYPE,
+                    "sling/exp-request/base");
+            ResourceUtil.getOrCreateResource(adminResolver, baseRequestComponentPath, properties, null, false);
+            properties.clear();
+
+            properties.put("sampleValue", "childTESTValue");
+            properties.put(
+                    SlingConstants.NAMESPACE_PREFIX + ":" + SlingConstants.PROPERTY_RESOURCE_TYPE, "sling/exp/child");
+            properties.put(
+                    SlingConstants.NAMESPACE_PREFIX + ":" + SlingConstants.PROPERTY_RESOURCE_SUPER_TYPE,
+                    "sling/exp/base");
+            ResourceUtil.getOrCreateResource(adminResolver, childComponentPath, properties, null, false);
+            properties.clear();
+
+            properties.put("sampleValue", "extendedTESTValue");
+            properties.put(
+                    SlingConstants.NAMESPACE_PREFIX + ":" + SlingConstants.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(
+                    SlingConstants.NAMESPACE_PREFIX + ":" + SlingConstants.PROPERTY_RESOURCE_TYPE,
+                    "sling/exp-request/extended");
+            ResourceUtil.getOrCreateResource(adminResolver, extendedRequestComponentPath, properties, null, false);
+            properties.clear();
+
+            properties.put("sampleValue", "interfaceTESTValue");
+            properties.put(
+                    SlingConstants.NAMESPACE_PREFIX + ":" + SlingConstants.PROPERTY_RESOURCE_TYPE,
+                    "sling/exp/interface");
+            ResourceUtil.getOrCreateResource(adminResolver, interfaceComponentPath, properties, null, false);
+
+            properties.put(
+                    SlingConstants.NAMESPACE_PREFIX + ":" + SlingConstants.PROPERTY_RESOURCE_TYPE,
+                    "sling/exp-request/interface");
+            ResourceUtil.getOrCreateResource(adminResolver, interfaceRequestComponentPath, properties, null, false);
+            properties.clear();
+
+            properties.put(
+                    SlingConstants.NAMESPACE_PREFIX + ":" + SlingConstants.PROPERTY_RESOURCE_TYPE, "sling/exp/doubled");
+            ResourceUtil.getOrCreateResource(adminResolver, doubledComponentPath, properties, null, false);
+
+            adminResolver.commit();
+        }
+    }
+
+    @Test
+    @SuppressWarnings("null")
+    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", StringUtils.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", StringUtils.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",
+                    StringUtils.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
+    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(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 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);
+    }
+}
diff --git a/it/src/test/java/org/apache/sling/models/testing/helper/FakeRequest.java b/it/src/test/java/org/apache/sling/models/testing/helper/FakeRequest.java
new file mode 100644
index 0000000..1290f8a
--- /dev/null
+++ b/it/src/test/java/org/apache/sling/models/testing/helper/FakeRequest.java
@@ -0,0 +1,400 @@
+/*
+ * 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.testing.helper;
+
+import javax.servlet.AsyncContext;
+import javax.servlet.DispatcherType;
+import javax.servlet.RequestDispatcher;
+import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
+import javax.servlet.ServletInputStream;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.Cookie;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+import javax.servlet.http.HttpUpgradeHandler;
+import javax.servlet.http.Part;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.security.Principal;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Locale;
+import java.util.Map;
+
+public class FakeRequest implements HttpServletRequest {
+
+    private final String path;
+
+    private final StringBuffer requestUrl;
+
+    private final Map<String, Object> attributes = new HashMap<String, Object>();
+
+    public FakeRequest(String path) {
+        this.path = path;
+        this.requestUrl = new StringBuffer("http://notarealhost").append(path);
+    }
+
+    @Override
+    public String getAuthType() {
+        return null;
+    }
+
+    @Override
+    public Cookie[] getCookies() {
+        return new Cookie[0];
+    }
+
+    @Override
+    public long getDateHeader(String name) {
+        return 0;
+    }
+
+    @Override
+    public String getHeader(String name) {
+        return null;
+    }
+
+    @Override
+    public Enumeration<String> getHeaders(String name) {
+        return null;
+    }
+
+    @Override
+    public Enumeration<String> getHeaderNames() {
+        return null;
+    }
+
+    @Override
+    public int getIntHeader(String name) {
+        return 0;
+    }
+
+    @Override
+    public String getMethod() {
+        return "GET";
+    }
+
+    @Override
+    public String getPathInfo() {
+        return path;
+    }
+
+    @Override
+    public String getPathTranslated() {
+        return null;
+    }
+
+    @Override
+    public String getContextPath() {
+        return null;
+    }
+
+    @Override
+    public String getQueryString() {
+        return null;
+    }
+
+    @Override
+    public String getRemoteUser() {
+        return null;
+    }
+
+    @Override
+    public boolean isUserInRole(String role) {
+        return false;
+    }
+
+    @Override
+    public Principal getUserPrincipal() {
+        return null;
+    }
+
+    @Override
+    public String getRequestedSessionId() {
+        return null;
+    }
+
+    @Override
+    public String getRequestURI() {
+        return null;
+    }
+
+    @Override
+    public StringBuffer getRequestURL() {
+        return requestUrl;
+    }
+
+    @Override
+    public String getServletPath() {
+        return "";
+    }
+
+    @Override
+    public HttpSession getSession(boolean create) {
+        return null;
+    }
+
+    @Override
+    public HttpSession getSession() {
+        return null;
+    }
+
+    @Override
+    public boolean isRequestedSessionIdValid() {
+        return false;
+    }
+
+    @Override
+    public boolean isRequestedSessionIdFromCookie() {
+        return false;
+    }
+
+    @Override
+    public boolean isRequestedSessionIdFromURL() {
+        return false;
+    }
+
+    @Override
+    public boolean isRequestedSessionIdFromUrl() {
+        return false;
+    }
+
+    @Override
+    public Object getAttribute(String name) {
+        return attributes.get(name);
+    }
+
+    @Override
+    public Enumeration<String> getAttributeNames() {
+        return null;
+    }
+
+    @Override
+    public String getCharacterEncoding() {
+        return null;
+    }
+
+    @Override
+    public void setCharacterEncoding(String env) throws UnsupportedEncodingException {}
+
+    @Override
+    public int getContentLength() {
+        return 0;
+    }
+
+    @Override
+    public String getContentType() {
+        return null;
+    }
+
+    @Override
+    public ServletInputStream getInputStream() throws IOException {
+        return null;
+    }
+
+    @Override
+    public String getParameter(String name) {
+        return null;
+    }
+
+    @Override
+    public Enumeration<String> getParameterNames() {
+        return null;
+    }
+
+    @Override
+    public String[] getParameterValues(String name) {
+        return new String[0];
+    }
+
+    @Override
+    public Map<String, String[]> getParameterMap() {
+        return Collections.emptyMap();
+    }
+
+    @Override
+    public String getProtocol() {
+        return null;
+    }
+
+    @Override
+    public String getScheme() {
+        return null;
+    }
+
+    @Override
+    public String getServerName() {
+        return null;
+    }
+
+    @Override
+    public int getServerPort() {
+        return 0;
+    }
+
+    @Override
+    public BufferedReader getReader() throws IOException {
+        return null;
+    }
+
+    @Override
+    public String getRemoteAddr() {
+        return null;
+    }
+
+    @Override
+    public String getRemoteHost() {
+        return null;
+    }
+
+    @Override
+    public void setAttribute(String name, Object o) {
+        attributes.put(name, o);
+    }
+
+    @Override
+    public void removeAttribute(String name) {
+        attributes.remove(name);
+    }
+
+    @Override
+    public Locale getLocale() {
+        return null;
+    }
+
+    @Override
+    public Enumeration<Locale> getLocales() {
+        return Collections.emptyEnumeration();
+    }
+
+    @Override
+    public boolean isSecure() {
+        return false;
+    }
+
+    @Override
+    public RequestDispatcher getRequestDispatcher(String path) {
+        return null;
+    }
+
+    @Override
+    public String getRealPath(String path) {
+        return null;
+    }
+
+    @Override
+    public int getRemotePort() {
+        return 0;
+    }
+
+    @Override
+    public String getLocalName() {
+        return null;
+    }
+
+    @Override
+    public String getLocalAddr() {
+        return null;
+    }
+
+    @Override
+    public int getLocalPort() {
+        return 0;
+    }
+
+    @Override
+    public long getContentLengthLong() {
+        return 0;
+    }
+
+    @Override
+    public ServletContext getServletContext() {
+        return null;
+    }
+
+    @Override
+    public AsyncContext startAsync() throws IllegalStateException {
+        return null;
+    }
+
+    @Override
+    public AsyncContext startAsync(ServletRequest servletRequest, ServletResponse servletResponse)
+            throws IllegalStateException {
+        return null;
+    }
+
+    @Override
+    public boolean isAsyncStarted() {
+        return false;
+    }
+
+    @Override
+    public boolean isAsyncSupported() {
+        return false;
+    }
+
+    @Override
+    public AsyncContext getAsyncContext() {
+        return null;
+    }
+
+    @Override
+    public DispatcherType getDispatcherType() {
+        return null;
+    }
+
+    @Override
+    public String changeSessionId() {
+        return null;
+    }
+
+    @Override
+    public boolean authenticate(HttpServletResponse response) throws IOException, ServletException {
+        return false;
+    }
+
+    @Override
+    public void login(String username, String password) throws ServletException {}
+
+    @Override
+    public void logout() throws ServletException {}
+
+    @Override
+    public Collection<Part> getParts() throws IOException, ServletException {
+        return null;
+    }
+
+    @Override
+    public Part getPart(String name) throws IOException, ServletException {
+        return null;
+    }
+
+    @Override
+    @SuppressWarnings("null")
+    public <T extends HttpUpgradeHandler> T upgrade(Class<T> handlerClass) throws IOException, ServletException {
+        return null;
+    }
+}
diff --git a/it/src/test/java/org/apache/sling/models/testing/helper/FakeResponse.java b/it/src/test/java/org/apache/sling/models/testing/helper/FakeResponse.java
new file mode 100644
index 0000000..fa474aa
--- /dev/null
+++ b/it/src/test/java/org/apache/sling/models/testing/helper/FakeResponse.java
@@ -0,0 +1,191 @@
+/*
+ * 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.testing.helper;
+
+import javax.servlet.ServletOutputStream;
+import javax.servlet.http.Cookie;
+import javax.servlet.http.HttpServletResponse;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.Collection;
+import java.util.Locale;
+
+public class FakeResponse implements HttpServletResponse {
+
+    private StringWriter stringWriter = new StringWriter();
+    private String contentType = null;
+    private String characterEncoding = null;
+    private int status = -1;
+
+    @Override
+    public void addCookie(Cookie cookie) {}
+
+    @Override
+    public boolean containsHeader(String name) {
+        return false;
+    }
+
+    @Override
+    public String encodeURL(String url) {
+        return null;
+    }
+
+    @Override
+    public String encodeRedirectURL(String url) {
+        return null;
+    }
+
+    @Override
+    public String encodeUrl(String url) {
+        return null;
+    }
+
+    @Override
+    public String encodeRedirectUrl(String url) {
+        return null;
+    }
+
+    @Override
+    public void sendError(int sc, String msg) throws IOException {}
+
+    @Override
+    public void sendError(int sc) throws IOException {}
+
+    @Override
+    public void sendRedirect(String location) throws IOException {}
+
+    @Override
+    public void setDateHeader(String name, long date) {}
+
+    @Override
+    public void addDateHeader(String name, long date) {}
+
+    @Override
+    public void setHeader(String name, String value) {}
+
+    @Override
+    public void addHeader(String name, String value) {}
+
+    @Override
+    public void setIntHeader(String name, int value) {}
+
+    @Override
+    public void addIntHeader(String name, int value) {}
+
+    @Override
+    public void setStatus(int sc) {
+        this.status = sc;
+    }
+
+    @Override
+    public void setStatus(int sc, String sm) {
+        setStatus(sc);
+    }
+
+    @Override
+    public String getCharacterEncoding() {
+        return characterEncoding;
+    }
+
+    @Override
+    public String getContentType() {
+        return contentType;
+    }
+
+    @Override
+    public ServletOutputStream getOutputStream() throws IOException {
+        return null;
+    }
+
+    @Override
+    public PrintWriter getWriter() throws IOException {
+        return new PrintWriter(stringWriter);
+    }
+
+    @Override
+    public void setCharacterEncoding(String charset) {
+        this.characterEncoding = charset;
+    }
+
+    @Override
+    public void setContentLength(int len) {}
+
+    @Override
+    public void setContentType(String type) {
+        this.contentType = type;
+    }
+
+    @Override
+    public void setBufferSize(int size) {}
+
+    @Override
+    public int getBufferSize() {
+        return 0;
+    }
+
+    @Override
+    public void flushBuffer() throws IOException {}
+
+    @Override
+    public void resetBuffer() {}
+
+    @Override
+    public boolean isCommitted() {
+        return false;
+    }
+
+    @Override
+    public void reset() {}
+
+    @Override
+    public void setLocale(Locale loc) {}
+
+    @Override
+    public Locale getLocale() {
+        return null;
+    }
+
+    public StringWriter getStringWriter() {
+        return stringWriter;
+    }
+
+    public int getStatus() {
+        return status;
+    }
+
+    @Override
+    public void setContentLengthLong(long len) {}
+
+    @Override
+    public String getHeader(String name) {
+        return null;
+    }
+
+    @Override
+    public Collection<String> getHeaders(String name) {
+        return null;
+    }
+
+    @Override
+    public Collection<String> getHeaderNames() {
+        return null;
+    }
+}
diff --git a/it/src/test/java/org/apache/sling/models/testing/rtbound/FakeRequest.java b/it/src/test/java/org/apache/sling/models/testing/rtbound/FakeRequest.java
new file mode 100644
index 0000000..56a8a78
--- /dev/null
+++ b/it/src/test/java/org/apache/sling/models/testing/rtbound/FakeRequest.java
@@ -0,0 +1,498 @@
+/*
+ * 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.testing.rtbound;
+
+import javax.servlet.AsyncContext;
+import javax.servlet.DispatcherType;
+import javax.servlet.RequestDispatcher;
+import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
+import javax.servlet.ServletInputStream;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.Cookie;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+import javax.servlet.http.HttpUpgradeHandler;
+import javax.servlet.http.Part;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.security.Principal;
+import java.util.Collection;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.ResourceBundle;
+
+import org.apache.sling.api.SlingHttpServletRequest;
+import org.apache.sling.api.request.RequestDispatcherOptions;
+import org.apache.sling.api.request.RequestParameter;
+import org.apache.sling.api.request.RequestParameterMap;
+import org.apache.sling.api.request.RequestPathInfo;
+import org.apache.sling.api.request.RequestProgressTracker;
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.api.resource.ResourceResolver;
+import org.jetbrains.annotations.NotNull;
+
+public class FakeRequest implements SlingHttpServletRequest {
+
+    private final Resource resource;
+    private final Map<String, Object> attributes = new HashMap<>();
+
+    public FakeRequest(Resource r) {
+        this.resource = r;
+    }
+
+    @Override
+    public @NotNull Resource getResource() {
+        return resource;
+    }
+
+    @Override
+    @SuppressWarnings("null")
+    public @NotNull ResourceResolver getResourceResolver() {
+        return null;
+    }
+
+    @Override
+    @SuppressWarnings("null")
+    public @NotNull RequestPathInfo getRequestPathInfo() {
+        return null;
+    }
+
+    @Override
+    public RequestParameter getRequestParameter(@NotNull String s) {
+        return null;
+    }
+
+    @Override
+    public RequestParameter[] getRequestParameters(@NotNull String s) {
+        return new RequestParameter[0];
+    }
+
+    @Override
+    @SuppressWarnings("null")
+    public @NotNull RequestParameterMap getRequestParameterMap() {
+        return null;
+    }
+
+    @Override
+    public RequestDispatcher getRequestDispatcher(
+            @NotNull String s, RequestDispatcherOptions requestDispatcherOptions) {
+        return null;
+    }
+
+    @Override
+    public RequestDispatcher getRequestDispatcher(
+            @NotNull Resource resource, RequestDispatcherOptions requestDispatcherOptions) {
+        return null;
+    }
+
+    @Override
+    public RequestDispatcher getRequestDispatcher(@NotNull Resource resource) {
+        return null;
+    }
+
+    @Override
+    public Cookie getCookie(String s) {
+        return null;
+    }
+
+    @Override
+    public String getResponseContentType() {
+        return null;
+    }
+
+    @Override
+    @SuppressWarnings("null")
+    public @NotNull Enumeration<String> getResponseContentTypes() {
+        return null;
+    }
+
+    @Override
+    public ResourceBundle getResourceBundle(Locale locale) {
+        return null;
+    }
+
+    @Override
+    public ResourceBundle getResourceBundle(String s, Locale locale) {
+        return null;
+    }
+
+    @Override
+    @SuppressWarnings("null")
+    public RequestProgressTracker getRequestProgressTracker() {
+        return null;
+    }
+
+    @Override
+    public String getAuthType() {
+        return null;
+    }
+
+    @Override
+    public Cookie[] getCookies() {
+        return new Cookie[0];
+    }
+
+    @Override
+    public long getDateHeader(String s) {
+        return 0;
+    }
+
+    @Override
+    public String getHeader(String s) {
+        return null;
+    }
+
+    @Override
+    public Enumeration<String> getHeaders(String s) {
+        return null;
+    }
+
+    @Override
+    public Enumeration<String> getHeaderNames() {
+        return null;
+    }
+
+    @Override
+    public int getIntHeader(String s) {
+        return 0;
+    }
+
+    @Override
+    public String getMethod() {
+        return null;
+    }
+
+    @Override
+    public String getPathInfo() {
+        return null;
+    }
+
+    @Override
+    public String getPathTranslated() {
+        return null;
+    }
+
+    @Override
+    public String getContextPath() {
+        return null;
+    }
+
+    @Override
+    public String getQueryString() {
+        return null;
+    }
+
+    @Override
+    public String getRemoteUser() {
+        return null;
+    }
+
+    @Override
+    public boolean isUserInRole(String s) {
+        return false;
+    }
+
+    @Override
+    public Principal getUserPrincipal() {
+        return null;
+    }
+
+    @Override
+    public String getRequestedSessionId() {
+        return null;
+    }
+
+    @Override
+    public String getRequestURI() {
+        return null;
+    }
+
+    @Override
+    public StringBuffer getRequestURL() {
+        return null;
+    }
+
+    @Override
+    public String getServletPath() {
+        return null;
+    }
+
+    @Override
+    public HttpSession getSession(boolean b) {
+        return null;
+    }
+
+    @Override
+    public HttpSession getSession() {
+        return null;
+    }
+
+    @Override
+    public boolean isRequestedSessionIdValid() {
+        return false;
+    }
+
+    @Override
+    public boolean isRequestedSessionIdFromCookie() {
+        return false;
+    }
+
+    @Override
+    public boolean isRequestedSessionIdFromURL() {
+        return false;
+    }
+
+    @Override
+    public boolean isRequestedSessionIdFromUrl() {
+        return false;
+    }
+
+    @Override
+    public Object getAttribute(String s) {
+        return attributes.get(s);
+    }
+
+    @Override
+    public Enumeration<String> getAttributeNames() {
+        return null;
+    }
+
+    @Override
+    public String getCharacterEncoding() {
+        return null;
+    }
+
+    @Override
+    public void setCharacterEncoding(String s) throws UnsupportedEncodingException {}
+
+    @Override
+    public int getContentLength() {
+        return 0;
+    }
+
+    @Override
+    public String getContentType() {
+        return null;
+    }
+
+    @Override
+    public ServletInputStream getInputStream() throws IOException {
+        return null;
+    }
+
+    @Override
+    public String getParameter(String s) {
+        return null;
+    }
+
+    @Override
+    public Enumeration<String> getParameterNames() {
+        return null;
+    }
+
+    @Override
+    public String[] getParameterValues(String s) {
+        return new String[0];
+    }
+
+    @Override
+    public Map<String, String[]> getParameterMap() {
+        return null;
+    }
+
+    @Override
+    public String getProtocol() {
+        return null;
+    }
+
+    @Override
+    public String getScheme() {
+        return null;
+    }
+
+    @Override
+    public String getServerName() {
+        return null;
+    }
+
+    @Override
+    public int getServerPort() {
+        return 0;
+    }
+
+    @Override
+    public BufferedReader getReader() throws IOException {
+        return null;
+    }
+
+    @Override
+    public String getRemoteAddr() {
+        return null;
+    }
+
+    @Override
+    public String getRemoteHost() {
+        return null;
+    }
+
+    @Override
+    public void setAttribute(String s, Object o) {
+        attributes.put(s, o);
+    }
+
+    @Override
+    public void removeAttribute(String s) {}
+
+    @Override
+    public Locale getLocale() {
+        return null;
+    }
+
+    @Override
+    public Enumeration<Locale> getLocales() {
+        return null;
+    }
+
+    @Override
+    public boolean isSecure() {
+        return false;
+    }
+
+    @Override
+    public RequestDispatcher getRequestDispatcher(String s) {
+        return null;
+    }
+
+    @Override
+    public String getRealPath(String s) {
+        return null;
+    }
+
+    @Override
+    public int getRemotePort() {
+        return 0;
+    }
+
+    @Override
+    public String getLocalName() {
+        return null;
+    }
+
+    @Override
+    public String getLocalAddr() {
+        return null;
+    }
+
+    @Override
+    public int getLocalPort() {
+        return 0;
+    }
+
+    @Override
+    @SuppressWarnings("null")
+    public <AdapterType> AdapterType adaptTo(@NotNull Class<AdapterType> aClass) {
+        return null;
+    }
+
+    @Override
+    public String changeSessionId() {
+        return null;
+    }
+
+    @Override
+    public boolean authenticate(HttpServletResponse response) throws IOException, ServletException {
+        return false;
+    }
+
+    @Override
+    public void login(String username, String password) throws ServletException {}
+
+    @Override
+    public void logout() throws ServletException {}
+
+    @Override
+    public Collection<Part> getParts() throws IOException, ServletException {
+        return null;
+    }
+
+    @Override
+    public Part getPart(String name) throws IOException, ServletException {
+        return null;
+    }
+
+    @Override
+    @SuppressWarnings("null")
+    public <T extends HttpUpgradeHandler> T upgrade(Class<T> handlerClass) throws IOException, ServletException {
+        return null;
+    }
+
+    @Override
+    public long getContentLengthLong() {
+        return 0;
+    }
+
+    @Override
+    public ServletContext getServletContext() {
+        return null;
+    }
+
+    @Override
+    public AsyncContext startAsync() throws IllegalStateException {
+        return null;
+    }
+
+    @Override
+    public AsyncContext startAsync(ServletRequest servletRequest, ServletResponse servletResponse)
+            throws IllegalStateException {
+        return null;
+    }
+
+    @Override
+    public boolean isAsyncStarted() {
+        return false;
+    }
+
+    @Override
+    public boolean isAsyncSupported() {
+        return false;
+    }
+
+    @Override
+    public AsyncContext getAsyncContext() {
+        return null;
+    }
+
+    @Override
+    public DispatcherType getDispatcherType() {
+        return null;
+    }
+
+    @Override
+    @SuppressWarnings("null")
+    public List<RequestParameter> getRequestParameterList() {
+        return null;
+    }
+}
diff --git a/it/src/test/java/org/apache/sling/models/testing/rtbound/ResourceTypeBindingIT.java b/it/src/test/java/org/apache/sling/models/testing/rtbound/ResourceTypeBindingIT.java
new file mode 100644
index 0000000..74ec330
--- /dev/null
+++ b/it/src/test/java/org/apache/sling/models/testing/rtbound/ResourceTypeBindingIT.java
@@ -0,0 +1,146 @@
+/*
+ * 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.testing.rtbound;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.sling.api.SlingConstants;
+import org.apache.sling.api.resource.LoginException;
+import org.apache.sling.api.resource.PersistenceException;
+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.junit.rules.TeleporterRule;
+import org.apache.sling.models.factory.ModelFactory;
+import org.apache.sling.models.it.rtbound.BaseComponent;
+import org.apache.sling.models.it.rtbound.ExtendedComponent;
+import org.apache.sling.models.it.rtbound.FromRequestComponent;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+
+public class ResourceTypeBindingIT {
+
+    @Rule
+    public final TeleporterRule teleporter = TeleporterRule.forClass(getClass(), "SM_Teleporter");
+
+    private ResourceResolverFactory rrFactory;
+
+    private ModelFactory modelFactory;
+
+    private final String baseComponentPath = "/content/rt/baseComponent";
+    private final String childComponentPath = "/content/rt/childComponent";
+    private final String child2ComponentPath = "/content/rt/child2Component";
+    private final String extendedComponentPath = "/content/rt/extendedComponent";
+    private final String fromRequestComponentPath = "/content/rt/fromRequest";
+
+    @Before
+    @SuppressWarnings("null")
+    public void setup() throws LoginException, PersistenceException {
+        rrFactory = teleporter.getService(ResourceResolverFactory.class);
+        modelFactory = teleporter.getService(ModelFactory.class);
+
+        try (ResourceResolver adminResolver = rrFactory.getServiceResourceResolver(null); ) {
+            Map<String, Object> properties = new HashMap<String, Object>();
+            properties.put("sampleValue", "baseTESTValue");
+            properties.put(
+                    SlingConstants.NAMESPACE_PREFIX + ":" + SlingConstants.PROPERTY_RESOURCE_TYPE, "sling/rt/base");
+            ResourceUtil.getOrCreateResource(adminResolver, baseComponentPath, properties, null, false);
+            properties.clear();
+
+            properties.put("sampleValue", "childTESTValue");
+            properties.put(
+                    SlingConstants.NAMESPACE_PREFIX + ":" + SlingConstants.PROPERTY_RESOURCE_TYPE, "sling/rt/child");
+            properties.put(
+                    SlingConstants.NAMESPACE_PREFIX + ":" + SlingConstants.PROPERTY_RESOURCE_SUPER_TYPE,
+                    "sling/rt/base");
+            ResourceUtil.getOrCreateResource(adminResolver, childComponentPath, properties, null, false);
+            properties.clear();
+
+            properties.put("sampleValue", "childTESTValue2");
+            properties.put(
+                    SlingConstants.NAMESPACE_PREFIX + ":" + SlingConstants.PROPERTY_RESOURCE_TYPE, "sling/rt/child");
+            ResourceUtil.getOrCreateResource(adminResolver, child2ComponentPath, properties, null, false);
+            properties.clear();
+
+            properties.put(
+                    SlingConstants.NAMESPACE_PREFIX + ":" + SlingConstants.PROPERTY_RESOURCE_SUPER_TYPE,
+                    "sling/rt/base");
+            ResourceUtil.getOrCreateResource(adminResolver, "/apps/sling/rt/child", properties, null, false);
+            properties.clear();
+
+            properties.put("sampleValue", "extendedTESTValue");
+            properties.put(
+                    SlingConstants.NAMESPACE_PREFIX + ":" + SlingConstants.PROPERTY_RESOURCE_TYPE, "sling/rt/extended");
+            ResourceUtil.getOrCreateResource(adminResolver, extendedComponentPath, properties, null, false);
+
+            properties.clear();
+            properties.put(
+                    SlingConstants.NAMESPACE_PREFIX + ":" + SlingConstants.PROPERTY_RESOURCE_TYPE,
+                    "sling/rt/fromRequest");
+            ResourceUtil.getOrCreateResource(adminResolver, fromRequestComponentPath, properties, null, false);
+
+            adminResolver.commit();
+        }
+    }
+
+    @Test
+    public void testClientModelCreateFromResource() throws LoginException {
+        try (ResourceResolver resolver = rrFactory.getServiceResourceResolver(null); ) {
+            final Resource baseComponentResource = resolver.getResource(baseComponentPath);
+            Assert.assertNotNull(baseComponentResource);
+            final Object baseModel = modelFactory.getModelFromResource(baseComponentResource);
+            Assert.assertNotNull("Model should not be null", baseModel);
+            Assert.assertTrue("Model should be a BaseComponent", baseModel instanceof BaseComponent);
+
+            final Resource childComponentResource = resolver.getResource(childComponentPath);
+            Assert.assertNotNull(childComponentResource);
+            final Object childModel = modelFactory.getModelFromResource(childComponentResource);
+            Assert.assertNotNull("Model should not be null", childModel);
+            Assert.assertTrue("Model should be a BaseComponent", childModel instanceof BaseComponent);
+
+            final Resource child2ComponentResource = resolver.getResource(child2ComponentPath);
+            Assert.assertNotNull(child2ComponentResource);
+            final Object child2Model = modelFactory.getModelFromResource(child2ComponentResource);
+            Assert.assertNotNull("Model should not be null", child2Model);
+            Assert.assertTrue("Model should be a BaseComponent", child2Model instanceof BaseComponent);
+
+            final Resource extendedComponentResource = resolver.getResource(extendedComponentPath);
+            Assert.assertNotNull(extendedComponentResource);
+            final Object extendedModel = modelFactory.getModelFromResource(extendedComponentResource);
+            Assert.assertNotNull("Model should not be null", extendedModel);
+            Assert.assertTrue("Model should be a BaseComponent", extendedModel instanceof BaseComponent);
+            Assert.assertTrue("Model should be an ExtendedComponent", extendedModel instanceof ExtendedComponent);
+        }
+    }
+
+    @Test
+    public void testClientModelCreateFromRequest() throws LoginException {
+        try (ResourceResolver resolver = rrFactory.getServiceResourceResolver(null); ) {
+            final Resource baseComponentResource = resolver.getResource(fromRequestComponentPath);
+            Assert.assertNotNull(baseComponentResource);
+            final Object baseModel = modelFactory.getModelFromRequest(new FakeRequest(baseComponentResource));
+            Assert.assertNotNull("Model should not be null", baseModel);
+            Assert.assertTrue("Model should be a FromRequestComponent", baseModel instanceof FromRequestComponent);
+        }
+    }
+}
diff --git a/it/src/test/java/org/apache/sling/models/testing/rtboundpicker/ResourceTypePickerIT.java b/it/src/test/java/org/apache/sling/models/testing/rtboundpicker/ResourceTypePickerIT.java
new file mode 100644
index 0000000..3faa6e9
--- /dev/null
+++ b/it/src/test/java/org/apache/sling/models/testing/rtboundpicker/ResourceTypePickerIT.java
@@ -0,0 +1,91 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.sling.models.testing.rtboundpicker;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.sling.api.SlingConstants;
+import org.apache.sling.api.resource.LoginException;
+import org.apache.sling.api.resource.PersistenceException;
+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.junit.rules.TeleporterRule;
+import org.apache.sling.models.it.rtboundpicker.BaseComponent;
+import org.apache.sling.models.it.rtboundpicker.SubRTComponent;
+import org.apache.sling.models.it.rtboundpicker.TestComponent;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+
+public class ResourceTypePickerIT {
+
+    @Rule
+    public final TeleporterRule teleporter = TeleporterRule.forClass(getClass(), "SM_Teleporter");
+
+    private ResourceResolverFactory rrFactory;
+
+    private final String baseComponentPath = "/content/rtpicker/baseComponent";
+    private final String childComponentPath = "/content/rtpicker/childComponent";
+
+    @Before
+    @SuppressWarnings("null")
+    public void setup() throws LoginException, PersistenceException {
+        rrFactory = teleporter.getService(ResourceResolverFactory.class);
+        try (ResourceResolver adminResolver = rrFactory.getServiceResourceResolver(null); ) {
+            Map<String, Object> properties = new HashMap<String, Object>();
+            properties.put(
+                    SlingConstants.NAMESPACE_PREFIX + ":" + SlingConstants.PROPERTY_RESOURCE_TYPE,
+                    "sling/rtpicker/base");
+            ResourceUtil.getOrCreateResource(adminResolver, baseComponentPath, properties, null, false);
+            properties.clear();
+
+            properties.put(
+                    SlingConstants.NAMESPACE_PREFIX + ":" + SlingConstants.PROPERTY_RESOURCE_TYPE,
+                    "sling/rtpicker/sub");
+            properties.put(
+                    SlingConstants.NAMESPACE_PREFIX + ":" + SlingConstants.PROPERTY_RESOURCE_SUPER_TYPE,
+                    "sling/rtpicker/base");
+            ResourceUtil.getOrCreateResource(adminResolver, childComponentPath, properties, null, false);
+            properties.clear();
+
+            adminResolver.commit();
+        }
+    }
+
+    @Test
+    public void testClientModelCreateFromResource() throws LoginException {
+        try (ResourceResolver resolver = rrFactory.getServiceResourceResolver(null); ) {
+            final Resource baseComponentResource = resolver.getResource(baseComponentPath);
+            Assert.assertNotNull(baseComponentResource);
+            TestComponent baseModel = baseComponentResource.adaptTo(TestComponent.class);
+            Assert.assertNotNull("Model should not be null", baseModel);
+            Assert.assertTrue("Model should be a BaseComponent", baseModel instanceof BaseComponent);
+
+            final Resource childComponentResource = resolver.getResource(childComponentPath);
+            Assert.assertNotNull(childComponentResource);
+            baseModel = childComponentResource.adaptTo(TestComponent.class);
+            Assert.assertNotNull("Model should not be null", baseModel);
+            Assert.assertTrue("Model should be a SubRTComponent", baseModel instanceof SubRTComponent);
+        }
+    }
+}
diff --git a/it/src/test/provisioning/sling-models-jacksonexporter.txt b/it/src/test/provisioning/sling-models-jacksonexporter.txt
new file mode 100644
index 0000000..a2a903d
--- /dev/null
+++ b/it/src/test/provisioning/sling-models-jacksonexporter.txt
@@ -0,0 +1,24 @@
+#
+#  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.
+#
+
+# must be the same feature name as the feature defined in slingstart to allow merging
+[feature name=models-jacksonexporter]
+
+[artifacts]
+    org.apache.sling/org.apache.sling.models.jacksonexporter
diff --git a/it/src/test/provisioning/sling.txt b/it/src/test/provisioning/sling.txt
new file mode 100644
index 0000000..d5d7e47
--- /dev/null
+++ b/it/src/test/provisioning/sling.txt
@@ -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.
+#
+
+# must be the same feature name as the feature defined in slingstart to allow merging
+[feature name=sling]
+
+[artifacts]
+    org.apache.sling/org.apache.sling.starter/11/slingstart
+
+    # Update to newer bundles required by sling models impl
+    org.osgi/org.osgi.util.converter/1.0.9
+    org.apache.sling/org.apache.sling.api/2.21.0
+    org.apache.sling/org.apache.sling.resourceresolver/1.6.16
+    org.apache.sling/org.apache.sling.servlets.resolver/2.5.8
+    org.apache.sling/org.apache.sling.scripting.core/2.1.0
+
+    # Use versions as defined in POM
+    org.apache.sling/org.apache.sling.models.api
+    org.apache.sling/org.apache.sling.models.impl
+
+    # Additional test bundles
+    org.apache.sling/org.apache.sling.junit.core
+    org.apache.sling/org.apache.sling.models.integration-tests
+
+[configurations]
+    # configure service user mapping for junit core (being used in the IT itself)
+    org.apache.sling.serviceusermapping.impl.ServiceUserMapperImpl.amended-junit
+        user.mapping=["org.apache.sling.junit.core\=models-it"]
+
+[:repoinit]
+    create service user models-it
+    set ACL for models-it
+        allow   jcr:all    on /
+    end
diff --git a/pom.xml b/pom.xml
index a7f30b4..df4c0df 100644
--- a/pom.xml
+++ b/pom.xml
@@ -35,5 +35,6 @@
     <modules>
         <module>parent</module>
         <module>impl</module>
+        <module>it</module>
     </modules>
 </project>