You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@juneau.apache.org by ja...@apache.org on 2026/06/10 14:18:37 UTC

(juneau) branch master updated: test: suppress Eclipse/SonarLint warnings on migrated TODO-160 tail tests

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

jamesbognar pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/juneau.git


The following commit(s) were added to refs/heads/master by this push:
     new 685d0b571f test: suppress Eclipse/SonarLint warnings on migrated TODO-160 tail tests
685d0b571f is described below

commit 685d0b571f561f2dbd9d422838708e1020188abf
Author: James Bognar <ja...@apache.org>
AuthorDate: Wed Jun 10 10:18:24 2026 -0400

    test: suppress Eclipse/SonarLint warnings on migrated TODO-160 tail tests
---
 README.md                                          |  11 +-
 .../juneau/commons/function/Function2_Test.java    |   1 -
 .../juneau/commons/function/Function3_Test.java    |   1 -
 .../juneau/commons/function/Function4_Test.java    |   1 -
 .../juneau/commons/function/Function5_Test.java    |   1 -
 .../juneau/commons/utils/AssertionUtils_Test.java  |   1 -
 .../juneau/commons/utils/CollectionUtils_Test.java |   1 -
 .../juneau/commons/utils/FileUtils_Test.java       |   1 -
 .../commons/utils/ResourceBundleUtils_Test.java    |   2 +-
 .../test/java/org/apache/juneau/BeanMap_Test.java  |   3 +-
 .../EncoderSet_OverridingBeanStore_Test.java       |   3 +
 .../org/apache/juneau/utils/ParserReaderTest.java  |   3 +
 juneau-distrib/pom.xml                             |  17 +-
 .../juneau-examples-rest-jetty-ftest/.gitignore    |   7 -
 .../logs/.gitignore                                |   1 -
 .../src/main/java/empty.txt                        |   0
 .../juneau/examples/rest/ContentComboTestBase.java | 116 --------
 .../apache/juneau/examples/rest/RestTestcase.java  |  40 ---
 .../juneau/examples/rest/RootContentTest.java      | 124 ---------
 .../juneau/examples/rest/RootResourcesTest.java    | 120 --------
 .../juneau/examples/rest/SamplesMicroservice.java  | 134 ---------
 .../org/apache/juneau/examples/rest/TestUtils.java | 250 -----------------
 .../apache/juneau/examples/rest/_TestSuite.java    |  49 ----
 .../juneau-examples-rest-jetty/.gitignore          |   7 -
 .../build-overlay/pom.xml                          | 167 -----------
 .../juneau-examples-rest-jetty.cfg                 | 209 --------------
 .../juneau-examples-rest-jetty.launch              |  17 --
 .../juneau-examples-rest-jetty/logs/.gitignore     |   1 -
 .../juneau-examples-rest-jetty/logs/empty.txt      |   0
 .../src/assembly/bin.xml                           |  62 -----
 .../juneau-examples-rest-springboot/.gitignore     |   7 -
 .../build-overlay/Procfile                         |   1 -
 .../build-overlay/app.json                         |   4 -
 .../build-overlay/pom.xml                          | 157 -----------
 .../juneau-examples-rest-springboot.launch         |  22 --
 .../juneau-examples-rest-springboot/settings.xml   |  50 ----
 .../juneau/examples/rest/springboot/App.java       |  92 ------
 .../examples/rest/springboot/RootResources.java    |  84 ------
 .../src/main/resources/juneau.cfg                  |  70 -----
 juneau-examples/juneau-examples-rest/.gitignore    |   6 -
 juneau-examples/juneau-examples-rest/pom.xml       | 118 --------
 .../src/main/java/META-INF/MANIFEST.MF             |   3 -
 .../apache/juneau/examples/rest/AdminGuard.java    |  32 ---
 .../juneau/examples/rest/HelloWorldResource.java   |  52 ----
 .../juneau/examples/rest/HtmlBeansResource.java    | 145 ----------
 .../juneau/examples/rest/PhotosResource.java       | 172 ------------
 .../juneau/examples/rest/RequestEchoResource.java  |  89 ------
 .../juneau/examples/rest/SseDemoResource.java      | 131 ---------
 .../juneau/examples/rest/UtilityBeansResource.java | 155 -----------
 .../juneau/examples/rest/command/EchoCommand.java  |  45 ---
 .../juneau/examples/rest/dto/AtomFeedResource.java | 142 ----------
 .../juneau/examples/rest/dto/DtoExamples.java      |  67 -----
 .../examples/rest/dto/JsonSchemaResource.java      | 118 --------
 .../examples/rest/AtomFeedResource_example.json    |  86 ------
 .../examples/rest/JsonSchemaResource_example.json  |  35 ---
 .../org/apache/juneau/examples/rest/htdocs/ok.png  | Bin 455 -> 0 bytes
 .../apache/juneau/examples/rest/htdocs/severe.png  | Bin 335 -> 0 bytes
 .../apache/juneau/examples/rest/htdocs/warning.png | Bin 444 -> 0 bytes
 .../petstore/rest/AddOrderMenuItem_beforeShow.js   |  32 ---
 .../rest/petstore/rest/PetStoreResource.json       |  75 -----
 .../rest/petstore/rest/htdocs/background.jpg       | Bin 105889 -> 0 bytes
 .../examples/rest/petstore/rest/htdocs/bird.png    | Bin 1925 -> 0 bytes
 .../examples/rest/petstore/rest/htdocs/cat.png     | Bin 1878 -> 0 bytes
 .../examples/rest/petstore/rest/htdocs/dog.png     | Bin 1980 -> 0 bytes
 .../examples/rest/petstore/rest/htdocs/fish.png    | Bin 2198 -> 0 bytes
 .../examples/rest/petstore/rest/htdocs/mouse.png   | Bin 1551 -> 0 bytes
 .../examples/rest/petstore/rest/htdocs/rabbit.png  | Bin 1603 -> 0 bytes
 .../examples/rest/petstore/rest/htdocs/snake.png   | Bin 1824 -> 0 bytes
 .../examples/rest/petstore/rest/photos/cat.jpg     | Bin 105889 -> 0 bytes
 juneau-examples/pom.xml                            |   4 -
 .../juneau-petstore-core}/pom.xml                  |  85 ++++--
 .../petstore/auth/StubBearerTokenValidator.java    |  75 +++++
 .../apache/juneau/petstore/auth}/package-info.java |  11 +-
 .../java/org/apache/juneau/petstore/dto/Order.java | 115 ++++++++
 .../apache/juneau/petstore/dto/OrderStatus.java    |  21 +-
 .../java/org/apache/juneau/petstore/dto/Pet.java   | 180 ++++++++++++
 .../org/apache/juneau/petstore/dto/PetStatus.java  |  21 +-
 .../org/apache/juneau/petstore/dto/Species.java    |  33 ++-
 .../java/org/apache/juneau/petstore/dto/User.java  | 181 ++++++++++++
 .../org/apache/juneau/petstore/dto/UserStatus.java |  18 +-
 .../apache/juneau/petstore/dto}/package-info.java  |   9 +-
 .../org/apache/juneau/petstore/package-info.java   |  34 +--
 .../petstore/rest/PetFreemarkerViewResource.java   |  82 ++++++
 .../petstore/rest/PetMustacheViewResource.java     |  91 ++++++
 .../juneau/petstore/rest/PetSecureResource.java    | 135 +++++++++
 .../juneau/petstore/rest/PetStoreResource.java     | 292 +++++++++++++++++++
 .../juneau/petstore/rest/PetstoreUiResource.java   |  51 ++++
 .../apache/juneau/petstore/rest}/package-info.java |   8 +-
 .../apache/juneau/petstore/service/PetStore.java   | 308 +++++++++++++++++++++
 .../service/PetstoreNotFoundException.java         |  22 +-
 .../juneau/petstore/service}/package-info.java     |   9 +-
 .../src/main/resources/htdocs/petstore-ui.html     | 104 +++++++
 .../src/main/resources/petstore-templates/pet.ftlh |  36 +--
 .../main/resources/petstore-templates/pet.mustache |  37 ++-
 .../src/main/resources}/petstore/init/Orders.json  |   0
 .../src/main/resources}/petstore/init/Pets.json    |   0
 .../src/main/resources}/petstore/init/Users.json   |   0
 .../rest/PetFreemarkerViewResource_Test.java       |  48 ++++
 .../rest/PetMustacheViewResource_Test.java         |  48 ++++
 .../petstore/rest/PetStoreResource_Test.java       | 143 ++++++++++
 .../petstore/rest/PetstoreUiResource_Test.java     |  48 ++++
 .../juneau/petstore/service/PetStore_Test.java     | 150 ++++++++++
 .../juneau-petstore-jetty.cfg                      | 266 ++++++++----------
 .../juneau-petstore-jetty}/pom.xml                 |  87 ++++--
 .../juneau-petstore-jetty}/src/assembly/bin.xml    |  28 +-
 .../org/apache/juneau/petstore}/jetty/App.java     |  21 +-
 .../juneau/petstore/jetty}/RootResources.java      |  51 ++--
 .../juneau/petstore}/jetty/package-info.java       |  11 +-
 .../src/main/resources/jetty.xml                   |  56 ++--
 .../microservice/MicroserviceTestFixture.java      | 199 +++++++++++++
 .../juneau/petstore/jetty/PetstoreJetty_Test.java  | 245 ++++++++++++++++
 .../testing/annotations/JettyMicroserviceTest.java |  19 +-
 .../juneau-petstore-springboot}/pom.xml            |  82 +++---
 .../org/apache/juneau/petstore/springboot/App.java |  98 +++++++
 .../petstore/springboot/HelloMessageProvider.java  |  17 +-
 .../juneau/petstore/springboot/HelloResource.java  |  40 ++-
 .../juneau/petstore/springboot/RootResources.java  |  88 ++++++
 .../juneau/petstore/springboot}/package-info.java  |  12 +-
 .../src/main/resources/application.properties      |   0
 .../springboot/PetstoreSpringboot_Test.java        | 241 ++++++++++++++++
 .../juneau/testing/annotations/SpringbootTest.java |  19 +-
 {juneau-examples => juneau-petstore}/pom.xml       |  19 +-
 juneau-release.sh                                  |   9 +-
 .../apache/juneau/mstat/MethodExecStore_Test.java  |   3 +
 .../org/apache/juneau/mstat/ThrownStore_Test.java  |   4 +-
 .../org/apache/juneau/utils/MethodInvokerTest.java |   3 +
 .../juneau-sc-server/juneau-server-config.cfg      |   2 +-
 juneau-sc/juneau-sc-server/pom.xml                 |   2 +-
 pom.xml                                            |   1 +
 scripts/apply-eclipse-prefs.py                     | 155 +++++++----
 .../source-prefs/org.eclipse.jdt.core.prefs        | 117 ++++++++
 .../source-prefs/org.eclipse.jdt.ui.prefs          |   5 +
 .../test-prefs/org.eclipse.jdt.core.prefs          | 117 ++++++++
 .../test-prefs/org.eclipse.jdt.ui.prefs            |   5 +
 scripts/release.py                                 |   6 +-
 ...mples-rest-jetty.py => start-petstore-jetty.py} |  65 ++---
 ...-springboot.py => start-petstore-springboot.py} |  61 ++--
 137 files changed, 3947 insertions(+), 3946 deletions(-)

diff --git a/README.md b/README.md
index ba37f8c725..cd838f5131 100644
--- a/README.md
+++ b/README.md
@@ -38,9 +38,7 @@
 * **[Framework Comparisons](https://juneau.apache.org/docs/topics/FrameworkComparisons)** - Compare Juneau with Jackson, Spring Boot, and JAX-RS
 * **[Examples](https://juneau.apache.org/docs/topics/JuneauExamplesCore)** - Code examples and tutorials
   * [juneau-examples-core](https://juneau.apache.org/docs/topics/JuneauExamplesCore) - Core serialization examples
-  * [juneau-examples-rest](https://juneau.apache.org/docs/topics/JuneauExamplesRest) - REST API examples
-  * [juneau-examples-rest-jetty](https://juneau.apache.org/docs/topics/JuneauExamplesRestJetty) - Jetty microservice examples
-  * [juneau-examples-rest-springboot](https://juneau.apache.org/docs/topics/JuneauExamplesRestSpringboot) - Spring Boot examples
+  * [juneau-petstore](https://juneau.apache.org/docs/topics/JuneauPetstoreOverview) - Canonical petstore showcase application (deployed under both Jetty/Microservice and Spring Boot)
 * **[Test Reports](https://juneau.apache.org/site/surefire.html)** - JUnit test execution results
 * **[Dependencies](https://juneau.apache.org/site/dependency-info.html)** - Project dependency analysis
 * **[Project Reports](https://juneau.apache.org/site/project-reports.html)** - Complete Maven site reports
@@ -288,10 +286,9 @@ Apache Juneau™ is a single cohesive Java ecosystem consisting of the following
 * **juneau-microservice** - Microservice API.
 * **juneau-microservice-jetty** - Jetty microservice API.
 * **juneau-examples-core** - Core code examples.
-* **juneau-examples-rest** - REST code examples.
-* **juneau-examples-rest-jetty** - Jetty microservice examples.
-* **juneau-examples-rest-springboot** - Spring Boot examples.
-* **juneau-petstore** - Complete REST application example.
+* **juneau-petstore-core** - Shared petstore domain + REST resources.
+* **juneau-petstore-jetty** - Jetty/Microservice deployment of the petstore.
+* **juneau-petstore-springboot** - Spring Boot deployment of the petstore.
 * **juneau-shaded** - Shaded (uber) JARs combining multiple Juneau modules for simplified dependency management, especially useful for Bazel builds. 
 
 Questions via email to dev@juneau.apache.org are always welcome.
diff --git a/juneau-core/juneau-commons/src/test/java/org/apache/juneau/commons/function/Function2_Test.java b/juneau-core/juneau-commons/src/test/java/org/apache/juneau/commons/function/Function2_Test.java
index 5a7a03f4e5..433a644134 100644
--- a/juneau-core/juneau-commons/src/test/java/org/apache/juneau/commons/function/Function2_Test.java
+++ b/juneau-core/juneau-commons/src/test/java/org/apache/juneau/commons/function/Function2_Test.java
@@ -16,7 +16,6 @@
  */
 package org.apache.juneau.commons.function;
 
-import static org.apache.juneau.commons.TestUtils.*;
 import static org.junit.jupiter.api.Assertions.*;
 
 import java.util.function.*;
diff --git a/juneau-core/juneau-commons/src/test/java/org/apache/juneau/commons/function/Function3_Test.java b/juneau-core/juneau-commons/src/test/java/org/apache/juneau/commons/function/Function3_Test.java
index a1a2961807..bfa2f8e04b 100644
--- a/juneau-core/juneau-commons/src/test/java/org/apache/juneau/commons/function/Function3_Test.java
+++ b/juneau-core/juneau-commons/src/test/java/org/apache/juneau/commons/function/Function3_Test.java
@@ -16,7 +16,6 @@
  */
 package org.apache.juneau.commons.function;
 
-import static org.apache.juneau.commons.TestUtils.*;
 import static org.junit.jupiter.api.Assertions.*;
 
 import java.util.function.*;
diff --git a/juneau-core/juneau-commons/src/test/java/org/apache/juneau/commons/function/Function4_Test.java b/juneau-core/juneau-commons/src/test/java/org/apache/juneau/commons/function/Function4_Test.java
index 238dabfe9e..bf59f23be7 100644
--- a/juneau-core/juneau-commons/src/test/java/org/apache/juneau/commons/function/Function4_Test.java
+++ b/juneau-core/juneau-commons/src/test/java/org/apache/juneau/commons/function/Function4_Test.java
@@ -16,7 +16,6 @@
  */
 package org.apache.juneau.commons.function;
 
-import static org.apache.juneau.commons.TestUtils.*;
 import static org.junit.jupiter.api.Assertions.*;
 
 import java.util.function.*;
diff --git a/juneau-core/juneau-commons/src/test/java/org/apache/juneau/commons/function/Function5_Test.java b/juneau-core/juneau-commons/src/test/java/org/apache/juneau/commons/function/Function5_Test.java
index c5a2e65d43..d5ccf200d9 100644
--- a/juneau-core/juneau-commons/src/test/java/org/apache/juneau/commons/function/Function5_Test.java
+++ b/juneau-core/juneau-commons/src/test/java/org/apache/juneau/commons/function/Function5_Test.java
@@ -16,7 +16,6 @@
  */
 package org.apache.juneau.commons.function;
 
-import static org.apache.juneau.commons.TestUtils.*;
 import static org.junit.jupiter.api.Assertions.*;
 
 import java.util.function.*;
diff --git a/juneau-core/juneau-commons/src/test/java/org/apache/juneau/commons/utils/AssertionUtils_Test.java b/juneau-core/juneau-commons/src/test/java/org/apache/juneau/commons/utils/AssertionUtils_Test.java
index 89c975526d..7cc535d3c5 100644
--- a/juneau-core/juneau-commons/src/test/java/org/apache/juneau/commons/utils/AssertionUtils_Test.java
+++ b/juneau-core/juneau-commons/src/test/java/org/apache/juneau/commons/utils/AssertionUtils_Test.java
@@ -16,7 +16,6 @@
  */
 package org.apache.juneau.commons.utils;
 
-import static org.apache.juneau.commons.TestUtils.*;
 import static org.apache.juneau.commons.utils.AssertionUtils.*;
 import static org.apache.juneau.commons.utils.CollectionUtils.*;
 import static org.junit.jupiter.api.Assertions.*;
diff --git a/juneau-core/juneau-commons/src/test/java/org/apache/juneau/commons/utils/CollectionUtils_Test.java b/juneau-core/juneau-commons/src/test/java/org/apache/juneau/commons/utils/CollectionUtils_Test.java
index a020b758e4..fae658e761 100644
--- a/juneau-core/juneau-commons/src/test/java/org/apache/juneau/commons/utils/CollectionUtils_Test.java
+++ b/juneau-core/juneau-commons/src/test/java/org/apache/juneau/commons/utils/CollectionUtils_Test.java
@@ -16,7 +16,6 @@
  */
 package org.apache.juneau.commons.utils;
 
-import static org.apache.juneau.commons.TestUtils.*;
 import static org.apache.juneau.commons.utils.CollectionUtils.*;
 import static org.apache.juneau.commons.TestAssertions.*;
 import static org.junit.jupiter.api.Assertions.*;
diff --git a/juneau-core/juneau-commons/src/test/java/org/apache/juneau/commons/utils/FileUtils_Test.java b/juneau-core/juneau-commons/src/test/java/org/apache/juneau/commons/utils/FileUtils_Test.java
index 84120a9429..bb96e5996c 100644
--- a/juneau-core/juneau-commons/src/test/java/org/apache/juneau/commons/utils/FileUtils_Test.java
+++ b/juneau-core/juneau-commons/src/test/java/org/apache/juneau/commons/utils/FileUtils_Test.java
@@ -16,7 +16,6 @@
  */
 package org.apache.juneau.commons.utils;
 
-import static org.apache.juneau.commons.TestUtils.*;
 import static org.junit.jupiter.api.Assertions.*;
 
 import java.io.*;
diff --git a/juneau-core/juneau-commons/src/test/java/org/apache/juneau/commons/utils/ResourceBundleUtils_Test.java b/juneau-core/juneau-commons/src/test/java/org/apache/juneau/commons/utils/ResourceBundleUtils_Test.java
index 1061e91589..f643ca388b 100644
--- a/juneau-core/juneau-commons/src/test/java/org/apache/juneau/commons/utils/ResourceBundleUtils_Test.java
+++ b/juneau-core/juneau-commons/src/test/java/org/apache/juneau/commons/utils/ResourceBundleUtils_Test.java
@@ -224,7 +224,7 @@ class ResourceBundleUtils_Test extends TestBase {
 			assertNotNull(direct);
 			assertNotNull(utils);
 			assertEquals(direct.getString("key1"), utils.getString("key1"));
-		} catch (MissingResourceException e) {
+		} catch (@SuppressWarnings("unused") MissingResourceException e) {
 			fail("Direct call should not throw for existing bundle");
 		}
 	}
diff --git a/juneau-core/juneau-marshall/src/test/java/org/apache/juneau/BeanMap_Test.java b/juneau-core/juneau-marshall/src/test/java/org/apache/juneau/BeanMap_Test.java
index 8d8ff651eb..b721ce02f7 100755
--- a/juneau-core/juneau-marshall/src/test/java/org/apache/juneau/BeanMap_Test.java
+++ b/juneau-core/juneau-marshall/src/test/java/org/apache/juneau/BeanMap_Test.java
@@ -42,7 +42,8 @@ import org.junit.jupiter.api.*;
 	"serial",
 	"java:S5961",
 	"java:S1186",
-	"unused" // Parameters retained for method-signature/functional-interface consistency in test fixtures.
+	"unused", // Parameters retained for method-signature/functional-interface consistency in test fixtures.
+	"unlikely-arg-type" // Intentionally tests containsKey() returns false for a wrong-typed key.
 })
 class BeanMap_Test extends TestBase {
 
diff --git a/juneau-core/juneau-marshall/src/test/java/org/apache/juneau/encoders/EncoderSet_OverridingBeanStore_Test.java b/juneau-core/juneau-marshall/src/test/java/org/apache/juneau/encoders/EncoderSet_OverridingBeanStore_Test.java
index 184e9b3197..8c037b463c 100644
--- a/juneau-core/juneau-marshall/src/test/java/org/apache/juneau/encoders/EncoderSet_OverridingBeanStore_Test.java
+++ b/juneau-core/juneau-marshall/src/test/java/org/apache/juneau/encoders/EncoderSet_OverridingBeanStore_Test.java
@@ -29,6 +29,9 @@ import org.junit.jupiter.api.*;
  * through to the builder's reflective bean lookups so test-time overrides win over the builder's
  * regular bean store entries.
  */
+@SuppressWarnings({
+	"resource" // Closeable resources in tests are intentionally unassigned; closing is handled by test infrastructure.
+})
 class EncoderSet_OverridingBeanStore_Test extends TestBase {
 
 	interface Marker {
diff --git a/juneau-core/juneau-marshall/src/test/java/org/apache/juneau/utils/ParserReaderTest.java b/juneau-core/juneau-marshall/src/test/java/org/apache/juneau/utils/ParserReaderTest.java
index 081d57ecf4..45d5d8c5ad 100755
--- a/juneau-core/juneau-marshall/src/test/java/org/apache/juneau/utils/ParserReaderTest.java
+++ b/juneau-core/juneau-marshall/src/test/java/org/apache/juneau/utils/ParserReaderTest.java
@@ -22,6 +22,9 @@ import org.apache.juneau.*;
 import org.apache.juneau.marshall.parser.*;
 import org.junit.jupiter.api.*;
 
+@SuppressWarnings({
+	"resource" // Closeable resources in tests are intentionally unassigned; closing is handled by test infrastructure.
+})
 class ParserReaderTest extends TestBase {
 
 	//====================================================================================================
diff --git a/juneau-distrib/pom.xml b/juneau-distrib/pom.xml
index 25b2362c4d..b41d5e35e1 100644
--- a/juneau-distrib/pom.xml
+++ b/juneau-distrib/pom.xml
@@ -894,26 +894,15 @@
 									<destFileName>apache-juneau-examples-core-${project.version}.zip</destFileName>
 								</artifactItem>
 
-								<!-- juneau-examples-rest-jetty -->
+								<!-- juneau-petstore-jetty -->
 								<artifactItem>
 									<outputDirectory>${project.build.directory}/bin/projects</outputDirectory>
 									<groupId>org.apache.juneau</groupId>
-									<artifactId>juneau-examples-rest-jetty</artifactId>
+									<artifactId>juneau-petstore-jetty</artifactId>
 									<classifier>bin</classifier>
 									<type>zip</type>
 									<version>${project.version}</version>
-									<destFileName>apache-juneau-examples-rest-jetty-${project.version}.zip</destFileName>
-								</artifactItem>
-
-								<!-- juneau-examples-springboot -->
-								<artifactItem>
-									<outputDirectory>${project.build.directory}/bin/projects</outputDirectory>
-									<groupId>org.apache.juneau</groupId>
-									<artifactId>juneau-examples-rest-springboot</artifactId>
-									<classifier>bin</classifier>
-									<type>zip</type>
-									<version>${project.version}</version>
-									<destFileName>apache-juneau-examples-rest-springboot-${project.version}.zip</destFileName>
+									<destFileName>apache-juneau-petstore-jetty-${project.version}.zip</destFileName>
 								</artifactItem>
 
 								<!-- juneau-my-springboot-microservice -->
diff --git a/juneau-examples/juneau-examples-rest-jetty-ftest/.gitignore b/juneau-examples/juneau-examples-rest-jetty-ftest/.gitignore
deleted file mode 100644
index 63826f18d5..0000000000
--- a/juneau-examples/juneau-examples-rest-jetty-ftest/.gitignore
+++ /dev/null
@@ -1,7 +0,0 @@
-/target/
-**/.DS_Store
-.classpath
-.project
-/.settings/
-/bin/
-/derby.log
diff --git a/juneau-examples/juneau-examples-rest-jetty-ftest/logs/.gitignore b/juneau-examples/juneau-examples-rest-jetty-ftest/logs/.gitignore
deleted file mode 100644
index bd317cc138..0000000000
--- a/juneau-examples/juneau-examples-rest-jetty-ftest/logs/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-/*log*
diff --git a/juneau-examples/juneau-examples-rest-jetty-ftest/src/main/java/empty.txt b/juneau-examples/juneau-examples-rest-jetty-ftest/src/main/java/empty.txt
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/juneau-examples/juneau-examples-rest-jetty-ftest/src/test/java/org/apache/juneau/examples/rest/ContentComboTestBase.java b/juneau-examples/juneau-examples-rest-jetty-ftest/src/test/java/org/apache/juneau/examples/rest/ContentComboTestBase.java
deleted file mode 100644
index f453b57d3c..0000000000
--- a/juneau-examples/juneau-examples-rest-jetty-ftest/src/test/java/org/apache/juneau/examples/rest/ContentComboTestBase.java
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.juneau.examples.rest;
-
-import static org.apache.juneau.commons.utils.CollectionUtils.*;
-import static org.apache.juneau.commons.utils.ThrowableUtils.*;
-import static org.apache.juneau.examples.rest.TestUtils.*;
-import static org.junit.runners.MethodSorters.*;
-
-import java.io.*;
-import java.util.*;
-import java.util.function.*;
-
-import org.apache.juneau.commons.http.*;
-import org.apache.juneau.marshall.csv.*;
-import org.apache.juneau.marshall.html.*;
-import org.apache.juneau.marshall.json.*;
-import org.apache.juneau.marshall.msgpack.*;
-import org.apache.juneau.marshall.parser.*;
-import org.apache.juneau.marshall.plaintext.*;
-import org.apache.juneau.marshall.serializer.*;
-import org.apache.juneau.marshall.uon.*;
-import org.apache.juneau.marshall.urlencoding.*;
-import org.apache.juneau.marshall.xml.*;
-import org.apache.juneau.rest.client.classic.*;
-import org.junit.*;
-
-@FixMethodOrder(NAME_ASCENDING)
-@Ignore("Base class for parameterized tests - not meant to be run directly")
-@SuppressWarnings({
-	"java:S3577", // Class name ends with "TestBase" to indicate it's a base class, not a test class itself
-	"resource" // RestClient lifecycle managed via the clients map and tearDown(); fluent API chains consume responses internally
-})
-public class ContentComboTestBase extends RestTestcase {
-
-	// Reusable RestClients keyed by label that live for the duration of a testcase class.
-	private static Map<String,RestClient> clients = map();
-
-	protected RestClient getClient(MediaType mediaType) {
-		var mt = mediaType.toString();
-		return switch (mt) {
-			case "text/csv" -> getClient(mt, CsvSerializer.DEFAULT, CsvParser.DEFAULT);
-			case "text/html" -> getClient(mt, HtmlSerializer.DEFAULT, HtmlParser.DEFAULT);
-			case "application/json" -> getClient(mt, JsonSerializer.DEFAULT, JsonParser.DEFAULT);
-			case "octal/msgpack" -> getClient(mt, MsgPackSerializer.DEFAULT, MsgPackParser.DEFAULT, x -> x.queryData("plainText", "true"));
-			case "text/plain" -> getClient(mt, PlainTextSerializer.DEFAULT, PlainTextParser.DEFAULT);
-			case "text/uon" -> getClient(mt, UonSerializer.DEFAULT, UonParser.DEFAULT);
-			case "application/x-www-form-urlencoded" -> getClient(mt, UrlEncodingSerializer.DEFAULT, UrlEncodingParser.DEFAULT);
-			case "text/xml" -> getClient(mt, XmlSerializer.DEFAULT, XmlParser.DEFAULT);
-			default -> throw rex("Client for mediaType ''{0}'' not found", mt);
-		};
-	}
-
-	@SafeVarargs
-	protected final RestClient getClient(String label, Serializer serializer, Parser parser, Consumer<RestClient.Builder<?>>...postApply) {
-		if (! clients.containsKey(label)) {
-			var b = SamplesMicroservice.client(serializer, parser);
-			for (var c : postApply)
-				c.accept(b);
-			clients.put(label, b.build());
-		}
-		return clients.get(label);
-	}
-
-	@AfterClass
-	public static void tearDown() {
-		clients.values().forEach(rc -> {
-			try {
-				rc.close();
-			} catch (IOException e) {
-				e.printStackTrace();
-			}
-		});
-		clients.clear();
-	}
-
-	public static class ComboInput {
-		public final String name, url;
-		public final MediaType mediaType;
-		public final String[] expectedResults;
-
-		public ComboInput(String name, String url, MediaType mediaType, String...expectedResults) {
-			this.name = name;
-			this.url = url;
-			this.mediaType = mediaType;
-			this.expectedResults = expectedResults;
-		}
-	}
-
-	private final ComboInput comboInput;
-
-	public ContentComboTestBase(ComboInput comboInput) {
-		this.comboInput = comboInput;
-	}
-
-	@Test
-	public void doTest() throws Exception {
-		var rc = getClient(comboInput.mediaType);
-		var s = rc.get(comboInput.url).run().getContent().asString();
-		assertContains(s, comboInput.expectedResults);
-	}
-}
\ No newline at end of file
diff --git a/juneau-examples/juneau-examples-rest-jetty-ftest/src/test/java/org/apache/juneau/examples/rest/RestTestcase.java b/juneau-examples/juneau-examples-rest-jetty-ftest/src/test/java/org/apache/juneau/examples/rest/RestTestcase.java
deleted file mode 100644
index 478d97d42c..0000000000
--- a/juneau-examples/juneau-examples-rest-jetty-ftest/src/test/java/org/apache/juneau/examples/rest/RestTestcase.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.juneau.examples.rest;
-
-import org.junit.*;
-
-/**
- * Superclass of REST testcases that start up the REST test microservice before running the tests locally.
- *
- * @author James Bognar (james.bognar@salesforce.com)
- */
-public class RestTestcase {
-
-	private static boolean microserviceStarted;
-
-	@BeforeClass
-	public static void setUp() {
-		microserviceStarted = SamplesMicroservice.startMicroservice();
-	}
-
-	@AfterClass
-	public static void tearDown() {
-		if (microserviceStarted)
-			SamplesMicroservice.stopMicroservice();
-	}
-}
\ No newline at end of file
diff --git a/juneau-examples/juneau-examples-rest-jetty-ftest/src/test/java/org/apache/juneau/examples/rest/RootContentTest.java b/juneau-examples/juneau-examples-rest-jetty-ftest/src/test/java/org/apache/juneau/examples/rest/RootContentTest.java
deleted file mode 100644
index c1e3967a85..0000000000
--- a/juneau-examples/juneau-examples-rest-jetty-ftest/src/test/java/org/apache/juneau/examples/rest/RootContentTest.java
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.juneau.examples.rest;
-
-import static org.apache.juneau.commons.utils.CollectionUtils.*;
-
-import java.util.*;
-
-import org.apache.juneau.commons.http.*;
-import org.junit.runner.*;
-import org.junit.runners.*;
-
-@RunWith(Parameterized.class)
-public class RootContentTest extends ContentComboTestBase {
-
-	@Parameterized.Parameters
-	public static Collection<Object[]> getParameters() {
-		// @formatter:off
-		return l(new Object[][] {
-			{ 	/* 0 */
-				new ComboInput("HTML-stylesheet", "/", MediaType.HTML,
-					"@import '/htdocs/themes/dark.css';",
-					".menu-item {"
-				)
-			},
-			{ 	/* 1 */
-				new ComboInput("HTML-stylesheet-contnt", "/htdocs/themes/devops.css", MediaType.PLAIN,
-					"/** DevOps look-and-feel */"
-				)
-			},
-			{ 	/* 2 */
-				new ComboInput("HTML-header", "/", MediaType.HTML,
-					"<head>",
-					"<h1>Root resources</h1>",
-					"<h2>Navigation page</h2>",
-					"<img src='/htdocs/images/juneau.png' style='position:absolute;top:5;right:5;background-color:transparent;height:30px'/>"
-				)
-			},
-			{ 	/* 3 */
-				new ComboInput("HTML-nav", "/", MediaType.HTML,
-					"<nav>",
-					"<a href='/api'>api</a>",
-					"<a onclick='menuClick(this);'>content-type</a>",
-					"<a href='https://github.com/apache/juneau/blob/master/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/RootResources.java'>source</a>"
-				)
-			},
-			{ 	/* 4 */
-				new ComboInput("HTML-nav-popup-contentType", "/", MediaType.HTML,
-					"<div class='popup-content'>",
-					"/?plainText=true&Accept=application%2Fjson"
-				)
-			},
-			{ 	/* 5 */
-				new ComboInput("HTML-aside", "/", MediaType.HTML,
-					"<aside>",
-					"<p>This is an example of a 'router' page that serves as a jumping-off point to child resources.</p>",
-					"<p>Other features (such as this aside) are added through annotations.</p>"
-				)
-			},
-			{ 	/* 6 */
-				new ComboInput("HTML-footer", "/", MediaType.HTML,
-					"<footer>",
-					"<img style='float:right;padding-right:20px;height:32px' src='/htdocs/images/asf.png'>"
-				)
-			},
-			{ 	/* 7 */
-				new ComboInput("HTML-content-text/html", "/", MediaType.HTML,
-					"<a href='/helloWorld'>helloWorld</a>",
-					"<td>Hello World</td>"
-				)
-			},
-			{ 	/* 8 */
-				new ComboInput("HTML-content-application/json", "/", MediaType.JSON,
-					"'name':'helloWorld',",
-					"'description':'Hello World'"
-				)
-			},
-			{ 	/* 9 */
-				new ComboInput("HTML-content-octal/msgpack", "/", MediaType.MSGPACK,
-					"82 A4 6E"
-				)
-			},
-			{ 	/* 10 */
-				new ComboInput("HTML-content-text/plain", "/", MediaType.PLAIN,
-					"Hello World"
-				)
-			},
-			{ 	/* 11 */
-				new ComboInput("HTML-content-text/uon", "/", MediaType.UON,
-					"(name=helloWorld,description='Hello World')"
-				)
-			},
-			{ 	/* 12 */
-				new ComboInput("HTML-content-application/x-www-form-urlencoded", "/", MediaType.URLENCODING,
-					"0=(name=helloWorld,description='Hello+World')"
-				)
-			},
-			{ 	/* 13 */
-				new ComboInput("HTML-content-text/xml", "/", MediaType.XML,
-					"<name>helloWorld</name><description>Hello World</description>"
-				)
-			}
-		});
-		// @formatter:on
-	}
-
-	public RootContentTest(ComboInput comboInput) {
-		super(comboInput);
-	}
-}
\ No newline at end of file
diff --git a/juneau-examples/juneau-examples-rest-jetty-ftest/src/test/java/org/apache/juneau/examples/rest/RootResourcesTest.java b/juneau-examples/juneau-examples-rest-jetty-ftest/src/test/java/org/apache/juneau/examples/rest/RootResourcesTest.java
deleted file mode 100644
index 6e3e627c5f..0000000000
--- a/juneau-examples/juneau-examples-rest-jetty-ftest/src/test/java/org/apache/juneau/examples/rest/RootResourcesTest.java
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.juneau.examples.rest;
-
-import static org.junit.Assert.*;
-import static org.junit.runners.MethodSorters.*;
-
-import org.apache.juneau.bean.swagger.*;
-import org.apache.juneau.marshall.collections.*;
-import org.apache.juneau.marshall.html.*;
-import org.apache.juneau.marshall.json5.*;
-import org.apache.juneau.rest.client.classic.*;
-import org.apache.juneau.rest.server.beans.*;
-import org.junit.*;
-
-@SuppressWarnings({
-	"resource" // RestClient lifecycle managed by SamplesMicroservice; fluent API chains consume and close responses internally
-})
-@FixMethodOrder(NAME_ASCENDING)
-public class RootResourcesTest extends RestTestcase {
-
-	private static boolean debug;
-
-	private RestClient jsonClient = SamplesMicroservice.defaultClient;
-
-	//====================================================================================================
-	// text/json
-	//====================================================================================================
-	@Test
-	public void testJson() throws Exception {
-		var client = SamplesMicroservice.defaultClient;
-
-		var x = client.get("").run().getContent().as(ResourceDescription[].class);
-		assertEquals("helloWorld", x[0].getName());
-		assertEquals("Hello World", x[0].getDescription());
-
-		var x2 = jsonClient.get("api").run().getContent().as(JsonMap.class);
-		var s = x2.getMap("info").getString("description");
-		if (debug)
-			System.err.println(s);
-		assertTrue(s, s.startsWith("Example of a router resource page"));
-	}
-
-	//====================================================================================================
-	// text/xml
-	//====================================================================================================
-	@Test
-	public void testXml() throws Exception {
-		try (var client = SamplesMicroservice.client().xml().build()) {
-
-			var x = client.get("").run().getContent().as(ResourceDescription[].class);
-			assertEquals("helloWorld", x[0].getName());
-			assertEquals("Hello World", x[0].getDescription());
-
-			var x2 = jsonClient.get("api").run().getContent().as(JsonMap.class);
-			var s = x2.getMap("info").getString("description");
-			if (debug)
-				System.err.println(s);
-			assertTrue(s, s.startsWith("Example of a router resource page"));
-		}
-	}
-
-	//====================================================================================================
-	// text/html+stripped
-	//====================================================================================================
-	@Test
-	public void testHtmlStripped() throws Exception {
-		try (RestClient client = SamplesMicroservice.client().parsers(HtmlParser.DEFAULT).accept("text/html+stripped").build()) {
-
-			var x = client.get("").run().getContent().as(ResourceDescription[].class);
-			assertEquals("helloWorld", x[0].getName());
-			assertEquals("Hello World", x[0].getDescription());
-
-			var x2 = jsonClient.get("api").run().getContent().as(JsonMap.class);
-			var s = x2.getMap("info").getString("description");
-			if (debug)
-				System.err.println(s);
-			assertTrue(s, s.startsWith("Example of a router resource page"));
-		}
-	}
-
-	//====================================================================================================
-	// application/json+schema
-	//====================================================================================================
-	@Test
-	public void testJsonSchema() throws Exception {
-		try (RestClient client = SamplesMicroservice.client().parsers(Json5Parser.DEFAULT).accept("text/json+schema").build()) {
-			var m = client.get("").run().getContent().as(JsonMap.class);
-			assertNotNull(m);
-			if (debug)
-				System.err.println(m);
-			client.closeQuietly();
-		}
-	}
-
-	//====================================================================================================
-	// OPTIONS page
-	//====================================================================================================
-	@Test
-	public void testOptionsPage() throws Exception {
-		Swagger o = jsonClient.get("api").run().getContent().as(Swagger.class);
-		if (debug)
-			System.err.println(o);
-		assertEquals("Example of a router resource page.", o.getInfo().getDescription());
-	}
-}
\ No newline at end of file
diff --git a/juneau-examples/juneau-examples-rest-jetty-ftest/src/test/java/org/apache/juneau/examples/rest/SamplesMicroservice.java b/juneau-examples/juneau-examples-rest-jetty-ftest/src/test/java/org/apache/juneau/examples/rest/SamplesMicroservice.java
deleted file mode 100644
index 9569ac8310..0000000000
--- a/juneau-examples/juneau-examples-rest-jetty-ftest/src/test/java/org/apache/juneau/examples/rest/SamplesMicroservice.java
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.juneau.examples.rest;
-
-import java.net.*;
-import java.util.*;
-
-import org.apache.juneau.commons.inject.*;
-import org.apache.juneau.marshall.parser.*;
-import org.apache.juneau.marshall.serializer.*;
-import org.apache.juneau.microservice.*;
-import org.apache.juneau.microservice.jetty.*;
-import org.apache.juneau.rest.client.classic.*;
-
-import jakarta.servlet.*;
-
-/**
- * Utility class for starting up the examples microservice.
- */
-@SuppressWarnings({
-	"resource"  // Closeable resources in tests are intentionally unassigned; closing is handled by test infrastructure.
-})
-public class SamplesMicroservice {
-	static volatile Microservice microservice;
-	static URI microserviceURI;
-
-	// Reusable HTTP clients that get created and shut down with the microservice.
-	public static RestClient defaultClient;
-	public static RestClient defaultClientPlaintext;
-
-	/**
-	 * Starts the microservice.
-	 * @return <jk>true</jk> if the service started, <jk>false</jk> if it's already started.
-	 * If this returns <jk>false</jk> then don't call stopMicroservice()!.
-	 */
-	public static synchronized boolean startMicroservice() {
-		if (microservice != null)
-			return false;
-		try {
-			Locale.setDefault(Locale.US);
-			microservice = Microservice.create().workingDir("../juneau-examples-rest-jetty").configName("juneau-examples-rest-jetty.cfg").configurations(JettyConfiguration.class, AppConfig.class).build();
-			microserviceURI = microservice.start().getBeanStore().getBean(JettyServerComponent.class).orElseThrow().getURI();
-			defaultClient = client().json5().build();
-			defaultClientPlaintext = client().plainText().build();
-			return true;
-		} catch (Throwable e) {
-			// Probably already started.
-			e.printStackTrace();
-			System.err.println(e); // NOT DEBUG
-			return false;
-		}
-	}
-
-	/**
-	 * Returns the URI of the microservice.
-	 * @return The URI of the microservice.
-	 */
-	public static URI getURI() {
-		if (microservice == null)
-			startMicroservice();
-		return microserviceURI;
-	}
-
-	/**
-	 * Stops the microservice.
-	 */
-	public static synchronized void stopMicroservice() {
-		try {
-			microservice.stop();
-			microservice = null;
-			defaultClient.closeQuietly();
-			defaultClientPlaintext.closeQuietly();
-		} catch (Exception e) {
-			System.err.println(e); // NOT DEBUG
-		}
-	}
-
-	/**
-	 * Create a new HTTP client.
-	 */
-	public static RestClient.Builder<?> client() {
-		try {
-			return RestClient.create().rootUrl(microserviceURI);
-		} catch (Exception e) {
-			throw new IllegalStateException(e);
-		}
-	}
-
-	/**
-	 * Create a new HTTP client using the specified serializer and parser.
-	 */
-	public static RestClient.Builder<?> client(Serializer s, Parser p) {
-		return client().serializer(s).parser(p);
-	}
-
-	/**
-	 * Create a new HTTP client using the specified serializer and parser.
-	 */
-	public static RestClient.Builder<?> client(Class<? extends Serializer> s, Class<? extends Parser> p) {
-		return client().serializer(s).parser(p);
-	}
-
-	/**
-	 * Application configuration contributing the {@link RootResources} servlet.
-	 */
-	@Configuration
-	public static class AppConfig {
-
-		/**
-		 * Provides the top-level REST servlet, auto-mounted by {@link JettyServerComponent} at
-		 * {@link org.apache.juneau.rest.server.Rest#path()}.
-		 *
-		 * @return The root servlet.
-		 */
-		@Bean
-		public Servlet rootResources() {
-			return new RootResources();
-		}
-	}
-}
\ No newline at end of file
diff --git a/juneau-examples/juneau-examples-rest-jetty-ftest/src/test/java/org/apache/juneau/examples/rest/TestUtils.java b/juneau-examples/juneau-examples-rest-jetty-ftest/src/test/java/org/apache/juneau/examples/rest/TestUtils.java
deleted file mode 100644
index e46c13285c..0000000000
--- a/juneau-examples/juneau-examples-rest-jetty-ftest/src/test/java/org/apache/juneau/examples/rest/TestUtils.java
+++ /dev/null
@@ -1,250 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.juneau.examples.rest;
-
-import static org.apache.juneau.commons.utils.IoUtils.*;
-import static org.apache.juneau.commons.utils.StringUtils.*;
-
-import java.io.*;
-import java.util.regex.*;
-
-import org.apache.juneau.marshall.json.*;
-import org.apache.juneau.marshall.json5.*;
-import org.apache.juneau.marshall.serializer.*;
-import org.apache.juneau.marshall.xml.*;
-import org.junit.*;
-
-public class TestUtils {
-
-	// @formatter:off
-	private static JsonSerializer js = Json5Serializer.create()
-		.keepNullProperties()
-		.build();
-
-	private static JsonSerializer jsSorted = Json5Serializer.create()
-		.sortCollections()
-		.sortMaps()
-		.keepNullProperties()
-		.build();
-
-	private static JsonSerializer js2 = Json5Serializer.create()
-		.build();
-
-	private static JsonSerializer js3 = Json5Serializer.create()
-		
-		.build();
-	// @formatter:on
-
-	/**
-	 * Verifies that two objects are equivalent.
-	 * Does this by doing a string comparison after converting both to JSON.
-	 */
-	public static void assertEqualObjects(Object o1, Object o2) throws SerializeException {
-		assertEqualObjects(o1, o2, false);
-	}
-
-	/**
-	 * Verifies that two objects are equivalent.
-	 * Does this by doing a string comparison after converting both to JSON.
-	 * @param sort If <jk>true</jk> sort maps and collections before comparison.
-	 */
-	public static void assertEqualObjects(Object o1, Object o2, boolean sort) throws SerializeException {
-		var s = (sort ? jsSorted : js);
-		var s1 = s.serialize(o1);
-		var s2 = s.serialize(o2);
-		if (s1.equals(s2))
-			return;
-		throw new ComparisonFailure(null, s1, s2);
-	}
-
-	/**
-	 * Validates that the whitespace is correct in the specified XML.
-	 */
-	public static void checkXmlWhitespace(String out) throws SerializeException {
-		if (out.indexOf('\u0000') != -1) {
-			for (var s : out.split("\u0000"))
-				checkXmlWhitespace(s);
-			return;
-		}
-
-		int indent = -1;
-		var startTag = Pattern.compile("^(\\s*)<[^/>]+(\\s+\\S+=['\"]\\S*['\"])*\\s*>$");
-		var endTag = Pattern.compile("^(\\s*)</[^>]+>$");
-		var combinedTag = Pattern.compile("^(\\s*)<[^>/]+(\\s+\\S+=['\"]\\S*['\"])*\\s*/>$");
-		var contentOnly = Pattern.compile("^(\\s*)[^\\s\\<]+$");
-		var tagWithContent = Pattern.compile("^(\\s*)<[^>]+>.*</[^>]+>$");
-		var lines = out.split("\n");
-		try {
-			for (var i = 0; i < lines.length; i++) {
-				var line = lines[i];
-				var m = startTag.matcher(line);
-				if (m.matches()) {
-					indent++;
-					if (m.group(1).length() != indent)
-						throw new SerializeException("Wrong indentation detected on start tag line ''{0}''", i + 1);
-					continue;
-				}
-				m = endTag.matcher(line);
-				if (m.matches()) {
-					if (m.group(1).length() != indent)
-						throw new SerializeException("Wrong indentation detected on end tag line ''{0}''", i + 1);
-					indent--;
-					continue;
-				}
-				m = combinedTag.matcher(line);
-				if (m.matches()) {
-					indent++;
-					if (m.group(1).length() != indent)
-						throw new SerializeException("Wrong indentation detected on combined tag line ''{0}''", i + 1);
-					indent--;
-					continue;
-				}
-				m = contentOnly.matcher(line);
-				if (m.matches()) {
-					indent++;
-					if (m.group(1).length() != indent)
-						throw new SerializeException("Wrong indentation detected on content-only line ''{0}''", i + 1);
-					indent--;
-					continue;
-				}
-				m = tagWithContent.matcher(line);
-				if (m.matches()) {
-					indent++;
-					if (m.group(1).length() != indent)
-						throw new SerializeException("Wrong indentation detected on tag-with-content line ''{0}''", i + 1);
-					indent--;
-					continue;
-				}
-				throw new SerializeException("Unmatched whitespace line at line number ''{0}''", i + 1);
-			}
-			if (indent != -1)
-				throw new SerializeException("Possible unmatched tag.  indent=''{0}''", indent);
-		} catch (SerializeException e) {
-			printLines(lines);
-			throw e;
-		}
-	}
-
-	private static void printLines(String[] lines) {
-		for (var i = 0; i < lines.length; i++)
-			System.err.println(String.format("%4s:%s", i + 1, lines[i]));  // NOT DEBUG
-	}
-
-	public static void validateXml(Object o) throws Exception {
-		validateXml(o, XmlSerializer.DEFAULT_NS_SQ);
-	}
-
-	/**
-	 * Test whitespace and generated schema.
-	 */
-	public static void validateXml(Object o, XmlSerializer s) throws Exception {
-		s = s.copy().ws().ns().addNamespaceUrisToRoot().build();
-		var xml = s.serialize(o);
-
-		try {
-			TestUtils.checkXmlWhitespace(xml);
-		} catch (Exception e) {
-			System.err.println("---XML---");  // NOT DEBUG
-			System.err.println(xml);  // NOT DEBUG
-			throw e;
-		}
-	}
-
-	public static String readFile(String p) throws Exception {
-		var is = TestUtils.class.getResourceAsStream(p);
-		if (is == null) {
-			is = new FileInputStream(p);
-		}
-		try (InputStream is2 = is) {
-			var e = read(is2);
-			e = e.replaceAll("\r", "");
-			return e;
-		}
-	}
-
-	protected static final char[] hexArray = "0123456789ABCDEF".toCharArray();
-
-	public static String toHex(byte b) {
-		var c = new char[2];
-		var v = b & 0xFF;
-		c[0] = hexArray[v >>> 4];
-		c[1] = hexArray[v & 0x0F];
-		return new String(c);
-	}
-
-	public static void debugOut(Object o) {
-		try {
-			System.err.println(decodeHex(Json5Serializer.DEFAULT.serialize(o)));  // NOT DEBUG
-		} catch (SerializeException e) {
-			e.printStackTrace();
-		}
-	}
-
-	/**
-	 * Assert that the object equals the specified string after running it through Json5Serializer.DEFAULT.toString().
-	 */
-	public static void assertObjectEquals(String s, Object o) {
-		assertObjectEquals(s, o, js2);
-	}
-
-	/**
-	 * Assert that the object equals the specified string after running it through Json5Serializer.DEFAULT.toString().
-	 */
-	public static void assertSortedObjectEquals(String s, Object o) {
-		assertObjectEquals(s, o, js3);
-	}
-
-	/**
-	 * Assert that the object equals the specified string after running it through ws.toString().
-	 */
-	public static void assertObjectEquals(String s, Object o, WriterSerializer ws) {
-		Assert.assertEquals(s, ws.toString(o));
-	}
-
-	/**
-	 * Replaces all newlines with pipes, then compares the strings.
-	 */
-	public static void assertTextEquals(String s, Object o) {
-		var s2 = o.toString().replaceAll("\\r?\\n", "|");
-		Assert.assertEquals(s, s2);
-	}
-
-	/**
-	 * Tries to turn the serialized output to a String.
-	 * If it's a byte[], convert it to a UTF-8 encoded String.
-	 */
-	public static final String toString(Object o) {
-		if (o == null)
-			return null;
-		if (o instanceof String)
-			return (String)o;
-		if (o instanceof byte[])
-			return new String((byte[])o, UTF8);
-		return o.toString();
-	}
-
-	public static final void assertContains(Object value, String...substrings) {
-		for (var substring : substrings)
-			if (! contains(toString(value), substring)) {
-				System.err.println("Text did not contain expected substring: '" + toString(substring) + "'");  // NOT DEBUG
-				System.err.println("=== TEXT ===");  // NOT DEBUG
-				System.err.println(toString(value));  // NOT DEBUG
-				System.err.println("============");  // NOT DEBUG
-				throw new ComparisonFailure("Text did not contain expected substring.", toString(substring), toString(value));  // NOT DEBUG
-			}
-	}
-}
\ No newline at end of file
diff --git a/juneau-examples/juneau-examples-rest-jetty-ftest/src/test/java/org/apache/juneau/examples/rest/_TestSuite.java b/juneau-examples/juneau-examples-rest-jetty-ftest/src/test/java/org/apache/juneau/examples/rest/_TestSuite.java
deleted file mode 100644
index 04f33b0a1b..0000000000
--- a/juneau-examples/juneau-examples-rest-jetty-ftest/src/test/java/org/apache/juneau/examples/rest/_TestSuite.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.juneau.examples.rest;
-
-import org.junit.*;
-import org.junit.runner.*;
-import org.junit.runners.*;
-import org.junit.runners.Suite.*;
-
-/**
- * Runs all the testcases in this project.
- * Starts a REST service running org.apache.juneau.marshall.examples.rest.RootResources on port 10000.
- * Stops the REST service after running the tests.
- */
-@RunWith(Suite.class)
-// @formatter:off
-@SuiteClasses({
-	RootResourcesTest.class,
-	RootContentTest.class
-})
-// @formatter:on
-public class _TestSuite {
-
-	@BeforeClass
-	public static void setUp() {
-		double version = Double.parseDouble(System.getProperty("java.specification.version"));
-		Assume.assumeFalse("Java version " + version + " detected.  Tests will be skipped.", version < 1.8);
-		SamplesMicroservice.startMicroservice();
-	}
-
-	@AfterClass
-	public static void tearDown() {
-		SamplesMicroservice.stopMicroservice();
-	}
-}
\ No newline at end of file
diff --git a/juneau-examples/juneau-examples-rest-jetty/.gitignore b/juneau-examples/juneau-examples-rest-jetty/.gitignore
deleted file mode 100644
index 63826f18d5..0000000000
--- a/juneau-examples/juneau-examples-rest-jetty/.gitignore
+++ /dev/null
@@ -1,7 +0,0 @@
-/target/
-**/.DS_Store
-.classpath
-.project
-/.settings/
-/bin/
-/derby.log
diff --git a/juneau-examples/juneau-examples-rest-jetty/build-overlay/pom.xml b/juneau-examples/juneau-examples-rest-jetty/build-overlay/pom.xml
deleted file mode 100644
index 3354f6dffd..0000000000
--- a/juneau-examples/juneau-examples-rest-jetty/build-overlay/pom.xml
+++ /dev/null
@@ -1,167 +0,0 @@
-<?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.
--->
-<!--
-	This project is meant to be used as a starting point for developers to use in creating their own REST microservices.
-	It creates a parent REST interface on port 10000 with a single child hello-world resource.
-	This POM is likewise meant to be used as a starting point for developers. It creates an uber-jar
-	to run the microserice from the command line. Copy the jar as well as the .cfg file and start it
-	with java -jar juneau-microservice-template-1.0.0.jar microservice.cfg
-	The group/artifact/version information is meant to be overwritten by developers to match their own needs.
--->
-<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
-	
-	<modelVersion>4.0.0</modelVersion>
-
-	<groupId>org.apache.juneau.examples</groupId>
-	<artifactId>juneau-examples-rest-jetty</artifactId>
-	<name>Apache Juneau REST Examples</name>
-	<version>${version}</version>
-	<description>Sample code packaged as a microservice.</description>
-
-	<properties>
-		<encoding>UTF-8</encoding>
-		<maven.compiler.source>17</maven.compiler.source>
-		<maven.compiler.target>17</maven.compiler.target>
-		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
-		<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
-
-		<derby.version>${derby.version}</derby.version>
-		<springboot.version>${springboot.version}</springboot.version>
-		<juneau.version>${version}</juneau.version>
-		<junit.version>${junit.version}</junit.version>
-		<xml.apis.version>${xml.apis.version}</xml.apis.version>
-	</properties>
-
-	<dependencies>
-
-		<!-- Juneau artifacts -->	
-		<dependency>
-			<groupId>org.apache.juneau</groupId>
-			<artifactId>juneau-microservice-jetty</artifactId>
-			<version>\${juneau.version}</version>
-		</dependency>
-
-		<!-- Optional RDF support -->
-		<dependency>
-			<groupId>org.apache.juneau</groupId>
-			<artifactId>juneau-marshall</artifactId>
-			<version>\${juneau.version}</version>
-		</dependency>
-
-		<!-- Used for JPA persistence of beans -->
-		<dependency>
-			<groupId>org.apache.derby</groupId>
-			<artifactId>derby</artifactId>
-			<version>\${derby.version}</version>
-		</dependency>
-		<dependency>
-			<groupId>xml-apis</groupId>
-			<artifactId>xml-apis</artifactId>
-			<version>\${xml.apis.version}</version>
-		</dependency>
-
-		<!-- Other -->		
-		<dependency>
-			<groupId>org.junit.vintage</groupId>
-			<artifactId>junit-vintage-engine</artifactId>
-			<version>${junit.version}</version>
-			<scope>test</scope>
-		</dependency>
-
-	</dependencies>
-
-	<build>
-		<plugins>
-
-			<plugin>
-				<artifactId>maven-compiler-plugin</artifactId>
-				<configuration>
-					<source>17</source>
-					<target>17</target>
-				</configuration>
-			</plugin>
-
-			<plugin>
-				<groupId>org.apache.maven.plugins</groupId>
-				<artifactId>maven-resources-plugin</artifactId>
-				<version>3.0.2</version>
- 				<executions>
-					<execution>
-						<id>package-config</id>
-						<phase>package</phase>
-						<goals>
-							<goal>copy-resources</goal>
-						</goals>
-						<configuration>
-							<outputDirectory>target</outputDirectory>
-							<resources>
-								<resource>
-									<directory>.</directory>
-									<includes>examples.cfg</includes>
-								</resource>
-							</resources>
-						</configuration>
-					</execution>
-				</executions>
-			</plugin>
-
-			<plugin>
-				<groupId>org.apache.maven.plugins</groupId>
-				<artifactId>maven-jar-plugin</artifactId>
-				<configuration>
-					<archive>
-						<manifest>
-							<mainClass>org.apache.juneau.examples.rest.jetty.App
-							</mainClass>
-						</manifest>
-					</archive>
-				</configuration>
-			</plugin>
-
-			<plugin>
-				<groupId>org.apache.maven.plugins</groupId>
-				<artifactId>maven-shade-plugin</artifactId>
-				<configuration>
-					<createDependencyReducedPom>false</createDependencyReducedPom>
-				</configuration>
-				<executions>
-					<execution>
-						<phase>package</phase>
-						<goals>
-							<goal>shade</goal>
-						</goals>
-						<configuration>
-							<filters>
-								<filter>
-									<artifact>*:*</artifact>
-									<excludes>
-										<exclude>META-INF/*.SF</exclude>
-										<exclude>META-INF/*.RSA</exclude>
-										<exclude>META-INF/*.INF</exclude> <!-- This one may not be required -->
-									</excludes>
-								</filter>
-							</filters>
-						</configuration>
-					</execution>
-				</executions>
-			</plugin>
-
-		</plugins>
-	</build>
-
-</project>
diff --git a/juneau-examples/juneau-examples-rest-jetty/juneau-examples-rest-jetty.cfg b/juneau-examples/juneau-examples-rest-jetty/juneau-examples-rest-jetty.cfg
deleted file mode 100755
index f5d4f1ba92..0000000000
--- a/juneau-examples/juneau-examples-rest-jetty/juneau-examples-rest-jetty.cfg
+++ /dev/null
@@ -1,209 +0,0 @@
-# ***************************************************************************************************************************
-# * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
-# * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
-# * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
-# * with the License.  You may obtain a copy of the License at                                                              * 
-# *                                                                                                                         *
-# *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
-# *                                                                                                                         *
-# * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
-# * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
-# * specific language governing permissions and limitations under the License.                                              *
-# ***************************************************************************************************************************
-
-#=======================================================================================================================
-# Basic configuration file for SaaS microservices
-# Subprojects can use this as a starting point.
-#=======================================================================================================================
-
-
-#=======================================================================================================================
-# Jetty settings
-#=======================================================================================================================
-[Jetty]
-
-# Path of the jetty.xml file used to configure the Jetty server.
-config = files/jetty.xml
-
-# Resolve Juneau variables in the jetty.xml file.
-resolveVars = true
-
-# Port to use for the jetty server.
-# You can specify multiple ports.  The first available will be used.  '0' indicates to try a random port.
-# The resulting available port gets set as the system property "availablePort" which can be referenced in the 
-# jetty.xml file as "$S{availablePort}" (assuming resolveVars is enabled).
-port = 10000,0,0,0
-
-#=======================================================================================================================
-# REST settings
-#=======================================================================================================================
-[REST]
-
-# Comma-delimited list of key-value pairs that represent locations of static files that can be served up by your @Rest-annotated
-# classes.  These are static files that are served up by the servlet under the specified sub-paths.
-# For example, given the following setting...
-# 	staticFiles = htdocs:my-docs,styles/my-styles
-# ...the URI "/servletPath/htdocs/javadoc.css" resolves to the path "/my-docs/javadoc.css".
-# This path can be relative to the working directory, classpath root, or package of your resource class.
-# Used by the BasicRestConfig interface that defines the following value:
-# 	staticFiles="$C{REST/staticFiles}"
-staticFiles = htdocs:htdocs
-
-# Stylesheet to use for HTML views.
-# Used by the BasicRestConfig interface that defines the following value:
-# 	stylesheet="$C{REST/theme,servlet:/htdocs/themes/devops.css}"
-theme = servlet:/htdocs/themes/dark.css
-
-# Various look-and-feel settings used in the BasicRestConfig interface.
-headerIcon = servlet:/htdocs/images/juneau.png
-headerLink = http://juneau.apache.org
-footerIcon = servlet:/htdocs/images/asf.png
-footerLink = http://www.apache.org
-favicon = $C{REST/headerIcon}
-head = <link rel='icon' href='$U{$C{REST/favicon}}'/>
-header = 
-	<a href='$U{$C{REST/headerLink}}'>
-		<img src='$U{$C{REST/headerIcon}}' style='position:absolute;top:5;right:5;background-color:transparent;height:30px'/>
-	</a>
-footer = 
-	<a href='$U{$C{REST/footerLink}}'>
-		<img style='float:right;padding-right:20px;height:32px' src='$U{$C{REST/footerIcon}}'>
-	</a>
-
-#=======================================================================================================================
-# Console settings
-#=======================================================================================================================
-[Console]
-
-enabled = true
-
-# List of available console commands.
-# These are classes that implements ConsoleCommand that allow you to submit commands to the microservice via
-# the console.
-# When listed here, the implementations must provide a no-arg constructor.
-# They can also be provided dynamically by overriding the Microservice.createConsoleCommands() method.
-commands = 
-	org.apache.juneau.marshall.microservice.console.ExitCommand,
-	org.apache.juneau.marshall.microservice.console.RestartCommand,
-	org.apache.juneau.marshall.microservice.console.HelpCommand,
-	org.apache.juneau.marshall.microservice.console.ConfigCommand,
-	org.apache.juneau.marshall.examples.rest.command.EchoCommand
-
-#=======================================================================================================================
-# Logger settings
-#-----------------------------------------------------------------------------------------------------------------------
-# See FileHandler Java class for details.
-#=======================================================================================================================
-[Logging]
-
-# The directory where to create the log file.
-# Default is "."
-logDir = ./target/logs
-
-# The name of the log file to create for the main logger.
-# The logDir and logFile make up the pattern that's passed to the FileHandler
-# constructor.
-# If value is not specified, then logging to a file will not be set up.
-logFile = microservice.%g.log
-
-# Whether to append to the existing log file or create a new one.
-append = false
-
-# The SimpleDateFormat format to use for dates.
-dateFormat = yyyy.MM.dd hh:mm:ss
-
-# The log message format.
-# The value can contain any of the following variables:
-# 	{date} - The date, formatted per dateFormat.
-#	{class} - The class name.
-#	{method} - The method name.
-#	{logger} - The logger name.
-#	{level} - The log level name.
-#	{msg} - The log message.
-#	{threadid} - The thread ID.
-#	{exception} - The localized exception message.
-format = [{date} {level}] {msg}%n
-
-# The maximum log file size.
-# Suffixes available for numbers.
-# See Config.getInt(String,int) for details.
-limit = 1M
-
-# Max number of log files.
-count = 5
-
-# Default log levels.
-# Format is lax-JSON.
-# Keys are logger names.
-# Values are serialized Level POJOs (SEVERE, WARNING, INFO, CONFIG, FINE, FINER, FINEST)
-levels = 
-	{ 
-		'': 'WARNING', 
-		org.apache.juneau.marshall: 'WARNING', 
-		org.eclipse.jetty: 'WARNING' 
-	}
-
-# Only print unique stack traces once and then refer to them by a simple 8 character hash identifier.
-# Useful for preventing log files from filling up with duplicate stack traces.
-useStackTraceHashes = true
-
-# The default level for the console logger.
-# Values are serialized Level POJOs (SEVERE, WARNING, INFO, CONFIG, FINE, FINER, FINEST)
-consoleLevel = WARNING
-
-# The default level for the file logger.
-# Values are serialized Level POJOs (SEVERE, WARNING, INFO, CONFIG, FINE, FINER, FINEST)
-# Default is INFO.
-fileLevel = INFO
-
-#=======================================================================================================================
-# System properties
-#-----------------------------------------------------------------------------------------------------------------------
-# These are arbitrary system properties that can be set during startup.
-#=======================================================================================================================
-[SystemProperties]
-
-# Configure Jetty for StdErrLog Logging
-# org.eclipse.jetty.util.log.class = org.eclipse.jetty.util.log.StrErrLog
-
-# Configure Jetty to log using java-util logging
-org.eclipse.jetty.util.log.class = org.apache.juneau.marshall.microservice.jetty.JettyLogger
-
-# Jetty logging level
-org.eclipse.jetty.LEVEL = WARN
-
-derby.stream.error.file = $C{Logging/logDir}/derby-errors.log
-
-# Note that any configuration properties can also be set globally as system properties...
-
-# Disable classpath resource caching.
-# Useful if you're attached using a debugger and you're modifying classpath resources while running.
-RestContext.disableClasspathResourceCaching.b = true
-
-#=======================================================================================================================
-# DockerRegistryResource properties
-#=======================================================================================================================
-[DockerRegistry]
-url = http://docker.apache.org:5000/v1
-
-#=======================================================================================================================
-# SqlQueryResource properties
-#=======================================================================================================================
-[SqlQueryResource]
-driver = org.apache.derby.jdbc.EmbeddedDriver
-directory = target/derby/testDB
-connectionUrl = jdbc:derby:$C{SqlQueryResource/directory};create=true
-allowTempUpdates = true
-includeRowNums = false
-
-#=======================================================================================================================
-# Source code location
-#=======================================================================================================================
-[Source]
-gitHub = https://github.com/apache/juneau/blob/master/juneau-examples/juneau-examples-rest/src/main/java
-
-#=======================================================================================================================
-# PetStoreResource properties
-#=======================================================================================================================
-[PetStore]
-headerImage = <a href='http://swagger.io'><img src='$U{servlet:/htdocs/cat.png}' style='position:absolute;top:5;right:5;background-color:transparent;height:30px'/></a>
diff --git a/juneau-examples/juneau-examples-rest-jetty/juneau-examples-rest-jetty.launch b/juneau-examples/juneau-examples-rest-jetty/juneau-examples-rest-jetty.launch
deleted file mode 100644
index 7439aeb75f..0000000000
--- a/juneau-examples/juneau-examples-rest-jetty/juneau-examples-rest-jetty.launch
+++ /dev/null
@@ -1,17 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<launchConfiguration type="org.eclipse.jdt.launching.localJavaApplication">
-    <listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS">
-        <listEntry value="/juneau-examples-rest-jetty/src/main/java/org/apache/juneau/examples/rest/jetty/App.java"/>
-    </listAttribute>
-    <listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES">
-        <listEntry value="1"/>
-    </listAttribute>
-    <booleanAttribute key="org.eclipse.jdt.debug.ui.CONSIDER_INHERITED_MAIN" value="true"/>
-    <booleanAttribute key="org.eclipse.jdt.debug.ui.INCLUDE_EXTERNAL_JARS" value="true"/>
-    <booleanAttribute key="org.eclipse.jdt.launching.ATTR_USE_START_ON_FIRST_THREAD" value="true"/>
-    <stringAttribute key="org.eclipse.jdt.launching.CLASSPATH_PROVIDER" value="org.eclipse.m2e.launchconfig.classpathProvider"/>
-    <stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value="org.apache.juneau.marshall.examples.rest.jetty.App"/>
-    <stringAttribute key="org.eclipse.jdt.launching.MODULE_NAME" value="juneau-examples-rest-jetty"/>
-    <stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="juneau-examples-rest-jetty"/>
-    <stringAttribute key="org.eclipse.jdt.launching.SOURCE_PATH_PROVIDER" value="org.eclipse.m2e.launchconfig.sourcepathProvider"/>
-</launchConfiguration>
diff --git a/juneau-examples/juneau-examples-rest-jetty/logs/.gitignore b/juneau-examples/juneau-examples-rest-jetty/logs/.gitignore
deleted file mode 100644
index bd317cc138..0000000000
--- a/juneau-examples/juneau-examples-rest-jetty/logs/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-/*log*
diff --git a/juneau-examples/juneau-examples-rest-jetty/logs/empty.txt b/juneau-examples/juneau-examples-rest-jetty/logs/empty.txt
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/juneau-examples/juneau-examples-rest-jetty/src/assembly/bin.xml b/juneau-examples/juneau-examples-rest-jetty/src/assembly/bin.xml
deleted file mode 100644
index af351a1eed..0000000000
--- a/juneau-examples/juneau-examples-rest-jetty/src/assembly/bin.xml
+++ /dev/null
@@ -1,62 +0,0 @@
-<?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.
--->
-
-<!--
-	This assembly is used to create the template zip file that developers use to import into Eclipse to start their
-	own projects.
- -->
-<assembly
-	xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3"
-	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-	xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3 https://maven.apache.org/xsd/assembly-1.1.3.xsd">
-	<id>bin</id>
-	<formats>
-		<format>zip</format>
-	</formats>
-	<baseDirectory>/</baseDirectory>
-	<includeBaseDirectory>true</includeBaseDirectory>
-	<fileSets>
-		<fileSet>
-			<directory>${basedir}/../juneau-examples-rest</directory>
-			<outputDirectory>/</outputDirectory>
-			<includes>
-				<include>src/main/**</include>
-			</includes>
-		</fileSet>
-		<fileSet>
-			<useDefaultExcludes>false</useDefaultExcludes>
-			<directory>${basedir}</directory>
-			<outputDirectory>/</outputDirectory>
-			<includes>
-				<include>src/main/**</include>
-				<include>files/**</include>
-				<include>.settings/**</include>
-				<include>.project</include>
-				<include>.classpath</include>
-				<include>*.launch</include>
-				<include>*.cfg</include>
-			</includes>
-		</fileSet>
-		<fileSet>
-			<directory>${basedir}/build-overlay</directory>
-			<outputDirectory>/</outputDirectory>
-			<filtered>true</filtered>
-		</fileSet>
-	</fileSets>
-	
-</assembly>
\ No newline at end of file
diff --git a/juneau-examples/juneau-examples-rest-springboot/.gitignore b/juneau-examples/juneau-examples-rest-springboot/.gitignore
deleted file mode 100644
index 63826f18d5..0000000000
--- a/juneau-examples/juneau-examples-rest-springboot/.gitignore
+++ /dev/null
@@ -1,7 +0,0 @@
-/target/
-**/.DS_Store
-.classpath
-.project
-/.settings/
-/bin/
-/derby.log
diff --git a/juneau-examples/juneau-examples-rest-springboot/build-overlay/Procfile b/juneau-examples/juneau-examples-rest-springboot/build-overlay/Procfile
deleted file mode 100644
index 992aac92f1..0000000000
--- a/juneau-examples/juneau-examples-rest-springboot/build-overlay/Procfile
+++ /dev/null
@@ -1 +0,0 @@
-web: java -jar target/juneau-examples-rest-springboot-${version}.jar
\ No newline at end of file
diff --git a/juneau-examples/juneau-examples-rest-springboot/build-overlay/app.json b/juneau-examples/juneau-examples-rest-springboot/build-overlay/app.json
deleted file mode 100644
index 85040f0b28..0000000000
--- a/juneau-examples/juneau-examples-rest-springboot/build-overlay/app.json
+++ /dev/null
@@ -1,4 +0,0 @@
-{
-  "name": "Start on Heroku: Juneau REST Examples",
-  "description": "Deployable REST examples to Heroku."
-}
diff --git a/juneau-examples/juneau-examples-rest-springboot/build-overlay/pom.xml b/juneau-examples/juneau-examples-rest-springboot/build-overlay/pom.xml
deleted file mode 100644
index 8beafaace1..0000000000
--- a/juneau-examples/juneau-examples-rest-springboot/build-overlay/pom.xml
+++ /dev/null
@@ -1,157 +0,0 @@
-<?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.
--->
-<!--
-	This project is meant to be used as a starting point for developers to use in creating their own REST microservices.
-	It creates a Spring Boot application on port 5000 populated with the Juneau REST examples.
-	This POM is likewise meant to be used as a starting point for developers. It creates an uber-jar
-	to run the microservice from the command line. 
-	
-	Copy the jar as well as the my-microservice.cfg and jetty.xml file and start it with: 
-		java -jar juneau-examples-rest-springboot-1.0.jar
-		
-	The group/artifact/version information is meant to be overwritten by developers to match their own needs.
--->
-<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
-	
-	<modelVersion>4.0.0</modelVersion>
-
-	<groupId>org.apache.juneau.examples</groupId>
-	<artifactId>juneau-examples-rest-springboot</artifactId>
-	<name>Apache Juneau REST Examples</name>
-	<version>${version}</version>
-	<description>REST examples packaged as a Spring Boot microservice.</description>
-
-	<parent>
-		<groupId>org.springframework.boot</groupId>
-		<artifactId>spring-boot-starter-parent</artifactId>
-		<version>2.4.2</version>
-		<relativePath />
-	</parent>
-
-	<properties>
-		<encoding>UTF-8</encoding>
-		<maven.compiler.source>17</maven.compiler.source>
-		<maven.compiler.target>17</maven.compiler.target>
-		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
-		<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
-
-		<juneau.version>${version}</juneau.version>
-		<springboot.version>2.4.2</springboot.version>
-	</properties>
-
-	<dependencies>
-
-		<!-- Juneau artifacts -->	
-		<dependency>
-			<groupId>org.apache.juneau</groupId>
-			<artifactId>juneau-all</artifactId>
-			<version>\${juneau.version}</version>
-		</dependency>
-		<dependency>
-			<groupId>org.apache.juneau</groupId>
-			<artifactId>juneau-marshall</artifactId>
-			<version>\${juneau.version}</version>
-		</dependency>
-		<dependency>
-			<groupId>org.apache.juneau</groupId>
-			<artifactId>juneau-microservice</artifactId>
-			<version>\${juneau.version}</version>
-		</dependency>
-		<dependency>
-			<groupId>org.apache.juneau</groupId>
-			<artifactId>juneau-rest-server-springboot</artifactId>
-			<version>\${juneau.version}</version>
-		</dependency>
-
-		<!-- Spring Boot dependencies-->
-		<dependency>
-			<groupId>org.springframework.boot</groupId>
-			<artifactId>spring-boot-starter-web</artifactId>
-			<exclusions>
-				<exclusion>
-					<groupId>org.springframework.boot</groupId>
-					<artifactId>spring-boot-starter-logging</artifactId>
-				</exclusion>
-			</exclusions>
-		</dependency>
-
-		<!-- Used for JPA persistence of beans -->
-		<dependency>
-			<groupId>org.apache.derby</groupId>
-			<artifactId>derby</artifactId>
-		</dependency>
-		<dependency>
-		    <groupId>xml-apis</groupId>
-		    <artifactId>xml-apis</artifactId>
-		</dependency>
-		
-		<dependency>
-			<groupId>org.slf4j</groupId>
-			<artifactId>slf4j-api</artifactId>
-			<version>1.7.5</version>
-		</dependency>
-
-		<dependency>
-			<groupId>org.slf4j</groupId>
-			<artifactId>slf4j-log4j12</artifactId>
-			<version>1.7.5</version>
-		</dependency>
-
-	</dependencies>
-
-	<build>
-		<plugins>
-
-			<plugin>
-				<groupId>org.springframework.boot</groupId>
-				<artifactId>spring-boot-maven-plugin</artifactId>
-				<version>${springboot.version}</version>
-				<executions>
-					<execution>
-						<goals>
-							<goal>build-info</goal>
-						</goals>
-						<configuration>
-							<additionalProperties>
-								<encoding.source>\${project.build.sourceEncoding}</encoding.source>
-								<encoding.reporting>\${project.reporting.outputEncoding}</encoding.reporting>
-								<java.source>\${maven.compiler.source}</java.source>
-								<java.target>\${maven.compiler.target}</java.target>
-							</additionalProperties>
-						</configuration>
-					</execution>
-				</executions>
-			</plugin>
-
-			<plugin>
-				<groupId>org.apache.maven.plugins</groupId>
-				<artifactId>maven-jar-plugin</artifactId>
-				<configuration>
-					<archive>
-						<manifest>
-							<mainClass>org.apache.juneau.examples.rest.springboot.App
-							</mainClass>
-						</manifest>
-					</archive>
-				</configuration>
-			</plugin>
-
-		</plugins>
-	</build>
-
-</project>
diff --git a/juneau-examples/juneau-examples-rest-springboot/juneau-examples-rest-springboot.launch b/juneau-examples/juneau-examples-rest-springboot/juneau-examples-rest-springboot.launch
deleted file mode 100644
index e2e06b7619..0000000000
--- a/juneau-examples/juneau-examples-rest-springboot/juneau-examples-rest-springboot.launch
+++ /dev/null
@@ -1,22 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<launchConfiguration type="org.eclipse.jdt.launching.localJavaApplication">
-    <booleanAttribute key="org.eclipse.debug.core.ATTR_FORCE_SYSTEM_CONSOLE_ENCODING" value="false"/>
-    <listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS">
-        <listEntry value="/juneau-examples-rest-springboot/src/main/java/org/apache/juneau/examples/rest/springboot/App.java"/>
-    </listAttribute>
-    <listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES">
-        <listEntry value="1"/>
-    </listAttribute>
-    <booleanAttribute key="org.eclipse.jdt.debug.ui.CONSIDER_INHERITED_MAIN" value="true"/>
-    <booleanAttribute key="org.eclipse.jdt.debug.ui.INCLUDE_EXTERNAL_JARS" value="true"/>
-    <booleanAttribute key="org.eclipse.jdt.launching.ATTR_ATTR_USE_ARGFILE" value="false"/>
-    <booleanAttribute key="org.eclipse.jdt.launching.ATTR_SHOW_CODEDETAILS_IN_EXCEPTION_MESSAGES" value="true"/>
-    <booleanAttribute key="org.eclipse.jdt.launching.ATTR_USE_CLASSPATH_ONLY_JAR" value="false"/>
-    <booleanAttribute key="org.eclipse.jdt.launching.ATTR_USE_START_ON_FIRST_THREAD" value="true"/>
-    <stringAttribute key="org.eclipse.jdt.launching.CLASSPATH_PROVIDER" value="org.eclipse.m2e.launchconfig.classpathProvider"/>
-    <stringAttribute key="org.eclipse.jdt.launching.JRE_CONTAINER" value="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-18/"/>
-    <stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value="org.apache.juneau.marshall.examples.rest.springboot.App"/>
-    <stringAttribute key="org.eclipse.jdt.launching.MODULE_NAME" value="juneau-examples-rest-springboot"/>
-    <stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="juneau-examples-rest-springboot"/>
-    <stringAttribute key="org.eclipse.jdt.launching.SOURCE_PATH_PROVIDER" value="org.eclipse.m2e.launchconfig.sourcepathProvider"/>
-</launchConfiguration>
diff --git a/juneau-examples/juneau-examples-rest-springboot/settings.xml b/juneau-examples/juneau-examples-rest-springboot/settings.xml
deleted file mode 100644
index 465f7d0175..0000000000
--- a/juneau-examples/juneau-examples-rest-springboot/settings.xml
+++ /dev/null
@@ -1,50 +0,0 @@
-<?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.
--->
-<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
-	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-	xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 https://maven.apache.org/xsd/settings-1.0.0.xsd">
-	<profiles>
-		<profile>
-			<id>apache-snapshots</id>
-			<repositories>
-				<repository>
-					<id>apache.snapshots</id>
-					<name>Apache Development Snapshot Repository</name>
-					<url>https://repository.apache.org/content/repositories/snapshots/</url>
-					<releases>
-						<enabled>false</enabled>
-					</releases>
-					<snapshots>
-						<enabled>true</enabled>
-					</snapshots>
-				</repository>
-				<repository>
-					<id>maven1</id>
-					<url>https://repo1.maven.org/maven2</url>
-					<releases>
-						<enabled>true</enabled>
-					</releases>
-				</repository>
-			</repositories>
-		</profile>
-	</profiles>
-
-	<activeProfiles>
-		<activeProfile>apache-snapshots</activeProfile>
-	</activeProfiles>
-</settings>
\ No newline at end of file
diff --git a/juneau-examples/juneau-examples-rest-springboot/src/main/java/org/apache/juneau/examples/rest/springboot/App.java b/juneau-examples/juneau-examples-rest-springboot/src/main/java/org/apache/juneau/examples/rest/springboot/App.java
deleted file mode 100644
index 01149dd055..0000000000
--- a/juneau-examples/juneau-examples-rest-springboot/src/main/java/org/apache/juneau/examples/rest/springboot/App.java
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.juneau.examples.rest.springboot;
-
-import org.apache.juneau.commons.logging.*;
-import org.apache.juneau.rest.server.*;
-import org.apache.juneau.rest.server.springboot.*;
-import org.springframework.boot.autoconfigure.*;
-import org.springframework.boot.builder.*;
-import org.springframework.boot.web.servlet.*;
-import org.springframework.context.annotation.*;
-import org.springframework.stereotype.*;
-
-/**
- * Entry point for Examples REST application when deployed as a Spring Boot application.
- *
- * <h5 class='section'>See Also:</h5><ul>
- * 	<li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/JuneauRestServerSpringbootBasics">juneau-rest-server-springboot Basics</a>
- * </ul>
- */
-@SpringBootApplication
-@Controller
-public class App {
-
-	/**
-	 * Entry point method.
-	 * @param args Command-line arguments.
-	 */
-	@SuppressWarnings({
-		"resource" // Spring ApplicationContext managed by Spring framework
-	})
-	public static void main(String[] args) {
-		try {
-			new SpringApplicationBuilder(App.class).run(args);
-			Logger.getLogger(App.class).info("Initialized.  App available on http://localhost:5000");
-		} catch (Exception e) {
-			e.printStackTrace();
-		}
-	}
-
-	/**
-	 * Optionally return an injectable message provider for the {@link HelloWorldResource} class.
-	 *
-	 * @return The message provider for the hello-world REST bean.
-	 */
-	@Bean
-	public HelloWorldMessageProvider getHelloWorldMessageProvider() { return new HelloWorldMessageProvider("Hello Spring injection user!"); }
-
-	/**
-	 * Optionally return the {@link HelloWorldResource} object as an injectable bean.
-	 *
-	 * @return The hello-world REST bean.
-	 */
-	@Bean
-	public HelloWorldResource getHelloWorldResource() { return new HelloWorldResource(); }
-
-	/**
-	 * Our root REST bean.
-	 * <p>
-	 * Note that this must extend from {@link SpringRestServlet} so that child resources can be resolved as Spring
-	 * beans.
-	 * <p>
-	 * All REST objects are attached to this bean using the {@link Rest#children()} annotation.
-	 *
-	 * @return The root resources REST bean.
-	 */
-	@Bean
-	public RootResources getRootResources() { return new RootResources(); }
-
-	/**
-	 * @param rootResources The root REST resource servlet
-	 * @return The servlet registration mapped to "/*".
-	 */
-	@Bean
-	public ServletRegistrationBean<jakarta.servlet.Servlet> getRootServlet(RootResources rootResources) {
-		return new ServletRegistrationBean<>(rootResources, "/*");
-	}
-}
\ No newline at end of file
diff --git a/juneau-examples/juneau-examples-rest-springboot/src/main/java/org/apache/juneau/examples/rest/springboot/RootResources.java b/juneau-examples/juneau-examples-rest-springboot/src/main/java/org/apache/juneau/examples/rest/springboot/RootResources.java
deleted file mode 100644
index 685da679da..0000000000
--- a/juneau-examples/juneau-examples-rest-springboot/src/main/java/org/apache/juneau/examples/rest/springboot/RootResources.java
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.juneau.examples.rest.springboot;
-
-import org.apache.juneau.examples.rest.*;
-import org.apache.juneau.examples.rest.dto.*;
-import org.apache.juneau.marshall.html.*;
-import org.apache.juneau.marshall.serializer.*;
-import org.apache.juneau.microservice.resources.*;
-import org.apache.juneau.rest.server.*;
-import org.apache.juneau.rest.server.springboot.*;
-import org.apache.juneau.rest.server.widget.*;
-
-/**
- * Sample REST resource showing how to implement a "router" resource page.
- *
- * <h5 class='section'>See Also:</h5><ul>
- * 	<li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/JuneauRestServerSpringbootBasics">juneau-rest-server-springboot Basics</a>
-
- * </ul>
- *
- * @serial exclude
- */
-@Rest(
-	title="Root resources",
-	description="Example of a router resource page.",
-	children={
-		HelloWorldResource.class,
-		DtoExamples.class,
-		UtilityBeansResource.class,
-		HtmlBeansResource.class,
-		ConfigResource.class,
-		ShutdownResource.class
-	}
-)
-@HtmlDocConfig(
-	widgets={
-		ContentTypeMenuItem.class
-	},
-	navlinks={
-		"api: servlet:/api",
-		"stats: servlet:/stats",
-		"$W{ContentTypeMenuItem}",
-		"source: $C{Source/gitHub}/org/apache/juneau/examples/rest/$R{servletClassSimple}.java"
-	},
-	aside={
-		"<div class='text'>",
-		"\t<p>This is an example of a 'router' page that serves as a jumping-off point to child resources.</p>",
-		"\t<p>Resources can be nested arbitrarily deep through router pages.</p>",
-		"\t<p>Note the <span class='link'>API</span> link provided that lets you see the generated swagger doc for this page.</p>",
-		"\t<p>Also note the <span class='link'>STATS</span> link that provides basic usage statistics.</p>",
-		"\t<p>Also note the <span class='link'>SOURCE</span> link on these pages to view the source code for the page.</p>",
-		"\t<p>All content on pages in the UI are serialized POJOs.  In this case, it's a serialized array of beans with 2 properties, 'name' and 'description'.</p>",
-		"\t<p>Other features (such as this aside) are added through annotations.</p>",
-		"</div>"
-	},
-	asideFloat="RIGHT"
-)
-@SerializerConfig(
-	// For testing purposes, we want to use single quotes in all the serializers so it's easier to do simple
-	// String comparisons.
-	// You can apply any of the Serializer/Parser/MarshallingContext settings this way.
-	quoteChar="'"
-)
-@SuppressWarnings({
-	"java:S110" // Inheritance depth acceptable for example/demo code
-})
-public class RootResources extends BasicSpringRestServletGroup {
-	private static final long serialVersionUID = 1L;
-}
\ No newline at end of file
diff --git a/juneau-examples/juneau-examples-rest-springboot/src/main/resources/juneau.cfg b/juneau-examples/juneau-examples-rest-springboot/src/main/resources/juneau.cfg
deleted file mode 100755
index 6932e4b86d..0000000000
--- a/juneau-examples/juneau-examples-rest-springboot/src/main/resources/juneau.cfg
+++ /dev/null
@@ -1,70 +0,0 @@
-# ***************************************************************************************************************************
-# * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
-# * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
-# * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
-# * with the License.  You may obtain a copy of the License at                                                              * 
-# *                                                                                                                         *
-# *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
-# *                                                                                                                         *
-# * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
-# * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
-# * specific language governing permissions and limitations under the License.                                              *
-# ***************************************************************************************************************************
-
-#=======================================================================================================================
-# REST settings
-#=======================================================================================================================
-[REST]
-
-# Comma-delimited list of key-value pairs that represent locations of static files that can be served up by your @Rest-annotated
-# classes.  These are static files that are served up by the servlet under the specified sub-paths.
-# For example, given the following setting...
-# 	staticFiles = htdocs:my-docs,styles/my-styles
-# ...the URI "/servletPath/htdocs/javadoc.css" resolves to the path "/my-docs/javadoc.css".
-# This path can be relative to the working directory, classpath root, or package of your resource class.
-# Used by the BasicRestConfig interface that defines the following value:
-# 	staticFiles="$C{REST/staticFiles}"
-staticFiles = htdocs:htdocs
-
-# Stylesheet to use for HTML views.
-# Used by the BasicRestConfig interface that defines the following value:
-# 	stylesheet="$C{REST/theme,servlet:/htdocs/themes/devops.css}"
-theme = servlet:/htdocs/themes/dark.css
-
-# Various look-and-feel settings used in the BasicRestConfig interface.
-headerIcon = servlet:/htdocs/images/juneau.png
-headerLink = http://juneau.apache.org
-footerIcon = servlet:/htdocs/images/asf.png
-footerLink = http://www.apache.org
-favicon = $C{REST/headerIcon}
-head = <link rel='icon' href='$U{$C{REST/favicon}}'/>
-header = 
-	<a href='$U{$C{REST/headerLink}}'>
-		<img src='$U{$C{REST/headerIcon}}' style='position:absolute;top:5;right:5;background-color:transparent;height:30px'/>
-	</a>
-footer = 
-	<a href='$U{$C{REST/footerLink}}'>
-		<img style='float:right;padding-right:20px;height:32px' src='$U{$C{REST/footerIcon}}'>
-	</a>
-
-#=======================================================================================================================
-# SqlQueryResource properties
-#=======================================================================================================================
-[SqlQueryResource]
-driver = org.apache.derby.jdbc.EmbeddedDriver
-directory = target/derby/testDB
-connectionUrl = jdbc:derby:$C{SqlQueryResource/directory};create=true
-allowTempUpdates = true
-includeRowNums = false
-
-#=======================================================================================================================
-# Source code location
-#=======================================================================================================================
-[Source]
-gitHub = https://github.com/apache/juneau/blob/master/juneau-examples/juneau-examples-rest/src/main/java
-
-#=======================================================================================================================
-# PetStoreResource properties
-#=======================================================================================================================
-[PetStore]
-headerImage = <a href='http://swagger.io'><img src='$U{servlet:/htdocs/cat.png}' style='position:absolute;top:5;right:5;background-color:transparent;height:30px'/></a>
diff --git a/juneau-examples/juneau-examples-rest/.gitignore b/juneau-examples/juneau-examples-rest/.gitignore
deleted file mode 100644
index 34acf885cb..0000000000
--- a/juneau-examples/juneau-examples-rest/.gitignore
+++ /dev/null
@@ -1,6 +0,0 @@
-/target/
-**/.DS_Store
-.classpath
-.project
-/.settings/
-/bin/
diff --git a/juneau-examples/juneau-examples-rest/pom.xml b/juneau-examples/juneau-examples-rest/pom.xml
deleted file mode 100644
index 449f4c846e..0000000000
--- a/juneau-examples/juneau-examples-rest/pom.xml
+++ /dev/null
@@ -1,118 +0,0 @@
-<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
-
-	<modelVersion>4.0.0</modelVersion>
-
-	<parent>
-		<groupId>org.apache.juneau</groupId>
-		<artifactId>juneau-examples</artifactId>
-		<version>10.0.0-SNAPSHOT</version>
-	</parent>
-
-	<artifactId>juneau-examples-rest</artifactId>
-	<name>Apache Juneau REST Examples</name>
-	<description>Apache Juneau REST Examples</description>
-	<packaging>bundle</packaging>
-
-	<properties>
-		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
-		<encoding>UTF-8</encoding>
-	</properties>
-
-	<dependencies>
-		<!-- Juneau dependencies -->
-		<dependency>
-			<groupId>org.apache.juneau</groupId>
-			<artifactId>juneau-microservice-jetty</artifactId>
-			<version>${project.version}</version>
-		</dependency>
-		<dependency>
-			<groupId>org.apache.juneau</groupId>
-			<artifactId>juneau-rest-server</artifactId>
-			<version>${project.version}</version>
-		</dependency>
-		<dependency>
-			<groupId>org.apache.juneau</groupId>
-			<artifactId>juneau-examples-core</artifactId>
-			<version>${project.version}</version>
-		</dependency>
-
-		<!-- Needed for JPA persistence of PetStore beans -->		
-		<dependency>
-			<groupId>org.apache.derby</groupId>
-			<artifactId>derby</artifactId>
-			<version>10.17.1.0</version>
-		</dependency>
-
-		<dependency>
-			<groupId>jakarta.servlet</groupId>
-			<artifactId>jakarta.servlet-api</artifactId>
-			<version>6.1.0</version>
-			<scope>compile</scope>
-		</dependency>
-
-	</dependencies>
-
-	<build>
-		<plugins>
-			<plugin>
-				<groupId>org.apache.felix</groupId>
-				<artifactId>maven-bundle-plugin</artifactId>
-				<extensions>true</extensions>
-				<configuration>
-					<supportIncrementalBuild>true</supportIncrementalBuild>
-				</configuration>
-				<executions>
-				<execution>
-					<id>bundle-manifest</id>
-					<phase>process-classes</phase>
-					<goals>
-						<goal>manifest</goal>
-					</goals>
-				</execution>
-			</executions>
-			</plugin>
-			<plugin>
-				<groupId>org.apache.maven.plugins</groupId>
-				<artifactId>maven-source-plugin</artifactId>
-				<executions>
-					<execution>
-						<id>attach-sources</id>
-						<phase>verify</phase>
-						<goals>
-							<goal>jar-no-fork</goal>
-						</goals>
-					</execution>
-				</executions>
-			</plugin>
-
-			<!-- This runs the _TestSuite class. You must run within the testsuite 
-				so the REST microservice is started for the tests. -->
-			<plugin>
-				<groupId>org.apache.maven.plugins</groupId>
-				<artifactId>maven-surefire-plugin</artifactId>
-				<configuration>
-					<includes>
-						<include>**/_TestSuite.java</include>
-					</includes>
-				</configuration>
-			</plugin>
-		</plugins>
-	</build>
-</project>
diff --git a/juneau-examples/juneau-examples-rest/src/main/java/META-INF/MANIFEST.MF b/juneau-examples/juneau-examples-rest/src/main/java/META-INF/MANIFEST.MF
deleted file mode 100644
index 5e9495128c..0000000000
--- a/juneau-examples/juneau-examples-rest/src/main/java/META-INF/MANIFEST.MF
+++ /dev/null
@@ -1,3 +0,0 @@
-Manifest-Version: 1.0
-Class-Path: 
-
diff --git a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/AdminGuard.java b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/AdminGuard.java
deleted file mode 100644
index 930b99cc89..0000000000
--- a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/AdminGuard.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.juneau.examples.rest;
-
-import org.apache.juneau.rest.server.*;
-import org.apache.juneau.rest.server.guard.*;
-
-/**
- * Sample guard that only lets administrators through.
- *
- */
-public class AdminGuard extends RestGuard {
-
-	@Override /* RestGuard */
-	public boolean isRequestAllowed(RestRequest req) {
-		return true;
-	}
-}
\ No newline at end of file
diff --git a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/HelloWorldResource.java b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/HelloWorldResource.java
deleted file mode 100644
index b5e53afe01..0000000000
--- a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/HelloWorldResource.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.juneau.examples.rest;
-
-import org.apache.juneau.marshall.html.*;
-import org.apache.juneau.rest.server.*;
-import org.apache.juneau.rest.server.servlet.*;
-
-/**
- * Sample REST resource that prints out a simple "Hello world!" message.
- *
- */
-@Rest(
-	title="Hello World",
-	description="An example of the simplest-possible resource",
-	path="/helloWorld"
-)
-@HtmlDocConfig(
-	aside={
-		"<div style='max-width:400px' class='text'>",
-		"\t<p>This page shows a resource that simply response with a 'Hello world!' message</p>",
-		"\t<p>The POJO serialized is a simple String.</p>",
-		"</div>"
-	}
-)
-public class HelloWorldResource extends BasicRestResource {
-
-	/**
-	 * [HTTP GET /helloworld]
-	 * Returns a simple string message.
-	 *
-	 * @return A simple Hello-World message.
-	 */
-	@RestGet(path = "/*", summary = "Responds with \"Hello world!\"")
-	public String sayHello() {
-		return "Hello world!";
-	}
-}
\ No newline at end of file
diff --git a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/HtmlBeansResource.java b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/HtmlBeansResource.java
deleted file mode 100644
index 5705441560..0000000000
--- a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/HtmlBeansResource.java
+++ /dev/null
@@ -1,145 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.juneau.examples.rest;
-
-import static org.apache.juneau.bean.html5.HtmlBuilder.*;
-
-import org.apache.juneau.bean.html5.*;
-import org.apache.juneau.marshall.html.*;
-import org.apache.juneau.rest.server.*;
-import org.apache.juneau.rest.server.beans.*;
-import org.apache.juneau.rest.server.servlet.*;
-import org.apache.juneau.rest.server.widget.*;
-
-/**
- * Sample resource that allows images to be uploaded and retrieved.
- *
- * <h5 class='section'>See Also:</h5><ul>
- * 	<li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/Marshalling">Marshalling</a>
- * 	<li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/HtmlBeans">Using with HTML Beans</a>
- * </ul>
- */
-@Rest(
-	path="/htmlbeans",
-	title="HTML bean examples",
-	description="Examples of serialized HTML beans."
-)
-@HtmlDocConfig(
-	widgets={
-		ContentTypeMenuItem.class
-	},
-	navlinks={
-		"up: request:/..",
-		"api: servlet:/api",
-		"stats: servlet:/stats",
-		"$W{ContentTypeMenuItem}",
-		"source: $C{Source/gitHub}/org/apache/juneau/examples/rest/HtmlBeansResource.java"
-	},
-	aside={
-		"<div class='text'>",
-		"\t<p>Examples of serialized HTML beans.</p>",
-		"</div>"
-	},
-	asideFloat="RIGHT"
-)
-public class HtmlBeansResource extends BasicRestResource {
-
-	@SuppressWarnings({
-		"unused" // serialVersionUID required for Serializable compliance; unused in code paths
-	})
-	private static final long serialVersionUID = 1L;
-
-	/**
-	 * [HTTP GET /htmlbeans/div]
-	 * @return An example div tag.
-	 */
-	@RestGet("/div")
-	@HtmlDocConfig(
-		aside={
-			"<div class='text'>",
-			"\t<p>Example of serialized div tag.</p>",
-			"</div>"
-		}
-	)
-	public HtmlElement aDiv() {
-		return div()
-			.children(
-				p("Juneau supports ", b(i("mixed")), " content!")
-			)
-			.onmouseover("alert(\"boo!\");");
-	}
-
-	/**
-	 * [HTTP GET /htmlbeans/form]
-	 * @return An example form tag.
-	 */
-	@RestGet("/form")
-	@HtmlDocConfig(
-		aside={
-			"<div class='text'>",
-			"\t<p>Example of serialized HTML form.</p>",
-			"</div>"
-		}
-	)
-	public Form aForm() {
-		return form().action("/submit").method("POST")
-			.children(
-				"Position (1-10000): ", input("number").name("pos").value(1), br(),
-				"Limit (1-10000): ", input("number").name("limit").value(100), br(),
-				button("submit", "Submit"),
-				button("reset", "Reset")
-			);
-	}
-
-	/**
-	 * [HTTP GET /htmlbeans/table]
-	 * @return An example table.
-	 */
-	@RestGet("/table")
-	@HtmlDocConfig(
-		aside={
-			"<div class='text'>",
-			"\t<p>Example of serialized table.</p>",
-			"</div>"
-		}
-	)
-	public Table aTable() {
-		return table(
-			tr(
-				th("c1"),
-				th("c2")
-			),
-			tr(
-				td("v1"),
-				td("v2")
-			)
-		);
-	}
-
-	/**
-	 * [HTTP GET /htmlbeans]
-	 * @return Descriptive links to the child endpoints.
-	 */
-	@RestGet("/")
-	public ResourceDescriptions getChildDescriptions() {
-		return ResourceDescriptions
-			.create()
-			.append("table", "Example of a serialized table")
-			.append("div", "Example of a serialized div tag")
-			.append("form", "Example of a serialized form");
-	}
-}
\ No newline at end of file
diff --git a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/PhotosResource.java b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/PhotosResource.java
deleted file mode 100644
index c2f77b1d24..0000000000
--- a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/PhotosResource.java
+++ /dev/null
@@ -1,172 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.juneau.examples.rest;
-
-import java.awt.image.*;
-import java.net.*;
-import java.util.*;
-import java.util.concurrent.*;
-
-import org.apache.juneau.examples.parser.*;
-import org.apache.juneau.examples.serializer.*;
-import org.apache.juneau.http.*;
-import org.apache.juneau.http.classic.response.*;
-import org.apache.juneau.marshall.html.*;
-import org.apache.juneau.rest.server.*;
-import org.apache.juneau.rest.server.servlet.*;
-import org.apache.juneau.rest.server.widget.*;
-
-/**
- * Sample resource that allows images to be uploaded and retrieved.
- *
- * <h5 class='section'>See Also:</h5><ul>
- * 	<li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/Marshalling">Marshalling</a>
- * 	<li class='jc'>{@link ImageSerializer}
- * 	<li class='jc'>{@link ImageParser}
- * </ul>
- */
-@Rest(
-	path="/photos",
-	messages="nls/PhotosResource",
-	title="Photo REST service",
-	description="Use a tool like Poster to upload and retrieve jpeg and png images."
-)
-@HtmlDocConfig(
-	widgets={
-		ContentTypeMenuItem.class
-	},
-	navlinks={
-		"api: servlet:/api",
-		"stats: servlet:/stats",
-		"$W{ContentTypeMenuItem}",
-		"source: $C{Source/gitHub}/org/apache/juneau/examples/rest/PhotosResource.java"
-	},
-	aside={
-		"<div class='text'>",
-		"\t<p>Examples of serialized beans in the org.apache.juneau.rest.server.utilitybeans package.</p>",
-		"</div>"
-	},
-	asideFloat="RIGHT"
-)
-public class PhotosResource extends BasicRestServlet {
-
-	/** Bean class for storing photos */
-	public static class Photo {
-		private int id;
-		BufferedImage image;
-
-		Photo(int id, BufferedImage image) {
-			this.id = id;
-			this.image = image;
-		}
-
-		/**
-		 * The photo ID
-		 *
-		 * @return The photo ID.
-		 */
-		public int getID() { return id; }
-
-		/**
-		 * The photo URL.
-		 *
-		 * @return The photo URL.
-		 */
-		public URI getURI() {
-			try {
-				return new URI("photos/" + id);
-			} catch (URISyntaxException e) {
-				throw new IllegalStateException(e); // Shouldn't happen.
-			}
-		}
-	}
-
-	private static final long serialVersionUID = 1L;
-
-	/** Photo cache. Static - shared by all requests (singleton servlet). */
-	private static final Map<Integer,Photo> photos = new ConcurrentHashMap<>();
-
-	/**
-	 * [HTTP PUT /photos/{id}]
-	 * PUT request handler.
-	 *
-	 * @param id The photo ID.
-	 * @param image The photo image.
-	 * @return OK.
-	 */
-	@RestPut(path = "/{id}", parsers = ImageParser.class)
-	public Ok addPhoto(@Path("id") int id, @Content BufferedImage image) {
-		photos.put(id, new Photo(id, image));
-		return Ok.OK;
-	}
-
-	/**
-	 * [HTTP DELETE /photos/{id}]
-	 * DELETE request handler
-	 *
-	 * @param id The photo ID.
-	 * @return OK.
-	 * @throws NotFound If photo not found.
-	 */
-	@RestDelete("/{id}")
-	public Ok deletePhoto(@Path("id") int id) throws NotFound {
-		var p = photos.remove(id);
-		if (p == null)
-			throw new NotFound("Photo not found");
-		return Ok.OK;
-	}
-
-	/**
-	 * [HTTP GET /photos]
-	 * GET request handler for list of all photos.
-	 *
-	 * @return A list of photo beans.
-	 */
-	@RestGet("/")
-	public Collection<Photo> getAllPhotos() { return photos.values(); }
-
-	/**
-	 * [HTTP GET /photos/{id}]
-	 * GET request handler for single photo.
-	 *
-	 * @param id The photo ID.
-	 * @return The photo image.
-	 * @throws NotFound If photo not found.
-	 */
-	@RestGet(path = "/{id}", serializers = ImageSerializer.class)
-	public BufferedImage getPhoto(@Path("id") int id) throws NotFound {
-		var p = photos.get(id);
-		if (p == null)
-			throw new NotFound("Photo not found");
-		return p.image;
-	}
-
-	/**
-	 * [HTTP POST /photos]
-	 * POST request handler.
-	 *
-	 * @param image The photo image.
-	 * @return The created photo bean.
-	 */
-	@RestPost(path = "/", parsers = ImageParser.class)
-	public Photo setPhoto(@Content BufferedImage image) {
-		int id = photos.size();
-		var p = new Photo(id, image);
-		photos.put(id, p);
-		return p;
-	}
-}
\ No newline at end of file
diff --git a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/RequestEchoResource.java b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/RequestEchoResource.java
deleted file mode 100644
index eb021737bb..0000000000
--- a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/RequestEchoResource.java
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.juneau.examples.rest;
-
-import org.apache.juneau.commons.*;
-import org.apache.juneau.commons.bean.*;
-import org.apache.juneau.http.*;
-import org.apache.juneau.marshall.*;
-import org.apache.juneau.marshall.html.*;
-import org.apache.juneau.marshall.serializer.*;
-import org.apache.juneau.rest.server.*;
-import org.apache.juneau.rest.server.converter.*;
-import org.apache.juneau.rest.server.servlet.*;
-import org.apache.juneau.rest.server.widget.*;
-
-import jakarta.servlet.*;
-import jakarta.servlet.http.*;
-
-/**
- * Sample REST resource for echoing HttpServletRequests back to the browser.
- *
- */
-@Rest(
-	path="/echo",
-	title="Request echo service",
-	description="Echos the current HttpServletRequest object back to the browser.",
-	swagger=@Swagger(
-		contact=@Contact(name="Juneau Developer",email="dev@juneau.apache.org"),
-		license=@License(name="Apache 2.0",url="http://www.apache.org/licenses/LICENSE-2.0.html"),
-		version="2.0",
-		termsOfService="You are on your own.",
-		externalDocs=@ExternalDocs(description="Apache Juneau",url="http://juneau.apache.org")
-	)
-)
-@HtmlDocConfig(
-	widgets={
-		ContentTypeMenuItem.class
-	},
-	navlinks={
-		"up: request:/..",
-		"api: servlet:/api",
-		"$W{ContentTypeMenuItem}",
-		"source: $C{Source/gitHub}/org/apache/juneau/examples/rest/RequestEchoResource.java"
-	},
-	aside={
-		"<div style='max-width:400px;min-width:200px' class='text'>",
-		"\t<p>Shows how even arbitrary POJOs such as <c>HttpServletRequest</c> can be serialized by the framework.</p>",
-		"\t<p>Also shows how to specify serializer properties, filters, and swaps at the servlet level to control how POJOs are serialized.</p>",
-		"\t<p>Also provides an example of how to use the Traversable and Queryable APIs.</p>",
-		"</div>"
-	},
-	nowrap="false"
-)
-@SerializerConfig(
-	maxDepth="5",
-	detectRecursions="true"
-)
-@BeanTypeApply(on="HttpServletRequest",value=@BeanType(interfaceClass=HttpServletRequest.class))
-@BeanTypeApply(on="HttpSession",value=@BeanType(interfaceClass=HttpSession.class))
-@BeanTypeApply(on="ServletContext",value=@BeanType(interfaceClass=ServletContext.class))
-public class RequestEchoResource extends BasicRestResource {
-
-	/**
-	 * [HTTP GET /echo/*]
-	 * GET request handler.
-	 *
-	 * @param req The HTTP servlet request.
-	 * @return The same request to serialize as the response.
-	 */
-	@RestOp(method = "*", path = "/*", converters = { Traversable.class, Queryable.class }, summary = "Serializes the incoming HttpServletRequest object.")
-	public HttpServletRequest doGet(RestRequest req) {
-		// Just echo the request back as the response.
-		return req.getHttpServletRequest();
-	}
-}
\ No newline at end of file
diff --git a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/SseDemoResource.java b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/SseDemoResource.java
deleted file mode 100644
index 263dd2036a..0000000000
--- a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/SseDemoResource.java
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.juneau.examples.rest;
-
-import static org.apache.juneau.commons.utils.Utils.*;
-
-import java.io.*;
-import java.time.*;
-import java.time.format.*;
-import java.util.*;
-import java.util.concurrent.*;
-import java.util.concurrent.atomic.*;
-
-import org.apache.juneau.marshall.sse.*;
-import org.apache.juneau.rest.server.*;
-import org.apache.juneau.rest.server.servlet.*;
-import org.apache.juneau.rest.server.sse.*;
-
-/**
- * Sample REST resource that emits a stream of Server-Sent Events.
- *
- * <p>
- * The {@link #stream()} endpoint returns a lazy {@link Iterable} of {@link SseEvent} objects whose
- * iterator sleeps {@value #SLEEP_MILLIS} milliseconds between calls to {@code next()}. Combined with the
- * per-event {@code Writer.flush()} performed by {@link SseSerializer}, this allows the per-event
- * arrival timing to be observed with a streaming HTTP client such as {@code curl -N}.
- *
- * <h5 class='section'>Example:</h5>
- * <p class='bcode'>
- * 	$ curl -N -H 'Accept: text/event-stream' http://localhost:10000/sseDemo/stream
- * 	event: tick-1
- * 	data: 2026-05-20T11:08:00.123Z
- *
- * 	event: tick-2
- * 	data: 2026-05-20T11:08:00.624Z
- * 	...
- * </p>
- */
-@Rest(
-	path = "/sseDemo",
-	title = "SSE demo",
-	description = "Emits a stream of Server-Sent Events with a short delay between events."
-)
-public class SseDemoResource extends BasicRestResource {
-
-	private static final int EVENT_COUNT = 10;
-	private static final long SLEEP_MILLIS = 500L;
-
-	/**
-	 * Streams {@value #EVENT_COUNT} SSE events with a {@value #SLEEP_MILLIS}-ms delay between
-	 * successive events. Each event carries a UTC timestamp in its {@code data:} field so that
-	 * per-event flush behavior is observable from the client's wall clock.
-	 *
-	 * @return A lazy iterable of {@link SseEvent} objects.
-	 */
-	@RestGet(path = "/stream", serializers = SseSerializer.class)
-	public Iterable<SseEvent> stream() {
-		return () -> new Iterator<>() {
-			private int i = 0;
-
-			@Override
-			public boolean hasNext() {
-				return i < EVENT_COUNT;
-			}
-
-			@Override
-			public SseEvent next() {
-				if (i >= EVENT_COUNT)
-					throw new NoSuchElementException();
-				if (i > 0) {
-					try {
-						Thread.sleep(SLEEP_MILLIS);
-					} catch (InterruptedException e) {
-						Thread.currentThread().interrupt();
-						throw new IllegalStateException("Interrupted while sleeping between SSE events", e);
-					}
-				}
-				i++;
-				var ts = DateTimeFormatter.ISO_INSTANT.format(Instant.now());
-				return new SseEvent("tick-" + i, ts).setId(String.valueOf(i));
-			}
-		};
-	}
-
-	/**
-	 * Demonstrates server-side broadcaster fan-out with heartbeat comments.
-	 *
-	 * @param req The request.
-	 * @param res The response.
-	 * @param broadcaster The broadcaster bean.
-	 * @throws IOException If the response write fails.
-	 */
-	@RestGet(path = "/broadcast", serializers = SseSerializer.class)
-	@SuppressWarnings({
-		"resource" // Scheduler is explicitly shutdown in finally; subscription/SSE support are closed via try-with-resources.
-	})
-	public void broadcast(RestRequest req, RestResponse res, SseBroadcaster broadcaster) throws IOException {
-		var id = opt(req.getHttpServletRequest().getRequestId()).orElse(UUID.randomUUID().toString());
-		var counter = new AtomicInteger();
-		var scheduler = Executors.newSingleThreadScheduledExecutor();
-		ScheduledFuture<?> task = null;
-		try (var subscription = broadcaster.subscribe(id); var sse = res.sse().heartbeat(Duration.ofSeconds(15))) {
-			task = scheduler.scheduleAtFixedRate(() -> {
-				var i = counter.incrementAndGet();
-				var ts = DateTimeFormatter.ISO_INSTANT.format(Instant.now());
-				broadcaster.publish(new SseEvent("tick-" + i, ts).setId(String.valueOf(i)));
-				if (i >= EVENT_COUNT)
-					subscription.close();
-			}, 0, SLEEP_MILLIS, TimeUnit.MILLISECONDS);
-			sse.sendFrom(subscription);
-		} finally {
-			if (task != null)
-				task.cancel(true);
-			scheduler.shutdownNow();
-		}
-	}
-}
diff --git a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/UtilityBeansResource.java b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/UtilityBeansResource.java
deleted file mode 100644
index e4bc820bc4..0000000000
--- a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/UtilityBeansResource.java
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.juneau.examples.rest;
-
-import org.apache.juneau.commons.bean.*;
-import org.apache.juneau.marshall.html.*;
-import org.apache.juneau.rest.server.*;
-import org.apache.juneau.rest.server.beans.*;
-import org.apache.juneau.rest.server.servlet.*;
-import org.apache.juneau.rest.server.widget.*;
-
-/**
- * Sample resource that allows images to be uploaded and retrieved.
- *
- * <h5 class='section'>See Also:</h5><ul>
- * 	<li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/Marshalling">Marshalling</a>
- * 	<li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/UtilityBeans">Utility Beans</a>
- * </ul>
- */
-@Rest(
-	path="/utilitybeans",
-	title="Utility beans examples",
-	description="Examples of utility bean usage."
-)
-@HtmlDocConfig(
-	widgets={
-		ContentTypeMenuItem.class
-	},
-	navlinks={
-		"up: request:/..",
-		"api: servlet:/api",
-		"stats: servlet:/stats",
-		"$W{ContentTypeMenuItem}",
-		"source: $C{Source/gitHub}/org/apache/juneau/examples/rest/UtilityBeansResource.java"
-	},
-	aside={
-		"<div class='text'>",
-		"\t<p>Examples of serialized beans in the org.apache.juneau.rest.server.utilitybeans package.</p>",
-		"</div>"
-	},
-	asideFloat="RIGHT"
-)
-public class UtilityBeansResource extends BasicRestResource {
-
-	/**
-	 * Sample address bean used for demonstrating utility bean functionality.
-	 */
-	@SuppressWarnings({
-		"java:S1104" // All public fields intentional for direct bean serialization in REST example demonstrations
-	})
-	@BeanType(p = "street,city,state,zip,isCurrent")
-	public static class Address {
-
-		/** Street address. */
-		public String street;
-
-		/** City name. */
-		public String city;
-
-		/** State abbreviation. */
-		public String state;
-
-		/** ZIP code. */
-		public int zip;
-
-		/** Whether this is the current address. */
-		public boolean isCurrent;
-
-		/** Default constructor. */
-		public Address() {
-			// No-op: Test helper class - intentionally empty for testing
-		}
-	}
-
-	@SuppressWarnings({
-		"unused" // serialVersionUID required for Serializable compliance; unused in code paths
-	})
-	private static final long serialVersionUID = 1L;
-
-	/**
-	 * [HTTP GET /utilitybeans/BeanDescription]
-	 * @return Example of serialized org.apache.juneau.rest.server.utilitybeans.ResourceDescriptions bean.
-	 */
-	@RestGet("/BeanDescription")
-	@HtmlDocConfig(
-		aside={
-			"<div class='text'>",
-			"\t<p>Example of serialized ResourceDescriptions bean.</p>",
-			"</div>"
-		}
-	)
-	public BeanDescription aBeanDescription() {
-		return BeanDescription.of(Address.class);
-	}
-
-	/**
-	 * [HTTP GET /utilitybeans/Hyperlink]
-	 * @return Example of serialized org.apache.juneau.rest.server.utilitybeans.Hyperlink bean.
-	 */
-	@RestGet("/Hyperlink")
-	@HtmlDocConfig(
-		aside={
-			"<div class='text'>",
-			"\t<p>Example of serialized Hyperlink bean.</p>",
-			"</div>"
-		}
-	)
-	public Hyperlink aHyperlink() {
-		return Hyperlink.create("/utilitybeans", "Back to /utilitybeans");
-	}
-
-	/**
-	 * [HTTP GET /utilitybeans/SeeOtherRoot]
-	 * @return Example of serialized SeeOtherRoot bean.
-	 * This just redirects back to the servlet root.
-	 */
-	@RestGet("/SeeOtherRoot")
-	@HtmlDocConfig(
-		aside={
-			"<div class='text'>",
-			"\t<p>Example of serialized org.apache.juneau.rest.server.utilitybeans.SeeOtherRoot bean.</p>",
-			"</div>"
-		}
-	)
-	public SeeOtherRoot aSeeOtherRoot() {
-		return SeeOtherRoot.INSTANCE;
-	}
-
-	/**
-	 * [HTTP GET /utilitybeans]
-	 * @return Descriptive links to the child endpoints.
-	 */
-	@RestGet("/")
-	public ResourceDescriptions getChildDescriptions() {
-		return ResourceDescriptions
-			.create()
-			.append("BeanDescription", "Example of BeanDescription bean")
-			.append("Hyperlink", "Example of Hyperlink bean")
-			.append("SeeOtherRoot", "Example of SeeOtherRoot bean");
-	}
-}
\ No newline at end of file
diff --git a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/command/EchoCommand.java b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/command/EchoCommand.java
deleted file mode 100644
index cc4aea56b8..0000000000
--- a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/command/EchoCommand.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.juneau.examples.rest.command;
-
-import java.io.*;
-import java.util.*;
-
-import org.apache.juneau.commons.runtime.*;
-import org.apache.juneau.microservice.console.*;
-
-/**
- * Implements an 'echo' console command that simply returns the command arguments as a comma-delimited list.
- *
- */
-public class EchoCommand extends ConsoleCommand {
-
-	@Override /* ConsoleCommand */
-	public boolean execute(Scanner in, PrintWriter out, Args args) {
-		out.println("positional=" + args.positional() + ", options=" + args.asMap());
-		return false;
-	}
-
-	@Override /* ConsoleCommand */
-	public String getDescription() { return "Simply prints the positional arguments and named options of the command."; }
-
-	@Override /* ConsoleCommand */
-	public String getInfo() { return "Echo command"; }
-
-	@Override /* ConsoleCommand */
-	public String getName() { return "echo"; }
-}
\ No newline at end of file
diff --git a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/dto/AtomFeedResource.java b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/dto/AtomFeedResource.java
deleted file mode 100644
index 03bd29bd05..0000000000
--- a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/dto/AtomFeedResource.java
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.juneau.examples.rest.dto;
-
-import static org.apache.juneau.bean.atom.AtomBuilder.*;
-
-import java.net.*;
-
-import org.apache.juneau.bean.atom.*;
-import org.apache.juneau.commons.*;
-import org.apache.juneau.http.*;
-import org.apache.juneau.http.Content;
-import org.apache.juneau.marshall.encoders.*;
-import org.apache.juneau.marshall.html.*;
-import org.apache.juneau.marshall.serializer.*;
-import org.apache.juneau.rest.server.*;
-import org.apache.juneau.rest.server.servlet.*;
-import org.apache.juneau.rest.server.widget.*;
-
-/**
- * Sample resource that shows how to generate ATOM feeds.
- *
- *
- * @serial exclude
- */
-@Rest(
-	path="/atom",
-	title="Sample ATOM feed resource",
-	description="Sample resource that shows how to render ATOM feeds",
-	encoders=GzipEncoder.class,
-	swagger=@Swagger(
-		contact=@Contact(name="Juneau Developer",email="dev@juneau.apache.org"),
-		license=@License(name="Apache 2.0",url="http://www.apache.org/licenses/LICENSE-2.0.html"),
-		version="2.0",
-		termsOfService="You are on your own.",
-		externalDocs=@ExternalDocs(description="Apache Juneau",url="http://juneau.apache.org")
-	)
-)
-@HtmlDocConfig(
-	widgets={
-		ContentTypeMenuItem.class
-	},
-	navlinks={
-		"up: request:/..",
-		"api: servlet:/api",
-		"stats: servlet:/stats",
-		"$W{ContentTypeMenuItem}",
-		"source: $C{Source/gitHub}/org/apache/juneau/examples/rest/dto/AtomFeedResource.java"
-	}
-)
-@SerializerConfig(
-	quoteChar="'"
-)
-@SuppressWarnings({
-	"java:S115" // Constants use UPPER_snakeCase convention (e.g., CONST_timestamp)
-})
-public class AtomFeedResource extends BasicRestServlet {
-	private static final long serialVersionUID = 1L;
-
-	private static final String CONST_timestamp = "2016-12-31T05:02:03Z";
-	private static final String EXAMPLE_URL_FOO_ORG = "http://foo.org/";
-	private static final String EXAMPLE_URL_WWW_FOO_ORG = "http://www.foo.org/";
-
-	private transient Feed feed;     // The root resource object
-
-	/**
-	 * [HTTP GET /dto/atom]
-	 * Get the sample ATOM feed
-	 *
-	 * @return The sample ATOM feed.
-	 */
-	@RestGet(summary = "Get the sample ATOM feed")
-	public Feed get() {
-		return feed;
-	}
-
-	@Override /* Servlet */
-	public void init() {
-		try {
-			feed =
-				feed("tag:foo.org", "Title", CONST_timestamp)
-				.setSubtitle(text("html").setText("Subtitle"))
-				.setLinks(
-					link("alternate", "text/html", EXAMPLE_URL_FOO_ORG).setHreflang("en"),
-					link("self", "application/atom+xml", "http://foo.org/feed.atom")
-				)
-				.setGenerator(
-					generator("Example Toolkit").setUri(EXAMPLE_URL_WWW_FOO_ORG).setVersion("1.0")
-				)
-				.setEntries(
-					entry("tag:foo.org", "Title", CONST_timestamp)
-					.setLinks(
-						link("alternate", "text/html", "http://foo.org/2005/04/02/atom"),
-						link("enclosure", "audio/mpeg", "http://foo.org/audio/foobar.mp3").setLength(1337)
-					)
-					.setPublished(CONST_timestamp)
-					.setAuthors(
-						person("John Smith").setUri(new URI(EXAMPLE_URL_FOO_ORG)).setEmail("foo@foo.org")
-					)
-					.setContributors(
-						person("John Smith"),
-						person("Jane Smith")
-					)
-					.setContent(
-						content("xhtml")
-						.setLang("en")
-						.setBase(EXAMPLE_URL_FOO_ORG)
-						.setText("<div><p><i>[Sample content]</i></p></div>")
-					)
-				);
-		} catch (Exception e) {
-			throw new IllegalStateException(e);
-		}
-	}
-
-	/**
-	 * [HTTP PUT /dto/atom]
-	 * Overwrite the sample ATOM feed
-	 *
-	 * @param feed The new ATOM feed.
-	 * @return The updated ATOM feed.
-	 */
-	@RestPut(summary = "Overwrite the sample ATOM feed", description = "Replaces the feed with the specified content, and then mirrors it as the response.")
-	public Feed put(@Content Feed feed) {
-		this.feed = feed;
-		return feed;
-	}
-}
\ No newline at end of file
diff --git a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/dto/DtoExamples.java b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/dto/DtoExamples.java
deleted file mode 100644
index d44a6a7362..0000000000
--- a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/dto/DtoExamples.java
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.juneau.examples.rest.dto;
-
-import org.apache.juneau.marshall.html.*;
-import org.apache.juneau.marshall.serializer.*;
-import org.apache.juneau.rest.server.*;
-import org.apache.juneau.rest.server.servlet.*;
-import org.apache.juneau.rest.server.widget.*;
-
-/**
- * Sample REST resource showing how to implement a nested "router" resource page.
- *
- *
- * @serial exclude
- */
-@Rest(
-	path="/dto",
-	title="DTO examples",
-	description="Example serialization of predefined Data Transfer Objects.",
-	children={
-		AtomFeedResource.class,
-		JsonSchemaResource.class
-	}
-)
-@HtmlDocConfig(
-	widgets={
-		ContentTypeMenuItem.class
-	},
-	navlinks={
-		"up: request:/..",
-		"api: servlet:/api",
-		"$W{ContentTypeMenuItem}",
-		"source: $C{Source/gitHub}/org/apache/juneau/examples/rest/dto/DtoExamples.java"
-	},
-	aside={
-		"<div style='max-width:400px' class='text'>",
-		"\t<p>This is an example of a nested 'router' page that serves as a jumping-off point to other child resources.</p>",
-		"</div>"
-	}
-)
-@SerializerConfig(
-	// For testing purposes, we want to use single quotes in all the serializers so it's easier to do simple
-	// String comparisons.
-	// You can apply any of the Serializer/Parser/MarshallingContext settings this way.
-	quoteChar="'"
-)
-@SuppressWarnings({
-	"java:S110" // Inheritance depth acceptable for example/demo code
-})
-public class DtoExamples extends BasicRestServletGroup {
-	private static final long serialVersionUID = 1L;
-}
\ No newline at end of file
diff --git a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/dto/JsonSchemaResource.java b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/dto/JsonSchemaResource.java
deleted file mode 100644
index 842fdd3f50..0000000000
--- a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/dto/JsonSchemaResource.java
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.juneau.examples.rest.dto;
-
-import org.apache.juneau.bean.jsonschema.*;
-import org.apache.juneau.commons.*;
-import org.apache.juneau.http.*;
-import org.apache.juneau.marshall.*;
-import org.apache.juneau.marshall.html.*;
-import org.apache.juneau.rest.server.*;
-import org.apache.juneau.rest.server.servlet.*;
-import org.apache.juneau.rest.server.widget.*;
-
-/**
- * Sample resource that shows how to serialize JSON-Schema documents.
- *
- *
- * @serial exclude
- */
-@Rest(
-	path="/jsonSchema",
-	messages="nls/JsonSchemaResource",
-	title="Sample JSON-Schema document",
-	description="Sample resource that shows how to generate JSON-Schema documents",
-	swagger=@Swagger(
-		contact=@Contact(name="Juneau Developer",email="dev@juneau.apache.org"),
-		license=@License(name="Apache 2.0",url="http://www.apache.org/licenses/LICENSE-2.0.html"),
-		version="2.0",
-		termsOfService="You are on your own.",
-		externalDocs=@ExternalDocs(description="Apache Juneau",url="http://juneau.apache.org")
-	)
-)
-@HtmlDocConfig(
-	widgets={
-		ContentTypeMenuItem.class
-	},
-	navlinks={
-		"up: request:/..",
-		"api: servlet:/api",
-		"stats: servlet:/stats",
-		"$W{ContentTypeMenuItem}",
-		"source: $C{Source/gitHub}/org/apache/juneau/examples/rest/dto/JsonSchemaResource.java"
-	},
-	aside={
-		"<div style='min-width:200px' class='text'>",
-		"\t<p>Shows how to produce JSON-Schema documents in a variety of languages using the JSON-Schema DTOs.</p>",
-		"</div>"
-	}
-)
-@MarshalledApply(on="Schema",value=@Marshalled(example="$F{JsonSchemaResource_example.json}"))
-public class JsonSchemaResource extends BasicRestServlet {
-	private static final long serialVersionUID = 1L;
-
-	private transient JsonSchema schema;     // The schema document
-
-	/**
-	 * [HTTP GET /dto/jsonSchema]
-	 * Get the JSON-Schema document.
-	 *
-	 * @return The JSON-Schema document.
-	 */
-	@RestGet(summary = "Get the JSON-Schema document")
-	public JsonSchema get() {
-		return schema;
-	}
-
-	@SuppressWarnings({
-		"removal" // Uses deprecated Schema annotation for example compatibility
-	})
-	@Override /* Servlet */
-	public void init() {
-
-		try {
-			schema = new JsonSchema()
-				.setId("http://example.com/sample-schema#")
-				.setSchemaVersionUri("http://json-schema.org/draft-04/schema#")
-				.setTitle("Example Schema")
-				.setType(JsonType.OBJECT)
-				.addProperties(
-					new JsonSchemaProperty("firstName", JsonType.STRING),
-					new JsonSchemaProperty("lastName", JsonType.STRING),
-					new JsonSchemaProperty("age", JsonType.INTEGER)
-						.setDescription("Age in years")
-						.setMinimum(0)
-				)
-				.addRequired("firstName", "lastName");
-		} catch (Exception e) {
-			throw new IllegalStateException(e);
-		}
-	}
-
-	/**
-	 * [HTTP PUT /dto/jsonSchema]
-	 * Overwrite the JSON-Schema document
-	 *
-	 * @param schema The new schema document.
-	 * @return The updated schema document.
-	 */
-	@RestPut(summary = "Overwrite the JSON-Schema document", description = "Replaces the schema document with the specified content, and then mirrors it as the response.")
-	public JsonSchema put(@Content JsonSchema schema) {
-		this.schema = schema;
-		return schema;
-	}
-}
\ No newline at end of file
diff --git a/juneau-examples/juneau-examples-rest/src/main/resources/org/apache/juneau/examples/rest/AtomFeedResource_example.json b/juneau-examples/juneau-examples-rest/src/main/resources/org/apache/juneau/examples/rest/AtomFeedResource_example.json
deleted file mode 100644
index e4c0e51262..0000000000
--- a/juneau-examples/juneau-examples-rest/src/main/resources/org/apache/juneau/examples/rest/AtomFeedResource_example.json
+++ /dev/null
@@ -1,86 +0,0 @@
-// ***************************************************************************************************************************
-// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
-// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
-// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
-// * with the License.  You may obtain a copy of the License at                                                              *
-// *                                                                                                                         *
-// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
-// *                                                                                                                         *
-// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
-// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
-// * specific language governing permissions and limitations under the License.                                              *
-// ***************************************************************************************************************************
-{
-	id: {
-		text: 'tag:juneau.sample.com,2013:1'
-	},
-	title: {
-		text: 'Juneau ATOM specification'
-	},
-	links: [
-		{
-			type: 'text/html',
-			href: 'http://www.sample.com/',
-			hreflang: 'en',
-			rel: 'alternate'
-		},
-		{
-			type: 'application/atom+xml',
-			href: 'http://www.sample.com/feed.atom',
-			rel: 'self'
-		}
-	],
-	updated: '2013-05-08T12:29:29Z',
-	entries: [
-		{
-			id: {
-				text: 'tag:juneau.sample.com,2013:1.2345'
-			},
-			title: {
-				text: 'Juneau ATOM specification snapshot'
-			},
-			links: [
-				{
-					type: 'text/html',
-					href: 'http://www.sample.com/2012/05/08/juneau.atom',
-					rel: 'alternate'
-				},
-				{
-					type: 'audio/mpeg',
-					length: 1337,
-					href: 'http://www.sample.com/audio/juneau_podcast.mp3',
-					rel: 'enclosure'
-				}
-			],
-			authors: [
-				{
-					name: 'James Bognar',
-					uri: 'http://www.sample.com/',
-					email: 'jamesbognar@apache.org'
-				}
-			],
-			contributors: [
-				{
-					name: 'Barry M. Caceres'
-				}
-			],
-			updated: '2013-05-08T12:29:29Z',
-			content: {
-				base: 'http://www.apache.org/',
-				lang: 'en',
-				type: 'xhtml',
-				text: '<div><p>[Update: Juneau supports ATOM.]</p></div>'
-			},
-			published: '2013-05-08T12:29:29Z'
-		}
-	],
-	generator: {
-		version: '1.0',
-		uri: 'http://juneau.apache.org/',
-		text: 'Juneau'
-	},
-	subtitle: {
-		type: 'html',
-		text: 'A <em>lot</em> of effort went into making this effortless'
-	}
-}
\ No newline at end of file
diff --git a/juneau-examples/juneau-examples-rest/src/main/resources/org/apache/juneau/examples/rest/JsonSchemaResource_example.json b/juneau-examples/juneau-examples-rest/src/main/resources/org/apache/juneau/examples/rest/JsonSchemaResource_example.json
deleted file mode 100644
index d5bdc9527a..0000000000
--- a/juneau-examples/juneau-examples-rest/src/main/resources/org/apache/juneau/examples/rest/JsonSchemaResource_example.json
+++ /dev/null
@@ -1,35 +0,0 @@
-// ***************************************************************************************************************************
-// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
-// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
-// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
-// * with the License.  You may obtain a copy of the License at                                                              *
-// *                                                                                                                         *
-// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
-// *                                                                                                                         *
-// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
-// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
-// * specific language governing permissions and limitations under the License.                                              *
-// ***************************************************************************************************************************
-{
-	id: 'http://example.com/sample-schema#',
-	'$schema': 'http://json-schema.org/draft-04/schema#',
-	title: 'Example Schema',
-	type: 'object',
-	properties: {
-		firstName: {
-			type: 'string'
-		},
-		lastName: {
-			type: 'string'
-		},
-		age: {
-			description: 'Age in years',
-			type: 'integer',
-			minimum: 0
-		}
-	},
-	required: [
-		'firstName',
-		'lastName'
-	]
-}
\ No newline at end of file
diff --git a/juneau-examples/juneau-examples-rest/src/main/resources/org/apache/juneau/examples/rest/htdocs/ok.png b/juneau-examples/juneau-examples-rest/src/main/resources/org/apache/juneau/examples/rest/htdocs/ok.png
deleted file mode 100644
index 31d84f728a..0000000000
Binary files a/juneau-examples/juneau-examples-rest/src/main/resources/org/apache/juneau/examples/rest/htdocs/ok.png and /dev/null differ
diff --git a/juneau-examples/juneau-examples-rest/src/main/resources/org/apache/juneau/examples/rest/htdocs/severe.png b/juneau-examples/juneau-examples-rest/src/main/resources/org/apache/juneau/examples/rest/htdocs/severe.png
deleted file mode 100644
index 7b71e143fa..0000000000
Binary files a/juneau-examples/juneau-examples-rest/src/main/resources/org/apache/juneau/examples/rest/htdocs/severe.png and /dev/null differ
diff --git a/juneau-examples/juneau-examples-rest/src/main/resources/org/apache/juneau/examples/rest/htdocs/warning.png b/juneau-examples/juneau-examples-rest/src/main/resources/org/apache/juneau/examples/rest/htdocs/warning.png
deleted file mode 100644
index 7a8ab4909c..0000000000
Binary files a/juneau-examples/juneau-examples-rest/src/main/resources/org/apache/juneau/examples/rest/htdocs/warning.png and /dev/null differ
diff --git a/juneau-examples/juneau-examples-rest/src/main/resources/org/apache/juneau/examples/rest/petstore/rest/AddOrderMenuItem_beforeShow.js b/juneau-examples/juneau-examples-rest/src/main/resources/org/apache/juneau/examples/rest/petstore/rest/AddOrderMenuItem_beforeShow.js
deleted file mode 100644
index bb7d703852..0000000000
--- a/juneau-examples/juneau-examples-rest/src/main/resources/org/apache/juneau/examples/rest/petstore/rest/AddOrderMenuItem_beforeShow.js
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- ***************************************************************************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
- * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
- * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
- * with the License.  You may obtain a copy of the License at                                                              *
- *                                                                                                                         *
- *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
- *                                                                                                                         *
- * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
- * specific language governing permissions and limitations under the License.                                              *
- ***************************************************************************************************************************
-*/
-
-/* Populates the list of pets on the add-order menu item. */
-const xhr = new XMLHttpRequest();
-xhr.open('GET', '/petstore/pet?s=status=AVAILABLE&v=id,name', true);
-xhr.setRequestHeader('Accept', 'application/json');
-xhr.onload = function() {
-	const pets = JSON.parse(xhr.responseText);
-	const select = document.getElementById('addPet_names');
-	select.innerHTML = '';
-	for (const i in pets) {
-		const pet = pets[i];
-		const opt = document.createElement('option');
-		opt.value = pet.id;
-		opt.innerHTML = pet.name;
-		select.appendChild(opt);
-	}
-}
-xhr.send();
\ No newline at end of file
diff --git a/juneau-examples/juneau-examples-rest/src/main/resources/org/apache/juneau/examples/rest/petstore/rest/PetStoreResource.json b/juneau-examples/juneau-examples-rest/src/main/resources/org/apache/juneau/examples/rest/petstore/rest/PetStoreResource.json
deleted file mode 100644
index 780c654151..0000000000
--- a/juneau-examples/juneau-examples-rest/src/main/resources/org/apache/juneau/examples/rest/petstore/rest/PetStoreResource.json
+++ /dev/null
@@ -1,75 +0,0 @@
-// ***************************************************************************************************************************
-// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
-// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
-// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
-// * with the License.  You may obtain a copy of the License at                                                              *
-// *                                                                                                                         *
-// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
-// *                                                                                                                         *
-// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
-// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
-// * specific language governing permissions and limitations under the License.                                              *
-// ***************************************************************************************************************************
-
-{
-	"swagger": "2.0",
-	"info": {
-		"version": "1.0.0",
-		"title": "Swagger Petstore",
-		"termsOfService": "You are on your own.",
-		"contact": {
-			"name": "Juneau Development Team",
-			"email": "dev@juneau.apache.org",
-			"url": "http://juneau.apache.org"
-		},
-		"license": {
-			"name": "Apache 2.0",
-			"url": "http://www.apache.org/licenses/LICENSE-2.0.html"
-		}
-	},
-	"externalDocs": {
-		"description": "Find out more about Juneau",
-		"url": "http://juneau.apache.org"
-	},
-	"tags": [
-		{
-			"name": "pet",
-			"description": "Everything about your Pets",
-			"externalDocs": {
-				"description": "Find out more",
-				"url": "http://juneau.apache.org"
-			}
-		},
-		{
-			"name": "store",
-			"description": "Access to Petstore orders"
-		},
-		{
-			"name": "user",
-			"description": "Operations about user",
-			"externalDocs": {
-				"description": "Find out more about our store",
-				"url": "http://juneau.apache.org"
-			}
-		}
-	],
-	"schemes": [
-		"http"
-	],
-	"securityDefinitions": {
-		"petstore_auth": {
-			"type": "oauth2",
-			"authorizationUrl": "http://petstore.swagger.io/oauth/dialog",
-			"flow": "implicit",
-			"scopes": {
-				"write:pets": "modify pets in your account",
-				"read:pets": "read your pets"
-			}
-		},
-		"api_key": {
-			"type": "apiKey",
-			"name": "api_key",
-			"in": "header"
-		}
-	}
-}
\ No newline at end of file
diff --git a/juneau-examples/juneau-examples-rest/src/main/resources/org/apache/juneau/examples/rest/petstore/rest/htdocs/background.jpg b/juneau-examples/juneau-examples-rest/src/main/resources/org/apache/juneau/examples/rest/petstore/rest/htdocs/background.jpg
deleted file mode 100644
index d75bcf13b6..0000000000
Binary files a/juneau-examples/juneau-examples-rest/src/main/resources/org/apache/juneau/examples/rest/petstore/rest/htdocs/background.jpg and /dev/null differ
diff --git a/juneau-examples/juneau-examples-rest/src/main/resources/org/apache/juneau/examples/rest/petstore/rest/htdocs/bird.png b/juneau-examples/juneau-examples-rest/src/main/resources/org/apache/juneau/examples/rest/petstore/rest/htdocs/bird.png
deleted file mode 100644
index 636ecf81dc..0000000000
Binary files a/juneau-examples/juneau-examples-rest/src/main/resources/org/apache/juneau/examples/rest/petstore/rest/htdocs/bird.png and /dev/null differ
diff --git a/juneau-examples/juneau-examples-rest/src/main/resources/org/apache/juneau/examples/rest/petstore/rest/htdocs/cat.png b/juneau-examples/juneau-examples-rest/src/main/resources/org/apache/juneau/examples/rest/petstore/rest/htdocs/cat.png
deleted file mode 100644
index 917abc616a..0000000000
Binary files a/juneau-examples/juneau-examples-rest/src/main/resources/org/apache/juneau/examples/rest/petstore/rest/htdocs/cat.png and /dev/null differ
diff --git a/juneau-examples/juneau-examples-rest/src/main/resources/org/apache/juneau/examples/rest/petstore/rest/htdocs/dog.png b/juneau-examples/juneau-examples-rest/src/main/resources/org/apache/juneau/examples/rest/petstore/rest/htdocs/dog.png
deleted file mode 100644
index e100eb269e..0000000000
Binary files a/juneau-examples/juneau-examples-rest/src/main/resources/org/apache/juneau/examples/rest/petstore/rest/htdocs/dog.png and /dev/null differ
diff --git a/juneau-examples/juneau-examples-rest/src/main/resources/org/apache/juneau/examples/rest/petstore/rest/htdocs/fish.png b/juneau-examples/juneau-examples-rest/src/main/resources/org/apache/juneau/examples/rest/petstore/rest/htdocs/fish.png
deleted file mode 100644
index ca76a46af9..0000000000
Binary files a/juneau-examples/juneau-examples-rest/src/main/resources/org/apache/juneau/examples/rest/petstore/rest/htdocs/fish.png and /dev/null differ
diff --git a/juneau-examples/juneau-examples-rest/src/main/resources/org/apache/juneau/examples/rest/petstore/rest/htdocs/mouse.png b/juneau-examples/juneau-examples-rest/src/main/resources/org/apache/juneau/examples/rest/petstore/rest/htdocs/mouse.png
deleted file mode 100644
index 53080064c0..0000000000
Binary files a/juneau-examples/juneau-examples-rest/src/main/resources/org/apache/juneau/examples/rest/petstore/rest/htdocs/mouse.png and /dev/null differ
diff --git a/juneau-examples/juneau-examples-rest/src/main/resources/org/apache/juneau/examples/rest/petstore/rest/htdocs/rabbit.png b/juneau-examples/juneau-examples-rest/src/main/resources/org/apache/juneau/examples/rest/petstore/rest/htdocs/rabbit.png
deleted file mode 100644
index f0134703da..0000000000
Binary files a/juneau-examples/juneau-examples-rest/src/main/resources/org/apache/juneau/examples/rest/petstore/rest/htdocs/rabbit.png and /dev/null differ
diff --git a/juneau-examples/juneau-examples-rest/src/main/resources/org/apache/juneau/examples/rest/petstore/rest/htdocs/snake.png b/juneau-examples/juneau-examples-rest/src/main/resources/org/apache/juneau/examples/rest/petstore/rest/htdocs/snake.png
deleted file mode 100644
index 7f176609ce..0000000000
Binary files a/juneau-examples/juneau-examples-rest/src/main/resources/org/apache/juneau/examples/rest/petstore/rest/htdocs/snake.png and /dev/null differ
diff --git a/juneau-examples/juneau-examples-rest/src/main/resources/org/apache/juneau/examples/rest/petstore/rest/photos/cat.jpg b/juneau-examples/juneau-examples-rest/src/main/resources/org/apache/juneau/examples/rest/petstore/rest/photos/cat.jpg
deleted file mode 100644
index d75bcf13b6..0000000000
Binary files a/juneau-examples/juneau-examples-rest/src/main/resources/org/apache/juneau/examples/rest/petstore/rest/photos/cat.jpg and /dev/null differ
diff --git a/juneau-examples/pom.xml b/juneau-examples/pom.xml
index 0a316e6a73..44e4b9176e 100644
--- a/juneau-examples/pom.xml
+++ b/juneau-examples/pom.xml
@@ -32,10 +32,6 @@
 
 	<modules>
 		<module>juneau-examples-core</module>
-		<module>juneau-examples-rest</module>
-		<module>juneau-examples-rest-jetty</module>
-		<module>juneau-examples-rest-springboot</module>
-		<module>juneau-examples-rest-jetty-ftest</module>
 	</modules>
 
 	<build>
diff --git a/juneau-examples/juneau-examples-rest-jetty-ftest/pom.xml b/juneau-petstore/juneau-petstore-core/pom.xml
similarity index 52%
rename from juneau-examples/juneau-examples-rest-jetty-ftest/pom.xml
rename to juneau-petstore/juneau-petstore-core/pom.xml
index d9d79dce26..902784401a 100644
--- a/juneau-examples/juneau-examples-rest-jetty-ftest/pom.xml
+++ b/juneau-petstore/juneau-petstore-core/pom.xml
@@ -21,30 +21,54 @@
 
 	<parent>
 		<groupId>org.apache.juneau</groupId>
-		<artifactId>juneau-examples</artifactId>
+		<artifactId>juneau-petstore</artifactId>
 		<version>10.0.0-SNAPSHOT</version>
 	</parent>
 
-	<artifactId>juneau-examples-rest-jetty-ftest</artifactId>
-	<name>Apache Juneau REST Jetty Functional Tests</name>
-	<description>Apache Juneau REST Example Function Tests</description>
+	<artifactId>juneau-petstore-core</artifactId>
+	<name>Apache Juneau Petstore Core</name>
+	<description>Apache Juneau Petstore - shared domain model and REST resources</description>
+	<packaging>jar</packaging>
 
 	<properties>
 		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
 	</properties>
 
-
 	<dependencies>
 		<dependency>
 			<groupId>org.apache.juneau</groupId>
-			<artifactId>juneau-examples-rest-jetty</artifactId>
+			<artifactId>juneau-rest-server</artifactId>
 			<version>${project.version}</version>
 		</dependency>
+
+		<!--
+			View-engine bridges (pure-classpath: render identically under Jetty AND Spring Boot's
+			embedded container, giving the petstore deployment-parity for the view-demo surface).
+			Bridge modules only ship engine APIs in `provided` scope, so each engine dep is declared
+			explicitly here.
+		-->
 		<dependency>
 			<groupId>org.apache.juneau</groupId>
-			<artifactId>juneau-rest-server</artifactId>
+			<artifactId>juneau-rest-server-view-mustache</artifactId>
 			<version>${project.version}</version>
 		</dependency>
+		<dependency>
+			<groupId>com.github.spullara.mustache.java</groupId>
+			<artifactId>compiler</artifactId>
+			<version>0.9.14</version>
+		</dependency>
+		<dependency>
+			<groupId>org.apache.juneau</groupId>
+			<artifactId>juneau-rest-server-view-freemarker</artifactId>
+			<version>${project.version}</version>
+		</dependency>
+		<dependency>
+			<groupId>org.freemarker</groupId>
+			<artifactId>freemarker</artifactId>
+			<version>2.3.34</version>
+		</dependency>
+
+		<!-- Test dependencies -->
 		<dependency>
 			<groupId>org.junit.jupiter</groupId>
 			<artifactId>junit-jupiter</artifactId>
@@ -52,9 +76,28 @@
 			<scope>test</scope>
 		</dependency>
 		<dependency>
-			<groupId>org.junit.vintage</groupId>
-			<artifactId>junit-vintage-engine</artifactId>
-			<version>${junit.version}</version>
+			<groupId>org.apache.juneau</groupId>
+			<artifactId>juneau-junit5</artifactId>
+			<version>${project.version}</version>
+			<scope>test</scope>
+		</dependency>
+		<dependency>
+			<groupId>org.apache.juneau</groupId>
+			<artifactId>juneau-test-utils</artifactId>
+			<version>${project.version}</version>
+			<scope>test</scope>
+		</dependency>
+		<dependency>
+			<groupId>org.apache.juneau</groupId>
+			<artifactId>juneau-rest-mock</artifactId>
+			<version>${project.version}</version>
+			<scope>test</scope>
+		</dependency>
+		<dependency>
+			<groupId>org.apache.juneau</groupId>
+			<artifactId>juneau-bct</artifactId>
+			<version>${project.version}</version>
+			<scope>test</scope>
 		</dependency>
 	</dependencies>
 
@@ -62,14 +105,20 @@
 		<plugins>
 			<plugin>
 				<groupId>org.apache.maven.plugins</groupId>
-				<artifactId>maven-surefire-plugin</artifactId>
-				<configuration>
-					<includes>
-						<include>
-							**/_TestSuite.java
-						</include>
-					</includes>
-				</configuration>
+				<artifactId>maven-source-plugin</artifactId>
+				<executions>
+					<execution>
+						<id>attach-sources</id>
+						<phase>verify</phase>
+						<goals>
+							<goal>jar-no-fork</goal>
+						</goals>
+					</execution>
+				</executions>
+			</plugin>
+			<plugin>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-jar-plugin</artifactId>
 			</plugin>
 			<plugin>
 				<groupId>org.jacoco</groupId>
diff --git a/juneau-petstore/juneau-petstore-core/src/main/java/org/apache/juneau/petstore/auth/StubBearerTokenValidator.java b/juneau-petstore/juneau-petstore-core/src/main/java/org/apache/juneau/petstore/auth/StubBearerTokenValidator.java
new file mode 100644
index 0000000000..3fa399f9d8
--- /dev/null
+++ b/juneau-petstore/juneau-petstore-core/src/main/java/org/apache/juneau/petstore/auth/StubBearerTokenValidator.java
@@ -0,0 +1,75 @@
+/*
+ * 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.juneau.petstore.auth;
+
+import java.security.*;
+import java.util.*;
+import java.util.concurrent.*;
+
+import org.apache.juneau.rest.server.auth.*;
+
+/**
+ * Stub {@link TokenValidator} for the petstore demo — recognises an in-memory map of opaque bearer tokens.
+ *
+ * <p>
+ * <b>NOT FOR PRODUCTION USE.</b>  This is a sample/demo validator that maps fixed token strings to fixed user
+ * principals.  Real deployments should plug in {@code JwtTokenValidator} from {@code juneau-rest-server-auth-jwt}
+ * (signed JWTs against a JWKS), an opaque-token store backed by a database, or RFC 7662 introspection.
+ *
+ * <p>
+ * Default token table:
+ * <ul>
+ * 	<li>{@code petstore-user} → principal {@code "alice"}
+ * 	<li>{@code petstore-admin} → principal {@code "admin"}
+ * </ul>
+ *
+ * <p>
+ * Other token strings throw {@link AuthenticationException} carrying a {@code WWW-Authenticate: Bearer realm="petstore"}
+ * challenge — the {@code AuthFilterChain} in turn returns {@code 401}.
+ */
+public class StubBearerTokenValidator implements TokenValidator {
+
+	/** Default in-memory token table. */
+	public static final Map<String,String> DEFAULT_TOKENS = Map.of(
+		"petstore-user", "alice",
+		"petstore-admin", "admin"
+	);
+
+	private final Map<String,String> tokenToUser;
+
+	/** Constructor using the {@link #DEFAULT_TOKENS} table. */
+	public StubBearerTokenValidator() {
+		this(DEFAULT_TOKENS);
+	}
+
+	/**
+	 * Constructor.
+	 *
+	 * @param tokenToUser Map of token string to principal name.  Copied defensively.
+	 */
+	public StubBearerTokenValidator(Map<String,String> tokenToUser) {
+		this.tokenToUser = new ConcurrentHashMap<>(Objects.requireNonNull(tokenToUser, "tokenToUser"));
+	}
+
+	@Override
+	public Principal validate(String token) throws AuthenticationException {
+		var name = tokenToUser.get(token);
+		if (name == null)
+			throw new AuthenticationException("Unknown bearer token").wwwAuthenticate("Bearer realm=\"petstore\"");
+		return () -> name;
+	}
+}
diff --git a/juneau-examples/juneau-examples-rest-jetty/src/main/java/org/apache/juneau/examples/rest/jetty/package-info.java b/juneau-petstore/juneau-petstore-core/src/main/java/org/apache/juneau/petstore/auth/package-info.java
old mode 100755
new mode 100644
similarity index 62%
copy from juneau-examples/juneau-examples-rest-jetty/src/main/java/org/apache/juneau/examples/rest/jetty/package-info.java
copy to juneau-petstore/juneau-petstore-core/src/main/java/org/apache/juneau/petstore/auth/package-info.java
index 0ba233d284..34727536f3
--- a/juneau-examples/juneau-examples-rest-jetty/src/main/java/org/apache/juneau/examples/rest/jetty/package-info.java
+++ b/juneau-petstore/juneau-petstore-core/src/main/java/org/apache/juneau/petstore/auth/package-info.java
@@ -15,11 +15,12 @@
  * limitations under the License.
  */
 /**
- * REST Jetty Examples
+ * Petstore auth helpers — stub validators and other glue used by the deployment-side
+ * {@code AuthFilterChain} configurations.
  *
  * <p>
- * Example classes demonstrating how to deploy Juneau REST servers using Jetty.
- * These examples show various Jetty-based REST API deployment scenarios.
- * </p>
+ * The core ships only deployment-agnostic validators (e.g. {@link org.apache.juneau.petstore.auth.StubBearerTokenValidator}).
+ * Each deployment ({@code juneau-petstore-jetty}, {@code juneau-petstore-springboot}) wires its own
+ * {@code AuthFilterChain} bean composing these validators with the appropriate filter mounts.
  */
-package org.apache.juneau.examples.rest.jetty;
+package org.apache.juneau.petstore.auth;
diff --git a/juneau-petstore/juneau-petstore-core/src/main/java/org/apache/juneau/petstore/dto/Order.java b/juneau-petstore/juneau-petstore-core/src/main/java/org/apache/juneau/petstore/dto/Order.java
new file mode 100644
index 0000000000..9cb4344f15
--- /dev/null
+++ b/juneau-petstore/juneau-petstore-core/src/main/java/org/apache/juneau/petstore/dto/Order.java
@@ -0,0 +1,115 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.juneau.petstore.dto;
+
+/**
+ * Order domain bean.
+ *
+ * <p>
+ * Represents an order placed against a {@link Pet}.
+ *
+ * <h5 class='section'>See Also:</h5><ul>
+ * 	<li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/JuneauPetstoreOverview">juneau-petstore</a>
+ * </ul>
+ */
+public class Order {
+
+	private long id;
+	private long petId;
+	private String shipDate;
+	private OrderStatus status;
+
+	/**
+	 * Returns the order ID.
+	 *
+	 * @return The order ID.
+	 */
+	public long getId() {
+		return id;
+	}
+
+	/**
+	 * Sets the order ID.
+	 *
+	 * @param value The new value.
+	 * @return This object.
+	 */
+	public Order setId(long value) {
+		id = value;
+		return this;
+	}
+
+	/**
+	 * Returns the ID of the pet being ordered.
+	 *
+	 * @return The ID of the pet being ordered.
+	 */
+	public long getPetId() {
+		return petId;
+	}
+
+	/**
+	 * Sets the ID of the pet being ordered.
+	 *
+	 * @param value The new value.
+	 * @return This object.
+	 */
+	public Order setPetId(long value) {
+		petId = value;
+		return this;
+	}
+
+	/**
+	 * Returns the shipping date as an ISO 8601 string.
+	 *
+	 * @return The shipping date as an ISO 8601 string.  Can be <jk>null</jk>.
+	 */
+	public String getShipDate() {
+		return shipDate;
+	}
+
+	/**
+	 * Sets the shipping date.
+	 *
+	 * @param value The new value.  Can be <jk>null</jk>.
+	 * @return This object.
+	 */
+	public Order setShipDate(String value) {
+		shipDate = value;
+		return this;
+	}
+
+	/**
+	 * Returns the lifecycle status of the order.
+	 *
+	 * @return The lifecycle status of the order.
+	 */
+	public OrderStatus getStatus() {
+		return status;
+	}
+
+	/**
+	 * Sets the lifecycle status of the order.
+	 *
+	 * @param value The new value.
+	 * @return This object.
+	 */
+	public Order setStatus(OrderStatus value) {
+		status = value;
+		return this;
+	}
+}
diff --git a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/command/package-info.java b/juneau-petstore/juneau-petstore-core/src/main/java/org/apache/juneau/petstore/dto/OrderStatus.java
old mode 100755
new mode 100644
similarity index 74%
copy from juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/command/package-info.java
copy to juneau-petstore/juneau-petstore-core/src/main/java/org/apache/juneau/petstore/dto/OrderStatus.java
index dd83076900..f4715ad3b7
--- a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/command/package-info.java
+++ b/juneau-petstore/juneau-petstore-core/src/main/java/org/apache/juneau/petstore/dto/OrderStatus.java
@@ -14,12 +14,19 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+package org.apache.juneau.petstore.dto;
+
 /**
- * REST Command Examples
- *
- * <p>
- * Example classes demonstrating how to use command pattern with Juneau's REST server.
- * These examples show various command-based REST API scenarios.
- * </p>
+ * Lifecycle status of an {@link Order}.
  */
-package org.apache.juneau.examples.rest.command;
+public enum OrderStatus {
+
+	/** Order has been placed but not yet approved. */
+	PLACED,
+
+	/** Order has been approved for shipment. */
+	APPROVED,
+
+	/** Order has been delivered. */
+	DELIVERED
+}
diff --git a/juneau-petstore/juneau-petstore-core/src/main/java/org/apache/juneau/petstore/dto/Pet.java b/juneau-petstore/juneau-petstore-core/src/main/java/org/apache/juneau/petstore/dto/Pet.java
new file mode 100644
index 0000000000..322472c5ba
--- /dev/null
+++ b/juneau-petstore/juneau-petstore-core/src/main/java/org/apache/juneau/petstore/dto/Pet.java
@@ -0,0 +1,180 @@
+/*
+ * 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.juneau.petstore.dto;
+
+import java.util.*;
+
+/**
+ * Pet domain bean.
+ *
+ * <p>
+ * Represents a pet for sale in the petstore.
+ *
+ * <h5 class='section'>See Also:</h5><ul>
+ * 	<li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/JuneauPetstoreOverview">juneau-petstore</a>
+ * </ul>
+ */
+public class Pet {
+
+	private long id;
+	private Species species;
+	private String name;
+	private float price;
+	private List<String> tags;
+	private PetStatus status;
+	private String photo;
+
+	/**
+	 * Returns the pet ID.
+	 *
+	 * @return The pet ID.
+	 */
+	public long getId() {
+		return id;
+	}
+
+	/**
+	 * Sets the pet ID.
+	 *
+	 * @param value The new value.
+	 * @return This object.
+	 */
+	public Pet setId(long value) {
+		id = value;
+		return this;
+	}
+
+	/**
+	 * Returns the species of the pet.
+	 *
+	 * @return The species of the pet.
+	 */
+	public Species getSpecies() {
+		return species;
+	}
+
+	/**
+	 * Sets the species of the pet.
+	 *
+	 * @param value The new value.
+	 * @return This object.
+	 */
+	public Pet setSpecies(Species value) {
+		species = value;
+		return this;
+	}
+
+	/**
+	 * Returns the name of the pet.
+	 *
+	 * @return The name of the pet.
+	 */
+	public String getName() {
+		return name;
+	}
+
+	/**
+	 * Sets the name of the pet.
+	 *
+	 * @param value The new value.
+	 * @return This object.
+	 */
+	public Pet setName(String value) {
+		name = value;
+		return this;
+	}
+
+	/**
+	 * Returns the price of the pet.
+	 *
+	 * @return The price of the pet.
+	 */
+	public float getPrice() {
+		return price;
+	}
+
+	/**
+	 * Sets the price of the pet.
+	 *
+	 * @param value The new value.
+	 * @return This object.
+	 */
+	public Pet setPrice(float value) {
+		price = value;
+		return this;
+	}
+
+	/**
+	 * Returns the tags associated with the pet.
+	 *
+	 * @return The tags associated with the pet.  Can be <jk>null</jk>.
+	 */
+	public List<String> getTags() {
+		return tags;
+	}
+
+	/**
+	 * Sets the tags associated with the pet.
+	 *
+	 * @param value The new value.  Can be <jk>null</jk>.
+	 * @return This object.
+	 */
+	public Pet setTags(List<String> value) {
+		tags = value;
+		return this;
+	}
+
+	/**
+	 * Returns the lifecycle status of the pet.
+	 *
+	 * @return The lifecycle status of the pet.
+	 */
+	public PetStatus getStatus() {
+		return status;
+	}
+
+	/**
+	 * Sets the lifecycle status of the pet.
+	 *
+	 * @param value The new value.
+	 * @return This object.
+	 */
+	public Pet setStatus(PetStatus value) {
+		status = value;
+		return this;
+	}
+
+	/**
+	 * Returns the URI of the pet photo.
+	 *
+	 * @return The URI of the pet photo.  Can be <jk>null</jk>.
+	 */
+	public String getPhoto() {
+		return photo;
+	}
+
+	/**
+	 * Sets the URI of the pet photo.
+	 *
+	 * @param value The new value.  Can be <jk>null</jk>.
+	 * @return This object.
+	 */
+	public Pet setPhoto(String value) {
+		photo = value;
+		return this;
+	}
+}
diff --git a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/command/package-info.java b/juneau-petstore/juneau-petstore-core/src/main/java/org/apache/juneau/petstore/dto/PetStatus.java
old mode 100755
new mode 100644
similarity index 76%
copy from juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/command/package-info.java
copy to juneau-petstore/juneau-petstore-core/src/main/java/org/apache/juneau/petstore/dto/PetStatus.java
index dd83076900..dff750be91
--- a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/command/package-info.java
+++ b/juneau-petstore/juneau-petstore-core/src/main/java/org/apache/juneau/petstore/dto/PetStatus.java
@@ -14,12 +14,19 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+package org.apache.juneau.petstore.dto;
+
 /**
- * REST Command Examples
- *
- * <p>
- * Example classes demonstrating how to use command pattern with Juneau's REST server.
- * These examples show various command-based REST API scenarios.
- * </p>
+ * Lifecycle status of a {@link Pet}.
  */
-package org.apache.juneau.examples.rest.command;
+public enum PetStatus {
+
+	/** Pet is available for purchase. */
+	AVAILABLE,
+
+	/** Pet has a pending order. */
+	PENDING,
+
+	/** Pet has been sold. */
+	SOLD
+}
diff --git a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/dto/package-info.java b/juneau-petstore/juneau-petstore-core/src/main/java/org/apache/juneau/petstore/dto/Species.java
old mode 100755
new mode 100644
similarity index 75%
rename from juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/dto/package-info.java
rename to juneau-petstore/juneau-petstore-core/src/main/java/org/apache/juneau/petstore/dto/Species.java
index 24446f8102..171c7d5ccd
--- a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/dto/package-info.java
+++ b/juneau-petstore/juneau-petstore-core/src/main/java/org/apache/juneau/petstore/dto/Species.java
@@ -14,12 +14,31 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+package org.apache.juneau.petstore.dto;
+
 /**
- * REST DTO Examples
- *
- * <p>
- * Example classes demonstrating how to use Data Transfer Objects (DTOs) with Juneau's REST server.
- * These examples show various DTO serialization and validation scenarios.
- * </p>
+ * Pet species enumeration.
  */
-package org.apache.juneau.examples.rest.dto;
+public enum Species {
+
+	/** Bird. */
+	BIRD,
+
+	/** Cat. */
+	CAT,
+
+	/** Dog. */
+	DOG,
+
+	/** Fish. */
+	FISH,
+
+	/** Mouse. */
+	MOUSE,
+
+	/** Rabbit. */
+	RABBIT,
+
+	/** Snake. */
+	SNAKE
+}
diff --git a/juneau-petstore/juneau-petstore-core/src/main/java/org/apache/juneau/petstore/dto/User.java b/juneau-petstore/juneau-petstore-core/src/main/java/org/apache/juneau/petstore/dto/User.java
new file mode 100644
index 0000000000..9cafa22815
--- /dev/null
+++ b/juneau-petstore/juneau-petstore-core/src/main/java/org/apache/juneau/petstore/dto/User.java
@@ -0,0 +1,181 @@
+/*
+ * 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.juneau.petstore.dto;
+
+/**
+ * User domain bean.
+ *
+ * <p>
+ * Represents a registered petstore user.  The {@code username} is the primary key.
+ *
+ * <h5 class='section'>See Also:</h5><ul>
+ * 	<li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/JuneauPetstoreOverview">juneau-petstore</a>
+ * </ul>
+ */
+public class User {
+
+	private String username;
+	private String firstName;
+	private String lastName;
+	private String email;
+	private String password;
+	private String phone;
+	private UserStatus userStatus;
+
+	/**
+	 * Returns the username (primary key).
+	 *
+	 * @return The username.
+	 */
+	public String getUsername() {
+		return username;
+	}
+
+	/**
+	 * Sets the username.
+	 *
+	 * @param value The new value.
+	 * @return This object.
+	 */
+	public User setUsername(String value) {
+		username = value;
+		return this;
+	}
+
+	/**
+	 * Returns the first name.
+	 *
+	 * @return The first name.  Can be <jk>null</jk>.
+	 */
+	public String getFirstName() {
+		return firstName;
+	}
+
+	/**
+	 * Sets the first name.
+	 *
+	 * @param value The new value.  Can be <jk>null</jk>.
+	 * @return This object.
+	 */
+	public User setFirstName(String value) {
+		firstName = value;
+		return this;
+	}
+
+	/**
+	 * Returns the last name.
+	 *
+	 * @return The last name.  Can be <jk>null</jk>.
+	 */
+	public String getLastName() {
+		return lastName;
+	}
+
+	/**
+	 * Sets the last name.
+	 *
+	 * @param value The new value.  Can be <jk>null</jk>.
+	 * @return This object.
+	 */
+	public User setLastName(String value) {
+		lastName = value;
+		return this;
+	}
+
+	/**
+	 * Returns the email address.
+	 *
+	 * @return The email address.  Can be <jk>null</jk>.
+	 */
+	public String getEmail() {
+		return email;
+	}
+
+	/**
+	 * Sets the email address.
+	 *
+	 * @param value The new value.  Can be <jk>null</jk>.
+	 * @return This object.
+	 */
+	public User setEmail(String value) {
+		email = value;
+		return this;
+	}
+
+	/**
+	 * Returns the password.
+	 *
+	 * <p>
+	 * Stored in plaintext for sample purposes only.  Do not use this pattern in production.
+	 *
+	 * @return The password.  Can be <jk>null</jk>.
+	 */
+	public String getPassword() {
+		return password;
+	}
+
+	/**
+	 * Sets the password.
+	 *
+	 * @param value The new value.  Can be <jk>null</jk>.
+	 * @return This object.
+	 */
+	public User setPassword(String value) {
+		password = value;
+		return this;
+	}
+
+	/**
+	 * Returns the phone number.
+	 *
+	 * @return The phone number.  Can be <jk>null</jk>.
+	 */
+	public String getPhone() {
+		return phone;
+	}
+
+	/**
+	 * Sets the phone number.
+	 *
+	 * @param value The new value.  Can be <jk>null</jk>.
+	 * @return This object.
+	 */
+	public User setPhone(String value) {
+		phone = value;
+		return this;
+	}
+
+	/**
+	 * Returns the user account status.
+	 *
+	 * @return The user account status.
+	 */
+	public UserStatus getUserStatus() {
+		return userStatus;
+	}
+
+	/**
+	 * Sets the user account status.
+	 *
+	 * @param value The new value.
+	 * @return This object.
+	 */
+	public User setUserStatus(UserStatus value) {
+		userStatus = value;
+		return this;
+	}
+}
diff --git a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/package-info.java b/juneau-petstore/juneau-petstore-core/src/main/java/org/apache/juneau/petstore/dto/UserStatus.java
old mode 100755
new mode 100644
similarity index 77%
copy from juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/package-info.java
copy to juneau-petstore/juneau-petstore-core/src/main/java/org/apache/juneau/petstore/dto/UserStatus.java
index fdfb46d460..11366966c2
--- a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/package-info.java
+++ b/juneau-petstore/juneau-petstore-core/src/main/java/org/apache/juneau/petstore/dto/UserStatus.java
@@ -14,12 +14,16 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+package org.apache.juneau.petstore.dto;
+
 /**
- * REST Server Examples
- *
- * <p>
- * Example classes demonstrating how to use Juneau's REST server capabilities.
- * These examples show various REST API creation and deployment scenarios.
- * </p>
+ * Lifecycle status of a {@link User}.
  */
-package org.apache.juneau.examples.rest;
+public enum UserStatus {
+
+	/** User account is active. */
+	ACTIVE,
+
+	/** User account is inactive. */
+	INACTIVE
+}
diff --git a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/package-info.java b/juneau-petstore/juneau-petstore-core/src/main/java/org/apache/juneau/petstore/dto/package-info.java
old mode 100755
new mode 100644
similarity index 78%
rename from juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/package-info.java
rename to juneau-petstore/juneau-petstore-core/src/main/java/org/apache/juneau/petstore/dto/package-info.java
index fdfb46d460..641a08b855
--- a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/package-info.java
+++ b/juneau-petstore/juneau-petstore-core/src/main/java/org/apache/juneau/petstore/dto/package-info.java
@@ -15,11 +15,10 @@
  * limitations under the License.
  */
 /**
- * REST Server Examples
+ * Petstore domain beans (DTOs).
  *
  * <p>
- * Example classes demonstrating how to use Juneau's REST server capabilities.
- * These examples show various REST API creation and deployment scenarios.
- * </p>
+ * Plain Juneau beans representing the petstore domain model.  Persistence is in-memory; no JPA or database
+ * dependencies.
  */
-package org.apache.juneau.examples.rest;
+package org.apache.juneau.petstore.dto;
diff --git a/juneau-examples/juneau-examples-rest-springboot/src/main/java/org/apache/juneau/examples/rest/springboot/HelloWorldMessageProvider.java b/juneau-petstore/juneau-petstore-core/src/main/java/org/apache/juneau/petstore/package-info.java
similarity index 60%
copy from juneau-examples/juneau-examples-rest-springboot/src/main/java/org/apache/juneau/examples/rest/springboot/HelloWorldMessageProvider.java
copy to juneau-petstore/juneau-petstore-core/src/main/java/org/apache/juneau/petstore/package-info.java
index 665715d937..25b896cd04 100644
--- a/juneau-examples/juneau-examples-rest-springboot/src/main/java/org/apache/juneau/examples/rest/springboot/HelloWorldMessageProvider.java
+++ b/juneau-petstore/juneau-petstore-core/src/main/java/org/apache/juneau/petstore/package-info.java
@@ -14,32 +14,18 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.juneau.examples.rest.springboot;
-
-import java.util.function.*;
-
 /**
- * An example of a Spring bean that can be used for injecting messages into {@link HelloWorldResource}.
+ * Apache Juneau Petstore - shared domain model and REST resources.
+ *
+ * <p>
+ * The {@code juneau-petstore-core} module owns the petstore's deployment-agnostic surface:
+ * domain DTOs ({@code dto}), the in-memory store ({@code service}), and the REST resources
+ * ({@code rest}).  It is consumed verbatim by both {@code juneau-petstore-jetty} and
+ * {@code juneau-petstore-springboot} so the two deployments demonstrate an identical REST
+ * surface by construction.
  *
  * <h5 class='section'>See Also:</h5><ul>
- * 	<li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/JuneauRestServerSpringbootBasics">juneau-rest-server-springboot Basics</a>
+ * 	<li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/JuneauPetstoreOverview">juneau-petstore</a>
  * </ul>
  */
-public class HelloWorldMessageProvider implements Supplier<String> {
-
-	private final String message;
-
-	/**
-	 * Constructor.
-	 *
-	 * @param message The message to display.
-	 */
-	public HelloWorldMessageProvider(String message) {
-		this.message = message;
-	}
-
-	@Override
-	public String get() {
-		return message;
-	}
-}
\ No newline at end of file
+package org.apache.juneau.petstore;
diff --git a/juneau-petstore/juneau-petstore-core/src/main/java/org/apache/juneau/petstore/rest/PetFreemarkerViewResource.java b/juneau-petstore/juneau-petstore-core/src/main/java/org/apache/juneau/petstore/rest/PetFreemarkerViewResource.java
new file mode 100644
index 0000000000..0633966fcd
--- /dev/null
+++ b/juneau-petstore/juneau-petstore-core/src/main/java/org/apache/juneau/petstore/rest/PetFreemarkerViewResource.java
@@ -0,0 +1,82 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.juneau.petstore.rest;
+
+import org.apache.juneau.commons.inject.Bean;
+import org.apache.juneau.http.*;
+import org.apache.juneau.http.response.*;
+import org.apache.juneau.petstore.service.*;
+import org.apache.juneau.rest.server.*;
+import org.apache.juneau.rest.server.servlet.*;
+import org.apache.juneau.rest.server.view.*;
+import org.apache.juneau.rest.server.view.freemarker.*;
+
+/**
+ * Petstore FreeMarker view demo.
+ *
+ * <p>
+ * Pure-classpath analogue of {@link PetMustacheViewResource}: the FreeMarker bridge is engine-agnostic and
+ * renders identically under both the Jetty and Spring Boot deployments.  Resolves
+ * {@code petstore-templates/pet.ftlh} via the configured {@link FreemarkerMixin}.
+ *
+ * <h5 class='section'>See Also:</h5><ul>
+ * 	<li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/FreemarkerViewSupport">FreeMarker View Support</a>
+ * 	<li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/JuneauPetstoreOverview">juneau-petstore</a>
+ * </ul>
+ */
+@Rest(
+	path="/pet-views/freemarker",
+	title="Pet detail (FreeMarker)",
+	description="Renders a pet detail page through the FreeMarker view-rendering bridge.",
+	responseProcessors={FreemarkerViewRenderer.class}
+)
+@SuppressWarnings({
+	"java:S110" // Inheritance depth acceptable for example/demo code
+})
+public class PetFreemarkerViewResource extends BasicRestServlet {
+
+	private static final long serialVersionUID = 1L;
+
+	private final PetStore store = new PetStore();
+
+	/**
+	 * Provides a {@link FreemarkerMixin} configured to resolve templates under {@code petstore-templates/}.
+	 *
+	 * @return The freemarker mixin bean.
+	 */
+	@Bean
+	public FreemarkerMixin freemarker() {
+		return FreemarkerMixin.create()
+			.basePath("/petstore-templates/")
+			.build();
+	}
+
+	/**
+	 * GET /pets/{id}/view — renders a pet detail HTML page through FreeMarker.
+	 *
+	 * @param id The pet ID.
+	 * @return A {@link FreemarkerView} bound to the {@code pet.ftlh} template.
+	 * @throws NotFound If no pet with the given ID exists.
+	 */
+	@RestGet("/pets/{id}/view")
+	public View viewPet(@Path("id") long id) {
+		var pet = store.getPet(id);
+		if (pet == null)
+			throw new NotFound("Pet not found: id={0}", id);
+		return FreemarkerView.of("pet.ftlh").attr("pet", pet);
+	}
+}
diff --git a/juneau-petstore/juneau-petstore-core/src/main/java/org/apache/juneau/petstore/rest/PetMustacheViewResource.java b/juneau-petstore/juneau-petstore-core/src/main/java/org/apache/juneau/petstore/rest/PetMustacheViewResource.java
new file mode 100644
index 0000000000..6ece716f8a
--- /dev/null
+++ b/juneau-petstore/juneau-petstore-core/src/main/java/org/apache/juneau/petstore/rest/PetMustacheViewResource.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.juneau.petstore.rest;
+
+import org.apache.juneau.commons.inject.Bean;
+import org.apache.juneau.http.*;
+import org.apache.juneau.http.response.*;
+import org.apache.juneau.petstore.service.*;
+import org.apache.juneau.rest.server.*;
+import org.apache.juneau.rest.server.servlet.*;
+import org.apache.juneau.rest.server.view.*;
+import org.apache.juneau.rest.server.view.mustache.*;
+
+/**
+ * Petstore Mustache view demo.
+ *
+ * <p>
+ * Demonstrates rendering a templated HTML pet detail page through the {@code juneau-rest-server-view-mustache}
+ * bridge.  Lives in {@code juneau-petstore-core} so both the Jetty and Spring Boot deployments inherit it
+ * unchanged — Mustache is a pure-classpath engine and renders identically under either embedded container.
+ *
+ * <p>
+ * The {@code @RestGet("/pets/{id}/view")} method returns {@link MustacheView}; the configured
+ * {@link MustacheViewRenderer} (registered via {@code @Rest(responseProcessors=...)}) detects the return type,
+ * resolves the {@code pet.mustache} template under {@code petstore-templates/} on the classpath, and renders
+ * it directly to the response writer.
+ *
+ * <h5 class='section'>See Also:</h5><ul>
+ * 	<li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/MustacheViewSupport">Mustache View Support</a>
+ * 	<li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/JuneauPetstoreOverview">juneau-petstore</a>
+ * </ul>
+ */
+@Rest(
+	path="/pet-views/mustache",
+	title="Pet detail (Mustache)",
+	description="Renders a pet detail page through the Mustache view-rendering bridge.",
+	responseProcessors={MustacheViewRenderer.class}
+)
+@SuppressWarnings({
+	"java:S110" // Inheritance depth acceptable for example/demo code
+})
+public class PetMustacheViewResource extends BasicRestServlet {
+
+	private static final long serialVersionUID = 1L;
+
+	private final PetStore store = new PetStore();
+
+	/**
+	 * Provides a {@link MustacheMixin} configured to resolve templates under {@code petstore-templates/} with
+	 * an implicit {@code .mustache} suffix — so {@code MustacheView.of("pet")} resolves to the classpath
+	 * resource {@code petstore-templates/pet.mustache}.
+	 *
+	 * @return The mustache mixin bean.
+	 */
+	@Bean
+	public MustacheMixin mustache() {
+		return MustacheMixin.create()
+			.basePath("/petstore-templates/")
+			.templateSuffix(".mustache")
+			.build();
+	}
+
+	/**
+	 * GET /pets/{id}/view — renders a pet detail HTML page through Mustache.
+	 *
+	 * @param id The pet ID.
+	 * @return A {@link MustacheView} bound to the {@code pet} template.
+	 * @throws NotFound If no pet with the given ID exists.
+	 */
+	@RestGet("/pets/{id}/view")
+	public View viewPet(@Path("id") long id) {
+		var pet = store.getPet(id);
+		if (pet == null)
+			throw new NotFound("Pet not found: id={0}", id);
+		return MustacheView.of("pet").attr("pet", pet);
+	}
+}
diff --git a/juneau-petstore/juneau-petstore-core/src/main/java/org/apache/juneau/petstore/rest/PetSecureResource.java b/juneau-petstore/juneau-petstore-core/src/main/java/org/apache/juneau/petstore/rest/PetSecureResource.java
new file mode 100644
index 0000000000..d9ae835f9c
--- /dev/null
+++ b/juneau-petstore/juneau-petstore-core/src/main/java/org/apache/juneau/petstore/rest/PetSecureResource.java
@@ -0,0 +1,135 @@
+/*
+ * 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.juneau.petstore.rest;
+
+import java.security.*;
+import java.util.*;
+
+import org.apache.juneau.commons.inject.*;
+import org.apache.juneau.http.*;
+import org.apache.juneau.http.response.*;
+import org.apache.juneau.petstore.auth.*;
+import org.apache.juneau.petstore.dto.*;
+import org.apache.juneau.petstore.service.*;
+import org.apache.juneau.rest.server.*;
+import org.apache.juneau.rest.server.auth.*;
+import org.apache.juneau.rest.server.guard.*;
+import org.apache.juneau.rest.server.servlet.*;
+
+/**
+ * Secure analogue of {@link PetStoreResource} demonstrating Juneau's {@link BearerTokenGuard} +
+ * {@link StubBearerTokenValidator} pattern.
+ *
+ * <p>
+ * Mounted at {@code /petstore-secure/*} and gated by a {@link BearerTokenGuard} that delegates to a
+ * {@link StubBearerTokenValidator}.  Any request lacking a valid {@code Authorization: Bearer <token>} header
+ * receives {@code 401} with a {@code WWW-Authenticate: Bearer realm="petstore"} challenge.  On success, the
+ * resolved {@link Principal} is stashed on the request and surfaces through {@link Auth @Auth Principal} op
+ * parameters — see {@link #whoami(Principal)}.
+ *
+ * <p>
+ * <b>Why guard rather than chain?</b>  Juneau also ships an {@code AuthFilterChain} for composing multiple
+ * mechanisms (JWT bearer, API key, OAuth, SAML, OIDC).  The chain is fail-open by design — a request that
+ * matches the chain's path pattern but presents no recognised credentials is passed through unchanged so a
+ * downstream guard can decide.  For a single-mechanism demo, the op-level {@code BearerTokenGuard} (fail-closed
+ * by default) is the right surface.  In a real multi-mechanism deployment you'd compose
+ * {@code AuthFilterChain.create(...).append(filterA, "/secure/*").append(filterB, "/secure/*").build()} and
+ * mount it via {@code @Bean AuthFilterChain} (auto-mounted by {@code JettyServerComponent}) or a Spring
+ * {@code FilterRegistrationBean}, then add this guard for fail-closed enforcement.
+ *
+ * <p>
+ * The CRUD surface is intentionally a thin subset of {@link PetStoreResource} — the demo is the auth gate, not
+ * the surface.  If you need richer auth integration (role-based guards, multi-mechanism chains, server-side
+ * OAuth2 / SAML / OIDC-RP), consult the {@code juneau-rest-server-auth-*} modules.
+ *
+ * <h5 class='section'>See Also:</h5><ul>
+ * 	<li class='jc'>{@link BearerTokenGuard}
+ * 	<li class='jc'>{@link AuthFilterChain}
+ * 	<li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/AuthGuards">AuthN Guards</a>
+ * 	<li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/AuthFilterFramework">AuthN Filter Framework</a>
+ * 	<li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/JuneauPetstoreOverview">juneau-petstore</a>
+ * </ul>
+ */
+@Rest(
+	path="/petstore-secure",
+	title="Petstore (secure)",
+	description="Auth-gated subset of the petstore CRUD surface; bearer-token-protected via AuthFilterChain."
+)
+@SuppressWarnings({
+	"java:S110" // Inheritance depth acceptable for example/demo code
+})
+public class PetSecureResource extends BasicRestServlet {
+
+	private static final long serialVersionUID = 1L;
+
+	private final PetStore store = new PetStore();
+
+	/**
+	 * Provides the {@link RestGuardList} that gates every op on this resource with a
+	 * {@link BearerTokenGuard} — fail-closed bearer-token enforcement.
+	 *
+	 * @param bs The bean store (Juneau supplies this automatically).
+	 * @return The guard list applied to all ops on this resource.
+	 */
+	@Bean
+	public RestGuardList guards(BeanStore bs) {
+		return RestGuardList.create(bs)
+			.append(
+				BearerTokenGuard.create()
+					.realm("petstore")
+					.validator(new StubBearerTokenValidator())
+					.build())
+			.build();
+	}
+
+	/**
+	 * Lists all pets.  Accessible only with a valid bearer token.
+	 *
+	 * @return All pets.
+	 */
+	@RestGet("/pets")
+	public Collection<Pet> getPets() {
+		return store.getPets();
+	}
+
+	/**
+	 * Retrieves a pet by ID.  Accessible only with a valid bearer token.
+	 *
+	 * @param id The pet ID.
+	 * @return The pet.
+	 * @throws NotFound If no pet with the given ID exists.
+	 */
+	@RestGet("/pets/{id}")
+	public Pet getPet(@Path("id") long id) {
+		var pet = store.getPet(id);
+		if (pet == null)
+			throw new NotFound("Pet not found: id={0}", id);
+		return pet;
+	}
+
+	/**
+	 * Returns the name of the authenticated principal — the simplest possible "auth worked" probe.
+	 *
+	 * @param caller The principal stashed on the request by the {@code AuthFilterChain}.  Never {@code null} —
+	 * 	if no caller is authenticated the chain rejects with {@code 401} before this op runs.
+	 * @return A small map carrying the principal's display name.
+	 */
+	@RestGet("/whoami")
+	public Map<String,String> whoami(@Auth Principal caller) {
+		return Map.of("name", caller.getName());
+	}
+}
diff --git a/juneau-petstore/juneau-petstore-core/src/main/java/org/apache/juneau/petstore/rest/PetStoreResource.java b/juneau-petstore/juneau-petstore-core/src/main/java/org/apache/juneau/petstore/rest/PetStoreResource.java
new file mode 100644
index 0000000000..1c5dc461c6
--- /dev/null
+++ b/juneau-petstore/juneau-petstore-core/src/main/java/org/apache/juneau/petstore/rest/PetStoreResource.java
@@ -0,0 +1,292 @@
+/*
+ * 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.juneau.petstore.rest;
+
+import java.util.*;
+
+import org.apache.juneau.http.*;
+import org.apache.juneau.http.response.*;
+import org.apache.juneau.petstore.dto.*;
+import org.apache.juneau.petstore.service.*;
+import org.apache.juneau.rest.server.*;
+import org.apache.juneau.rest.server.servlet.*;
+
+/**
+ * Petstore CRUD REST resource.
+ *
+ * <p>
+ * Deployment-agnostic.  Mounted by both {@code juneau-petstore-jetty} and {@code juneau-petstore-springboot} via
+ * the {@code @Rest(children=...)} of their root router.
+ *
+ * <p>
+ * Endpoints:
+ * <ul>
+ * 	<li>{@code GET    /pets}                — list pets
+ * 	<li>{@code GET    /pets/{id}}           — get pet
+ * 	<li>{@code POST   /pets}                — create pet
+ * 	<li>{@code PUT    /pets/{id}}           — update pet
+ * 	<li>{@code DELETE /pets/{id}}           — delete pet
+ * 	<li>{@code GET    /orders}              — list orders
+ * 	<li>{@code GET    /orders/{id}}         — get order
+ * 	<li>{@code POST   /orders}              — create order
+ * 	<li>{@code PUT    /orders/{id}}         — update order
+ * 	<li>{@code DELETE /orders/{id}}         — delete order
+ * 	<li>{@code GET    /users}               — list users
+ * 	<li>{@code GET    /users/{username}}    — get user
+ * 	<li>{@code POST   /users}               — create user
+ * 	<li>{@code PUT    /users/{username}}    — update user
+ * 	<li>{@code DELETE /users/{username}}    — delete user
+ * </ul>
+ *
+ * <h5 class='section'>See Also:</h5><ul>
+ * 	<li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/JuneauPetstoreOverview">juneau-petstore</a>
+ * </ul>
+ */
+@Rest(
+	path="/petstore",
+	title="Petstore",
+	description="Apache Juneau petstore sample resource."
+)
+@SuppressWarnings({
+	"java:S110" // Inheritance depth acceptable for example/demo code
+})
+public class PetStoreResource extends BasicRestServlet {
+
+	private static final long serialVersionUID = 1L;
+
+	/** Backing store.  Singleton servlet → singleton store, shared across requests. */
+	private final PetStore store = new PetStore();
+
+	//------------------------------------------------------------------------------------------------------------------
+	// Pets
+	//------------------------------------------------------------------------------------------------------------------
+
+	/**
+	 * Lists all pets.
+	 *
+	 * @return All pets.
+	 */
+	@RestGet("/pets")
+	public Collection<Pet> getPets() {
+		return store.getPets();
+	}
+
+	/**
+	 * Retrieves a pet by ID.
+	 *
+	 * @param id The pet ID.
+	 * @return The pet.
+	 * @throws NotFound If no pet with the given ID exists.
+	 */
+	@RestGet("/pets/{id}")
+	public Pet getPet(@Path("id") long id) {
+		var pet = store.getPet(id);
+		if (pet == null)
+			throw new NotFound("Pet not found: id={0}", id);
+		return pet;
+	}
+
+	/**
+	 * Creates a new pet.
+	 *
+	 * @param pet The pet to create.
+	 * @return The created pet (with assigned ID).
+	 */
+	@RestPost("/pets")
+	public Pet createPet(@Content Pet pet) {
+		return store.createPet(pet);
+	}
+
+	/**
+	 * Updates an existing pet.
+	 *
+	 * @param id The pet ID.
+	 * @param pet The replacement pet body.
+	 * @return The updated pet.
+	 * @throws NotFound If no pet with the given ID exists.
+	 */
+	@RestPut("/pets/{id}")
+	public Pet updatePet(@Path("id") long id, @Content Pet pet) {
+		pet.setId(id);
+		try {
+			return store.updatePet(pet);
+		} catch (PetstoreNotFoundException e) {
+			throw new NotFound(e.getMessage());
+		}
+	}
+
+	/**
+	 * Deletes a pet by ID.
+	 *
+	 * @param id The pet ID.
+	 * @throws NotFound If no pet with the given ID exists.
+	 */
+	@RestDelete("/pets/{id}")
+	public void deletePet(@Path("id") long id) {
+		try {
+			store.deletePet(id);
+		} catch (PetstoreNotFoundException e) {
+			throw new NotFound(e.getMessage());
+		}
+	}
+
+	//------------------------------------------------------------------------------------------------------------------
+	// Orders
+	//------------------------------------------------------------------------------------------------------------------
+
+	/**
+	 * Lists all orders.
+	 *
+	 * @return All orders.
+	 */
+	@RestGet("/orders")
+	public Collection<Order> getOrders() {
+		return store.getOrders();
+	}
+
+	/**
+	 * Retrieves an order by ID.
+	 *
+	 * @param id The order ID.
+	 * @return The order.
+	 * @throws NotFound If no order with the given ID exists.
+	 */
+	@RestGet("/orders/{id}")
+	public Order getOrder(@Path("id") long id) {
+		var order = store.getOrder(id);
+		if (order == null)
+			throw new NotFound("Order not found: id={0}", id);
+		return order;
+	}
+
+	/**
+	 * Creates a new order.
+	 *
+	 * @param order The order to create.
+	 * @return The created order (with assigned ID).
+	 */
+	@RestPost("/orders")
+	public Order createOrder(@Content Order order) {
+		return store.createOrder(order);
+	}
+
+	/**
+	 * Updates an existing order.
+	 *
+	 * @param id The order ID.
+	 * @param order The replacement order body.
+	 * @return The updated order.
+	 * @throws NotFound If no order with the given ID exists.
+	 */
+	@RestPut("/orders/{id}")
+	public Order updateOrder(@Path("id") long id, @Content Order order) {
+		order.setId(id);
+		try {
+			return store.updateOrder(order);
+		} catch (PetstoreNotFoundException e) {
+			throw new NotFound(e.getMessage());
+		}
+	}
+
+	/**
+	 * Deletes an order by ID.
+	 *
+	 * @param id The order ID.
+	 * @throws NotFound If no order with the given ID exists.
+	 */
+	@RestDelete("/orders/{id}")
+	public void deleteOrder(@Path("id") long id) {
+		try {
+			store.deleteOrder(id);
+		} catch (PetstoreNotFoundException e) {
+			throw new NotFound(e.getMessage());
+		}
+	}
+
+	//------------------------------------------------------------------------------------------------------------------
+	// Users
+	//------------------------------------------------------------------------------------------------------------------
+
+	/**
+	 * Lists all users.
+	 *
+	 * @return All users.
+	 */
+	@RestGet("/users")
+	public Collection<User> getUsers() {
+		return store.getUsers();
+	}
+
+	/**
+	 * Retrieves a user by username.
+	 *
+	 * @param username The username.
+	 * @return The user.
+	 * @throws NotFound If no user with the given username exists.
+	 */
+	@RestGet("/users/{username}")
+	public User getUser(@Path("username") String username) {
+		var user = store.getUser(username);
+		if (user == null)
+			throw new NotFound("User not found: username={0}", username);
+		return user;
+	}
+
+	/**
+	 * Creates a new user.
+	 *
+	 * @param user The user to create.  Must carry a non-null username not already in use.
+	 * @return The created user.
+	 */
+	@RestPost("/users")
+	public User createUser(@Content User user) {
+		return store.createUser(user);
+	}
+
+	/**
+	 * Updates an existing user.
+	 *
+	 * @param username The username.
+	 * @param user The replacement user body.
+	 * @return The updated user.
+	 * @throws NotFound If no user with the given username exists.
+	 */
+	@RestPut("/users/{username}")
+	public User updateUser(@Path("username") String username, @Content User user) {
+		user.setUsername(username);
+		try {
+			return store.updateUser(user);
+		} catch (PetstoreNotFoundException e) {
+			throw new NotFound(e.getMessage());
+		}
+	}
+
+	/**
+	 * Deletes a user by username.
+	 *
+	 * @param username The username.
+	 * @throws NotFound If no user with the given username exists.
+	 */
+	@RestDelete("/users/{username}")
+	public void deleteUser(@Path("username") String username) {
+		try {
+			store.deleteUser(username);
+		} catch (PetstoreNotFoundException e) {
+			throw new NotFound(e.getMessage());
+		}
+	}
+}
diff --git a/juneau-petstore/juneau-petstore-core/src/main/java/org/apache/juneau/petstore/rest/PetstoreUiResource.java b/juneau-petstore/juneau-petstore-core/src/main/java/org/apache/juneau/petstore/rest/PetstoreUiResource.java
new file mode 100644
index 0000000000..86944321a1
--- /dev/null
+++ b/juneau-petstore/juneau-petstore-core/src/main/java/org/apache/juneau/petstore/rest/PetstoreUiResource.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.juneau.petstore.rest;
+
+import org.apache.juneau.rest.server.*;
+import org.apache.juneau.rest.server.servlet.*;
+import org.apache.juneau.rest.server.staticfile.*;
+
+/**
+ * Petstore React SPA demo — serves the no-build single-page React UI from the core classpath.
+ *
+ * <p>
+ * Composes {@link StaticFilesMixin} to serve {@code /static/*} from the importer's classpath: the file
+ * {@code static/petstore-ui.html} is reachable at {@code GET /petstore-ui/static/petstore-ui.html}.  The HTML
+ * loads React + Babel and uses {@code fetch()} against {@code /petstore/pets} to demonstrate the headless-JSON +
+ * decoupled-SPA pattern alongside the server-rendered HTML-doc UI.
+ *
+ * <p>
+ * Lives in {@code juneau-petstore-core} so both the Jetty and Spring Boot deployments inherit it for free.
+ *
+ * <h5 class='section'>See Also:</h5><ul>
+ * 	<li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/JuneauPetstoreOverview">juneau-petstore</a>
+ * </ul>
+ */
+@Rest(
+	path="/petstore-ui",
+	title="Petstore — React SPA demo",
+	description="No-build single-page React UI loaded as static classpath resource; calls /petstore/* over fetch().",
+	mixins=StaticFilesMixin.class
+)
+@SuppressWarnings({
+	"java:S110" // Inheritance depth acceptable for example/demo code
+})
+public class PetstoreUiResource extends BasicRestServlet {
+
+	private static final long serialVersionUID = 1L;
+}
diff --git a/juneau-examples/juneau-examples-rest-jetty/src/main/java/org/apache/juneau/examples/rest/jetty/package-info.java b/juneau-petstore/juneau-petstore-core/src/main/java/org/apache/juneau/petstore/rest/package-info.java
old mode 100755
new mode 100644
similarity index 77%
copy from juneau-examples/juneau-examples-rest-jetty/src/main/java/org/apache/juneau/examples/rest/jetty/package-info.java
copy to juneau-petstore/juneau-petstore-core/src/main/java/org/apache/juneau/petstore/rest/package-info.java
index 0ba233d284..e74f6b0492
--- a/juneau-examples/juneau-examples-rest-jetty/src/main/java/org/apache/juneau/examples/rest/jetty/package-info.java
+++ b/juneau-petstore/juneau-petstore-core/src/main/java/org/apache/juneau/petstore/rest/package-info.java
@@ -15,11 +15,9 @@
  * limitations under the License.
  */
 /**
- * REST Jetty Examples
+ * Petstore REST resources.
  *
  * <p>
- * Example classes demonstrating how to deploy Juneau REST servers using Jetty.
- * These examples show various Jetty-based REST API deployment scenarios.
- * </p>
+ * Deployment-agnostic Juneau REST resources mounted by both the Jetty and Spring Boot petstore deployments.
  */
-package org.apache.juneau.examples.rest.jetty;
+package org.apache.juneau.petstore.rest;
diff --git a/juneau-petstore/juneau-petstore-core/src/main/java/org/apache/juneau/petstore/service/PetStore.java b/juneau-petstore/juneau-petstore-core/src/main/java/org/apache/juneau/petstore/service/PetStore.java
new file mode 100644
index 0000000000..447a431f6e
--- /dev/null
+++ b/juneau-petstore/juneau-petstore-core/src/main/java/org/apache/juneau/petstore/service/PetStore.java
@@ -0,0 +1,308 @@
+/*
+ * 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.juneau.petstore.service;
+
+import static org.apache.juneau.commons.utils.ThrowableUtils.*;
+
+import java.io.*;
+import java.nio.charset.*;
+import java.util.*;
+import java.util.concurrent.*;
+import java.util.concurrent.atomic.*;
+
+import org.apache.juneau.marshall.json5.*;
+import org.apache.juneau.petstore.dto.*;
+
+/**
+ * In-memory {@link Pet}/{@link Order}/{@link User} store seeded from classpath JSON.
+ *
+ * <p>
+ * Backed by {@link ConcurrentHashMap}s; pet and order IDs auto-assign via {@link AtomicLong} starting from
+ * the highest seeded ID plus one (or {@code 1} if no seeds existed).  Seed files live on the classpath at
+ * {@code petstore/init/{Pets,Orders,Users}.json} and are loaded lazily on first access.
+ *
+ * <p>
+ * This is a sample/demo store — there is no persistence, no transactions, and no replication.  Restart wipes
+ * state back to the seeded baseline.
+ *
+ * <h5 class='section'>See Also:</h5><ul>
+ * 	<li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/JuneauPetstoreOverview">juneau-petstore</a>
+ * </ul>
+ */
+public class PetStore {
+
+	private static final String SEED_PETS = "petstore/init/Pets.json";
+	private static final String SEED_ORDERS = "petstore/init/Orders.json";
+	private static final String SEED_USERS = "petstore/init/Users.json";
+
+	private final Map<Long,Pet> pets = new ConcurrentHashMap<>();
+	private final Map<Long,Order> orders = new ConcurrentHashMap<>();
+	private final Map<String,User> users = new ConcurrentHashMap<>();
+
+	private final AtomicLong nextPetId = new AtomicLong();
+	private final AtomicLong nextOrderId = new AtomicLong();
+
+	/**
+	 * Constructor.
+	 *
+	 * <p>
+	 * Eagerly loads the bundled classpath seed data.
+	 */
+	public PetStore() {
+		var seededPets = loadList(SEED_PETS, Pet.class);
+		var maxPetId = 0L;
+		for (var p : seededPets) {
+			if (p.getId() == 0L)
+				p.setId(++maxPetId);
+			else
+				maxPetId = Math.max(maxPetId, p.getId());
+			pets.put(p.getId(), p);
+		}
+		nextPetId.set(maxPetId);
+
+		var seededOrders = loadList(SEED_ORDERS, Order.class);
+		var maxOrderId = 0L;
+		for (var o : seededOrders) {
+			if (o.getId() == 0L)
+				o.setId(++maxOrderId);
+			else
+				maxOrderId = Math.max(maxOrderId, o.getId());
+			orders.put(o.getId(), o);
+		}
+		nextOrderId.set(maxOrderId);
+
+		var seededUsers = loadList(SEED_USERS, User.class);
+		for (var u : seededUsers)
+			users.put(u.getUsername(), u);
+	}
+
+	private static <T> List<T> loadList(String resourcePath, Class<T> elementType) {
+		var loader = PetStore.class.getClassLoader();
+		try (var in = loader.getResourceAsStream(resourcePath)) {
+			if (in == null)
+				return new ArrayList<>();
+			try (var reader = new InputStreamReader(in, StandardCharsets.UTF_8)) {
+				return Json5Parser.DEFAULT.parse(reader, List.class, elementType);
+			}
+		} catch (Exception e) {
+			throw bex(e, "Failed to load petstore seed resource ''{0}''", resourcePath);
+		}
+	}
+
+	//------------------------------------------------------------------------------------------------------------------
+	// Pets
+	//------------------------------------------------------------------------------------------------------------------
+
+	/**
+	 * Returns all pets.
+	 *
+	 * @return All pets, in arbitrary order.  Never <jk>null</jk>.
+	 */
+	public Collection<Pet> getPets() {
+		return pets.values();
+	}
+
+	/**
+	 * Returns a pet by ID.
+	 *
+	 * @param id The pet ID.
+	 * @return The pet, or <jk>null</jk> if not found.
+	 */
+	public Pet getPet(long id) {
+		return pets.get(id);
+	}
+
+	/**
+	 * Creates a new pet.
+	 *
+	 * <p>
+	 * Assigns the next available ID, ignoring any caller-supplied ID.
+	 *
+	 * @param pet The pet to create.  Must not be <jk>null</jk>.
+	 * @return The created pet (same instance, with assigned ID).
+	 */
+	public Pet createPet(Pet pet) {
+		if (pet == null)
+			throw illegalArg("Pet must not be null");
+		var id = nextPetId.incrementAndGet();
+		pet.setId(id);
+		pets.put(id, pet);
+		return pet;
+	}
+
+	/**
+	 * Updates an existing pet.
+	 *
+	 * @param pet The pet to update.  Must not be <jk>null</jk>; must carry an ID matching an existing pet.
+	 * @return The updated pet.
+	 * @throws PetstoreNotFoundException If no pet with the given ID exists.
+	 */
+	public Pet updatePet(Pet pet) {
+		if (pet == null)
+			throw illegalArg("Pet must not be null");
+		if (! pets.containsKey(pet.getId()))
+			throw new PetstoreNotFoundException("Pet not found: id=" + pet.getId());
+		pets.put(pet.getId(), pet);
+		return pet;
+	}
+
+	/**
+	 * Deletes a pet by ID.
+	 *
+	 * @param id The pet ID.
+	 * @throws PetstoreNotFoundException If no pet with the given ID exists.
+	 */
+	public void deletePet(long id) {
+		if (pets.remove(id) == null)
+			throw new PetstoreNotFoundException("Pet not found: id=" + id);
+	}
+
+	//------------------------------------------------------------------------------------------------------------------
+	// Orders
+	//------------------------------------------------------------------------------------------------------------------
+
+	/**
+	 * Returns all orders.
+	 *
+	 * @return All orders, in arbitrary order.  Never <jk>null</jk>.
+	 */
+	public Collection<Order> getOrders() {
+		return orders.values();
+	}
+
+	/**
+	 * Returns an order by ID.
+	 *
+	 * @param id The order ID.
+	 * @return The order, or <jk>null</jk> if not found.
+	 */
+	public Order getOrder(long id) {
+		return orders.get(id);
+	}
+
+	/**
+	 * Creates a new order.
+	 *
+	 * <p>
+	 * Assigns the next available ID, ignoring any caller-supplied ID.
+	 *
+	 * @param order The order to create.  Must not be <jk>null</jk>.
+	 * @return The created order (same instance, with assigned ID).
+	 */
+	public Order createOrder(Order order) {
+		if (order == null)
+			throw illegalArg("Order must not be null");
+		var id = nextOrderId.incrementAndGet();
+		order.setId(id);
+		orders.put(id, order);
+		return order;
+	}
+
+	/**
+	 * Updates an existing order.
+	 *
+	 * @param order The order to update.  Must not be <jk>null</jk>; must carry an ID matching an existing order.
+	 * @return The updated order.
+	 * @throws PetstoreNotFoundException If no order with the given ID exists.
+	 */
+	public Order updateOrder(Order order) {
+		if (order == null)
+			throw illegalArg("Order must not be null");
+		if (! orders.containsKey(order.getId()))
+			throw new PetstoreNotFoundException("Order not found: id=" + order.getId());
+		orders.put(order.getId(), order);
+		return order;
+	}
+
+	/**
+	 * Deletes an order by ID.
+	 *
+	 * @param id The order ID.
+	 * @throws PetstoreNotFoundException If no order with the given ID exists.
+	 */
+	public void deleteOrder(long id) {
+		if (orders.remove(id) == null)
+			throw new PetstoreNotFoundException("Order not found: id=" + id);
+	}
+
+	//------------------------------------------------------------------------------------------------------------------
+	// Users
+	//------------------------------------------------------------------------------------------------------------------
+
+	/**
+	 * Returns all users.
+	 *
+	 * @return All users, in arbitrary order.  Never <jk>null</jk>.
+	 */
+	public Collection<User> getUsers() {
+		return users.values();
+	}
+
+	/**
+	 * Returns a user by username.
+	 *
+	 * @param username The username (primary key).
+	 * @return The user, or <jk>null</jk> if not found.
+	 */
+	public User getUser(String username) {
+		return users.get(username);
+	}
+
+	/**
+	 * Creates a new user.
+	 *
+	 * @param user The user to create.  Must not be <jk>null</jk>; must carry a non-null username not already in use.
+	 * @return The created user.
+	 * @throws IllegalArgumentException If the username is already in use.
+	 */
+	public User createUser(User user) {
+		if (user == null)
+			throw illegalArg("User must not be null");
+		if (user.getUsername() == null)
+			throw illegalArg("User username must not be null");
+		if (users.putIfAbsent(user.getUsername(), user) != null)
+			throw illegalArg("User already exists: username=''{0}''", user.getUsername());
+		return user;
+	}
+
+	/**
+	 * Updates an existing user.
+	 *
+	 * @param user The user to update.  Must not be <jk>null</jk>; must carry a username matching an existing user.
+	 * @return The updated user.
+	 * @throws PetstoreNotFoundException If no user with the given username exists.
+	 */
+	public User updateUser(User user) {
+		if (user == null)
+			throw illegalArg("User must not be null");
+		if (! users.containsKey(user.getUsername()))
+			throw new PetstoreNotFoundException("User not found: username=" + user.getUsername());
+		users.put(user.getUsername(), user);
+		return user;
+	}
+
+	/**
+	 * Deletes a user by username.
+	 *
+	 * @param username The username.
+	 * @throws PetstoreNotFoundException If no user with the given username exists.
+	 */
+	public void deleteUser(String username) {
+		if (users.remove(username) == null)
+			throw new PetstoreNotFoundException("User not found: username=" + username);
+	}
+}
diff --git a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/command/package-info.java b/juneau-petstore/juneau-petstore-core/src/main/java/org/apache/juneau/petstore/service/PetstoreNotFoundException.java
old mode 100755
new mode 100644
similarity index 63%
copy from juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/command/package-info.java
copy to juneau-petstore/juneau-petstore-core/src/main/java/org/apache/juneau/petstore/service/PetstoreNotFoundException.java
index dd83076900..7911d567ea
--- a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/command/package-info.java
+++ b/juneau-petstore/juneau-petstore-core/src/main/java/org/apache/juneau/petstore/service/PetstoreNotFoundException.java
@@ -14,12 +14,24 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+package org.apache.juneau.petstore.service;
+
 /**
- * REST Command Examples
+ * Thrown by {@link PetStore} when the requested entity does not exist.
  *
  * <p>
- * Example classes demonstrating how to use command pattern with Juneau's REST server.
- * These examples show various command-based REST API scenarios.
- * </p>
+ * The REST layer translates this to a {@code 404 Not Found} response.
  */
-package org.apache.juneau.examples.rest.command;
+public class PetstoreNotFoundException extends RuntimeException {
+
+	private static final long serialVersionUID = 1L;
+
+	/**
+	 * Constructor.
+	 *
+	 * @param message Detail message describing what was not found.
+	 */
+	public PetstoreNotFoundException(String message) {
+		super(message);
+	}
+}
diff --git a/juneau-examples/juneau-examples-rest-springboot/src/main/java/org/apache/juneau/examples/rest/springboot/package-info.java b/juneau-petstore/juneau-petstore-core/src/main/java/org/apache/juneau/petstore/service/package-info.java
old mode 100755
new mode 100644
similarity index 75%
rename from juneau-examples/juneau-examples-rest-springboot/src/main/java/org/apache/juneau/examples/rest/springboot/package-info.java
rename to juneau-petstore/juneau-petstore-core/src/main/java/org/apache/juneau/petstore/service/package-info.java
index 47ace2c470..2a49b1c62a
--- a/juneau-examples/juneau-examples-rest-springboot/src/main/java/org/apache/juneau/examples/rest/springboot/package-info.java
+++ b/juneau-petstore/juneau-petstore-core/src/main/java/org/apache/juneau/petstore/service/package-info.java
@@ -15,11 +15,10 @@
  * limitations under the License.
  */
 /**
- * REST Spring Boot Examples
+ * Petstore service layer (in-memory store).
  *
  * <p>
- * Example classes demonstrating how to integrate Juneau REST servers with Spring Boot.
- * These examples show various Spring Boot-based REST API integration scenarios.
- * </p>
+ * The service is HTTP-agnostic: it throws {@link org.apache.juneau.petstore.service.PetstoreNotFoundException}
+ * which the REST layer translates to a {@code 404 Not Found}.
  */
-package org.apache.juneau.examples.rest.springboot;
+package org.apache.juneau.petstore.service;
diff --git a/juneau-petstore/juneau-petstore-core/src/main/resources/htdocs/petstore-ui.html b/juneau-petstore/juneau-petstore-core/src/main/resources/htdocs/petstore-ui.html
new file mode 100644
index 0000000000..c48c66ae09
--- /dev/null
+++ b/juneau-petstore/juneau-petstore-core/src/main/resources/htdocs/petstore-ui.html
@@ -0,0 +1,104 @@
+<!DOCTYPE html>
+<!--
+  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.
+-->
+<!--
+  No-build single-page React demo for the Juneau petstore.
+
+  Demonstrates the "Juneau as a headless JSON backend + decoupled client-side SPA frontend" pattern
+  alongside the built-in server-rendered HTML-doc UI.
+
+  IMPORTANT: This v1 loads React from a CDN to keep the demo simple.  For ASF-release-quality, the React/
+  ReactDOM UMD bundles + Babel standalone should be vendored into a /static/vendor/ subdirectory and
+  served from the classpath, with appropriate NOTICE/LICENSE acknowledgements.  No Node/npm in the
+  Maven build either way.
+-->
+<html lang="en">
+<head>
+	<meta charset="utf-8">
+	<title>Juneau Petstore — React UI</title>
+	<style>
+		body { font-family: system-ui, -apple-system, sans-serif; padding: 2em; max-width: 60em; margin: 0 auto; }
+		h1 { border-bottom: 1px solid #ccc; padding-bottom: 0.3em; }
+		table { border-collapse: collapse; width: 100%; }
+		th, td { text-align: left; padding: 0.4em 0.8em; border-bottom: 1px solid #eee; }
+		th { background: #f4f4f4; }
+		.error { color: #b00; padding: 0.5em; background: #fee; border: 1px solid #fcc; border-radius: 3px; }
+		.muted { color: #666; }
+	</style>
+</head>
+<body>
+	<div id="root"></div>
+
+	<script src="https://unpkg.com/react@18/umd/react.production.min.js" crossorigin></script>
+	<script src="https://unpkg.com/react-dom@18/umd/react-dom.production.min.js" crossorigin></script>
+	<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
+
+	<script type="text/babel">
+		const { useState, useEffect } = React;
+
+		function PetTable({ pets }) {
+			if (!pets.length) return <p className="muted">No pets.</p>;
+			return (
+				<table>
+					<thead>
+						<tr><th>ID</th><th>Name</th><th>Species</th><th>Price</th><th>Status</th></tr>
+					</thead>
+					<tbody>
+						{pets.map(p => (
+							<tr key={p.id}>
+								<td>{p.id}</td>
+								<td>{p.name}</td>
+								<td>{p.species}</td>
+								<td>{p.price?.toFixed?.(2) ?? p.price}</td>
+								<td>{p.status}</td>
+							</tr>
+						))}
+					</tbody>
+				</table>
+			);
+		}
+
+		function App() {
+			const [pets, setPets] = useState([]);
+			const [err, setErr] = useState(null);
+			const [loading, setLoading] = useState(true);
+
+			useEffect(() => {
+				fetch('/petstore/pets', { headers: { 'Accept': 'application/json' } })
+					.then(r => {
+						if (!r.ok) throw new Error('HTTP ' + r.status);
+						return r.json();
+					})
+					.then(data => { setPets(data); setLoading(false); })
+					.catch(e => { setErr(String(e)); setLoading(false); });
+			}, []);
+
+			return (
+				<div>
+					<h1>Juneau Petstore — React UI</h1>
+					<p className="muted">Headless Juneau backend at <code>/petstore/*</code>, rendered by a no-build React SPA.</p>
+					{loading && <p>Loading…</p>}
+					{err && <div className="error">Failed to load pets: {err}</div>}
+					{!loading && !err && <PetTable pets={pets} />}
+				</div>
+			);
+		}
+
+		ReactDOM.createRoot(document.getElementById('root')).render(<App />);
+	</script>
+</body>
+</html>
diff --git a/juneau-examples/juneau-examples-rest-springboot/src/main/resources/log4j.xml b/juneau-petstore/juneau-petstore-core/src/main/resources/petstore-templates/pet.ftlh
similarity index 56%
copy from juneau-examples/juneau-examples-rest-springboot/src/main/resources/log4j.xml
copy to juneau-petstore/juneau-petstore-core/src/main/resources/petstore-templates/pet.ftlh
index dc5d853829..0912ec9ae2 100644
--- a/juneau-examples/juneau-examples-rest-springboot/src/main/resources/log4j.xml
+++ b/juneau-petstore/juneau-petstore-core/src/main/resources/petstore-templates/pet.ftlh
@@ -1,5 +1,4 @@
-<?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.
@@ -15,19 +14,20 @@
   See the License for the specific language governing permissions and
   limitations under the License.
 -->
-<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
-<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
-
-    <appender name="console" class="org.apache.log4j.ConsoleAppender">
-        <param name="Target" value="System.out"/>
-        <layout class="org.apache.log4j.PatternLayout">
-            <param name="ConversionPattern" value="%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n"/>
-        </layout>
-    </appender>
-
-    <root>
-        <priority value="INFO"/>
-        <appender-ref ref="console"/>
-    </root>
-
-</log4j:configuration>
\ No newline at end of file
+<!DOCTYPE html>
+<html>
+<head>
+	<title>Pet: ${pet.name}</title>
+	<style>body { font-family: sans-serif; padding: 2em; } dl { display: grid; grid-template-columns: max-content 1fr; gap: 0.5em 1em; }</style>
+</head>
+<body>
+	<h1>${pet.name}</h1>
+	<dl>
+		<dt>ID</dt><dd>${pet.id}</dd>
+		<dt>Species</dt><dd>${pet.species}</dd>
+		<dt>Price</dt><dd>${pet.price?string("0.00")}</dd>
+		<dt>Status</dt><dd>${pet.status}</dd>
+	</dl>
+	<p><em>Rendered via FreeMarker.</em></p>
+</body>
+</html>
diff --git a/juneau-examples/juneau-examples-rest-springboot/src/main/resources/log4j.xml b/juneau-petstore/juneau-petstore-core/src/main/resources/petstore-templates/pet.mustache
similarity index 56%
rename from juneau-examples/juneau-examples-rest-springboot/src/main/resources/log4j.xml
rename to juneau-petstore/juneau-petstore-core/src/main/resources/petstore-templates/pet.mustache
index dc5d853829..e7dc523f33 100644
--- a/juneau-examples/juneau-examples-rest-springboot/src/main/resources/log4j.xml
+++ b/juneau-petstore/juneau-petstore-core/src/main/resources/petstore-templates/pet.mustache
@@ -1,5 +1,4 @@
-<?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.
@@ -14,20 +13,20 @@
   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.
--->
-<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
-<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
-
-    <appender name="console" class="org.apache.log4j.ConsoleAppender">
-        <param name="Target" value="System.out"/>
-        <layout class="org.apache.log4j.PatternLayout">
-            <param name="ConversionPattern" value="%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n"/>
-        </layout>
-    </appender>
-
-    <root>
-        <priority value="INFO"/>
-        <appender-ref ref="console"/>
-    </root>
-
-</log4j:configuration>
\ No newline at end of file
+}}<!DOCTYPE html>
+<html>
+<head>
+	<title>Pet: {{pet.name}}</title>
+	<style>body { font-family: sans-serif; padding: 2em; } dl { display: grid; grid-template-columns: max-content 1fr; gap: 0.5em 1em; }</style>
+</head>
+<body>
+	<h1>{{pet.name}}</h1>
+	<dl>
+		<dt>ID</dt><dd>{{pet.id}}</dd>
+		<dt>Species</dt><dd>{{pet.species}}</dd>
+		<dt>Price</dt><dd>{{pet.price}}</dd>
+		<dt>Status</dt><dd>{{pet.status}}</dd>
+	</dl>
+	<p><em>Rendered via Mustache.</em></p>
+</body>
+</html>
diff --git a/juneau-examples/juneau-examples-rest/src/main/resources/org/apache/juneau/examples/rest/petstore/init/Orders.json b/juneau-petstore/juneau-petstore-core/src/main/resources/petstore/init/Orders.json
similarity index 100%
rename from juneau-examples/juneau-examples-rest/src/main/resources/org/apache/juneau/examples/rest/petstore/init/Orders.json
rename to juneau-petstore/juneau-petstore-core/src/main/resources/petstore/init/Orders.json
diff --git a/juneau-examples/juneau-examples-rest/src/main/resources/org/apache/juneau/examples/rest/petstore/init/Pets.json b/juneau-petstore/juneau-petstore-core/src/main/resources/petstore/init/Pets.json
similarity index 100%
rename from juneau-examples/juneau-examples-rest/src/main/resources/org/apache/juneau/examples/rest/petstore/init/Pets.json
rename to juneau-petstore/juneau-petstore-core/src/main/resources/petstore/init/Pets.json
diff --git a/juneau-examples/juneau-examples-rest/src/main/resources/org/apache/juneau/examples/rest/petstore/init/Users.json b/juneau-petstore/juneau-petstore-core/src/main/resources/petstore/init/Users.json
similarity index 100%
rename from juneau-examples/juneau-examples-rest/src/main/resources/org/apache/juneau/examples/rest/petstore/init/Users.json
rename to juneau-petstore/juneau-petstore-core/src/main/resources/petstore/init/Users.json
diff --git a/juneau-petstore/juneau-petstore-core/src/test/java/org/apache/juneau/petstore/rest/PetFreemarkerViewResource_Test.java b/juneau-petstore/juneau-petstore-core/src/test/java/org/apache/juneau/petstore/rest/PetFreemarkerViewResource_Test.java
new file mode 100644
index 0000000000..f777b90fc8
--- /dev/null
+++ b/juneau-petstore/juneau-petstore-core/src/test/java/org/apache/juneau/petstore/rest/PetFreemarkerViewResource_Test.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.juneau.petstore.rest;
+
+import org.apache.juneau.*;
+import org.apache.juneau.rest.mock.classic.*;
+import org.junit.jupiter.api.*;
+
+class PetFreemarkerViewResource_Test extends TestBase {
+
+	private static final MockRestClient CLIENT = MockRestClient.buildLax(PetFreemarkerViewResource.class);
+
+	@Test void a01_viewPet_rendersTemplateWithPetName() throws Exception {
+		CLIENT.get("/pets/1/view")
+			.run()
+			.assertStatus(200)
+			.assertContent().asString().isContains("Mr. Frisky")
+			.assertContent().asString().isContains("Rendered via FreeMarker.");
+	}
+
+	@Test void a02_viewPet_rendersSpeciesAndStatus() throws Exception {
+		CLIENT.get("/pets/1/view")
+			.run()
+			.assertStatus(200)
+			.assertContent().asString().isContains("CAT")
+			.assertContent().asString().isContains("AVAILABLE");
+	}
+
+	@Test void a03_viewPet_unknownId_404() throws Exception {
+		CLIENT.get("/pets/99999/view")
+			.run()
+			.assertStatus(404);
+	}
+}
diff --git a/juneau-petstore/juneau-petstore-core/src/test/java/org/apache/juneau/petstore/rest/PetMustacheViewResource_Test.java b/juneau-petstore/juneau-petstore-core/src/test/java/org/apache/juneau/petstore/rest/PetMustacheViewResource_Test.java
new file mode 100644
index 0000000000..cfd9cc889c
--- /dev/null
+++ b/juneau-petstore/juneau-petstore-core/src/test/java/org/apache/juneau/petstore/rest/PetMustacheViewResource_Test.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.juneau.petstore.rest;
+
+import org.apache.juneau.*;
+import org.apache.juneau.rest.mock.classic.*;
+import org.junit.jupiter.api.*;
+
+class PetMustacheViewResource_Test extends TestBase {
+
+	private static final MockRestClient CLIENT = MockRestClient.buildLax(PetMustacheViewResource.class);
+
+	@Test void a01_viewPet_rendersTemplateWithPetName() throws Exception {
+		CLIENT.get("/pets/1/view")
+			.run()
+			.assertStatus(200)
+			.assertContent().asString().isContains("Mr. Frisky")
+			.assertContent().asString().isContains("Rendered via Mustache.");
+	}
+
+	@Test void a02_viewPet_rendersSpeciesAndStatus() throws Exception {
+		CLIENT.get("/pets/1/view")
+			.run()
+			.assertStatus(200)
+			.assertContent().asString().isContains("CAT")
+			.assertContent().asString().isContains("AVAILABLE");
+	}
+
+	@Test void a03_viewPet_unknownId_404() throws Exception {
+		CLIENT.get("/pets/99999/view")
+			.run()
+			.assertStatus(404);
+	}
+}
diff --git a/juneau-petstore/juneau-petstore-core/src/test/java/org/apache/juneau/petstore/rest/PetStoreResource_Test.java b/juneau-petstore/juneau-petstore-core/src/test/java/org/apache/juneau/petstore/rest/PetStoreResource_Test.java
new file mode 100644
index 0000000000..6980e25d89
--- /dev/null
+++ b/juneau-petstore/juneau-petstore-core/src/test/java/org/apache/juneau/petstore/rest/PetStoreResource_Test.java
@@ -0,0 +1,143 @@
+/*
+ * 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.juneau.petstore.rest;
+
+import static org.apache.juneau.junit.bct.BctAssertions.*;
+import static org.junit.jupiter.api.Assertions.*;
+
+import org.apache.juneau.*;
+import org.apache.juneau.petstore.dto.*;
+import org.apache.juneau.petstore.dto.Order;
+import org.apache.juneau.rest.mock.classic.*;
+import org.junit.jupiter.api.*;
+
+class PetStoreResource_Test extends TestBase {
+
+	/**
+	 * Builds a JSON-configured MockRestClient: requests carry {@code Content-Type: application/json}, responses
+	 * carry {@code Accept: application/json}, and 4xx/5xx responses do not throw.
+	 */
+	private static MockRestClient client() {
+		return MockRestClient.buildJsonLax(PetStoreResource.class);
+	}
+
+	//------------------------------------------------------------------------------------------------------------------
+	// a — pets
+	//------------------------------------------------------------------------------------------------------------------
+
+	@Test void a01_getPet_byId() throws Exception {
+		var pet = client().get("/pets/1").run().assertStatus(200).getContent().as(Pet.class);
+		assertBean(pet, "id,name,species,status", "1,Mr. Frisky,CAT,AVAILABLE");
+	}
+
+	@Test void a02_getPet_unknownId_404() throws Exception {
+		client().get("/pets/99999").run().assertStatus(404);
+	}
+
+	@Test void a03_getPets_returnsAllSeeded() throws Exception {
+		var content = client().get("/pets").run().assertStatus(200).getContent().asString();
+		// Seed has 9 pets — confirm the first one's name is in the response.
+		assertNotNull(content);
+		assertTrue(content.contains("Mr. Frisky"), "expected seeded pet name in response: " + content);
+	}
+
+	@Test void a04_createPet_roundTrip() throws Exception {
+		var c = client();
+		var created = c.post("/pets", new Pet()
+				.setName("Wanda")
+				.setSpecies(Species.RABBIT)
+				.setPrice(12.50f)
+				.setStatus(PetStatus.AVAILABLE))
+			.run()
+			.assertStatus(200)
+			.getContent().as(Pet.class);
+		assertNotEquals(0L, created.getId());
+
+		var fetched = c.get("/pets/" + created.getId()).run().assertStatus(200).getContent().as(Pet.class);
+		assertBean(fetched, "name,species,status", "Wanda,RABBIT,AVAILABLE");
+	}
+
+	@Test void a05_updatePet_replaces() throws Exception {
+		var c = client();
+		c.put("/pets/1", new Pet().setName("Renamed").setSpecies(Species.CAT).setStatus(PetStatus.AVAILABLE))
+			.run().assertStatus(200);
+		var fetched = c.get("/pets/1").run().assertStatus(200).getContent().as(Pet.class);
+		assertEquals("Renamed", fetched.getName());
+	}
+
+	@Test void a06_updatePet_unknownId_404() throws Exception {
+		client().put("/pets/99999", new Pet().setName("Ghost").setSpecies(Species.CAT).setStatus(PetStatus.AVAILABLE))
+			.run().assertStatus(404);
+	}
+
+	@Test void a07_deletePet_removes() throws Exception {
+		var c = client();
+		c.delete("/pets/2").run().assertStatus(200);
+		c.get("/pets/2").run().assertStatus(404);
+	}
+
+	@Test void a08_deletePet_unknownId_404() throws Exception {
+		client().delete("/pets/99999").run().assertStatus(404);
+	}
+
+	//------------------------------------------------------------------------------------------------------------------
+	// b — orders
+	//------------------------------------------------------------------------------------------------------------------
+
+	@Test void b01_getOrder_byId() throws Exception {
+		var o = client().get("/orders/101").run().assertStatus(200).getContent().as(Order.class);
+		assertBean(o, "id,petId,shipDate,status", "101,101,2018-01-01,PLACED");
+	}
+
+	@Test void b02_getOrder_unknownId_404() throws Exception {
+		client().get("/orders/99999").run().assertStatus(404);
+	}
+
+	@Test void b03_createOrder_roundTrip() throws Exception {
+		var c = client();
+		var created = c.post("/orders", new Order().setPetId(1L).setStatus(OrderStatus.PLACED))
+			.run().assertStatus(200).getContent().as(Order.class);
+		assertNotEquals(0L, created.getId());
+	}
+
+	//------------------------------------------------------------------------------------------------------------------
+	// c — users
+	//------------------------------------------------------------------------------------------------------------------
+
+	@Test void c01_getUser_byUsername() throws Exception {
+		var u = client().get("/users/mwatson").run().assertStatus(200).getContent().as(User.class);
+		assertBean(u, "username,firstName,lastName,userStatus", "mwatson,Marie,Watson,ACTIVE");
+	}
+
+	@Test void c02_getUser_unknown_404() throws Exception {
+		client().get("/users/no-such-user").run().assertStatus(404);
+	}
+
+	@Test void c03_createUser_roundTrip() throws Exception {
+		var c = client();
+		c.post("/users", new User().setUsername("newuser").setFirstName("New").setUserStatus(UserStatus.ACTIVE))
+			.run().assertStatus(200);
+		var fetched = c.get("/users/newuser").run().assertStatus(200).getContent().as(User.class);
+		assertBean(fetched, "username,firstName", "newuser,New");
+	}
+
+	@Test void c04_deleteUser_removes() throws Exception {
+		var c = client();
+		c.delete("/users/dvaughn").run().assertStatus(200);
+		c.get("/users/dvaughn").run().assertStatus(404);
+	}
+}
diff --git a/juneau-petstore/juneau-petstore-core/src/test/java/org/apache/juneau/petstore/rest/PetstoreUiResource_Test.java b/juneau-petstore/juneau-petstore-core/src/test/java/org/apache/juneau/petstore/rest/PetstoreUiResource_Test.java
new file mode 100644
index 0000000000..3d84d0ea4f
--- /dev/null
+++ b/juneau-petstore/juneau-petstore-core/src/test/java/org/apache/juneau/petstore/rest/PetstoreUiResource_Test.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.juneau.petstore.rest;
+
+import org.apache.juneau.*;
+import org.apache.juneau.rest.mock.classic.*;
+import org.junit.jupiter.api.*;
+
+class PetstoreUiResource_Test extends TestBase {
+
+	private static final MockRestClient CLIENT = MockRestClient.buildLax(PetstoreUiResource.class);
+
+	@Test void a01_uiHtml_servedFromClasspath() throws Exception {
+		CLIENT.get("/static/petstore-ui.html")
+			.run()
+			.assertStatus(200)
+			.assertContent().asString().isContains("<title>Juneau Petstore — React UI</title>");
+	}
+
+	@Test void a02_uiHtml_referencesPetstoreEndpoint() throws Exception {
+		// Sanity check that the SPA actually points at the right backend route — guards against
+		// accidental rename of /petstore/pets without updating the SPA.
+		CLIENT.get("/static/petstore-ui.html")
+			.run()
+			.assertStatus(200)
+			.assertContent().asString().isContains("/petstore/pets");
+	}
+
+	@Test void a03_unknownStaticFile_404() throws Exception {
+		CLIENT.get("/static/no-such-file.html")
+			.run()
+			.assertStatus(404);
+	}
+}
diff --git a/juneau-petstore/juneau-petstore-core/src/test/java/org/apache/juneau/petstore/service/PetStore_Test.java b/juneau-petstore/juneau-petstore-core/src/test/java/org/apache/juneau/petstore/service/PetStore_Test.java
new file mode 100644
index 0000000000..f4f2c89aa0
--- /dev/null
+++ b/juneau-petstore/juneau-petstore-core/src/test/java/org/apache/juneau/petstore/service/PetStore_Test.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.juneau.petstore.service;
+
+import static org.apache.juneau.junit.bct.BctAssertions.*;
+import static org.junit.jupiter.api.Assertions.*;
+
+import org.apache.juneau.*;
+import org.apache.juneau.petstore.dto.*;
+import org.apache.juneau.petstore.dto.Order;
+import org.junit.jupiter.api.*;
+
+class PetStore_Test extends TestBase {
+
+	//------------------------------------------------------------------------------------------------------------------
+	// a — seed loading
+	//------------------------------------------------------------------------------------------------------------------
+
+	@Test void a01_seededPetsLoaded() {
+		var s = new PetStore();
+		assertEquals(9, s.getPets().size());
+	}
+
+	@Test void a02_seededOrdersLoaded() {
+		var s = new PetStore();
+		assertEquals(3, s.getOrders().size());
+	}
+
+	@Test void a03_seededUsersLoaded() {
+		var s = new PetStore();
+		assertEquals(3, s.getUsers().size());
+	}
+
+	@Test void a04_seededPetByIdHasCorrectShape() {
+		var s = new PetStore();
+		// First seeded pet — id auto-assigned to 1.
+		assertBean(s.getPet(1L), "name,species,price,status", "Mr. Frisky,CAT,39.99,AVAILABLE");
+	}
+
+	@Test void a05_seededOrderById() {
+		var s = new PetStore();
+		assertBean(s.getOrder(101L), "id,petId,shipDate,status", "101,101,2018-01-01,PLACED");
+	}
+
+	@Test void a06_seededUserByUsername() {
+		var s = new PetStore();
+		assertBean(s.getUser("mwatson"), "username,firstName,lastName,userStatus", "mwatson,Marie,Watson,ACTIVE");
+	}
+
+	//------------------------------------------------------------------------------------------------------------------
+	// b — pets CRUD
+	//------------------------------------------------------------------------------------------------------------------
+
+	@Test void b01_createPet_assignsId() {
+		var s = new PetStore();
+		var p = s.createPet(new Pet().setName("Newpet").setSpecies(Species.DOG).setPrice(10f).setStatus(PetStatus.AVAILABLE));
+		assertNotEquals(0L, p.getId());
+		assertEquals(p, s.getPet(p.getId()));
+	}
+
+	@Test void b02_updatePet_replacesContent() {
+		var s = new PetStore();
+		var p = s.getPet(1L).setName("Renamed");
+		s.updatePet(p);
+		assertEquals("Renamed", s.getPet(1L).getName());
+	}
+
+	@Test void b03_updatePet_unknownId_throws() {
+		var s = new PetStore();
+		var ghost = new Pet().setId(99999L).setName("Ghost").setSpecies(Species.CAT).setStatus(PetStatus.AVAILABLE);
+		assertThrows(PetstoreNotFoundException.class, () -> s.updatePet(ghost));
+	}
+
+	@Test void b04_deletePet_removes() {
+		var s = new PetStore();
+		s.deletePet(1L);
+		assertNull(s.getPet(1L));
+	}
+
+	@Test void b05_deletePet_unknownId_throws() {
+		var s = new PetStore();
+		assertThrows(PetstoreNotFoundException.class, () -> s.deletePet(99999L));
+	}
+
+	//------------------------------------------------------------------------------------------------------------------
+	// c — orders CRUD
+	//------------------------------------------------------------------------------------------------------------------
+
+	@Test void c01_createOrder_assignsId() {
+		var s = new PetStore();
+		var o = s.createOrder(new Order().setPetId(1L).setStatus(OrderStatus.PLACED));
+		assertNotEquals(0L, o.getId());
+		assertTrue(o.getId() > 103L); // greater than highest seeded id
+	}
+
+	@Test void c02_updateOrder_replacesContent() {
+		var s = new PetStore();
+		var o = s.getOrder(101L).setStatus(OrderStatus.DELIVERED);
+		s.updateOrder(o);
+		assertEquals(OrderStatus.DELIVERED, s.getOrder(101L).getStatus());
+	}
+
+	@Test void c03_deleteOrder_removes() {
+		var s = new PetStore();
+		s.deleteOrder(101L);
+		assertNull(s.getOrder(101L));
+	}
+
+	//------------------------------------------------------------------------------------------------------------------
+	// d — users CRUD
+	//------------------------------------------------------------------------------------------------------------------
+
+	@Test void d01_createUser_byUsername() {
+		var s = new PetStore();
+		s.createUser(new User().setUsername("newuser").setFirstName("New").setUserStatus(UserStatus.ACTIVE));
+		assertNotNull(s.getUser("newuser"));
+	}
+
+	@Test void d02_createUser_duplicate_throws() {
+		var s = new PetStore();
+		assertThrows(IllegalArgumentException.class,
+			() -> s.createUser(new User().setUsername("mwatson").setUserStatus(UserStatus.ACTIVE)));
+	}
+
+	@Test void d03_updateUser_replacesContent() {
+		var s = new PetStore();
+		s.updateUser(s.getUser("mwatson").setFirstName("Mary"));
+		assertEquals("Mary", s.getUser("mwatson").getFirstName());
+	}
+
+	@Test void d04_deleteUser_removes() {
+		var s = new PetStore();
+		s.deleteUser("mwatson");
+		assertNull(s.getUser("mwatson"));
+	}
+}
diff --git a/juneau-sc/juneau-sc-server/juneau-server-config.cfg b/juneau-petstore/juneau-petstore-jetty/juneau-petstore-jetty.cfg
old mode 100755
new mode 100644
similarity index 51%
copy from juneau-sc/juneau-sc-server/juneau-server-config.cfg
copy to juneau-petstore/juneau-petstore-jetty/juneau-petstore-jetty.cfg
index a97e0aff3a..d09858b04a
--- a/juneau-sc/juneau-sc-server/juneau-server-config.cfg
+++ b/juneau-petstore/juneau-petstore-jetty/juneau-petstore-jetty.cfg
@@ -1,146 +1,120 @@
-# ***************************************************************************************************************************
-# * 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.                                              *
-# ***************************************************************************************************************************
-
-#=======================================================================================================================
-# Basic configuration file for SaaS microservices
-# Subprojects can use this as a starting point.
-#=======================================================================================================================
-
-
-#=======================================================================================================================
-# Jetty settings
-#=======================================================================================================================
-[Jetty]
-
-# Path of the jetty.xml file used to configure the Jetty server.
-config = files/jetty.xml
-
-# Resolve Juneau variables in the jetty.xml file.
-resolveVars = true
-
-# Port to use for the jetty server.
-# You can specify multiple ports.  The first available will be used.  '0' indicates to try a random port.
-# The resulting available port gets set as the system property "availablePort" which can be referenced in the 
-# jetty.xml file as "$S{availablePort}" (assuming resolveVars is enabled).
-port = 10000,0,0,0
-
-#=======================================================================================================================
-# REST settings
-#=======================================================================================================================
-[REST]
-
-# Comma-delimited list of key-value pairs that represent locations of static files that can be served up by your @Rest-annotated
-# classes.  These are static files that are served up by the servlet under the specified sub-paths.
-# For example, given the following setting...
-# 	staticFiles = htdocs:my-docs,styles/my-styles
-# ...the URI "/servletPath/htdocs/javadoc.css" resolves to the path "/my-docs/javadoc.css".
-# This path can be relative to the working directory, classpath root, or package of your resource class.
-# Used by the BasicRestConfig interface that defines the following value:
-# 	staticFiles="$C{REST/staticFiles}"
-staticFiles = htdocs:htdocs
-
-# Stylesheet to use for HTML views.
-# Used by the BasicRestConfig interface that defines the following value:
-# 	stylesheet="$C{REST/theme,servlet:/htdocs/themes/devops.css}"
-theme = servlet:/htdocs/themes/devops.css
-
-# Various look-and-feel settings used in the BasicRestConfig interface.
-headerIcon = servlet:/htdocs/images/juneau.png
-headerLink = http://juneau.apache.org
-footerIcon = servlet:/htdocs/images/asf.png
-footerLink = http://www.apache.org
-favicon = $C{REST/headerIcon}
-header = 
-	<a href='$U{$C{REST/headerLink}}'>
-		<img src='$U{$C{REST/headerIcon}}' style='position:absolute;top:5;right:5;background-color:transparent;height:30px'/>
-	</a>
-footer = 
-	<a href='$U{$C{REST/footerLink}}'>
-		<img style='float:right;padding-right:20px;height:32px' src='$U{$C{REST/footerIcon}}'>
-	</a>
-
-#=======================================================================================================================
-# Console settings
-#=======================================================================================================================
-[Console]
-
-enabled = true
-
-# List of available console commands.
-# These are classes that implements ConsoleCommand that allow you to submit commands to the microservice via
-# the console.
-# When listed here, the implementations must provide a no-arg constructor.
-# They can also be provided dynamically by overriding the Microservice.createConsoleCommands() method.
-commands = 
-	org.apache.juneau.marshall.microservice.console.ExitCommand,
-	org.apache.juneau.marshall.microservice.console.RestartCommand,
-	org.apache.juneau.marshall.microservice.console.HelpCommand,
-	org.apache.juneau.marshall.microservice.console.ConfigCommand,
-	org.apache.juneau.marshall.examples.rest.command.EchoCommand
-
-#=======================================================================================================================
-# System properties
-#-----------------------------------------------------------------------------------------------------------------------
-# These are arbitrary system properties that can be set during startup.
-#=======================================================================================================================
-[SystemProperties]
-
-# Configure Jetty for StdErrLog Logging
-# org.eclipse.jetty.util.log.class = org.eclipse.jetty.util.log.StrErrLog
-
-# Configure Jetty to log using java-util logging
-org.eclipse.jetty.util.log.class = org.apache.juneau.marshall.microservice.jetty.JettyLogger
-
-# Jetty logging level
-org.eclipse.jetty.LEVEL = WARN
-
-derby.stream.error.file = $C{Logging/logDir}/derby-errors.log
-
-# Note that any configuration properties can also be set globally as system properties...
-
-# Disable classpath resource caching.
-# Useful if you're attached using a debugger and you're modifying classpath resources while running.
-RestContext.disableClasspathResourceCaching.b = true
-
-#=======================================================================================================================
-# DockerRegistryResource properties
-#=======================================================================================================================
-[DockerRegistry]
-url = http://docker.apache.org:5000/v1
-
-#=======================================================================================================================
-# SqlQueryResource properties
-#=======================================================================================================================
-[SqlQueryResource]
-driver = org.apache.derby.jdbc.EmbeddedDriver
-directory = target/derby/testDB
-connectionUrl = jdbc:derby:$C{SqlQueryResource/directory};create=true
-allowTempUpdates = true
-includeRowNums = false
-
-#=======================================================================================================================
-# Source code location
-#=======================================================================================================================
-[Source]
-gitHub = https://github.com/apache/juneau/blob/master/juneau-examples/juneau-examples-rest/src/main/java
-
-#=======================================================================================================================
-# PetStoreResource properties
-#=======================================================================================================================
-[PetStore]
-headerImage = <a href='http://swagger.io'><img src='$U{servlet:/htdocs/cat.png}' style='position:absolute;top:5;right:5;background-color:transparent;height:30px'/></a>
-
-[GitServer]
-pathLocal = /home/marcelo/desenvolvimento/tmp/juneau-config-test
-gitRemote = https://github.com/marcelosv/juneau-config-test.git
-
+# ***************************************************************************************************************************
+# * 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.                                              *
+# ***************************************************************************************************************************
+
+#=======================================================================================================================
+# juneau-petstore-jetty configuration
+#=======================================================================================================================
+
+
+#=======================================================================================================================
+# Jetty settings
+#=======================================================================================================================
+[Jetty]
+
+# Path of the jetty.xml file used to configure the Jetty server.
+config = files/jetty.xml
+
+# Resolve Juneau variables in the jetty.xml file.
+resolveVars = true
+
+# Port to use for the jetty server.
+# You can specify multiple ports.  The first available will be used.  '0' indicates to try a random port.
+# The resulting available port gets set as the system property "availablePort" which can be referenced in the
+# jetty.xml file as "$S{availablePort}" (assuming resolveVars is enabled).
+port = 10000,0,0,0
+
+
+#=======================================================================================================================
+# Console settings
+#=======================================================================================================================
+[Console]
+
+enabled = true
+
+# List of available console commands.
+# These are classes that implements ConsoleCommand that allow you to submit commands to the microservice via
+# the console.
+commands =
+	org.apache.juneau.marshall.microservice.console.ExitCommand,
+	org.apache.juneau.marshall.microservice.console.RestartCommand,
+	org.apache.juneau.marshall.microservice.console.HelpCommand,
+	org.apache.juneau.marshall.microservice.console.ConfigCommand
+
+
+#=======================================================================================================================
+# Logger settings
+#-----------------------------------------------------------------------------------------------------------------------
+# See FileHandler Java class for details.
+#=======================================================================================================================
+[Logging]
+
+# The directory where to create the log file.
+logDir = ./target/logs
+
+# The name of the log file to create for the main logger.
+logFile = microservice.%g.log
+
+# Whether to append to the existing log file or create a new one.
+append = false
+
+# The SimpleDateFormat format to use for dates.
+dateFormat = yyyy.MM.dd hh:mm:ss
+
+# The log message format.
+format = [{date} {level}] {msg}%n
+
+# The maximum log file size.
+limit = 1M
+
+# Max number of log files.
+count = 5
+
+# Default log levels.
+levels =
+	{
+		'': 'WARNING',
+		org.apache.juneau.marshall: 'WARNING',
+		org.eclipse.jetty: 'WARNING'
+	}
+
+# Only print unique stack traces once and then refer to them by a simple 8 character hash identifier.
+useStackTraceHashes = true
+
+# The default level for the console logger.
+consoleLevel = WARNING
+
+# The default level for the file logger.
+fileLevel = INFO
+
+
+#=======================================================================================================================
+# System properties
+#=======================================================================================================================
+[SystemProperties]
+
+# Configure Jetty to log using java-util logging.
+org.eclipse.jetty.util.log.class = org.apache.juneau.marshall.microservice.jetty.JettyLogger
+
+# Jetty logging level.
+org.eclipse.jetty.LEVEL = WARN
+
+# Disable classpath resource caching.
+# Useful if you're attached using a debugger and you're modifying classpath resources while running.
+RestContext.disableClasspathResourceCaching.b = true
+
+
+#=======================================================================================================================
+# Source code location
+#=======================================================================================================================
+[Source]
+gitHub = https://github.com/apache/juneau/blob/master/juneau-petstore/juneau-petstore-jetty/src/main/java
diff --git a/juneau-examples/juneau-examples-rest-jetty/pom.xml b/juneau-petstore/juneau-petstore-jetty/pom.xml
similarity index 57%
rename from juneau-examples/juneau-examples-rest-jetty/pom.xml
rename to juneau-petstore/juneau-petstore-jetty/pom.xml
index 36de70cb6a..e9438a6c1f 100644
--- a/juneau-examples/juneau-examples-rest-jetty/pom.xml
+++ b/juneau-petstore/juneau-petstore-jetty/pom.xml
@@ -21,14 +21,14 @@
 
 	<parent>
 		<groupId>org.apache.juneau</groupId>
-		<artifactId>juneau-examples</artifactId>
+		<artifactId>juneau-petstore</artifactId>
 		<version>10.0.0-SNAPSHOT</version>
 	</parent>
 
-	<artifactId>juneau-examples-rest-jetty</artifactId>
-	<name>Apache Juneau REST Jetty Examples</name>
-	<description>Apache Juneau REST Examples using Jetty</description>
-	<packaging>bundle</packaging>
+	<artifactId>juneau-petstore-jetty</artifactId>
+	<name>Apache Juneau Petstore Jetty</name>
+	<description>Apache Juneau Petstore - Jetty/Microservice deployment</description>
+	<packaging>jar</packaging>
 
 	<properties>
 		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
@@ -37,7 +37,7 @@
 	<dependencies>
 		<dependency>
 			<groupId>org.apache.juneau</groupId>
-			<artifactId>juneau-examples-rest</artifactId>
+			<artifactId>juneau-petstore-core</artifactId>
 			<version>${project.version}</version>
 		</dependency>
 		<dependency>
@@ -45,27 +45,42 @@
 			<artifactId>juneau-microservice-jetty</artifactId>
 			<version>${project.version}</version>
 		</dependency>
+
+		<!-- Test dependencies -->
+		<dependency>
+			<groupId>org.junit.jupiter</groupId>
+			<artifactId>junit-jupiter</artifactId>
+			<version>${junit.version}</version>
+			<scope>test</scope>
+		</dependency>
+		<dependency>
+			<groupId>org.apache.juneau</groupId>
+			<artifactId>juneau-junit5</artifactId>
+			<version>${project.version}</version>
+			<scope>test</scope>
+		</dependency>
+		<dependency>
+			<groupId>org.apache.juneau</groupId>
+			<artifactId>juneau-test-utils</artifactId>
+			<version>${project.version}</version>
+			<scope>test</scope>
+		</dependency>
+		<dependency>
+			<groupId>org.apache.juneau</groupId>
+			<artifactId>juneau-bct</artifactId>
+			<version>${project.version}</version>
+			<scope>test</scope>
+		</dependency>
+		<dependency>
+			<groupId>org.apache.juneau</groupId>
+			<artifactId>juneau-rest-client-classic</artifactId>
+			<version>${project.version}</version>
+			<scope>test</scope>
+		</dependency>
 	</dependencies>
 
 	<build>
 		<plugins>
-			<plugin>
-				<groupId>org.apache.felix</groupId>
-				<artifactId>maven-bundle-plugin</artifactId>
-				<extensions>true</extensions>
-				<configuration>
-					<supportIncrementalBuild>true</supportIncrementalBuild>
-				</configuration>
-				<executions>
-				<execution>
-					<id>bundle-manifest</id>
-					<phase>process-classes</phase>
-					<goals>
-						<goal>manifest</goal>
-					</goals>
-				</execution>
-			</executions>
-			</plugin>
 			<plugin>
 				<groupId>org.apache.maven.plugins</groupId>
 				<artifactId>maven-source-plugin</artifactId>
@@ -79,7 +94,10 @@
 					</execution>
 				</executions>
 			</plugin>
-
+			<plugin>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-jar-plugin</artifactId>
+			</plugin>
 			<plugin>
 				<artifactId>maven-assembly-plugin</artifactId>
 				<configuration>
@@ -93,7 +111,7 @@
 							<goal>single</goal>
 						</goals>
 						<configuration>
-							<finalName>juneau-examples-rest-jetty-${project.version}</finalName>
+							<finalName>juneau-petstore-jetty-${project.version}</finalName>
 							<descriptors>
 								<descriptor>src/assembly/bin.xml</descriptor>
 							</descriptors>
@@ -101,6 +119,25 @@
 					</execution>
 				</executions>
 			</plugin>
+			<plugin>
+				<groupId>org.jacoco</groupId>
+				<artifactId>jacoco-maven-plugin</artifactId>
+				<executions>
+					<execution>
+						<id>default-prepare-agent</id>
+						<goals>
+							<goal>prepare-agent</goal>
+						</goals>
+					</execution>
+					<execution>
+						<id>default-report</id>
+						<phase>prepare-package</phase>
+						<goals>
+							<goal>report</goal>
+						</goals>
+					</execution>
+				</executions>
+			</plugin>
 		</plugins>
 	</build>
 </project>
diff --git a/juneau-examples/juneau-examples-rest-springboot/src/assembly/bin.xml b/juneau-petstore/juneau-petstore-jetty/src/assembly/bin.xml
similarity index 72%
rename from juneau-examples/juneau-examples-rest-springboot/src/assembly/bin.xml
rename to juneau-petstore/juneau-petstore-jetty/src/assembly/bin.xml
index af351a1eed..5282bbbf32 100644
--- a/juneau-examples/juneau-examples-rest-springboot/src/assembly/bin.xml
+++ b/juneau-petstore/juneau-petstore-jetty/src/assembly/bin.xml
@@ -17,9 +17,10 @@
 -->
 
 <!--
-	This assembly is used to create the template zip file that developers use to import into Eclipse to start their
-	own projects.
- -->
+	Builds a starter zip — sources + classpath resources + petstore .cfg + jetty.xml + pom.xml — that can be
+	imported into an IDE or used as a template for derived petstore projects.  Source-template style (not a
+	runnable distribution — no fat jar bundled).
+-->
 <assembly
 	xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3"
 	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
@@ -32,31 +33,22 @@
 	<includeBaseDirectory>true</includeBaseDirectory>
 	<fileSets>
 		<fileSet>
-			<directory>${basedir}/../juneau-examples-rest</directory>
-			<outputDirectory>/</outputDirectory>
+			<directory>${basedir}/../juneau-petstore-core</directory>
+			<outputDirectory>juneau-petstore-core</outputDirectory>
 			<includes>
 				<include>src/main/**</include>
+				<include>pom.xml</include>
 			</includes>
 		</fileSet>
 		<fileSet>
 			<useDefaultExcludes>false</useDefaultExcludes>
 			<directory>${basedir}</directory>
-			<outputDirectory>/</outputDirectory>
+			<outputDirectory>juneau-petstore-jetty</outputDirectory>
 			<includes>
 				<include>src/main/**</include>
-				<include>files/**</include>
-				<include>.settings/**</include>
-				<include>.project</include>
-				<include>.classpath</include>
-				<include>*.launch</include>
 				<include>*.cfg</include>
+				<include>pom.xml</include>
 			</includes>
 		</fileSet>
-		<fileSet>
-			<directory>${basedir}/build-overlay</directory>
-			<outputDirectory>/</outputDirectory>
-			<filtered>true</filtered>
-		</fileSet>
 	</fileSets>
-	
-</assembly>
\ No newline at end of file
+</assembly>
diff --git a/juneau-examples/juneau-examples-rest-jetty/src/main/java/org/apache/juneau/examples/rest/jetty/App.java b/juneau-petstore/juneau-petstore-jetty/src/main/java/org/apache/juneau/petstore/jetty/App.java
similarity index 70%
rename from juneau-examples/juneau-examples-rest-jetty/src/main/java/org/apache/juneau/examples/rest/jetty/App.java
rename to juneau-petstore/juneau-petstore-jetty/src/main/java/org/apache/juneau/petstore/jetty/App.java
index 6f11a30806..49bd27839b 100644
--- a/juneau-examples/juneau-examples-rest-jetty/src/main/java/org/apache/juneau/examples/rest/jetty/App.java
+++ b/juneau-petstore/juneau-petstore-jetty/src/main/java/org/apache/juneau/petstore/jetty/App.java
@@ -14,29 +14,32 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.juneau.examples.rest.jetty;
+package org.apache.juneau.petstore.jetty;
 
 import org.apache.juneau.commons.inject.*;
-import org.apache.juneau.examples.rest.*;
 import org.apache.juneau.microservice.*;
 import org.apache.juneau.microservice.jetty.*;
 
 import jakarta.servlet.*;
 
 /**
- * An example of an extended REST microservice.
+ * Petstore Jetty/Microservice deployment entry point.
  *
  * <p>
- * The {@link Microservice} class will locate the <c>examples.cfg</c> file in the home directory and initialize
- * the resources and commands defined in that file.
+ * Locates {@code juneau-petstore-jetty.cfg} (in the working directory or on the classpath), wires Jetty via
+ * {@link JettyConfiguration}, and mounts {@link RootResources} as the root servlet.
+ *
+ * <h5 class='section'>See Also:</h5><ul>
+ * 	<li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/JuneauPetstoreOverview">juneau-petstore</a>
+ * </ul>
  */
 public class App {
 
 	/**
-	 * Entry point method.
+	 * Entry point.
 	 *
-	 * @param args Command line arguments.
-	 * @throws Exception General exception occurred.
+	 * @param args Command-line arguments forwarded to {@link Microservice}.
+	 * @throws Exception If the microservice fails to start.
 	 */
 	public static void main(String[] args) throws Exception {
 		// @formatter:off
@@ -58,7 +61,7 @@ public class App {
 	public static class AppConfig {
 
 		/**
-		 * Provides the top-level REST servlet, auto-mounted by {@link JettyServerComponent} at
+		 * Provides the top-level REST servlet, auto-mounted by {@code JettyServerComponent} at
 		 * {@link org.apache.juneau.rest.server.Rest#path()}.
 		 *
 		 * @return The root servlet.
diff --git a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/RootResources.java b/juneau-petstore/juneau-petstore-jetty/src/main/java/org/apache/juneau/petstore/jetty/RootResources.java
similarity index 51%
rename from juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/RootResources.java
rename to juneau-petstore/juneau-petstore-jetty/src/main/java/org/apache/juneau/petstore/jetty/RootResources.java
index 572aa05462..c12e14ab4c 100644
--- a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/RootResources.java
+++ b/juneau-petstore/juneau-petstore-jetty/src/main/java/org/apache/juneau/petstore/jetty/RootResources.java
@@ -14,31 +14,40 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.juneau.examples.rest;
+package org.apache.juneau.petstore.jetty;
 
-import org.apache.juneau.examples.rest.dto.*;
 import org.apache.juneau.marshall.html.*;
 import org.apache.juneau.marshall.serializer.*;
 import org.apache.juneau.microservice.resources.*;
+import org.apache.juneau.petstore.rest.*;
 import org.apache.juneau.rest.server.*;
 import org.apache.juneau.rest.server.servlet.*;
 import org.apache.juneau.rest.server.widget.*;
 
 /**
- * Sample REST resource showing how to implement a "router" resource page.
+ * Root router resource for the Jetty deployment.
  *
+ * <p>
+ * Mounts the deployment-agnostic {@link PetStoreResource} from {@code juneau-petstore-core} and the
+ * Jetty/Microservice-specific admin resources ({@link ConfigResource}, {@link LogsResource},
+ * {@link ShutdownResource}).  The admin trio is a documented Jetty-only non-parity feature — the Spring Boot
+ * deployment in {@code juneau-petstore-springboot} does not mount it.
+ *
+ * <h5 class='section'>See Also:</h5><ul>
+ * 	<li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/JuneauPetstoreOverview">juneau-petstore</a>
+ * </ul>
  *
  * @serial exclude
  */
 @Rest(
-	title="Root resources",
-	description="Example of a router resource page.",
+	title="Juneau Petstore (Jetty)",
+	description="Apache Juneau petstore sample application running under Jetty/Microservice.",
 	children={
-		HelloWorldResource.class,
-		DtoExamples.class,
-		UtilityBeansResource.class,
-		HtmlBeansResource.class,
-		SseDemoResource.class,
+		PetStoreResource.class,
+		PetSecureResource.class,
+		PetMustacheViewResource.class,
+		PetFreemarkerViewResource.class,
+		PetstoreUiResource.class,
 		ConfigResource.class,
 		LogsResource.class,
 		ShutdownResource.class
@@ -52,33 +61,27 @@ import org.apache.juneau.rest.server.widget.*;
 		"api: servlet:/api",
 		"stats: servlet:/stats",
 		"$W{ContentTypeMenuItem}",
-		"source: $C{Source/gitHub}/org/apache/juneau/examples/rest/RootResources.java"
+		"source: $C{Source/gitHub}/org/apache/juneau/petstore/jetty/RootResources.java"
 	},
 	aside={
 		"<div class='text'>",
-		"\t<p>This is an example of a 'router' page that serves as a jumping-off point to child resources.</p>",
-		"\t<p>Resources can be nested arbitrarily deep through router pages.</p>",
-		"\t<p>Note the <span class='link'>API</span> link provided that lets you see the generated swagger doc for this page.</p>",
-		"\t<p>Also note the <span class='link'>STATS</span> link to view runtime statistics on this page.</p>",
-		"\t<p>Also note the <span class='link'>SOURCE</span> link to view the source code for the page.</p>",
-		"\t<p>All content on pages in the UI are serialized POJOs.  In this case, it's a serialized array of beans with 2 properties, 'name' and 'description'.</p>",
-		"\t<p>Other features (such as this aside) are added through annotations.</p>",
+		"\t<p>Apache Juneau petstore sample application.</p>",
+		"\t<p>This is a 'router' page that serves as a jumping-off point to the petstore CRUD resource and",
+		"\t   the microservice admin endpoints.</p>",
+		"\t<p>Click <span class='link'>API</span> for the generated swagger doc, or <span class='link'>STATS</span>",
+		"\t   for runtime statistics.</p>",
 		"</div>"
 	},
 	asideFloat="RIGHT"
 )
 @SerializerConfig(
-	// For testing purposes, we want to use single quotes in all the serializers so it's easier to do simple
-	// String comparisons.
-	// You can apply any of the Serializer/Parser/MarshallingContext settings this way.
+	// For consistency with other Juneau samples — single quotes simplify HTML/string assertions in tests.
 	quoteChar="'"
 )
 @SuppressWarnings({
 	"java:S110" // Inheritance depth acceptable for example/demo code
 })
 public class RootResources extends BasicRestServletGroup {
-	// IMPORTANT!  If you don't need RDF support, change the parent interface to BasicUniversalConfig.
-	// It allows you to remove the Jena prerequisite.
 
 	private static final long serialVersionUID = 1L;
-}
\ No newline at end of file
+}
diff --git a/juneau-examples/juneau-examples-rest-jetty/src/main/java/org/apache/juneau/examples/rest/jetty/package-info.java b/juneau-petstore/juneau-petstore-jetty/src/main/java/org/apache/juneau/petstore/jetty/package-info.java
old mode 100755
new mode 100644
similarity index 63%
copy from juneau-examples/juneau-examples-rest-jetty/src/main/java/org/apache/juneau/examples/rest/jetty/package-info.java
copy to juneau-petstore/juneau-petstore-jetty/src/main/java/org/apache/juneau/petstore/jetty/package-info.java
index 0ba233d284..3b5647dc5b
--- a/juneau-examples/juneau-examples-rest-jetty/src/main/java/org/apache/juneau/examples/rest/jetty/package-info.java
+++ b/juneau-petstore/juneau-petstore-jetty/src/main/java/org/apache/juneau/petstore/jetty/package-info.java
@@ -15,11 +15,12 @@
  * limitations under the License.
  */
 /**
- * REST Jetty Examples
+ * Apache Juneau Petstore - Jetty/Microservice deployment.
  *
  * <p>
- * Example classes demonstrating how to deploy Juneau REST servers using Jetty.
- * These examples show various Jetty-based REST API deployment scenarios.
- * </p>
+ * Provides {@link org.apache.juneau.petstore.jetty.App} (the {@link org.apache.juneau.microservice.Microservice}
+ * bootstrap) and {@link org.apache.juneau.petstore.jetty.RootResources} (the root router that mounts
+ * {@link org.apache.juneau.petstore.rest.PetStoreResource} from {@code juneau-petstore-core} alongside the
+ * Jetty/Microservice admin resources).
  */
-package org.apache.juneau.examples.rest.jetty;
+package org.apache.juneau.petstore.jetty;
diff --git a/juneau-examples/juneau-examples-rest-jetty/src/main/resources/jetty.xml b/juneau-petstore/juneau-petstore-jetty/src/main/resources/jetty.xml
similarity index 64%
rename from juneau-examples/juneau-examples-rest-jetty/src/main/resources/jetty.xml
rename to juneau-petstore/juneau-petstore-jetty/src/main/resources/jetty.xml
index edf7af7a71..78bab32aef 100644
--- a/juneau-examples/juneau-examples-rest-jetty/src/main/resources/jetty.xml
+++ b/juneau-petstore/juneau-petstore-jetty/src/main/resources/jetty.xml
@@ -17,22 +17,22 @@
   limitations under the License.
 -->
 
-<Configure id="ExampleServer" class="org.eclipse.jetty.server.Server">
+<Configure id="PetstoreServer" class="org.eclipse.jetty.server.Server">
 
 	<Set name="connectors">
 		<Array type="org.eclipse.jetty.server.Connector">
 			<Item>
 				<New class="org.eclipse.jetty.server.ServerConnector">
 					<Arg>
-						<Ref refid="ExampleServer" />
+						<Ref refid="PetstoreServer" />
 					</Arg>
-					<Set name="port">$S{availablePort,8080}</Set>
+					<Set name="port">$S{availablePort,10000}</Set>
 				</New>
 			</Item>
 		</Array>
 	</Set>
 
-    <!-- Juneau adds its servlets in this ServletContextHandler -->
+	<!-- Juneau adds its servlets in this ServletContextHandler -->
 	<New id="context" class="org.eclipse.jetty.ee11.servlet.ServletContextHandler">
 		<Set name="contextPath">/</Set>
 		<Set name="sessionHandler">
@@ -40,28 +40,28 @@
 		</Set>
 	</New>
 
-    <!-- Save ServletContextHandler for Juneau -->  
-    <Call name="setAttribute">
-        <Arg>ServletContextHandler</Arg>
-        <Arg><Ref refid="context" /></Arg>
-    </Call>
- 
+	<!-- Save ServletContextHandler for Juneau -->
+	<Call name="setAttribute">
+		<Arg>ServletContextHandler</Arg>
+		<Arg><Ref refid="context" /></Arg>
+	</Call>
+
 	<Set name="handler">
-        <New id="collection" class="org.eclipse.jetty.server.handler.ContextHandlerCollection">
-	     	<Arg>
+		<New id="collection" class="org.eclipse.jetty.server.handler.ContextHandlerCollection">
+			<Arg>
 				<Array type="org.eclipse.jetty.server.handler.ContextHandler">
-                    <Item>
-                        <New class="org.eclipse.jetty.server.handler.ContextHandler">
-                            <!-- This is setHandler(Supplier) -->
-                            <Set name="handler"><Ref refid="context" /></Set>    
-                        </New>
-                    </Item>
 					<Item>
 						<New class="org.eclipse.jetty.server.handler.ContextHandler">
-                        	<New class="org.eclipse.jetty.server.handler.DefaultHandler" />
-                        </New>
+							<!-- This is setHandler(Supplier) -->
+							<Set name="handler"><Ref refid="context" /></Set>
+						</New>
+					</Item>
+					<Item>
+						<New class="org.eclipse.jetty.server.handler.ContextHandler">
+							<New class="org.eclipse.jetty.server.handler.DefaultHandler" />
+						</New>
 					</Item>
-                </Array>
+				</Array>
 			</Arg>
 		</New>
 	</Set>
@@ -81,14 +81,14 @@
 			<!-- Param 1: String -->
 			<Arg>
 				<Get class="org.eclipse.jetty.server.CustomRequestLog" name="EXTENDED_NCSA_FORMAT" />
-			</Arg>      
+			</Arg>
 		</New>
 	</Set>
 
-    <Get name="ThreadPool">
-        <Set name="minThreads" type="int">10</Set>
-        <Set name="maxThreads" type="int">100</Set>
-        <Set name="idleTimeout" type="int">60000</Set>
-        <Set name="detailedDump">true</Set>
-    </Get>
+	<Get name="ThreadPool">
+		<Set name="minThreads" type="int">10</Set>
+		<Set name="maxThreads" type="int">100</Set>
+		<Set name="idleTimeout" type="int">60000</Set>
+		<Set name="detailedDump">true</Set>
+	</Get>
 </Configure>
diff --git a/juneau-petstore/juneau-petstore-jetty/src/test/java/org/apache/juneau/microservice/MicroserviceTestFixture.java b/juneau-petstore/juneau-petstore-jetty/src/test/java/org/apache/juneau/microservice/MicroserviceTestFixture.java
new file mode 100644
index 0000000000..4696ad2896
--- /dev/null
+++ b/juneau-petstore/juneau-petstore-jetty/src/test/java/org/apache/juneau/microservice/MicroserviceTestFixture.java
@@ -0,0 +1,199 @@
+/*
+ * 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.juneau.microservice;
+
+import java.net.*;
+import java.util.*;
+
+import org.apache.juneau.commons.inject.*;
+import org.apache.juneau.microservice.jetty.*;
+import org.eclipse.jetty.ee11.servlet.*;
+import org.eclipse.jetty.server.*;
+import org.junit.jupiter.api.extension.*;
+
+/**
+ * JUnit 5 extension that boots a {@link Microservice} backed by {@link JettyConfiguration} on an ephemeral port for
+ * the duration of a test class.
+ *
+ * <p>
+ * Typical usage:
+ *
+ * <p class='bjava'>
+ * 	<ja>@RegisterExtension</ja>
+ * 	<jk>static</jk> MicroserviceTestFixture <jv>fixture</jv> = MicroserviceTestFixture.<jsm>create</jsm>()
+ * 		.configurations(MyServerConfig.<jk>class</jk>);
+ *
+ * 	<ja>@Configuration</ja>
+ * 	<jk>static class</jk> MyServerConfig {{
+ * 		<ja>@Bean</ja> Servlet myService() {{ <jk>return new</jk> MyRestService(); }}
+ * 	}}
+ *
+ * 	<ja>@Test</ja>
+ * 	<jk>void</jk> exampleTest() {{
+ * 		<jk>var</jk> rootUrl = <jv>fixture</jv>.getRootUrl();
+ * 		<jc>// build a client against rootUrl ...</jc>
+ * 	}}
+ * </p>
+ *
+ * <h5 class='section'>How it works:</h5>
+ * <ul>
+ * 	<li>The fixture installs {@link JettyConfiguration} plus a private {@link EphemeralJettyServerConfig}
+ * 		{@code @Configuration} that contributes a Jetty {@link Server} bound to port {@code 0} (OS-assigned
+ * 		ephemeral port). User-supplied configurations should typically contribute {@code @Bean Servlet} definitions
+ * 		which {@link JettyServerComponent} auto-mounts at {@code @Rest(path=...)}.
+ * 	<li>{@link #beforeAll(ExtensionContext) beforeAll} builds and {@link Microservice#start() starts} the service,
+ * 		then probes the bound port via the {@link Server}'s {@link ServerConnector}.
+ * 	<li>{@link #afterAll(ExtensionContext) afterAll} calls {@link Microservice#stop() stop()} so the bound port is
+ * 		released and {@code @PreDestroy} hooks on bean-store beans fire.
+ * </ul>
+ *
+ * <p>
+ * The fixture is intended to amortize Jetty-startup cost across a whole test class — combined with the dynamic
+ * {@link org.apache.juneau.rest.server.RestChildren#addChild RestChildren.addChild} / {@code removeChild} API, individual
+ * test methods can mount and unmount their own child resources against a single long-running server.
+ */
+public final class MicroserviceTestFixture implements BeforeAllCallback, AfterAllCallback {
+
+	private final List<Class<?>> configurations = new ArrayList<>();
+	private Microservice microservice;
+	private URI rootUrl;
+
+	private MicroserviceTestFixture() {}
+
+	/**
+	 * Creates a new fixture.
+	 *
+	 * @return A new fixture instance.
+	 */
+	public static MicroserviceTestFixture create() {
+		return new MicroserviceTestFixture();
+	}
+
+	/**
+	 * Registers one or more {@code @Configuration} classes whose {@code @Bean Servlet} methods will be auto-mounted
+	 * by the microservice. May be called multiple times to append.
+	 *
+	 * @param cs The configuration classes.
+	 * @return This fixture (fluent).
+	 */
+	public MicroserviceTestFixture configurations(Class<?>... cs) {
+		Collections.addAll(configurations, cs);
+		return this;
+	}
+
+	/**
+	 * Returns the root URI of the running microservice (after {@link #beforeAll(ExtensionContext)} has fired).
+	 *
+	 * @return The root URI, e.g. {@code http://localhost:54321/}.
+	 */
+	public URI getRootUrl() {
+		return rootUrl;
+	}
+
+	/**
+	 * Returns the actual port the server is listening on (post-{@code start()}).
+	 *
+	 * @return The bound port.
+	 */
+	public int getPort() {
+		return rootUrl.getPort();
+	}
+
+	/**
+	 * Returns the underlying microservice instance, useful for fixture-scoped child-resource mutations.
+	 *
+	 * @return The microservice.
+	 */
+	public Microservice getMicroservice() {
+		return microservice;
+	}
+
+	/**
+	 * Returns the {@link JettyServerComponent} bean for the running microservice.
+	 *
+	 * @return The Jetty server component.
+	 */
+	public JettyServerComponent getJettyServerComponent() {
+		return microservice.getBeanStore().getBean(JettyServerComponent.class).orElseThrow();
+	}
+
+	@Override
+	public void beforeAll(ExtensionContext ctx) throws Exception {
+		// The user's configurations come first (so @Bean Servlet methods are visible); EphemeralJettyServerConfig
+		// supplies the Jetty Server bound to port 0; JettyConfiguration wires the lifecycle and remaining defaults.
+		// JettyServerComponent resolves Server from the bean store by type, and BeanStore.getBean(...) returns the
+		// first registered match (so a user-supplied @Bean Server would still win).
+		var classes = new ArrayList<>(configurations);
+		classes.add(EphemeralJettyServerConfig.class);
+		classes.add(JettyConfiguration.class);
+		microservice = Microservice.create()
+			.configurations(classes.toArray(new Class<?>[0]))
+			.build();
+		microservice.start();
+		// JettyServerComponent.getURI() uses InetAddress.getLocalHost().getHostName() (may resolve to a non-loopback
+		// IP on some machines) and ServerConnector.getPort() (returns the configured port = 0, not the bound port).
+		// For test fixtures we want a deterministic loopback URL with the actual bound port.
+		var server = getJettyServerComponent().getServer();
+		var localPort = -1;
+		for (var c : server.getConnectors()) {
+			if (c instanceof ServerConnector sc) {
+				localPort = sc.getLocalPort();
+				break;
+			}
+		}
+		if (localPort <= 0)
+			throw new IllegalStateException("Could not determine local port of ServerConnector after start.");
+		rootUrl = URI.create("http://localhost:" + localPort);
+	}
+
+	@Override
+	public void afterAll(ExtensionContext ctx) throws Exception {
+		if (microservice != null)
+			microservice.stop();
+	}
+
+	/**
+	 * Default {@code @Configuration} that supplies a Jetty {@link Server} bound to port {@code 0}.
+	 *
+	 * <p>
+	 * The server has a single {@link ServerConnector} on port 0 (OS-assigned) and a single root
+	 * {@link ServletContextHandler} at context path {@code "/"}. {@link JettyServerComponent} discovers the handler
+	 * via the {@code "ServletContextHandler"} server attribute (the same convention used by {@code jetty.xml}).
+	 */
+	@Configuration
+	public static class EphemeralJettyServerConfig {
+
+		/**
+		 * Provides the bean-supplied Jetty {@link Server} that {@link JettyServerComponent} consumes during
+		 * {@code onStart()}.
+		 *
+		 * @return A configured {@link Server} bound to port 0.
+		 */
+		@Bean
+		public Server jettyServer() {
+			var server = new Server();
+			var connector = new ServerConnector(server);
+			connector.setPort(0);
+			server.addConnector(connector);
+			var sch = new ServletContextHandler();
+			sch.setContextPath("/");
+			server.setAttribute("ServletContextHandler", sch);
+			server.setHandler(sch);
+			return server;
+		}
+	}
+}
diff --git a/juneau-petstore/juneau-petstore-jetty/src/test/java/org/apache/juneau/petstore/jetty/PetstoreJetty_Test.java b/juneau-petstore/juneau-petstore-jetty/src/test/java/org/apache/juneau/petstore/jetty/PetstoreJetty_Test.java
new file mode 100644
index 0000000000..905bcab0d2
--- /dev/null
+++ b/juneau-petstore/juneau-petstore-jetty/src/test/java/org/apache/juneau/petstore/jetty/PetstoreJetty_Test.java
@@ -0,0 +1,245 @@
+/*
+ * 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.juneau.petstore.jetty;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+import java.net.*;
+import java.net.http.*;
+import java.net.http.HttpResponse.*;
+import java.time.*;
+
+import org.apache.juneau.*;
+import org.apache.juneau.microservice.*;
+import org.apache.juneau.testing.annotations.*;
+import org.junit.jupiter.api.*;
+import org.junit.jupiter.api.extension.*;
+
+/**
+ * Integration test that boots the petstore Jetty deployment on an ephemeral port and exercises the CRUD surface
+ * + content-negotiation through a real HTTP client.
+ *
+ * <p>
+ * Tagged {@code @JettyMicroserviceTest} (which composes {@code @Tag("container")} + {@code @Tag("jetty")}) so it
+ * skips under {@code scripts/test.py --no-container}.
+ */
+@JettyMicroserviceTest
+class PetstoreJetty_Test extends TestBase {
+
+	@RegisterExtension
+	static MicroserviceTestFixture fixture = MicroserviceTestFixture.create()
+		.configurations(App.AppConfig.class);
+
+	private static final HttpClient HTTP = HttpClient.newBuilder()
+		.connectTimeout(Duration.ofSeconds(5))
+		.followRedirects(HttpClient.Redirect.NEVER)
+		.build();
+
+	private static HttpResponse<String> get(String path, String accept) throws Exception {
+		var req = HttpRequest.newBuilder()
+			.uri(URI.create(fixture.getRootUrl() + path))
+			.timeout(Duration.ofSeconds(10))
+			.header("Accept", accept)
+			.GET()
+			.build();
+		return HTTP.send(req, BodyHandlers.ofString());
+	}
+
+	private static HttpResponse<String> getWithAuth(String path, String accept, String authValue) throws Exception {
+		var req = HttpRequest.newBuilder()
+			.uri(URI.create(fixture.getRootUrl() + path))
+			.timeout(Duration.ofSeconds(10))
+			.header("Accept", accept)
+			.header("Authorization", authValue)
+			.GET()
+			.build();
+		return HTTP.send(req, BodyHandlers.ofString());
+	}
+
+	private static HttpResponse<String> post(String path, String contentType, String body) throws Exception {
+		var req = HttpRequest.newBuilder()
+			.uri(URI.create(fixture.getRootUrl() + path))
+			.timeout(Duration.ofSeconds(10))
+			.header("Content-Type", contentType)
+			.header("Accept", "application/json")
+			.POST(HttpRequest.BodyPublishers.ofString(body))
+			.build();
+		return HTTP.send(req, BodyHandlers.ofString());
+	}
+
+	private static HttpResponse<String> delete(String path) throws Exception {
+		var req = HttpRequest.newBuilder()
+			.uri(URI.create(fixture.getRootUrl() + path))
+			.timeout(Duration.ofSeconds(10))
+			.DELETE()
+			.build();
+		return HTTP.send(req, BodyHandlers.ofString());
+	}
+
+	//-----------------------------------------------------------------------------------------------------------------
+	// a — root router page
+	//-----------------------------------------------------------------------------------------------------------------
+
+	@Test void a01_rootRendersHtml() throws Exception {
+		var resp = get("/", "text/html");
+		assertEquals(200, resp.statusCode(), "body: " + resp.body());
+		var body = resp.body();
+		assertTrue(body.contains("petstore"), "expected petstore link on root: " + body);
+	}
+
+	//-----------------------------------------------------------------------------------------------------------------
+	// b — petstore CRUD over real HTTP, JSON
+	//-----------------------------------------------------------------------------------------------------------------
+
+	@Test void b01_listPets_jsonContainsSeed() throws Exception {
+		var resp = get("/petstore/pets", "application/json");
+		assertEquals(200, resp.statusCode(), "body: " + resp.body());
+		var ct = resp.headers().firstValue("Content-Type").orElse("");
+		assertTrue(ct.startsWith("application/json"), "Content-Type was: " + ct);
+		assertTrue(resp.body().contains("Mr. Frisky"), "expected seeded pet name in response: " + resp.body());
+	}
+
+	@Test void b02_getPet_byId_json() throws Exception {
+		var resp = get("/petstore/pets/1", "application/json");
+		assertEquals(200, resp.statusCode(), "body: " + resp.body());
+		assertTrue(resp.body().contains("\"name\":\"Mr. Frisky\""), resp.body());
+	}
+
+	@Test void b03_getPet_unknown_404() throws Exception {
+		var resp = get("/petstore/pets/99999", "application/json");
+		assertEquals(404, resp.statusCode(), "body: " + resp.body());
+	}
+
+	@Test void b04_createPet_thenGet_roundTrip() throws Exception {
+		var body = "{\"name\":\"Wanda\",\"species\":\"RABBIT\",\"price\":12.50,\"status\":\"AVAILABLE\"}";
+		var post = post("/petstore/pets", "application/json", body);
+		assertEquals(200, post.statusCode(), "post body: " + post.body());
+		// Extract id from posted response (assigned server-side).
+		var id = extractLong(post.body(), "\"id\":");
+		assertNotEquals(0L, id, "server-assigned id missing in: " + post.body());
+
+		var get = get("/petstore/pets/" + id, "application/json");
+		assertEquals(200, get.statusCode(), "get body: " + get.body());
+		assertTrue(get.body().contains("\"name\":\"Wanda\""), get.body());
+	}
+
+	@Test void b05_deletePet_removes() throws Exception {
+		// Seed has pet id=2; delete then verify 404.
+		var del = delete("/petstore/pets/2");
+		assertEquals(200, del.statusCode(), "delete body: " + del.body());
+		var get = get("/petstore/pets/2", "application/json");
+		assertEquals(404, get.statusCode());
+	}
+
+	//-----------------------------------------------------------------------------------------------------------------
+	// c — content negotiation
+	//-----------------------------------------------------------------------------------------------------------------
+
+	@Test void c01_listPets_xml() throws Exception {
+		var resp = get("/petstore/pets", "text/xml");
+		assertEquals(200, resp.statusCode(), "body: " + resp.body());
+		var ct = resp.headers().firstValue("Content-Type").orElse("");
+		assertTrue(ct.startsWith("text/xml"), "Content-Type was: " + ct);
+		assertTrue(resp.body().contains("Mr. Frisky"), resp.body());
+	}
+
+	@Test void c02_listPets_html() throws Exception {
+		var resp = get("/petstore/pets", "text/html");
+		assertEquals(200, resp.statusCode(), "body: " + resp.body());
+		var ct = resp.headers().firstValue("Content-Type").orElse("");
+		assertTrue(ct.startsWith("text/html"), "Content-Type was: " + ct);
+		assertTrue(resp.body().contains("Mr. Frisky"), resp.body());
+	}
+
+	//-----------------------------------------------------------------------------------------------------------------
+	// d — view-engine demos (parity with springboot deployment — both inherit from core)
+	//-----------------------------------------------------------------------------------------------------------------
+
+	@Test void d01_mustacheView_rendersPet() throws Exception {
+		var resp = get("/pet-views/mustache/pets/1/view", "text/html");
+		assertEquals(200, resp.statusCode(), "body: " + resp.body());
+		var ct = resp.headers().firstValue("Content-Type").orElse("");
+		assertTrue(ct.startsWith("text/html"), "Content-Type was: " + ct);
+		assertTrue(resp.body().contains("Mr. Frisky"), "expected pet name in mustache view: " + resp.body());
+		assertTrue(resp.body().contains("Rendered via Mustache."), "expected mustache marker: " + resp.body());
+	}
+
+	@Test void d02_freemarkerView_rendersPet() throws Exception {
+		var resp = get("/pet-views/freemarker/pets/1/view", "text/html");
+		assertEquals(200, resp.statusCode(), "body: " + resp.body());
+		var ct = resp.headers().firstValue("Content-Type").orElse("");
+		assertTrue(ct.startsWith("text/html"), "Content-Type was: " + ct);
+		assertTrue(resp.body().contains("Mr. Frisky"), "expected pet name in freemarker view: " + resp.body());
+		assertTrue(resp.body().contains("Rendered via FreeMarker."), "expected freemarker marker: " + resp.body());
+	}
+
+	//-----------------------------------------------------------------------------------------------------------------
+	// e — AuthFilterChain gating /petstore-secure/* (parity with springboot deployment)
+	//-----------------------------------------------------------------------------------------------------------------
+
+	@Test void e01_secureEndpoint_noAuth_401() throws Exception {
+		var resp = get("/petstore-secure/pets", "application/json");
+		assertEquals(401, resp.statusCode(), "body: " + resp.body());
+		var challenge = resp.headers().firstValue("WWW-Authenticate").orElse("");
+		assertTrue(challenge.contains("Bearer"), "WWW-Authenticate should advertise Bearer scheme: " + challenge);
+	}
+
+	@Test void e02_secureEndpoint_validToken_200() throws Exception {
+		var resp = getWithAuth("/petstore-secure/pets", "application/json", "Bearer petstore-user");
+		assertEquals(200, resp.statusCode(), "body: " + resp.body());
+		assertTrue(resp.body().contains("Mr. Frisky"), "body: " + resp.body());
+	}
+
+	@Test void e03_secureEndpoint_unknownToken_401() throws Exception {
+		var resp = getWithAuth("/petstore-secure/pets", "application/json", "Bearer wrong-token");
+		assertEquals(401, resp.statusCode(), "body: " + resp.body());
+	}
+
+	@Test void e04_secureEndpoint_whoami_returnsPrincipalName() throws Exception {
+		var resp = getWithAuth("/petstore-secure/whoami", "application/json", "Bearer petstore-admin");
+		assertEquals(200, resp.statusCode(), "body: " + resp.body());
+		assertTrue(resp.body().contains("\"name\":\"admin\""), "body: " + resp.body());
+	}
+
+	@Test void e05_unsecuredEndpoint_stillOpen() throws Exception {
+		// /petstore/* is NOT in the chain pattern, so anonymous access still works.
+		var resp = get("/petstore/pets/1", "application/json");
+		assertEquals(200, resp.statusCode(), "body: " + resp.body());
+	}
+
+	//-----------------------------------------------------------------------------------------------------------------
+	// helpers
+	//-----------------------------------------------------------------------------------------------------------------
+
+	/**
+	 * Cheap brittle JSON int extractor — finds the first occurrence of {@code key} (e.g. {@code "id":}) and reads
+	 * the integer that follows. Sufficient for the simple CRUD round-trip assertions; we don't pull in a full JSON
+	 * parser just for this test class.
+	 */
+	private static long extractLong(String body, String key) {
+		var i = body.indexOf(key);
+		if (i < 0)
+			return 0L;
+		i += key.length();
+		var end = i;
+		while (end < body.length() && (Character.isDigit(body.charAt(end)) || body.charAt(end) == '-'))
+			end++;
+		if (end == i)
+			return 0L;
+		return Long.parseLong(body.substring(i, end));
+	}
+}
diff --git a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/command/package-info.java b/juneau-petstore/juneau-petstore-jetty/src/test/java/org/apache/juneau/testing/annotations/JettyMicroserviceTest.java
old mode 100755
new mode 100644
similarity index 72%
copy from juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/command/package-info.java
copy to juneau-petstore/juneau-petstore-jetty/src/test/java/org/apache/juneau/testing/annotations/JettyMicroserviceTest.java
index dd83076900..a9dd6b690e
--- a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/command/package-info.java
+++ b/juneau-petstore/juneau-petstore-jetty/src/test/java/org/apache/juneau/testing/annotations/JettyMicroserviceTest.java
@@ -14,12 +14,17 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+package org.apache.juneau.testing.annotations;
+
+import java.lang.annotation.*;
+
+import org.junit.jupiter.api.*;
+
 /**
- * REST Command Examples
- *
- * <p>
- * Example classes demonstrating how to use command pattern with Juneau's REST server.
- * These examples show various command-based REST API scenarios.
- * </p>
+ * Marker for container-backed Jetty microservice tests.
  */
-package org.apache.juneau.examples.rest.command;
+@Target(ElementType.TYPE)
+@Retention(RetentionPolicy.RUNTIME)
+@Tag("container")
+@Tag("jetty")
+public @interface JettyMicroserviceTest {}
diff --git a/juneau-examples/juneau-examples-rest-springboot/pom.xml b/juneau-petstore/juneau-petstore-springboot/pom.xml
similarity index 63%
rename from juneau-examples/juneau-examples-rest-springboot/pom.xml
rename to juneau-petstore/juneau-petstore-springboot/pom.xml
index c08ac1a052..aeb3cd27d0 100644
--- a/juneau-examples/juneau-examples-rest-springboot/pom.xml
+++ b/juneau-petstore/juneau-petstore-springboot/pom.xml
@@ -21,13 +21,14 @@
 
 	<parent>
 		<groupId>org.apache.juneau</groupId>
-		<artifactId>juneau-examples</artifactId>
+		<artifactId>juneau-petstore</artifactId>
 		<version>10.0.0-SNAPSHOT</version>
 	</parent>
 
-	<artifactId>juneau-examples-rest-springboot</artifactId>
-	<name>Apache Juneau REST Spring Boot Examples</name>
-	<description>Apache Juneau REST Examples using Spring Boot</description>
+	<artifactId>juneau-petstore-springboot</artifactId>
+	<name>Apache Juneau Petstore Spring Boot</name>
+	<description>Apache Juneau Petstore - Spring Boot deployment</description>
+	<packaging>jar</packaging>
 
 	<properties>
 		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
@@ -36,7 +37,7 @@
 	<dependencies>
 		<dependency>
 			<groupId>org.apache.juneau</groupId>
-			<artifactId>juneau-examples-rest</artifactId>
+			<artifactId>juneau-petstore-core</artifactId>
 			<version>${project.version}</version>
 		</dependency>
 		<dependency>
@@ -44,10 +45,37 @@
 			<artifactId>juneau-rest-server-springboot</artifactId>
 			<version>${project.version}</version>
 		</dependency>
+
+		<!-- Test dependencies -->
+		<dependency>
+			<groupId>org.junit.jupiter</groupId>
+			<artifactId>junit-jupiter</artifactId>
+			<version>${junit.version}</version>
+			<scope>test</scope>
+		</dependency>
+		<dependency>
+			<groupId>org.apache.juneau</groupId>
+			<artifactId>juneau-junit5</artifactId>
+			<version>${project.version}</version>
+			<scope>test</scope>
+		</dependency>
+		<dependency>
+			<groupId>org.apache.juneau</groupId>
+			<artifactId>juneau-test-utils</artifactId>
+			<version>${project.version}</version>
+			<scope>test</scope>
+		</dependency>
+		<dependency>
+			<groupId>org.apache.juneau</groupId>
+			<artifactId>juneau-bct</artifactId>
+			<version>${project.version}</version>
+			<scope>test</scope>
+		</dependency>
 		<dependency>
 			<groupId>org.springframework.boot</groupId>
-			<artifactId>spring-boot-starter-web</artifactId>
+			<artifactId>spring-boot-starter-test</artifactId>
 			<version>${spring.version}</version>
+			<scope>test</scope>
 			<exclusions>
 				<exclusion>
 					<groupId>org.springframework.boot</groupId>
@@ -72,6 +100,10 @@
 					</execution>
 				</executions>
 			</plugin>
+			<plugin>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-jar-plugin</artifactId>
+			</plugin>
 			<plugin>
 				<groupId>org.springframework.boot</groupId>
 				<artifactId>spring-boot-maven-plugin</artifactId>
@@ -85,40 +117,24 @@
 				</executions>
 			</plugin>
 			<plugin>
-				<artifactId>maven-assembly-plugin</artifactId>
-				<configuration>
-					<escapeString>\</escapeString>
-				</configuration>
+				<groupId>org.jacoco</groupId>
+				<artifactId>jacoco-maven-plugin</artifactId>
 				<executions>
 					<execution>
-						<id>juneau-assembly</id>
-						<phase>package</phase>
+						<id>default-prepare-agent</id>
 						<goals>
-							<goal>single</goal>
+							<goal>prepare-agent</goal>
+						</goals>
+					</execution>
+					<execution>
+						<id>default-report</id>
+						<phase>prepare-package</phase>
+						<goals>
+							<goal>report</goal>
 						</goals>
-						<configuration>
-							<finalName>juneau-examples-rest-springboot-${project.version}</finalName>
-							<descriptors>
-								<descriptor>src/assembly/bin.xml</descriptor>
-							</descriptors>
-						</configuration>
 					</execution>
 				</executions>
 			</plugin>
 		</plugins>
 	</build>
-
-	<distributionManagement>
-		<repository>
-			<id>apache.releases.https</id>
-			<name>Apache Release Distribution Repository</name>
-			<url>https://repository.apache.org/service/local/staging/deploy/maven2</url>
-		</repository>
-		<snapshotRepository>
-			<id>apache.snapshots.https</id>
-			<name>Apache Development Snapshot Repository</name>
-			<url>https://repository.apache.org/content/repositories/snapshots</url>
-		</snapshotRepository>
-	</distributionManagement>
-
 </project>
diff --git a/juneau-petstore/juneau-petstore-springboot/src/main/java/org/apache/juneau/petstore/springboot/App.java b/juneau-petstore/juneau-petstore-springboot/src/main/java/org/apache/juneau/petstore/springboot/App.java
new file mode 100644
index 0000000000..cccf059bbd
--- /dev/null
+++ b/juneau-petstore/juneau-petstore-springboot/src/main/java/org/apache/juneau/petstore/springboot/App.java
@@ -0,0 +1,98 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.juneau.petstore.springboot;
+
+import org.springframework.boot.autoconfigure.*;
+import org.springframework.boot.builder.*;
+import org.springframework.boot.web.servlet.*;
+import org.springframework.context.annotation.*;
+import org.springframework.stereotype.*;
+
+import jakarta.servlet.*;
+
+/**
+ * Petstore Spring Boot deployment entry point.
+ *
+ * <p>
+ * Boots a Spring Boot embedded servlet container, wires {@link RootResources} as a Spring bean, and mounts it at
+ * {@code /*} via {@link ServletRegistrationBean}.
+ *
+ * <p>
+ * Provides a {@code @Bean HelloMessageProvider} to demonstrate Spring {@code @Autowired} injection into the
+ * companion {@link HelloResource} child — preserving the deployment-glue Spring-injection demo.
+ *
+ * <h5 class='section'>See Also:</h5><ul>
+ * 	<li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/JuneauPetstoreOverview">juneau-petstore</a>
+ * </ul>
+ */
+@SpringBootApplication
+@Controller
+public class App {
+
+	/**
+	 * Entry point.
+	 *
+	 * @param args Command-line arguments forwarded to Spring Boot.
+	 */
+	@SuppressWarnings({
+		"resource" // ApplicationContext is owned by Spring; not a leak.
+	})
+	public static void main(String[] args) {
+		new SpringApplicationBuilder(App.class).run(args);
+	}
+
+	/**
+	 * Spring-injected message provider consumed by {@link HelloResource}.
+	 *
+	 * @return The hello-message provider bean.
+	 */
+	@Bean
+	public HelloMessageProvider helloMessageProvider() {
+		return new HelloMessageProvider("Hello from Spring-injected bean!");
+	}
+
+	/**
+	 * Returns {@link HelloResource} as a Spring bean so {@code @Autowired} fields resolve.
+	 *
+	 * @return The hello-world REST resource.
+	 */
+	@Bean
+	public HelloResource helloResource() {
+		return new HelloResource();
+	}
+
+	/**
+	 * Returns the root router as a Spring bean so child resources resolve as Spring beans.
+	 *
+	 * @return The root router REST resource.
+	 */
+	@Bean
+	public RootResources rootResources() {
+		return new RootResources();
+	}
+
+	/**
+	 * Mounts the root router servlet at {@code /*}.
+	 *
+	 * @param rootResources The Spring-managed root router.
+	 * @return The servlet registration mapped to {@code /*}.
+	 */
+	@Bean
+	public ServletRegistrationBean<Servlet> rootServlet(RootResources rootResources) {
+		return new ServletRegistrationBean<>(rootResources, "/*");
+	}
+}
diff --git a/juneau-examples/juneau-examples-rest-springboot/src/main/java/org/apache/juneau/examples/rest/springboot/HelloWorldMessageProvider.java b/juneau-petstore/juneau-petstore-springboot/src/main/java/org/apache/juneau/petstore/springboot/HelloMessageProvider.java
similarity index 64%
rename from juneau-examples/juneau-examples-rest-springboot/src/main/java/org/apache/juneau/examples/rest/springboot/HelloWorldMessageProvider.java
rename to juneau-petstore/juneau-petstore-springboot/src/main/java/org/apache/juneau/petstore/springboot/HelloMessageProvider.java
index 665715d937..e043841aa6 100644
--- a/juneau-examples/juneau-examples-rest-springboot/src/main/java/org/apache/juneau/examples/rest/springboot/HelloWorldMessageProvider.java
+++ b/juneau-petstore/juneau-petstore-springboot/src/main/java/org/apache/juneau/petstore/springboot/HelloMessageProvider.java
@@ -14,27 +14,24 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.juneau.examples.rest.springboot;
+package org.apache.juneau.petstore.springboot;
 
 import java.util.function.*;
 
 /**
- * An example of a Spring bean that can be used for injecting messages into {@link HelloWorldResource}.
- *
- * <h5 class='section'>See Also:</h5><ul>
- * 	<li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/JuneauRestServerSpringbootBasics">juneau-rest-server-springboot Basics</a>
- * </ul>
+ * Sample Spring bean injected into {@link HelloResource} to demonstrate the {@code @Autowired} pattern under
+ * Juneau {@code SpringRestServlet}-based deployments.
  */
-public class HelloWorldMessageProvider implements Supplier<String> {
+public class HelloMessageProvider implements Supplier<String> {
 
 	private final String message;
 
 	/**
 	 * Constructor.
 	 *
-	 * @param message The message to display.
+	 * @param message The message to surface from {@link #get()}.
 	 */
-	public HelloWorldMessageProvider(String message) {
+	public HelloMessageProvider(String message) {
 		this.message = message;
 	}
 
@@ -42,4 +39,4 @@ public class HelloWorldMessageProvider implements Supplier<String> {
 	public String get() {
 		return message;
 	}
-}
\ No newline at end of file
+}
diff --git a/juneau-examples/juneau-examples-rest-springboot/src/main/java/org/apache/juneau/examples/rest/springboot/HelloWorldResource.java b/juneau-petstore/juneau-petstore-springboot/src/main/java/org/apache/juneau/petstore/springboot/HelloResource.java
similarity index 51%
rename from juneau-examples/juneau-examples-rest-springboot/src/main/java/org/apache/juneau/examples/rest/springboot/HelloWorldResource.java
rename to juneau-petstore/juneau-petstore-springboot/src/main/java/org/apache/juneau/petstore/springboot/HelloResource.java
index cb68020b77..a0fd3aa253 100644
--- a/juneau-examples/juneau-examples-rest-springboot/src/main/java/org/apache/juneau/examples/rest/springboot/HelloWorldResource.java
+++ b/juneau-petstore/juneau-petstore-springboot/src/main/java/org/apache/juneau/petstore/springboot/HelloResource.java
@@ -14,46 +14,42 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.juneau.examples.rest.springboot;
+package org.apache.juneau.petstore.springboot;
 
-import org.apache.juneau.marshall.html.*;
 import org.apache.juneau.rest.server.*;
 import org.apache.juneau.rest.server.servlet.*;
 import org.springframework.beans.factory.annotation.*;
 
 /**
- * Sample REST resource that prints out a simple "Hello world!" message.
+ * Tiny REST resource that demonstrates Spring {@code @Autowired} injection into a Juneau {@code @Rest} servlet
+ * under a Spring Boot deployment.  Mirrors the legacy {@code HelloWorldResource} demo.
+ *
+ * <p>
+ * The {@link HelloMessageProvider} bean is wired by Spring; the {@code GET /hello/*} endpoint surfaces its message.
+ * Resolution of the {@code HelloMessageProvider} bean works because the parent router extends
+ * {@code BasicSpringRestServletGroup} (i.e. {@code SpringRestServlet}), which lets child resources be Spring beans.
  *
  * <h5 class='section'>See Also:</h5><ul>
- * 	<li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/JuneauRestServerSpringbootBasics">juneau-rest-server-springboot Basics</a>
-
+ * 	<li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/JuneauPetstoreOverview">juneau-petstore</a>
  * </ul>
  */
 @Rest(
-	title="Hello World",
-	description="An example of the simplest-possible resource",
-	path="/helloWorld"
-)
-@HtmlDocConfig(
-	aside={
-		"<div style='max-width:400px' class='text'>",
-		"\t<p>This page shows a resource that simply response with a 'Hello world!' message</p>",
-		"\t<p>The POJO serialized is a simple String.</p>",
-		"</div>"
-	}
+	path="/hello",
+	title="Hello (Spring injection demo)",
+	description="A trivial REST resource demonstrating Spring @Autowired injection of a HelloMessageProvider bean."
 )
-public class HelloWorldResource extends BasicRestResource {
+public class HelloResource extends BasicRestResource {
 
 	@Autowired
-	private HelloWorldMessageProvider messageProvider;
+	private HelloMessageProvider messageProvider;
 
 	/**
-	 * GET request handler.
+	 * GET /hello/* — returns the message provided by the injected Spring bean.
 	 *
-	 * @return A simple Hello-World message.
+	 * @return The injected message.
 	 */
-	@RestGet(path = "/*", summary = "Responds with injected message")
+	@RestGet(path="/*", summary="Responds with the Spring-injected message.")
 	public String sayHello() {
 		return messageProvider.get();
 	}
-}
\ No newline at end of file
+}
diff --git a/juneau-petstore/juneau-petstore-springboot/src/main/java/org/apache/juneau/petstore/springboot/RootResources.java b/juneau-petstore/juneau-petstore-springboot/src/main/java/org/apache/juneau/petstore/springboot/RootResources.java
new file mode 100644
index 0000000000..0a1034bfbb
--- /dev/null
+++ b/juneau-petstore/juneau-petstore-springboot/src/main/java/org/apache/juneau/petstore/springboot/RootResources.java
@@ -0,0 +1,88 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.juneau.petstore.springboot;
+
+import org.apache.juneau.marshall.html.*;
+import org.apache.juneau.marshall.serializer.*;
+import org.apache.juneau.petstore.rest.*;
+import org.apache.juneau.rest.server.*;
+import org.apache.juneau.rest.server.springboot.*;
+import org.apache.juneau.rest.server.widget.*;
+
+/**
+ * Root router resource for the Spring Boot deployment.
+ *
+ * <p>
+ * Extends {@link BasicSpringRestServletGroup} (i.e. {@link SpringRestServlet}) so child resources can be resolved
+ * as Spring beans — required for {@link HelloResource} to receive its {@code @Autowired} {@link HelloMessageProvider}.
+ * Mounts the deployment-agnostic {@link PetStoreResource} from {@code juneau-petstore-core} alongside the local
+ * {@link HelloResource} injection demo.
+ *
+ * <p>
+ * Note: this Spring Boot deployment intentionally does NOT mount the Jetty/Microservice admin trio
+ * ({@code ConfigResource}/{@code LogsResource}/{@code ShutdownResource}) — those are Jetty-only and have no
+ * meaningful analogue here (Spring Boot has its own actuator surface).  This is the documented non-parity
+ * deployment-specific difference between the two petstore deployments.
+ *
+ * <h5 class='section'>See Also:</h5><ul>
+ * 	<li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/JuneauPetstoreOverview">juneau-petstore</a>
+ * </ul>
+ *
+ * @serial exclude
+ */
+@Rest(
+	title="Juneau Petstore (Spring Boot)",
+	description="Apache Juneau petstore sample application running under Spring Boot.",
+	children={
+		PetStoreResource.class,
+		PetSecureResource.class,
+		PetMustacheViewResource.class,
+		PetFreemarkerViewResource.class,
+		PetstoreUiResource.class,
+		HelloResource.class
+	}
+)
+@HtmlDocConfig(
+	widgets={
+		ContentTypeMenuItem.class
+	},
+	navlinks={
+		"api: servlet:/api",
+		"stats: servlet:/stats",
+		"$W{ContentTypeMenuItem}",
+		"source: $C{Source/gitHub}/org/apache/juneau/petstore/springboot/RootResources.java"
+	},
+	aside={
+		"<div class='text'>",
+		"\t<p>Apache Juneau petstore sample application — Spring Boot deployment.</p>",
+		"\t<p>This is the same Juneau REST surface as the Jetty deployment, deployed unchanged under Spring Boot",
+		"\t   (note: child resources resolve as Spring beans).</p>",
+		"</div>"
+	},
+	asideFloat="RIGHT"
+)
+@SerializerConfig(
+	// Single quotes for consistency with other Juneau samples — simplifies HTML/string assertions in tests.
+	quoteChar="'"
+)
+@SuppressWarnings({
+	"java:S110" // Inheritance depth acceptable for example/demo code
+})
+public class RootResources extends BasicSpringRestServletGroup {
+
+	private static final long serialVersionUID = 1L;
+}
diff --git a/juneau-examples/juneau-examples-rest-jetty/src/main/java/org/apache/juneau/examples/rest/jetty/package-info.java b/juneau-petstore/juneau-petstore-springboot/src/main/java/org/apache/juneau/petstore/springboot/package-info.java
old mode 100755
new mode 100644
similarity index 59%
rename from juneau-examples/juneau-examples-rest-jetty/src/main/java/org/apache/juneau/examples/rest/jetty/package-info.java
rename to juneau-petstore/juneau-petstore-springboot/src/main/java/org/apache/juneau/petstore/springboot/package-info.java
index 0ba233d284..135781fc29
--- a/juneau-examples/juneau-examples-rest-jetty/src/main/java/org/apache/juneau/examples/rest/jetty/package-info.java
+++ b/juneau-petstore/juneau-petstore-springboot/src/main/java/org/apache/juneau/petstore/springboot/package-info.java
@@ -15,11 +15,13 @@
  * limitations under the License.
  */
 /**
- * REST Jetty Examples
+ * Apache Juneau Petstore - Spring Boot deployment.
  *
  * <p>
- * Example classes demonstrating how to deploy Juneau REST servers using Jetty.
- * These examples show various Jetty-based REST API deployment scenarios.
- * </p>
+ * Provides {@link org.apache.juneau.petstore.springboot.App} ({@code @SpringBootApplication} bootstrap) and
+ * {@link org.apache.juneau.petstore.springboot.RootResources} ({@code BasicSpringRestServletGroup}-based router
+ * mounting {@link org.apache.juneau.petstore.rest.PetStoreResource} from {@code juneau-petstore-core}).  The
+ * {@link org.apache.juneau.petstore.springboot.HelloResource} child preserves the legacy {@code @Autowired}
+ * injection demo.
  */
-package org.apache.juneau.examples.rest.jetty;
+package org.apache.juneau.petstore.springboot;
diff --git a/juneau-examples/juneau-examples-rest-springboot/src/main/resources/application.properties b/juneau-petstore/juneau-petstore-springboot/src/main/resources/application.properties
similarity index 100%
rename from juneau-examples/juneau-examples-rest-springboot/src/main/resources/application.properties
rename to juneau-petstore/juneau-petstore-springboot/src/main/resources/application.properties
diff --git a/juneau-petstore/juneau-petstore-springboot/src/test/java/org/apache/juneau/petstore/springboot/PetstoreSpringboot_Test.java b/juneau-petstore/juneau-petstore-springboot/src/test/java/org/apache/juneau/petstore/springboot/PetstoreSpringboot_Test.java
new file mode 100644
index 0000000000..c7e4030858
--- /dev/null
+++ b/juneau-petstore/juneau-petstore-springboot/src/test/java/org/apache/juneau/petstore/springboot/PetstoreSpringboot_Test.java
@@ -0,0 +1,241 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.juneau.petstore.springboot;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+import java.net.*;
+import java.net.http.*;
+import java.net.http.HttpResponse.*;
+import java.time.*;
+
+import org.junit.jupiter.api.*;
+import org.springframework.boot.test.context.*;
+import org.springframework.boot.test.context.SpringBootTest.*;
+import org.springframework.boot.test.web.server.*;
+
+/**
+ * Integration test that boots the petstore Spring Boot deployment on a random port and exercises the CRUD
+ * surface plus the Spring {@code @Autowired} injection demo.
+ *
+ * <p>
+ * Tagged {@code @SpringbootTest} ({@code @Tag("container")} + {@code @Tag("springboot")}) so it skips under
+ * {@code scripts/test.py --no-container}.
+ *
+ * <p>
+ * Asserts the parity story: the same CRUD surface from {@code juneau-petstore-core} that the Jetty deployment
+ * mounts is reachable identically here, plus the Spring-injected {@link HelloResource} demonstrates the
+ * deployment-specific {@code @Autowired} pattern.
+ */
+@org.apache.juneau.testing.annotations.SpringbootTest
+@SpringBootTest(classes = App.class, webEnvironment = WebEnvironment.RANDOM_PORT)
+class PetstoreSpringboot_Test {
+
+	@LocalServerPort
+	int port;
+
+	private static final HttpClient HTTP = HttpClient.newBuilder()
+		.connectTimeout(Duration.ofSeconds(5))
+		.followRedirects(HttpClient.Redirect.NEVER)
+		.build();
+
+	private HttpResponse<String> get(String path, String accept) throws Exception {
+		var req = HttpRequest.newBuilder()
+			.uri(URI.create("http://localhost:" + port + path))
+			.timeout(Duration.ofSeconds(10))
+			.header("Accept", accept)
+			.GET()
+			.build();
+		return HTTP.send(req, BodyHandlers.ofString());
+	}
+
+	private HttpResponse<String> getWithAuth(String path, String accept, String authValue) throws Exception {
+		var req = HttpRequest.newBuilder()
+			.uri(URI.create("http://localhost:" + port + path))
+			.timeout(Duration.ofSeconds(10))
+			.header("Accept", accept)
+			.header("Authorization", authValue)
+			.GET()
+			.build();
+		return HTTP.send(req, BodyHandlers.ofString());
+	}
+
+	private HttpResponse<String> post(String path, String contentType, String body) throws Exception {
+		var req = HttpRequest.newBuilder()
+			.uri(URI.create("http://localhost:" + port + path))
+			.timeout(Duration.ofSeconds(10))
+			.header("Content-Type", contentType)
+			.header("Accept", "application/json")
+			.POST(HttpRequest.BodyPublishers.ofString(body))
+			.build();
+		return HTTP.send(req, BodyHandlers.ofString());
+	}
+
+	private HttpResponse<String> delete(String path) throws Exception {
+		var req = HttpRequest.newBuilder()
+			.uri(URI.create("http://localhost:" + port + path))
+			.timeout(Duration.ofSeconds(10))
+			.DELETE()
+			.build();
+		return HTTP.send(req, BodyHandlers.ofString());
+	}
+
+	//-----------------------------------------------------------------------------------------------------------------
+	// a — root router page
+	//-----------------------------------------------------------------------------------------------------------------
+
+	@Test void a01_rootRendersHtml() throws Exception {
+		var resp = get("/", "text/html");
+		assertEquals(200, resp.statusCode(), "body: " + resp.body());
+		assertTrue(resp.body().contains("petstore"), "expected petstore link on root: " + resp.body());
+	}
+
+	//-----------------------------------------------------------------------------------------------------------------
+	// b — petstore CRUD over real HTTP
+	//-----------------------------------------------------------------------------------------------------------------
+
+	@Test void b01_listPets_jsonContainsSeed() throws Exception {
+		var resp = get("/petstore/pets", "application/json");
+		assertEquals(200, resp.statusCode(), "body: " + resp.body());
+		assertTrue(resp.body().contains("Mr. Frisky"), "expected seeded pet name in response: " + resp.body());
+	}
+
+	@Test void b02_getPet_byId_json() throws Exception {
+		var resp = get("/petstore/pets/1", "application/json");
+		assertEquals(200, resp.statusCode(), "body: " + resp.body());
+		assertTrue(resp.body().contains("\"name\":\"Mr. Frisky\""), resp.body());
+	}
+
+	@Test void b03_getPet_unknown_404() throws Exception {
+		var resp = get("/petstore/pets/99999", "application/json");
+		assertEquals(404, resp.statusCode(), "body: " + resp.body());
+	}
+
+	@Test void b04_createPet_thenGet_roundTrip() throws Exception {
+		var body = "{\"name\":\"Wanda\",\"species\":\"RABBIT\",\"price\":12.50,\"status\":\"AVAILABLE\"}";
+		var post = post("/petstore/pets", "application/json", body);
+		assertEquals(200, post.statusCode(), "post body: " + post.body());
+		var id = extractLong(post.body(), "\"id\":");
+		assertNotEquals(0L, id, "server-assigned id missing in: " + post.body());
+
+		var get = get("/petstore/pets/" + id, "application/json");
+		assertEquals(200, get.statusCode(), "get body: " + get.body());
+		assertTrue(get.body().contains("\"name\":\"Wanda\""), get.body());
+	}
+
+	@Test void b05_deletePet_removes() throws Exception {
+		var del = delete("/petstore/pets/2");
+		assertEquals(200, del.statusCode(), "delete body: " + del.body());
+		var get = get("/petstore/pets/2", "application/json");
+		assertEquals(404, get.statusCode());
+	}
+
+	//-----------------------------------------------------------------------------------------------------------------
+	// c — content negotiation parity with the Jetty deployment
+	//-----------------------------------------------------------------------------------------------------------------
+
+	@Test void c01_listPets_xml() throws Exception {
+		var resp = get("/petstore/pets", "text/xml");
+		assertEquals(200, resp.statusCode(), "body: " + resp.body());
+		assertTrue(resp.body().contains("Mr. Frisky"), resp.body());
+	}
+
+	@Test void c02_listPets_html() throws Exception {
+		var resp = get("/petstore/pets", "text/html");
+		assertEquals(200, resp.statusCode(), "body: " + resp.body());
+		assertTrue(resp.body().contains("Mr. Frisky"), resp.body());
+	}
+
+	//-----------------------------------------------------------------------------------------------------------------
+	// d — Spring @Autowired injection demo
+	//-----------------------------------------------------------------------------------------------------------------
+
+	@Test void d01_helloResource_returnsInjectedMessage() throws Exception {
+		var resp = get("/hello", "text/plain");
+		assertEquals(200, resp.statusCode(), "body: " + resp.body());
+		assertTrue(resp.body().contains("Hello from Spring-injected bean!"),
+			"expected injected message in response: " + resp.body());
+	}
+
+	//-----------------------------------------------------------------------------------------------------------------
+	// e — view-engine demos (parity with jetty deployment — both inherit from core)
+	//-----------------------------------------------------------------------------------------------------------------
+
+	@Test void e01_mustacheView_rendersPet() throws Exception {
+		var resp = get("/pet-views/mustache/pets/1/view", "text/html");
+		assertEquals(200, resp.statusCode(), "body: " + resp.body());
+		assertTrue(resp.body().contains("Mr. Frisky"), "expected pet name in mustache view: " + resp.body());
+		assertTrue(resp.body().contains("Rendered via Mustache."), "expected mustache marker: " + resp.body());
+	}
+
+	@Test void e02_freemarkerView_rendersPet() throws Exception {
+		var resp = get("/pet-views/freemarker/pets/1/view", "text/html");
+		assertEquals(200, resp.statusCode(), "body: " + resp.body());
+		assertTrue(resp.body().contains("Mr. Frisky"), "expected pet name in freemarker view: " + resp.body());
+		assertTrue(resp.body().contains("Rendered via FreeMarker."), "expected freemarker marker: " + resp.body());
+	}
+
+	//-----------------------------------------------------------------------------------------------------------------
+	// f — AuthFilterChain gating /petstore-secure/* (parity with jetty deployment)
+	//-----------------------------------------------------------------------------------------------------------------
+
+	@Test void f01_secureEndpoint_noAuth_401() throws Exception {
+		var resp = get("/petstore-secure/pets", "application/json");
+		assertEquals(401, resp.statusCode(), "body: " + resp.body());
+		var challenge = resp.headers().firstValue("WWW-Authenticate").orElse("");
+		assertTrue(challenge.contains("Bearer"), "WWW-Authenticate should advertise Bearer scheme: " + challenge);
+	}
+
+	@Test void f02_secureEndpoint_validToken_200() throws Exception {
+		var resp = getWithAuth("/petstore-secure/pets", "application/json", "Bearer petstore-user");
+		assertEquals(200, resp.statusCode(), "body: " + resp.body());
+		assertTrue(resp.body().contains("Mr. Frisky"), "body: " + resp.body());
+	}
+
+	@Test void f03_secureEndpoint_unknownToken_401() throws Exception {
+		var resp = getWithAuth("/petstore-secure/pets", "application/json", "Bearer wrong-token");
+		assertEquals(401, resp.statusCode(), "body: " + resp.body());
+	}
+
+	@Test void f04_secureEndpoint_whoami_returnsPrincipalName() throws Exception {
+		var resp = getWithAuth("/petstore-secure/whoami", "application/json", "Bearer petstore-admin");
+		assertEquals(200, resp.statusCode(), "body: " + resp.body());
+		assertTrue(resp.body().contains("\"name\":\"admin\""), "body: " + resp.body());
+	}
+
+	@Test void f05_unsecuredEndpoint_stillOpen() throws Exception {
+		var resp = get("/petstore/pets/1", "application/json");
+		assertEquals(200, resp.statusCode(), "body: " + resp.body());
+	}
+
+	//-----------------------------------------------------------------------------------------------------------------
+	// helpers
+	//-----------------------------------------------------------------------------------------------------------------
+
+	private static long extractLong(String body, String key) {
+		var i = body.indexOf(key);
+		if (i < 0)
+			return 0L;
+		i += key.length();
+		var end = i;
+		while (end < body.length() && (Character.isDigit(body.charAt(end)) || body.charAt(end) == '-'))
+			end++;
+		if (end == i)
+			return 0L;
+		return Long.parseLong(body.substring(i, end));
+	}
+}
diff --git a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/command/package-info.java b/juneau-petstore/juneau-petstore-springboot/src/test/java/org/apache/juneau/testing/annotations/SpringbootTest.java
old mode 100755
new mode 100644
similarity index 73%
rename from juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/command/package-info.java
rename to juneau-petstore/juneau-petstore-springboot/src/test/java/org/apache/juneau/testing/annotations/SpringbootTest.java
index dd83076900..0ff3f8bc07
--- a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/command/package-info.java
+++ b/juneau-petstore/juneau-petstore-springboot/src/test/java/org/apache/juneau/testing/annotations/SpringbootTest.java
@@ -14,12 +14,17 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+package org.apache.juneau.testing.annotations;
+
+import java.lang.annotation.*;
+
+import org.junit.jupiter.api.*;
+
 /**
- * REST Command Examples
- *
- * <p>
- * Example classes demonstrating how to use command pattern with Juneau's REST server.
- * These examples show various command-based REST API scenarios.
- * </p>
+ * Marker for container-backed Spring Boot tests.
  */
-package org.apache.juneau.examples.rest.command;
+@Target(ElementType.TYPE)
+@Retention(RetentionPolicy.RUNTIME)
+@Tag("container")
+@Tag("springboot")
+public @interface SpringbootTest {}
diff --git a/juneau-examples/pom.xml b/juneau-petstore/pom.xml
similarity index 75%
copy from juneau-examples/pom.xml
copy to juneau-petstore/pom.xml
index 0a316e6a73..43005b3638 100644
--- a/juneau-examples/pom.xml
+++ b/juneau-petstore/pom.xml
@@ -25,22 +25,15 @@
 		<version>10.0.0-SNAPSHOT</version>
 	</parent>
 
-	<artifactId>juneau-examples</artifactId>
+	<artifactId>juneau-petstore</artifactId>
 	<packaging>pom</packaging>
-	<name>Apache Juneau Examples</name>
-	<description>Apache Juneau Examples</description>
+	<name>Apache Juneau Petstore</name>
+	<description>Apache Juneau Petstore Sample Applications</description>
 
 	<modules>
-		<module>juneau-examples-core</module>
-		<module>juneau-examples-rest</module>
-		<module>juneau-examples-rest-jetty</module>
-		<module>juneau-examples-rest-springboot</module>
-		<module>juneau-examples-rest-jetty-ftest</module>
+		<module>juneau-petstore-core</module>
+		<module>juneau-petstore-jetty</module>
+		<module>juneau-petstore-springboot</module>
 	</modules>
 
-	<build>
-		<plugins>
-		</plugins>
-	</build>
-
 </project>
diff --git a/juneau-release.sh b/juneau-release.sh
index ecb30605c9..b9c793d520 100755
--- a/juneau-release.sh
+++ b/juneau-release.sh
@@ -150,13 +150,8 @@ ZIP_TGT=$WORKSPACE/juneau-examples-core
 echo Unzipping $ZIP_SRC to $ZIP_TGT
 unzip -o $ZIP_SRC -d $ZIP_TGT
 
-ZIP_SRC=juneau-examples/juneau-examples-rest-jetty/target/juneau-examples-rest-jetty-$XV-bin.zip
-ZIP_TGT=$WORKSPACE/juneau-examples-rest-jetty
-echo Unzipping $ZIP_SRC to $ZIP_TGT
-unzip -o $ZIP_SRC -d $ZIP_TGT
-
-ZIP_SRC=juneau-examples/juneau-examples-rest-springboot/target/juneau-examples-rest-springboot-$XV-bin.zip
-ZIP_TGT=$WORKSPACE/juneau-examples-rest-springboot
+ZIP_SRC=juneau-petstore/juneau-petstore-jetty/target/juneau-petstore-jetty-$XV-bin.zip
+ZIP_TGT=$WORKSPACE/juneau-petstore-jetty
 echo Unzipping $ZIP_SRC to $ZIP_TGT
 unzip -o $ZIP_SRC -d $ZIP_TGT
 
diff --git a/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/mstat/MethodExecStore_Test.java b/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/mstat/MethodExecStore_Test.java
index fec50fdf23..8bd777dae3 100644
--- a/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/mstat/MethodExecStore_Test.java
+++ b/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/mstat/MethodExecStore_Test.java
@@ -27,6 +27,9 @@ import org.apache.juneau.commons.inject.*;
 import org.apache.juneau.rest.server.stats.*;
 import org.junit.jupiter.api.*;
 
+@SuppressWarnings({
+	"resource" // Closeable resources in tests are intentionally unassigned; closing is handled by test infrastructure.
+})
 class MethodExecStore_Test extends TestBase {
 
 	//------------------------------------------------------------------------------------------------------------------
diff --git a/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/mstat/ThrownStore_Test.java b/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/mstat/ThrownStore_Test.java
index 8249538ff9..caac1ab9cb 100644
--- a/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/mstat/ThrownStore_Test.java
+++ b/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/mstat/ThrownStore_Test.java
@@ -29,7 +29,9 @@ import org.apache.juneau.rest.server.stats.*;
 import org.junit.jupiter.api.*;
 
 @SuppressWarnings({
-	"java:S1172" // Unused parameters in tests are intentional
+	"java:S1172", // Unused parameters in tests are intentional
+	"unused", // Constructor parameters retained for bean-instantiation signature consistency in test fixtures.
+	"resource" // Closeable resources in tests are intentionally unassigned; closing is handled by test infrastructure.
 })
 class ThrownStore_Test extends TestBase {
 
diff --git a/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/utils/MethodInvokerTest.java b/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/utils/MethodInvokerTest.java
index 48b5fdc9e0..5318339d4b 100644
--- a/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/utils/MethodInvokerTest.java
+++ b/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/utils/MethodInvokerTest.java
@@ -37,6 +37,9 @@ class MethodInvokerTest extends TestBase {
 	public static class A {
 		public int foo() { return 0; }
 		public int bar() { throw new RuntimeException("bar"); }
+		@SuppressWarnings({
+			"unused" // Parameter is intentionally unused; exercises illegal-argument handling via reflection.
+		})
 		public void baz(int x) { /* no-op */ }
 	}
 
diff --git a/juneau-sc/juneau-sc-server/juneau-server-config.cfg b/juneau-sc/juneau-sc-server/juneau-server-config.cfg
index a97e0aff3a..1c42634fd8 100755
--- a/juneau-sc/juneau-sc-server/juneau-server-config.cfg
+++ b/juneau-sc/juneau-sc-server/juneau-server-config.cfg
@@ -132,7 +132,7 @@ includeRowNums = false
 # Source code location
 #=======================================================================================================================
 [Source]
-gitHub = https://github.com/apache/juneau/blob/master/juneau-examples/juneau-examples-rest/src/main/java
+gitHub = https://github.com/apache/juneau/blob/master/juneau-petstore/juneau-petstore-core/src/main/java
 
 #=======================================================================================================================
 # PetStoreResource properties
diff --git a/juneau-sc/juneau-sc-server/pom.xml b/juneau-sc/juneau-sc-server/pom.xml
index 9d48ac5de3..219b47ac8f 100644
--- a/juneau-sc/juneau-sc-server/pom.xml
+++ b/juneau-sc/juneau-sc-server/pom.xml
@@ -76,7 +76,7 @@
 							<goal>single</goal>
 						</goals>
 						<configuration>
-							<finalName>juneau-examples-rest-jetty-${project.version}</finalName>
+							<finalName>juneau-sc-server-${project.version}</finalName>
 							<descriptors>
 								<descriptor>src/assembly/bin.xml</descriptor>
 							</descriptors>
diff --git a/pom.xml b/pom.xml
index 7c84d6a16d..74c831c1e3 100644
--- a/pom.xml
+++ b/pom.xml
@@ -63,6 +63,7 @@
 		<module>juneau-microservice</module>
 		<module>juneau-sc</module>
 		<module>juneau-examples</module>
+		<module>juneau-petstore</module>
 		<module>juneau-integration-tests</module>
 		<module>juneau-bean</module>
 		<module>juneau-shaded</module>
diff --git a/scripts/apply-eclipse-prefs.py b/scripts/apply-eclipse-prefs.py
index 3b6fe8644f..9d7a245179 100755
--- a/scripts/apply-eclipse-prefs.py
+++ b/scripts/apply-eclipse-prefs.py
@@ -16,15 +16,30 @@
 # limitations under the License.
 
 """
-Applies Eclipse IDE preference files to all Juneau project modules.
+Applies Eclipse IDE preference files to every Juneau Maven module.
 
-This script copies Eclipse JDT preferences from the eclipse-preferences directory
-to each module's .settings folder, ensuring consistent IDE configuration across
-all developers.
+Walks the reactor under each REACTOR_GROUPS entry plus STANDALONE_PROJECTS,
+finds every leaf directory with a pom.xml that is NOT a packaging=pom aggregator,
+classifies each as source or test (test = name == 'juneau-integration-tests' or
+*-ftest suffix), and copies the matching .prefs files into each module's
+.settings/ directory.
 
-There are two sets of preferences:
-- source-prefs: For main source modules
-- test-prefs: For test modules (juneau-integration-tests and *-ftest modules)
+Two sets of preferences live under scripts/eclipse-preferences/:
+- source-prefs/ — main source modules (warnings on resource leaks, unused params, etc.)
+- test-prefs/  — test modules (those warnings relaxed to ignore)
+
+Each set contains:
+- org.eclipse.jdt.core.prefs — JDT compiler problem severities + warning-token settings
+- org.eclipse.jdt.ui.prefs   — JDT UI cleanup-on-save settings
+
+Run this whenever a new Maven module is added to the reactor, or whenever the
+canonical preference baseline is updated. Module discovery is automatic — the
+script does not need to be edited when modules are added or removed (only when
+a new top-level reactor group is introduced).
+
+The .settings/ directories are gitignored locally; this script's output is a
+developer-machine-only convenience and never enters version control. The
+canonical preference files under scripts/eclipse-preferences/ ARE tracked.
 """
 
 import os
@@ -33,45 +48,81 @@ import shutil
 from pathlib import Path
 
 
-# Source modules (main code)
-SOURCE_PROJECTS = [
-    "juneau-bean/juneau-bean-atom",
-    "juneau-bean/juneau-bean-common",
-    "juneau-bean/juneau-bean-html5",
-    "juneau-bean/juneau-bean-jsonschema",
-    "juneau-bean/juneau-bean-openapi-v3",
-    "juneau-bean/juneau-bean-swagger-v2",
-    "juneau-core/juneau-assertions",
-    "juneau-core/juneau-bct",
-    "juneau-core/juneau-commons",
-    "juneau-core/juneau-config",
-    "juneau-core/juneau-marshall",
-    "juneau-core/juneau-marshall-rdf",
-    "juneau-examples/juneau-examples-core",
-    "juneau-examples/juneau-examples-rest",
-    "juneau-examples/juneau-examples-rest-jetty",
-    "juneau-examples/juneau-examples-rest-springboot",
-    "juneau-microservice/juneau-microservice",
-    "juneau-microservice/juneau-microservice-jetty",
-    "juneau-microservice/juneau-my-jetty-microservice",
-    "juneau-microservice/juneau-my-springboot-microservice",
-    "juneau-rest/juneau-rest-client",
-    "juneau-rest/juneau-rest-common",
-    "juneau-rest/juneau-rest-mock",
-    "juneau-rest/juneau-rest-server",
-    "juneau-rest/juneau-rest-server-rdf",
-    "juneau-rest/juneau-rest-server-springboot",
-    "juneau-sc/juneau-sc-client",
-    "juneau-sc/juneau-sc-server",
+# Top-level reactor groups under which to scan for modules.
+# Each leaf directory containing a pom.xml that is NOT a packaging=pom aggregator
+# is treated as a project to apply preferences to.
+REACTOR_GROUPS = [
+    "juneau-bean",
+    "juneau-core",
+    "juneau-examples",
+    "juneau-microservice",
+    "juneau-petstore",
+    "juneau-rest",
+    "juneau-sc",
+    "juneau-shaded",
 ]
 
-# Test modules
-TEST_PROJECTS = [
+# Standalone (non-grouped) projects at the repo root.
+STANDALONE_PROJECTS = [
     "juneau-integration-tests",
-    "juneau-examples/juneau-examples-rest-jetty-ftest",
 ]
 
 
+def is_aggregator_pom(pom_path):
+    """Return True if the pom.xml has <packaging>pom</packaging>."""
+    try:
+        with open(pom_path, "r", encoding="utf-8") as f:
+            content = f.read()
+        return "<packaging>pom</packaging>" in content
+    except OSError:
+        return False
+
+
+def is_test_module(project_path):
+    """
+    Returns True if the project should get test-prefs applied (relaxed rules
+    around resource leaks, unused parameters, etc.) — typically integration-test
+    aggregators or *-ftest functional-test overlays.
+    """
+    name = Path(project_path).name
+    return name == "juneau-integration-tests" or name.endswith("-ftest")
+
+
+def discover_projects(root_dir):
+    """
+    Walk the reactor groups and standalone roots; return (source_projects, test_projects)
+    as lists of paths relative to root_dir.
+    """
+    source_projects = []
+    test_projects = []
+
+    candidates = []
+    for group in REACTOR_GROUPS:
+        group_dir = Path(root_dir) / group
+        if not group_dir.exists():
+            continue
+        for child in sorted(group_dir.iterdir()):
+            if not child.is_dir():
+                continue
+            if (child / "pom.xml").exists():
+                candidates.append(child)
+    for standalone in STANDALONE_PROJECTS:
+        standalone_dir = Path(root_dir) / standalone
+        if standalone_dir.exists() and (standalone_dir / "pom.xml").exists():
+            candidates.append(standalone_dir)
+
+    for project_dir in candidates:
+        if is_aggregator_pom(project_dir / "pom.xml"):
+            continue
+        relative = project_dir.relative_to(root_dir).as_posix()
+        if is_test_module(project_dir):
+            test_projects.append(relative)
+        else:
+            source_projects.append(relative)
+
+    return source_projects, test_projects
+
+
 def apply_preferences(root_dir, projects, prefs_type):
     """
     Apply Eclipse preferences to a list of projects.
@@ -133,31 +184,35 @@ def main():
     # Determine root directory (parent of scripts directory)
     script_dir = Path(__file__).parent
     root_dir = script_dir.parent
-    
+
     if len(sys.argv) > 1:
         root_dir = Path(sys.argv[1])
-    
+
     print(f"Applying Eclipse preferences to Juneau modules in: {root_dir}\n")
-    
+
+    source_projects, test_projects = discover_projects(root_dir)
+
+    print(f"Discovered {len(source_projects)} source modules + {len(test_projects)} test modules.\n")
+
     # Apply source preferences
     print("Applying source preferences...")
-    src_success, src_failed = apply_preferences(root_dir, SOURCE_PROJECTS, "source-prefs")
-    
+    src_success, src_failed = apply_preferences(root_dir, source_projects, "source-prefs")
+
     print("\nApplying test preferences...")
-    test_success, test_failed = apply_preferences(root_dir, TEST_PROJECTS, "test-prefs")
-    
+    test_success, test_failed = apply_preferences(root_dir, test_projects, "test-prefs")
+
     # Summary
     total_success = src_success + test_success
     total_failed = src_failed + test_failed
-    total_projects = len(SOURCE_PROJECTS) + len(TEST_PROJECTS)
-    
+    total_projects = len(source_projects) + len(test_projects)
+
     print(f"\n{'='*60}")
     print("Summary:")
     print(f"  Total projects: {total_projects}")
     print(f"  Successfully updated: {total_success}")
     print(f"  Failed: {total_failed}")
     print(f"{'='*60}")
-    
+
     if total_failed > 0:
         sys.exit(1)
 
diff --git a/scripts/eclipse-preferences/source-prefs/org.eclipse.jdt.core.prefs b/scripts/eclipse-preferences/source-prefs/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000000..d6026868b8
--- /dev/null
+++ b/scripts/eclipse-preferences/source-prefs/org.eclipse.jdt.core.prefs
@@ -0,0 +1,117 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.builder.annotationPath.allLocations=disabled
+org.eclipse.jdt.core.compiler.annotation.inheritNullAnnotations=disabled
+org.eclipse.jdt.core.compiler.annotation.missingNonNullByDefaultAnnotation=ignore
+org.eclipse.jdt.core.compiler.annotation.nonnull=org.eclipse.jdt.annotation.NonNull
+org.eclipse.jdt.core.compiler.annotation.nonnull.secondary=
+org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=org.eclipse.jdt.annotation.NonNullByDefault
+org.eclipse.jdt.core.compiler.annotation.nonnullbydefault.secondary=
+org.eclipse.jdt.core.compiler.annotation.notowning=org.eclipse.jdt.annotation.NotOwning
+org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nullable
+org.eclipse.jdt.core.compiler.annotation.nullable.secondary=
+org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled
+org.eclipse.jdt.core.compiler.annotation.owning=org.eclipse.jdt.annotation.Owning
+org.eclipse.jdt.core.compiler.annotation.resourceanalysis=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=17
+org.eclipse.jdt.core.compiler.compliance=17
+org.eclipse.jdt.core.compiler.problem.APILeak=warning
+org.eclipse.jdt.core.compiler.problem.annotatedTypeArgumentToUnannotated=info
+org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=ignore
+org.eclipse.jdt.core.compiler.problem.autoboxing=ignore
+org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning
+org.eclipse.jdt.core.compiler.problem.deadCode=warning
+org.eclipse.jdt.core.compiler.problem.deprecation=warning
+org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled
+org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled
+org.eclipse.jdt.core.compiler.problem.discouragedReference=warning
+org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore
+org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled
+org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable=ignore
+org.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore
+org.eclipse.jdt.core.compiler.problem.fatalOptionalError=disabled
+org.eclipse.jdt.core.compiler.problem.fieldHiding=ignore
+org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning
+org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
+org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning
+org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=disabled
+org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning
+org.eclipse.jdt.core.compiler.problem.incompatibleOwningContract=warning
+org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=warning
+org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore
+org.eclipse.jdt.core.compiler.problem.insufficientResourceAnalysis=warning
+org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore
+org.eclipse.jdt.core.compiler.problem.memberOfDeprecatedTypeNotDeprecated=info
+org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning
+org.eclipse.jdt.core.compiler.problem.missingDefaultCase=ignore
+org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore
+org.eclipse.jdt.core.compiler.problem.missingEnumCaseDespiteDefault=disabled
+org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=ignore
+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=ignore
+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled
+org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning
+org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore
+org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning
+org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning
+org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore
+org.eclipse.jdt.core.compiler.problem.nonnullParameterAnnotationDropped=warning
+org.eclipse.jdt.core.compiler.problem.nonnullTypeVariableFromLegacyInvocation=warning
+org.eclipse.jdt.core.compiler.problem.nullAnnotationInferenceConflict=error
+org.eclipse.jdt.core.compiler.problem.nullReference=warning
+org.eclipse.jdt.core.compiler.problem.nullSpecViolation=error
+org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=warning
+org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning
+org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
+org.eclipse.jdt.core.compiler.problem.pessimisticNullAnalysisForFreeTypeVariables=warning
+org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=ignore
+org.eclipse.jdt.core.compiler.problem.potentialNullReference=ignore
+org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore
+org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning
+org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning
+org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore
+org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=ignore
+org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore
+org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore
+org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore
+org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=ignore
+org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled
+org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning
+org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled
+org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled
+org.eclipse.jdt.core.compiler.problem.suppressWarningsNotFullyAnalysed=ignore
+org.eclipse.jdt.core.compiler.problem.syntacticNullAnalysisForFields=disabled
+org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore
+org.eclipse.jdt.core.compiler.problem.terminalDeprecation=warning
+org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning
+org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=enabled
+org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning
+org.eclipse.jdt.core.compiler.problem.unclosedCloseable=warning
+org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore
+org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=ignore
+org.eclipse.jdt.core.compiler.problem.unlikelyCollectionMethodArgumentType=warning
+org.eclipse.jdt.core.compiler.problem.unlikelyCollectionMethodArgumentTypeStrict=disabled
+org.eclipse.jdt.core.compiler.problem.unlikelyEqualsArgumentType=info
+org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore
+org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=ignore
+org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore
+org.eclipse.jdt.core.compiler.problem.unstableAutoModuleName=warning
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=warning
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled
+org.eclipse.jdt.core.compiler.problem.unusedExceptionParameter=ignore
+org.eclipse.jdt.core.compiler.problem.unusedImport=warning
+org.eclipse.jdt.core.compiler.problem.unusedLabel=warning
+org.eclipse.jdt.core.compiler.problem.unusedLambdaParameter=warning
+org.eclipse.jdt.core.compiler.problem.unusedLocal=warning
+org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=warning
+org.eclipse.jdt.core.compiler.problem.unusedParameter=warning
+org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled
+org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning
+org.eclipse.jdt.core.compiler.problem.unusedTypeParameter=warning
+org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
+org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
+org.eclipse.jdt.core.compiler.release=enabled
+org.eclipse.jdt.core.compiler.source=17
diff --git a/scripts/eclipse-preferences/source-prefs/org.eclipse.jdt.ui.prefs b/scripts/eclipse-preferences/source-prefs/org.eclipse.jdt.ui.prefs
new file mode 100644
index 0000000000..0cf8a2ede4
--- /dev/null
+++ b/scripts/eclipse-preferences/source-prefs/org.eclipse.jdt.ui.prefs
@@ -0,0 +1,5 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.ui.ignorelowercasenames=true
+org.eclipse.jdt.ui.importorder=java;javax;org;com;
+org.eclipse.jdt.ui.ondemandthreshold=1
+org.eclipse.jdt.ui.staticondemandthreshold=1
diff --git a/scripts/eclipse-preferences/test-prefs/org.eclipse.jdt.core.prefs b/scripts/eclipse-preferences/test-prefs/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000000..ad58d94f90
--- /dev/null
+++ b/scripts/eclipse-preferences/test-prefs/org.eclipse.jdt.core.prefs
@@ -0,0 +1,117 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.builder.annotationPath.allLocations=disabled
+org.eclipse.jdt.core.compiler.annotation.inheritNullAnnotations=disabled
+org.eclipse.jdt.core.compiler.annotation.missingNonNullByDefaultAnnotation=ignore
+org.eclipse.jdt.core.compiler.annotation.nonnull=org.eclipse.jdt.annotation.NonNull
+org.eclipse.jdt.core.compiler.annotation.nonnull.secondary=
+org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=org.eclipse.jdt.annotation.NonNullByDefault
+org.eclipse.jdt.core.compiler.annotation.nonnullbydefault.secondary=
+org.eclipse.jdt.core.compiler.annotation.notowning=org.eclipse.jdt.annotation.NotOwning
+org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nullable
+org.eclipse.jdt.core.compiler.annotation.nullable.secondary=
+org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled
+org.eclipse.jdt.core.compiler.annotation.owning=org.eclipse.jdt.annotation.Owning
+org.eclipse.jdt.core.compiler.annotation.resourceanalysis=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=17
+org.eclipse.jdt.core.compiler.compliance=17
+org.eclipse.jdt.core.compiler.problem.APILeak=warning
+org.eclipse.jdt.core.compiler.problem.annotatedTypeArgumentToUnannotated=info
+org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=ignore
+org.eclipse.jdt.core.compiler.problem.autoboxing=ignore
+org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning
+org.eclipse.jdt.core.compiler.problem.deadCode=warning
+org.eclipse.jdt.core.compiler.problem.deprecation=warning
+org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled
+org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled
+org.eclipse.jdt.core.compiler.problem.discouragedReference=warning
+org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore
+org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled
+org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable=ignore
+org.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore
+org.eclipse.jdt.core.compiler.problem.fatalOptionalError=disabled
+org.eclipse.jdt.core.compiler.problem.fieldHiding=ignore
+org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning
+org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
+org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning
+org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=disabled
+org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning
+org.eclipse.jdt.core.compiler.problem.incompatibleOwningContract=warning
+org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=warning
+org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore
+org.eclipse.jdt.core.compiler.problem.insufficientResourceAnalysis=ignore
+org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore
+org.eclipse.jdt.core.compiler.problem.memberOfDeprecatedTypeNotDeprecated=info
+org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning
+org.eclipse.jdt.core.compiler.problem.missingDefaultCase=ignore
+org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore
+org.eclipse.jdt.core.compiler.problem.missingEnumCaseDespiteDefault=disabled
+org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=ignore
+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=ignore
+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled
+org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning
+org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore
+org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning
+org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning
+org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore
+org.eclipse.jdt.core.compiler.problem.nonnullParameterAnnotationDropped=warning
+org.eclipse.jdt.core.compiler.problem.nonnullTypeVariableFromLegacyInvocation=warning
+org.eclipse.jdt.core.compiler.problem.nullAnnotationInferenceConflict=error
+org.eclipse.jdt.core.compiler.problem.nullReference=warning
+org.eclipse.jdt.core.compiler.problem.nullSpecViolation=error
+org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=warning
+org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning
+org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
+org.eclipse.jdt.core.compiler.problem.pessimisticNullAnalysisForFreeTypeVariables=warning
+org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=ignore
+org.eclipse.jdt.core.compiler.problem.potentialNullReference=ignore
+org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore
+org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning
+org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning
+org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore
+org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=ignore
+org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore
+org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore
+org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore
+org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=ignore
+org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled
+org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning
+org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled
+org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled
+org.eclipse.jdt.core.compiler.problem.suppressWarningsNotFullyAnalysed=ignore
+org.eclipse.jdt.core.compiler.problem.syntacticNullAnalysisForFields=disabled
+org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore
+org.eclipse.jdt.core.compiler.problem.terminalDeprecation=warning
+org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning
+org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=enabled
+org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning
+org.eclipse.jdt.core.compiler.problem.unclosedCloseable=ignore
+org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore
+org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=ignore
+org.eclipse.jdt.core.compiler.problem.unlikelyCollectionMethodArgumentType=warning
+org.eclipse.jdt.core.compiler.problem.unlikelyCollectionMethodArgumentTypeStrict=disabled
+org.eclipse.jdt.core.compiler.problem.unlikelyEqualsArgumentType=info
+org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore
+org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=ignore
+org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore
+org.eclipse.jdt.core.compiler.problem.unstableAutoModuleName=warning
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=warning
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled
+org.eclipse.jdt.core.compiler.problem.unusedExceptionParameter=ignore
+org.eclipse.jdt.core.compiler.problem.unusedImport=warning
+org.eclipse.jdt.core.compiler.problem.unusedLabel=warning
+org.eclipse.jdt.core.compiler.problem.unusedLambdaParameter=warning
+org.eclipse.jdt.core.compiler.problem.unusedLocal=warning
+org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=ignore
+org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore
+org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled
+org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning
+org.eclipse.jdt.core.compiler.problem.unusedTypeParameter=warning
+org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
+org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
+org.eclipse.jdt.core.compiler.release=enabled
+org.eclipse.jdt.core.compiler.source=17
diff --git a/scripts/eclipse-preferences/test-prefs/org.eclipse.jdt.ui.prefs b/scripts/eclipse-preferences/test-prefs/org.eclipse.jdt.ui.prefs
new file mode 100644
index 0000000000..0cf8a2ede4
--- /dev/null
+++ b/scripts/eclipse-preferences/test-prefs/org.eclipse.jdt.ui.prefs
@@ -0,0 +1,5 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.ui.ignorelowercasenames=true
+org.eclipse.jdt.ui.importorder=java;javax;org;com;
+org.eclipse.jdt.ui.ondemandthreshold=1
+org.eclipse.jdt.ui.staticondemandthreshold=1
diff --git a/scripts/release.py b/scripts/release.py
index 70a8fdd7b4..db33402385 100755
--- a/scripts/release.py
+++ b/scripts/release.py
@@ -689,10 +689,8 @@ class ReleaseScript:
              'my-springboot-microservice'),
             ('juneau-examples/juneau-examples-core/target/juneau-examples-core-{}-bin.zip',
              'juneau-examples-core'),
-            ('juneau-examples/juneau-examples-rest-jetty/target/juneau-examples-rest-jetty-{}-bin.zip',
-             'juneau-examples-rest-jetty'),
-            ('juneau-examples/juneau-examples-rest-springboot/target/juneau-examples-rest-springboot-{}-bin.zip',
-             'juneau-examples-rest-springboot'),
+            ('juneau-petstore/juneau-petstore-jetty/target/juneau-petstore-jetty-{}-bin.zip',
+             'juneau-petstore-jetty'),
         ]
         
         for zip_src_pattern, zip_tgt_name in zip_files:
diff --git a/scripts/start-examples-rest-jetty.py b/scripts/start-petstore-jetty.py
similarity index 72%
rename from scripts/start-examples-rest-jetty.py
rename to scripts/start-petstore-jetty.py
index f4318ff102..cdd914f93e 100755
--- a/scripts/start-examples-rest-jetty.py
+++ b/scripts/start-petstore-jetty.py
@@ -13,16 +13,15 @@
 # ***************************************************************************************************************************
 
 """
-Start Juneau REST Examples (Jetty) Application
+Start Juneau Petstore (Jetty) Application
 
-This script starts the Juneau REST examples application using the embedded Jetty server.
-It runs the org.apache.juneau.examples.rest.jetty.App main class using Maven's exec plugin.
+This script starts the Juneau petstore sample application using the embedded Jetty/Microservice server.
+It runs the org.apache.juneau.petstore.jetty.App main class using Maven's exec plugin.
 
 Usage:
-    python3 scripts/start-examples-rest-jetty.py
+    python3 scripts/start-petstore-jetty.py
 """
 
-import os
 import sys
 import subprocess
 from pathlib import Path
@@ -45,67 +44,62 @@ def find_project_root():
     return None
 
 def main():
-    """Start the Jetty examples application."""
-    print(f"{BLUE}🚀 Starting Juneau REST Examples (Jetty)...{RESET}")
-    
-    # Find project root
+    """Start the petstore Jetty application."""
+    print(f"{BLUE}🚀 Starting Juneau Petstore (Jetty)...{RESET}")
+
     project_root = find_project_root()
     if not project_root:
         print(f"{RED}[ERROR] Could not find project root directory{RESET}")
         sys.exit(1)
-    
-    # Set working directory to the examples-rest-jetty module
-    examples_dir = project_root / 'juneau-examples' / 'juneau-examples-rest-jetty'
-    
-    if not examples_dir.exists():
-        print(f"{RED}[ERROR] Examples directory not found: {examples_dir}{RESET}")
+
+    petstore_dir = project_root / 'juneau-petstore' / 'juneau-petstore-jetty'
+
+    if not petstore_dir.exists():
+        print(f"{RED}[ERROR] Petstore Jetty directory not found: {petstore_dir}{RESET}")
         sys.exit(1)
-    
-    print(f"{BLUE}📁 Working directory: {examples_dir}{RESET}")
-    
-    # Check if project is built
-    target_dir = examples_dir / 'target' / 'classes'
+
+    print(f"{BLUE}📁 Working directory: {petstore_dir}{RESET}")
+
+    target_dir = petstore_dir / 'target' / 'classes'
     if not target_dir.exists():
         print(f"{YELLOW}⚠️  Classes not found. Building project first...{RESET}")
         print(f"{BLUE}🔨 Running: mvn clean compile{RESET}\n")
-        
+
         result = subprocess.run(
             ['mvn', 'clean', 'compile'],
-            cwd=str(examples_dir),
+            cwd=str(petstore_dir),
             stdout=sys.stdout,
             stderr=sys.stderr
         )
-        
+
         if result.returncode != 0:
             print(f"\n{RED}[ERROR] Build failed. Please fix compilation errors.{RESET}")
             sys.exit(1)
-        
+
         print(f"\n{GREEN}✓ Build completed successfully{RESET}\n")
-    
-    # Run the application
-    print(f"{BLUE}🚀 Starting Jetty microservice...{RESET}")
-    print(f"{BLUE}Main class: org.apache.juneau.examples.rest.jetty.App{RESET}")
+
+    print(f"{BLUE}🚀 Starting Jetty/Microservice...{RESET}")
+    print(f"{BLUE}Main class: org.apache.juneau.petstore.jetty.App{RESET}")
     print(f"{BLUE}Default URL: http://localhost:10000{RESET}")
     print(f"\n{YELLOW}Press Ctrl+C to stop the server{RESET}\n")
     print("=" * 80)
-    
+
     try:
-        # Use Maven exec plugin to run the main class with proper classpath
         cmd = [
             'mvn',
             'exec:java',
-            '-Dexec.mainClass=org.apache.juneau.examples.rest.jetty.App'
+            '-Dexec.mainClass=org.apache.juneau.petstore.jetty.App'
         ]
-        
+
         process = subprocess.run(
             cmd,
-            cwd=str(examples_dir),
+            cwd=str(petstore_dir),
             stdout=sys.stdout,
             stderr=sys.stderr
         )
-        
+
         sys.exit(process.returncode)
-        
+
     except KeyboardInterrupt:
         print(f"\n\n{YELLOW}🛑 Shutting down server...{RESET}")
         print(f"{GREEN}Server stopped{RESET}")
@@ -116,4 +110,3 @@ def main():
 
 if __name__ == '__main__':
     main()
-
diff --git a/scripts/start-examples-rest-springboot.py b/scripts/start-petstore-springboot.py
similarity index 74%
rename from scripts/start-examples-rest-springboot.py
rename to scripts/start-petstore-springboot.py
index a3b9016ae1..90b4ea38bb 100755
--- a/scripts/start-examples-rest-springboot.py
+++ b/scripts/start-petstore-springboot.py
@@ -13,16 +13,15 @@
 # ***************************************************************************************************************************
 
 """
-Start Juneau REST Examples (Spring Boot) Application
+Start Juneau Petstore (Spring Boot) Application
 
-This script starts the Juneau REST examples application using Spring Boot.
-It runs the org.apache.juneau.examples.rest.springboot.App main class using Maven's Spring Boot plugin.
+This script starts the Juneau petstore sample application using Spring Boot.
+It runs the org.apache.juneau.petstore.springboot.App main class via the Spring Boot Maven plugin.
 
 Usage:
-    python3 scripts/start-examples-rest-springboot.py
+    python3 scripts/start-petstore-springboot.py
 """
 
-import os
 import sys
 import subprocess
 from pathlib import Path
@@ -45,66 +44,61 @@ def find_project_root():
     return None
 
 def main():
-    """Start the Spring Boot examples application."""
-    print(f"{BLUE}🚀 Starting Juneau REST Examples (Spring Boot)...{RESET}")
-    
-    # Find project root
+    """Start the petstore Spring Boot application."""
+    print(f"{BLUE}🚀 Starting Juneau Petstore (Spring Boot)...{RESET}")
+
     project_root = find_project_root()
     if not project_root:
         print(f"{RED}[ERROR] Could not find project root directory{RESET}")
         sys.exit(1)
-    
-    # Set working directory to the examples-rest-springboot module
-    examples_dir = project_root / 'juneau-examples' / 'juneau-examples-rest-springboot'
-    
-    if not examples_dir.exists():
-        print(f"{RED}[ERROR] Examples directory not found: {examples_dir}{RESET}")
+
+    petstore_dir = project_root / 'juneau-petstore' / 'juneau-petstore-springboot'
+
+    if not petstore_dir.exists():
+        print(f"{RED}[ERROR] Petstore Spring Boot directory not found: {petstore_dir}{RESET}")
         sys.exit(1)
-    
-    print(f"{BLUE}📁 Working directory: {examples_dir}{RESET}")
-    
-    # Check if project is built
-    target_dir = examples_dir / 'target' / 'classes'
+
+    print(f"{BLUE}📁 Working directory: {petstore_dir}{RESET}")
+
+    target_dir = petstore_dir / 'target' / 'classes'
     if not target_dir.exists():
         print(f"{YELLOW}⚠️  Classes not found. Building project first...{RESET}")
         print(f"{BLUE}🔨 Running: mvn clean compile{RESET}\n")
-        
+
         result = subprocess.run(
             ['mvn', 'clean', 'compile'],
-            cwd=str(examples_dir),
+            cwd=str(petstore_dir),
             stdout=sys.stdout,
             stderr=sys.stderr
         )
-        
+
         if result.returncode != 0:
             print(f"\n{RED}[ERROR] Build failed. Please fix compilation errors.{RESET}")
             sys.exit(1)
-        
+
         print(f"\n{GREEN}✓ Build completed successfully{RESET}\n")
-    
-    # Run the application
+
     print(f"{BLUE}🚀 Starting Spring Boot application...{RESET}")
-    print(f"{BLUE}Main class: org.apache.juneau.examples.rest.springboot.App{RESET}")
+    print(f"{BLUE}Main class: org.apache.juneau.petstore.springboot.App{RESET}")
     print(f"{BLUE}Default URL: http://localhost:5000{RESET}")
     print(f"\n{YELLOW}Press Ctrl+C to stop the server{RESET}\n")
     print("=" * 80)
-    
+
     try:
-        # Use Spring Boot Maven plugin to run the application
         cmd = [
             'mvn',
             'spring-boot:run'
         ]
-        
+
         process = subprocess.run(
             cmd,
-            cwd=str(examples_dir),
+            cwd=str(petstore_dir),
             stdout=sys.stdout,
             stderr=sys.stderr
         )
-        
+
         sys.exit(process.returncode)
-        
+
     except KeyboardInterrupt:
         print(f"\n\n{YELLOW}🛑 Shutting down server...{RESET}")
         print(f"{GREEN}Server stopped{RESET}")
@@ -115,4 +109,3 @@ def main():
 
 if __name__ == '__main__':
     main()
-