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/05/18 21:03:54 UTC
(juneau) branch master updated: refactor microservice wiring and normalize marshalled collection factories
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 5dd8947e27 refactor microservice wiring and normalize marshalled collection factories
5dd8947e27 is described below
commit 5dd8947e273723bb2986963b30249dc998df4162
Author: James Bognar <ja...@jamesbog-ltmjqf2.internal.salesforce.com>
AuthorDate: Mon May 18 17:03:48 2026 -0400
refactor microservice wiring and normalize marshalled collection factories
---
README.md | 2 +-
.../apache/juneau/commons/bean/BeanSession.java | 2 +-
.../main/java/org/apache/juneau/BeanMapLoader.java | 7 +-
.../juneau/MarshalledBeanMetaInitializer.java | 7 -
.../java/org/apache/juneau/MarshallingContext.java | 27 +-
.../java/org/apache/juneau/MarshallingSession.java | 48 +-
.../main/java/org/apache/juneau/UriContext.java | 2 +-
.../org/apache/juneau/collections/JsonList.java | 14 +-
.../org/apache/juneau/collections/JsonMap.java | 14 +-
.../apache/juneau/collections/package-info.java | 4 +-
.../org/apache/juneau/html/HtmlSerializer.java | 12 +-
.../java/org/apache/juneau/json5/Json5List.java | 6 +-
.../java/org/apache/juneau/json5/Json5Map.java | 12 +-
.../org/apache/juneau/jsonschema/SchemaUtils.java | 4 +-
.../org/apache/juneau/objecttools/ObjectRest.java | 4 +-
.../org/apache/juneau/uon/UonParserSession.java | 6 +-
.../java/org/apache/juneau/uon/UonSerializer.java | 2 +-
.../juneau/urlencoding/UrlEncodingSerializer.java | 2 +-
juneau-distrib/pom.xml | 14 +-
.../juneau/examples/rest/SamplesMicroservice.java | 28 +-
.../org/apache/juneau/examples/rest/jetty/App.java | 37 +-
.../build-overlay/pom.xml | 2 +-
.../juneau-microservice-jetty/pom.xml | 4 +-
.../jetty/BasicJettyMicroserviceListener.java | 54 --
.../microservice/jetty/JettyConfiguration.java | 113 +++
.../microservice/jetty/JettyMicroservice.java | 907 ---------------------
.../jetty/JettyMicroserviceListener.java | 64 --
.../microservice/jetty/JettyServerComponent.java | 398 +++++++++
.../juneau/microservice/jetty/JettySettings.java | 177 ++++
.../jetty/resources/DebugResource.java | 13 +-
....properties => JettyServerComponent.properties} | 0
.../.gitignore | 0
.../Dockerfile | 0
.../pom.xml | 8 +-
.../microservice/BasicMicroserviceListener.java | 2 +-
.../org/apache/juneau/microservice/LogConfig.java | 0
.../apache/juneau/microservice/Microservice.java | 49 +-
.../juneau/microservice/MicroserviceListener.java | 2 +-
.../juneau/microservice/console/ConfigCommand.java | 2 +-
.../microservice/console/ConsoleCommand.java | 4 +-
.../juneau/microservice/console/ExitCommand.java | 2 +-
.../juneau/microservice/console/HelpCommand.java | 2 +-
.../microservice/console/RestartCommand.java | 2 +-
.../juneau/microservice/console/package-info.java | 0
.../apache/juneau/microservice/package-info.java | 0
.../juneau/microservice/resources/ConfigEdit.html | 0
.../microservice/resources/ConfigResource.java | 2 +-
.../microservice/resources/DirectoryResource.java | 2 +-
.../microservice/resources/LogEntryFormatter.java | 0
.../juneau/microservice/resources/LogParser.java | 0
.../microservice/resources/LogsResource.java | 0
.../microservice/resources/SampleRootResource.java | 2 +-
.../microservice/resources/ShutdownResource.java | 2 +-
.../microservice/resources/package-info.java | 0
.../juneau/microservice/Microservice.properties | 0
.../microservice/console/Messages.properties | 0
.../juneau-my-jetty-microservice/pom.xml | 2 +-
.../juneau/microservice/jetty/template/App.java | 30 +-
.../build-overlay/pom.xml.2 | 2 +-
.../juneau-my-springboot-microservice/pom.xml | 4 +-
juneau-microservice/pom.xml | 4 +-
.../org/apache/juneau/rest/client/RestClient.java | 2 +-
.../java/org/apache/juneau/rest/RestContext.java | 5 -
.../rest/annotation/RestDeleteAnnotation.java | 2 +-
.../juneau/rest/annotation/RestGetAnnotation.java | 2 +-
.../apache/juneau/rest/annotation/RestInit.java | 2 +-
.../juneau/rest/annotation/RestOpAnnotation.java | 2 +-
.../rest/annotation/RestOptionsAnnotation.java | 2 +-
.../rest/annotation/RestPatchAnnotation.java | 2 +-
.../juneau/rest/annotation/RestPostAnnotation.java | 2 +-
.../juneau/rest/annotation/RestPutAnnotation.java | 2 +-
.../rest/processor/PlainTextPojoProcessor.java | 4 -
.../rest/swagger/BasicSwaggerProviderSession.java | 4 +-
.../java/org/apache/juneau/server/config/App.java | 40 +-
juneau-shaded/juneau-shaded-all/pom.xml | 2 +-
juneau-utest/pom.xml | 2 +-
.../test/java/org/apache/juneau/BeanMap_Test.java | 88 +-
.../org/apache/juneau/DataConversion_Test.java | 4 +-
.../test/java/org/apache/juneau/JsonList_Test.java | 2 +-
.../test/java/org/apache/juneau/JsonMap_Test.java | 224 ++---
.../org/apache/juneau/MarshalledConfig_Test.java | 4 +-
.../java/org/apache/juneau/ObjectSwap_Test.java | 2 +-
.../juneau/a/rttests/JsonMaps_RoundTripTest.java | 6 +-
.../a/rttests/ParentProperty_RoundTripTest.java | 3 +-
.../a/rttests/SimpleObjects_RoundTripTest.java | 2 +-
.../a/rttests/TrimStrings_RoundTripTest.java | 12 +-
.../jsonschema/JsonSchemaBeanGenerator_Test.java | 2 +-
.../apache/juneau/cbor/CborCompliance_Test.java | 2 +-
.../apache/juneau/cbor/CborOutputStream_Test.java | 4 +-
.../org/apache/juneau/cbor/CborRoundTrip_Test.java | 2 +-
.../apache/juneau/cbor/CborSerializer_Test.java | 6 +-
.../juneau/commons/inject/BasicBeanStore_Test.java | 4 -
.../httppart/OpenApiPartSerializer_Test.java | 68 +-
.../java/org/apache/juneau/json/Json_Test.java | 4 +-
.../org/apache/juneau/json5/Json5List_Test.java | 10 +-
.../org/apache/juneau/json5/Json5Map_Test.java | 12 +-
.../juneau/jsonschema/JsonSchemaGeneratorTest.java | 4 -
.../annotation/SchemaAnnotation_Test.java | 4 -
.../microservice/MicroserviceTestFixture.java | 54 +-
.../Microservice_Listener_Fanout_Test.java | 141 ++++
.../jetty/BasicJettyMicroserviceListener_Test.java | 52 --
...ject_Test.java => JettyConfiguration_Test.java} | 120 +--
.../jetty/JettyMicroservice_Builder_Test.java | 181 ----
.../juneau/msgpack/MsgPackSerializerTest.java | 8 +-
.../apache/juneau/objecttools/ObjectRest_Test.java | 16 +-
.../juneau/rest/annotation/RestInit_Test.java | 10 -
.../annotation/Rest_BeanCreatorOverrides_Test.java | 4 -
.../org/apache/juneau/uon/UonSerializer_Test.java | 58 +-
.../urlencoding/UrlEncodingSerializer_Test.java | 58 +-
.../org/apache/juneau/utils/FilteredMapTest.java | 2 +-
scripts/apply-eclipse-prefs.py | 2 +-
...tty-as-bean.md => FINISHED-36-jetty-as-bean.md} | 0
todo/TODO.md | 2 -
113 files changed, 1498 insertions(+), 1863 deletions(-)
diff --git a/README.md b/README.md
index 7f09a8ac94..028ef98549 100644
--- a/README.md
+++ b/README.md
@@ -285,7 +285,7 @@ Apache Juneau™ is a single cohesive Java ecosystem consisting of the following
* **juneau-rest-client** - A universal REST client API for interacting with Juneau or 3rd-party REST interfaces using POJOs and proxy interfaces.
* **juneau-rest-server-springboot** - Spring boot integration for juneau-rest-servlet.
* **juneau-rest-mock** - REST testing API.
-* **juneau-microservice-core** - Core microservice API.
+* **juneau-microservice** - Microservice API.
* **juneau-microservice-jetty** - Jetty microservice API.
* **juneau-examples-core** - Core code examples.
* **juneau-examples-rest** - REST code examples.
diff --git a/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/bean/BeanSession.java b/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/bean/BeanSession.java
index ed6d98f3ba..359c4595bb 100644
--- a/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/bean/BeanSession.java
+++ b/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/bean/BeanSession.java
@@ -84,7 +84,7 @@ public interface BeanSession {
* directly, so the parse is delegated to the session via this SPI.
*
* <p>
- * Implementations typically route through {@code JsonMap.ofJson(value).session(this)}.
+ * Implementations typically route through {@code JsonMap.ofText(value).session(this)}.
*
* @param value The JSON-formatted character sequence to parse. Must not be <jk>null</jk>.
* @return The parsed map.
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanMapLoader.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanMapLoader.java
index 075d45ce37..27824e84b7 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanMapLoader.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanMapLoader.java
@@ -26,11 +26,6 @@ import org.apache.juneau.commons.bean.BeanMap;
/**
* Marshalling-side helper for loading {@link BeanMap} contents from JSON text or a reader/parser pair.
*
- * <p>
- * These entry points used to live as {@code BeanMap.load(Reader, ReaderParser)} and {@code BeanMap.load(String)}.
- * They were lifted out as part of TODO-5 Step 8b-ii because they reach into the marshalling-side
- * {@link JsonMap} parser and {@link ReaderParser} types — neither belongs in the bean-modeling layer.
- *
* <h5 class='section'>Example:</h5>
* <p class='bjava'>
* <jc>// Populate a bean map from a JSON string.</jc>
@@ -55,7 +50,7 @@ public final class BeanMapLoader {
* @throws ParseException Malformed input encountered.
*/
public static <T> BeanMap<T> load(BeanMap<T> m, String input) throws ParseException {
- m.putAll(Json5Map.ofJson5(input));
+ m.putAll(Json5Map.ofText(input));
return m;
}
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/MarshalledBeanMetaInitializer.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/MarshalledBeanMetaInitializer.java
index 6027d2fa86..a868b0534a 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/MarshalledBeanMetaInitializer.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/MarshalledBeanMetaInitializer.java
@@ -30,13 +30,6 @@ import org.apache.juneau.commons.utils.*;
* Marshalling-side bridge for {@link BeanMeta} construction.
*
* <p>
- * Encapsulates marshalling-aware operations that were lifted out of {@link BeanMeta} as part of TODO-5
- * Step 8b-ii Phase C Task 3, so that {@link BeanMeta} can physically move into the
- * {@code org.apache.juneau.commons.bean} package without directly referencing
- * {@link BeanRegistry}, {@link MarshallingContext}, or marshalling-side annotations like
- * {@link Marshalled @Marshalled} from inside its constructor body.
- *
- * <p>
* Each helper takes the marshalling-side {@link MarshallingContext} as an {@link Object} so the
* call sites inside {@link BeanMeta} do not need to import {@link MarshallingContext}. The helper
* casts back internally.
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/MarshallingContext.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/MarshallingContext.java
index e30144db2e..712839a4f4 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/MarshallingContext.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/MarshallingContext.java
@@ -16,7 +16,10 @@
*/
package org.apache.juneau;
+import org.apache.juneau.commons.annotation.Schema;
import org.apache.juneau.commons.http.MediaType;
+import org.apache.juneau.commons.httppart.SchemaValidationException;
+import org.apache.juneau.parser.ParseException;
import static org.apache.juneau.commons.reflect.ReflectionUtils.*;
import static org.apache.juneau.commons.reflect.Visibility.*;
import static org.apache.juneau.commons.utils.AssertionUtils.*;
@@ -174,7 +177,7 @@ import org.apache.juneau.commons.bean.*;
"java:S1452", // Wildcard required - ClassMeta<?> for parameter resolution and type variables
"java:S1612" // Lambdas used instead of method references for readability in complex chained expressions
})
-public class MarshallingContext extends Context implements ConversionFinder, org.apache.juneau.commons.bean.BeanTypeResolver {
+public class MarshallingContext extends Context implements ConversionFinder, BeanTypeResolver {
// Property name constants
private static final String PROP_beanClassVisibility = "beanClassVisibility";
@@ -1768,7 +1771,7 @@ public class MarshallingContext extends Context implements ConversionFinder, org
}
@Override /* Overridden from Builder */
- public Builder cache(Cache<HashKey,? extends org.apache.juneau.Context> value) {
+ public Builder cache(Cache<HashKey,? extends Context> value) {
super.cache(value);
return this;
}
@@ -2451,15 +2454,15 @@ public class MarshallingContext extends Context implements ConversionFinder, org
*
* <p>
* When enabled, bean property values are validated against the constraints declared by
- * {@link org.apache.juneau.commons.annotation.Schema @Schema} annotations on those properties. Validation runs
+ * {@link Schema @Schema} annotations on those properties. Validation runs
* during both <b>parsing</b> (value set on the bean) and <b>serialization</b> (value read from the bean).
*
* <p>
* Backed by the typed {@code JsonSchema} bean in {@code juneau-bean-jsonschema} and JSON Schema Draft 2020-12
- * semantics. Validation failures throw {@link org.apache.juneau.commons.httppart.SchemaValidationException}
+ * semantics. Validation failures throw {@link SchemaValidationException}
* wrapped in {@code BeanRuntimeException}; the parser surfaces them as
- * {@link org.apache.juneau.parser.ParseException} and the serializer surfaces them as
- * {@link org.apache.juneau.serializer.SerializeException}.
+ * {@link ParseException} and the serializer surfaces them as
+ * {@link SerializeException}.
*
* <p>
* If {@code juneau-bean-jsonschema} is not on the classpath, this flag becomes a silent no-op.
@@ -3391,7 +3394,7 @@ public class MarshallingContext extends Context implements ConversionFinder, org
}
@Override /* Overridden from Builder */
- public Builder type(Class<? extends org.apache.juneau.Context> value) {
+ public Builder type(Class<? extends Context> value) {
assertArgNotNull(ARG_value, value);
super.type(value);
return this;
@@ -4115,7 +4118,7 @@ public class MarshallingContext extends Context implements ConversionFinder, org
var str = in.toString();
Json5List list;
if (startsWith(str, '['))
- list = Json5List.ofJson5(str).setBeanSession(bs);
+ list = Json5List.ofText(str).setBeanSession(bs);
else
list = new Json5List((Object[]) splita(str)).setBeanSession(bs);
return bs.convertToType(list, outType);
@@ -4130,7 +4133,7 @@ public class MarshallingContext extends Context implements ConversionFinder, org
return (in, memberOf, session, args) -> {
try {
var bs = beanSessionOrDefault(session);
- var m = Json5Map.ofJson5(in.toString());
+ var m = Json5Map.ofText(in.toString());
m.setBeanSession(bs);
return bs.convertToType(m, outType);
} catch (Exception e) {
@@ -4194,7 +4197,7 @@ public class MarshallingContext extends Context implements ConversionFinder, org
if (!isProbablyJsonArray(str, false))
throw rex("Cannot convert string to {0}: {1}", outType.getName(), str);
var elemType = args.length > 0 ? args[0] : null;
- var l2 = Json5List.ofJson5(str).setBeanSession(bs);
+ var l2 = Json5List.ofText(str).setBeanSession(bs);
var result = newCollection(outType);
l2.forEach(x -> result.add(elemType != null && x != null ? converter.to(x, elemType) : x));
return result;
@@ -4951,7 +4954,7 @@ public class MarshallingContext extends Context implements ConversionFinder, org
//-----------------------------------------------------------------------------------------------------------------
@Override /* Overridden from BeanTypeResolver */
- public org.apache.juneau.commons.bean.BeanInfo<?> resolveType(AnnotationInfo<org.apache.juneau.commons.bean.BeanProp> lastBeanProp, ClassInfo type, TypeVariables typeVarImpls) {
+ public org.apache.juneau.commons.bean.BeanInfo<?> resolveType(AnnotationInfo<BeanProp> lastBeanProp, ClassInfo type, TypeVariables typeVarImpls) {
return resolveClassMeta(lastBeanProp, type, typeVarImpls);
}
@@ -5004,7 +5007,7 @@ public class MarshallingContext extends Context implements ConversionFinder, org
@SuppressWarnings({
"java:S3776" // Cognitive complexity acceptable for ClassMeta resolution with property annotations
})
- protected final <T> ClassMeta<T> resolveClassMeta(AnnotationInfo<org.apache.juneau.commons.bean.BeanProp> p, ClassInfo ci, TypeVariables typeVarImpls) {
+ protected final <T> ClassMeta<T> resolveClassMeta(AnnotationInfo<BeanProp> p, ClassInfo ci, TypeVariables typeVarImpls) {
var cm = resolveClassMeta(ci, typeVarImpls);
var cm2 = cm;
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/MarshallingSession.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/MarshallingSession.java
index b1b3103ca5..3e8b3f9241 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/MarshallingSession.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/MarshallingSession.java
@@ -32,12 +32,14 @@ import java.util.logging.*;
import org.apache.juneau.annotation.*;
import org.apache.juneau.collections.*;
+import org.apache.juneau.commons.bean.*;
import org.apache.juneau.commons.collections.FluentMap;
import org.apache.juneau.commons.conversion.*;
import org.apache.juneau.commons.lang.*;
import org.apache.juneau.commons.reflect.*;
+import org.apache.juneau.json.JsonParserSession;
+import org.apache.juneau.json5.*;
import org.apache.juneau.swap.*;
-import org.apache.juneau.commons.bean.*;
/**
* Session object that lives for the duration of a single use of {@link MarshallingContext}.
@@ -1250,17 +1252,9 @@ public class MarshallingSession extends ContextSession implements ConverterSessi
*
* <p>
* This is the main factory hook overridden by per-marshaller parser sessions to return their flavored
- * {@code XMap} variant (for example, {@link org.apache.juneau.json.JsonParserSession} returns
- * {@link JsonMap}; {@link org.apache.juneau.json5.Json5ParserSession} returns
- * {@link org.apache.juneau.json5.Json5Map}).
- *
- * <p>
- * As of Phase C of the TODO-34 refactor, the base implementation returns the neutral
- * {@link MarshalledMap}. Only {@link org.apache.juneau.json.JsonParserSession} and
- * {@link org.apache.juneau.json5.Json5ParserSession} actually override this hook today; every other
- * parser session (HTML, URL-encoding, XML, MessagePack, CSV, etc.) inherits the base and therefore
- * produces {@link MarshalledMap} instances during generic parsing. Phase D will fan out per-language
- * {@code XMap} / {@code XList} variants from those parsers as well.
+ * {@code XMap} variant (for example, {@link JsonParserSession} returns
+ * {@link JsonMap}; {@link Json5ParserSession} returns
+ * {@link Json5Map}).
*
* @return A new map.
*/
@@ -1273,17 +1267,9 @@ public class MarshallingSession extends ContextSession implements ConverterSessi
*
* <p>
* Per-marshaller parser sessions override this hook to return their flavored {@code XList} variant
- * (for example, {@link org.apache.juneau.json.JsonParserSession} returns {@link JsonList};
- * {@link org.apache.juneau.json5.Json5ParserSession} returns
- * {@link org.apache.juneau.json5.Json5List}).
- *
- * <p>
- * As of Phase C of the TODO-34 refactor, the base implementation returns the neutral
- * {@link MarshalledList}. Only {@link org.apache.juneau.json.JsonParserSession} and
- * {@link org.apache.juneau.json5.Json5ParserSession} actually override this hook today; every other
- * parser session inherits the base and therefore produces {@link MarshalledList} instances during
- * generic parsing. Phase D will fan out per-language {@code XList} variants from those parsers as
- * well.
+ * (for example, {@link JsonParserSession} returns {@link JsonList};
+ * {@link Json5ParserSession} returns
+ * {@link Json5List}).
*
* @return A new list.
*/
@@ -1388,7 +1374,7 @@ public class MarshallingSession extends ContextSession implements ConverterSessi
/**
* Bridge implementation of {@link BeanSession#parseToMap(CharSequence)} that delegates to
- * {@link org.apache.juneau.json5.Json5Map#ofJson5(CharSequence)} paired with this session.
+ * {@link Json5Map#ofText(CharSequence)} paired with this session.
*
* <p>
* Used by {@link BeanPropertyMeta#setPropertyValue} to parse a {@link CharSequence} into a {@link Map} when
@@ -1396,21 +1382,21 @@ public class MarshallingSession extends ContextSession implements ConverterSessi
* references the marshalling-side JSON parser.
*
* <p>
- * Uses {@link org.apache.juneau.json5.Json5Map} so that historic JSON5-form inputs (e.g. annotation default
+ * Uses {@link Json5Map} so that historic JSON5-form inputs (e.g. annotation default
* values written as <c>{a:'b'}</c>) continue to parse — the strict-JSON {@link JsonMap} retargeting in v9.5
* would otherwise break those call sites.
*
* @param value The JSON-formatted character sequence to parse. Must not be <jk>null</jk>.
- * @return The parsed {@link org.apache.juneau.json5.Json5Map}.
+ * @return The parsed {@link Json5Map}.
*/
@Override /* BeanSession */
public final java.util.Map<?,?> parseToMap(CharSequence value) {
- return org.apache.juneau.json5.Json5Map.ofJson5(value).session(this);
+ return Json5Map.ofText(value).session(this);
}
/**
* Bridge implementation of {@link BeanSession#parseToList(CharSequence)} that delegates to
- * {@link org.apache.juneau.json5.Json5List#Json5List(CharSequence)} paired with this session.
+ * {@link Json5List#Json5List(CharSequence)} paired with this session.
*
* <p>
* Used by {@link BeanPropertyMeta#setPropertyValue} to parse a {@link CharSequence} into a {@link Collection}
@@ -1418,15 +1404,15 @@ public class MarshallingSession extends ContextSession implements ConverterSessi
* no longer references the marshalling-side JSON parser.
*
* <p>
- * Uses {@link org.apache.juneau.json5.Json5List} for the same back-compat reasons as
+ * Uses {@link Json5List} for the same back-compat reasons as
* {@link #parseToMap(CharSequence)}.
*
* @param value The JSON-formatted character sequence to parse. Must not be <jk>null</jk>.
- * @return The parsed {@link org.apache.juneau.json5.Json5List}.
+ * @return The parsed {@link Json5List}.
*/
@Override /* BeanSession */
public final java.util.Collection<?> parseToList(CharSequence value) {
- return new org.apache.juneau.json5.Json5List(value).setBeanSession(this);
+ return new Json5List(value).setBeanSession(this);
}
}
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/UriContext.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/UriContext.java
index 3a804a61e6..1673177574 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/UriContext.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/UriContext.java
@@ -159,7 +159,7 @@ public class UriContext {
* If input string is not a valid JSON object.
*/
public UriContext(String s) throws ParseException {
- var m = Json5Map.ofJson5(s);
+ var m = Json5Map.ofText(s);
this.authority = nullIfEmpty(trimSlashes(m.getString(PROP_authority)));
this.contextRoot = nullIfEmpty(trimSlashes(m.getString(PROP_contextRoot)));
this.servletPath = nullIfEmpty(trimSlashes(m.getString(PROP_servletPath)));
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/collections/JsonList.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/collections/JsonList.java
index 85062b33e4..e413047a7e 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/collections/JsonList.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/collections/JsonList.java
@@ -64,24 +64,24 @@ import org.apache.juneau.serializer.*;
* <jv>list</jv> = JsonList.<jsm>of</jsm>(<js>"foo"</js>, 123, <jk>true</jk>); <jc>// Equivalent</jc>
*
* <jc>// Construct a list of integers from JSON</jc>
- * <jv>list</jv> = JsonList.<jsm>ofJson</jsm>(<js>"[1,2,3]"</js>);
+ * <jv>list</jv> = JsonList.<jsm>ofText</jsm>(<js>"[1,2,3]"</js>);
*
* <jc>// Construct a list of generic JsonMap objects from JSON</jc>
- * <jv>list</jv> = JsonList.<jsm>ofJson</jsm>(<js>"[{foo:'bar'},{baz:'bing'}]"</js>);
+ * <jv>list</jv> = JsonList.<jsm>ofText</jsm>(<js>"[{foo:'bar'},{baz:'bing'}]"</js>);
*
* <jc>// Construct JSON from JsonList</jc>
- * <jv>list</jv> = JsonList.<jsm>ofJson</jsm>(<js>"[{foo:'bar'},{baz:'bing'}]"</js>);
+ * <jv>list</jv> = JsonList.<jsm>ofText</jsm>(<js>"[{foo:'bar'},{baz:'bing'}]"</js>);
* String <jv>json</jv> = <jv>list</jv>.toString(); <jc>// Produces "[{foo:'bar'},{baz:'bing'}]"</jc>
* <jv>json</jv> = <jv>list</jv>.toString(JsonSerializer.<jsf>DEFAULT</jsf>); <jc>// Equivalent</jc>
* <jv>json</jv> = JsonSerializer.<jsf>DEFAULT</jsf>.serialize(<jv>list</jv>); <jc>// Equivalent</jc>
*
* <jc>// Get one of the entries in the list as an Integer</jc>
- * <jv>list</jv> = JsonList.<jsm>ofJson</jsm>(<js>"[1,2,3]"</js>);
+ * <jv>list</jv> = JsonList.<jsm>ofText</jsm>(<js>"[1,2,3]"</js>);
* Integer <jv>integer</jv> = <jv>list</jv>.getInt(1);
* <jv>integer</jv> = <jv>list</jv>.get(Integer.<jk>class</jk>, 1); <jc>// Equivalent</jc>
*
* <jc>// Iterate over a list of beans using the elements() method</jc>
- * <jv>list</jv> = JsonList.<jsm>ofJson</jsm>(<js>"[{name:'John Smith',age:45}]"</js>);
+ * <jv>list</jv> = JsonList.<jsm>ofText</jsm>(<js>"[{name:'John Smith',age:45}]"</js>);
* <jk>for</jk> (Person <jv>person</jv> : <jv>list</jv>.elements(Person.<jk>class</jk>) {
* <jc>// Do something with p</jc>
* }
@@ -236,7 +236,7 @@ public class JsonList extends MarshalledList {
* @return A new list or <jk>null</jk> if the string was null.
* @throws ParseException Malformed input encountered.
*/
- public static JsonList ofJson(CharSequence json) throws ParseException {
+ public static JsonList ofText(CharSequence json) throws ParseException {
return json == null ? null : new JsonList(json);
}
@@ -252,7 +252,7 @@ public class JsonList extends MarshalledList {
@SuppressWarnings({
"java:S1168" // TODO: null input = null output by design. Consider empty JsonList.
})
- public static JsonList ofJson(Reader json) throws ParseException {
+ public static JsonList ofText(Reader json) throws ParseException {
return json == null ? null : new JsonList(json);
}
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/collections/JsonMap.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/collections/JsonMap.java
index 3d8c40152d..b69dddf231 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/collections/JsonMap.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/collections/JsonMap.java
@@ -58,7 +58,7 @@ import org.apache.juneau.serializer.*;
* JsonMap <jv>map</jv> = JsonMap.<jsm>of</jsm>();
*
* <jc>// Construct a Map from JSON</jc>
- * <jv>map</jv> = JsonMap.<jsm>ofJson</jsm>(<js>"{a:'A',b:{c:'C',d:123}}"</js>);
+ * <jv>map</jv> = JsonMap.<jsm>ofText</jsm>(<js>"{a:'A',b:{c:'C',d:123}}"</js>);
*
* <jc>// Construct a Map using the append method</jc>
* <jv>map</jv> = JsonMap.<jsm>of</jsm>().a(<js>"foo"</js>,<js>"x"</js>).a(<js>"bar"</js>,123).a(<js>"baz"</js>,<jk>true</jk>);
@@ -72,19 +72,19 @@ import org.apache.juneau.serializer.*;
* <jv>map</jv> = JsonMap.<jsm>of</jsm>(<jv>urlParams</jv>, UrlEncodingParser.<jsf>DEFAULT</jsf>);
*
* <jc>// Construct JSON from JsonMap</jc>
- * <jv>map</jv> = JsonMap.<jsm>ofJson</jsm>(<js>"{foo:'bar'},{baz:[123,true]}"</js>);
+ * <jv>map</jv> = JsonMap.<jsm>ofText</jsm>(<js>"{foo:'bar'},{baz:[123,true]}"</js>);
* String <jv>json</jv> = <jv>map</jv>.toString(); <jc>// Produces "{foo:'bar'},{baz:[123,true]}"</jc>
* <jv>json</jv> = <jv>map</jv>.toString(JsonSerializer.<jsf>DEFAULT</jsf>); <jc>// Equivalent</jc>
* <jv>json</jv> = JsonSerializer.<jsf>DEFAULT</jsf>.serialize(<jv>map</jv>); <jc>// Equivalent</jc>
*
* <jc>// Get a map entry as an Integer</jc>
- * <jv>map</jv> = JsonMap.<jsm>ofJson</jsm>(<js>"{foo:123}"</js>);
+ * <jv>map</jv> = JsonMap.<jsm>ofText</jsm>(<js>"{foo:123}"</js>);
* Integer <jv>integer</jv> = <jv>map</jv>.getInt(<js>"foo"</js>);
* <jv>integer</jv> = <jv>map</jv>.get(Integer.<jk>class</jk>, <js>"foo"</js>); <jc>// Equivalent</jc>
*
* <jc>// Add an inner map</jc>
- * JsonMap <jv>map1</jv> = JsonMap.<jsm>ofJson</jsm>(<js>"{a:1}"</js>);
- * JsonMap <jv>map2</jv> = JsonMap.<jsm>ofJson</jsm>(<js>"{b:2}"</js>).setInner(<jv>map1</jv>);
+ * JsonMap <jv>map1</jv> = JsonMap.<jsm>ofText</jsm>(<js>"{a:1}"</js>);
+ * JsonMap <jv>map2</jv> = JsonMap.<jsm>ofText</jsm>(<js>"{b:2}"</js>).setInner(<jv>map1</jv>);
* <jk>int</jk> <jv>_int</jv> = <jv>map2</jv>.getInt(<js>"a"</js>); <jc>// a == 1 </jc>
* </p>
*
@@ -233,7 +233,7 @@ public class JsonMap extends MarshalledMap {
* @return A new map or <jk>null</jk> if the string was null.
* @throws ParseException Malformed input encountered.
*/
- public static JsonMap ofJson(CharSequence json) throws ParseException {
+ public static JsonMap ofText(CharSequence json) throws ParseException {
return json == null ? null : new JsonMap(json);
}
@@ -246,7 +246,7 @@ public class JsonMap extends MarshalledMap {
* @return A new map or <jk>null</jk> if the input was <jk>null</jk>.
* @throws ParseException Malformed input encountered.
*/
- public static JsonMap ofJson(Reader json) throws ParseException {
+ public static JsonMap ofText(Reader json) throws ParseException {
return json == null ? null : new JsonMap(json);
}
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/collections/package-info.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/collections/package-info.java
index ff7a48a5be..8e3354f86c 100755
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/collections/package-info.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/collections/package-info.java
@@ -28,13 +28,13 @@
* — strict-JSON-flavored subclasses. Their {@code toString()} renders as strict
* <a href="https://www.rfc-editor.org/rfc/rfc8259" target="_blank">RFC 8259</a> JSON via
* {@link org.apache.juneau.marshaller.Json#of(Object)}, and their {@code (CharSequence)} /
- * {@code (Reader)} constructors and {@code ofJson(...)} factories default to
+ * {@code (Reader)} constructors and {@code ofText(...)} factories default to
* {@link org.apache.juneau.json.JsonParser#DEFAULT}.
* <li>{@link org.apache.juneau.json5.Json5Map} / {@link org.apache.juneau.json5.Json5List}
* (in {@link org.apache.juneau.json5}) — JSON5-flavored siblings of
* {@code JsonMap} / {@code JsonList}. Their {@code toString()} renders as JSON5 via
* {@link org.apache.juneau.marshaller.Json5#of(Object)}, and their {@code (CharSequence)} /
- * {@code (Reader)} constructors and {@code ofJson5(...)} factories default to
+ * {@code (Reader)} constructors and {@code ofText(...)} factories default to
* {@link org.apache.juneau.json5.Json5Parser#DEFAULT}. These are the drop-in replacement
* for callers that previously relied on {@code JsonMap.toString()} producing JSON5 or on
* {@code new JsonMap("{unquoted:'json5'}")} parsing JSON5.
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlSerializer.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlSerializer.java
index 48857ca27c..4b64574043 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlSerializer.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlSerializer.java
@@ -104,9 +104,9 @@ import org.apache.juneau.commons.bean.BeanPropertyMeta;
* <jc>// <tr><td>Barney</td><td>Miller</td></tr> </jc>
* <jc>// </table> </jc>
* <jv>html</jv> = JsonList.<jsm>of</jsm>(
- * JsonMap.<jsm>ofJson</jsm>(<js>"{firstName:'Bob',lastName:'Costas'}"</js>),
- * JsonMap.<jsm>ofJson</jsm>(<js>"{firstName:'Billy',lastName:'TheKid'}"</js>),
- * JsonMap.<jsm>ofJson</jsm>(<js>"{firstName:'Barney',lastName:'Miller'}"</js>)
+ * JsonMap.<jsm>ofText</jsm>(<js>"{firstName:'Bob',lastName:'Costas'}"</js>),
+ * JsonMap.<jsm>ofText</jsm>(<js>"{firstName:'Billy',lastName:'TheKid'}"</js>),
+ * JsonMap.<jsm>ofText</jsm>(<js>"{firstName:'Barney',lastName:'Miller'}"</js>)
* );
* String <jv>html</jv> = HtmlSerializer.<jsf>DEFAULT</jsf>.serialize(<jv>list</jv>);
*
@@ -116,7 +116,7 @@ import org.apache.juneau.commons.bean.BeanPropertyMeta;
* <jc>// <tr><td>foo</td><td>bar</td></tr> </jc>
* <jc>// <tr><td>baz</td><td>123</td></tr> </jc>
* <jc>// </table> </jc>
- * Map <jv>map</jv> = JsonMap.<jsm>ofJson</jsm>(<js>"{foo:'bar',baz:123}"</js>);
+ * Map <jv>map</jv> = JsonMap.<jsm>ofText</jsm>(<js>"{foo:'bar',baz:123}"</js>);
* String <jv>html</jv> = HtmlSerializer.<jsf>DEFAULT</jsf>.serialize(<jv>map</jv>);
*
* <jc>// HTML elements can be nested arbitrarily deep</jc>
@@ -133,9 +133,9 @@ import org.apache.juneau.commons.bean.BeanPropertyMeta;
* <jc>// </table> </jc>
* <jc>// </td></tr> </jc>
* <jc>// </table> </jc>
- * Map <jv>map</jv> = JsonMap.<jsm>ofJson</jsm>(<js>"{foo:'bar',baz:123}"</js>);
+ * Map <jv>map</jv> = JsonMap.<jsm>ofText</jsm>(<js>"{foo:'bar',baz:123}"</js>);
* <jv>map</jv>.put(<js>"someNumbers"</js>, JsonList.<jsm>of</jsm>(1, 2, 3));
- * <jv>map</jv>.put(<js>"someSubMap"</js>, JsonMap.<jsm>ofJson</jsm>(<js>"{a:'b'}"</js>));
+ * <jv>map</jv>.put(<js>"someSubMap"</js>, JsonMap.<jsm>ofText</jsm>(<js>"{a:'b'}"</js>));
* String <jv>html</jv> = HtmlSerializer.<jsf>DEFAULT</jsf>.serialize(<jv>map</jv>);
* </p>
*
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/json5/Json5List.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/json5/Json5List.java
index 2449b02331..8b6c4422d3 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/json5/Json5List.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/json5/Json5List.java
@@ -49,7 +49,7 @@ import org.apache.juneau.serializer.*;
* Json5List <jv>list</jv> = Json5List.<jsm>of</jsm>();
*
* <jc>// Construct a list of generic Json5Map objects from JSON5</jc>
- * <jv>list</jv> = Json5List.<jsm>ofJson5</jsm>(<js>"[{foo:'bar'},{baz:'bing'}]"</js>);
+ * <jv>list</jv> = Json5List.<jsm>ofText</jsm>(<js>"[{foo:'bar'},{baz:'bing'}]"</js>);
*
* <jc>// JSON5 round-trip via toString()</jc>
* String <jv>s</jv> = <jv>list</jv>.toString(); <jc>// "[{foo:'bar'},{baz:'bing'}]"</jc>
@@ -200,7 +200,7 @@ public class Json5List extends MarshalledList {
* @return A new list or <jk>null</jk> if the string was null.
* @throws ParseException Malformed input encountered.
*/
- public static Json5List ofJson5(CharSequence json5) throws ParseException {
+ public static Json5List ofText(CharSequence json5) throws ParseException {
return json5 == null ? null : new Json5List(json5);
}
@@ -214,7 +214,7 @@ public class Json5List extends MarshalledList {
@SuppressWarnings({
"java:S1168" // TODO: null input = null output by design. Consider empty Json5List.
})
- public static Json5List ofJson5(Reader json5) throws ParseException {
+ public static Json5List ofText(Reader json5) throws ParseException {
return json5 == null ? null : new Json5List(json5);
}
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/json5/Json5Map.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/json5/Json5Map.java
index 4369aa1fb3..df777e52f3 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/json5/Json5Map.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/json5/Json5Map.java
@@ -49,7 +49,7 @@ import org.apache.juneau.serializer.*;
* Json5Map <jv>map</jv> = Json5Map.<jsm>of</jsm>();
*
* <jc>// Construct a Map from JSON5</jc>
- * <jv>map</jv> = Json5Map.<jsm>ofJson5</jsm>(<js>"{a:'A',b:{c:'C',d:123}}"</js>);
+ * <jv>map</jv> = Json5Map.<jsm>ofText</jsm>(<js>"{a:'A',b:{c:'C',d:123}}"</js>);
*
* <jc>// JSON5 round-trip via toString()</jc>
* String <jv>s</jv> = <jv>map</jv>.toString(); <jc>// "{a:'A',b:{c:'C',d:123}}"</jc>
@@ -65,7 +65,8 @@ import org.apache.juneau.serializer.*;
public class Json5Map extends MarshalledMap {
@SuppressWarnings({
- "java:S2160" // equals() / hashCode() inherited from Json5Map; map equality is element-based
+ "java:S2160", // equals() / hashCode() inherited from Json5Map; map equality is element-based
+ "java:S110" // Inheritance depth inherited from MarshalledMap -> LinkedHashMap chain; intentional
})
private static class UnmodifiableJson5Map extends Json5Map {
private static final long serialVersionUID = 1L;
@@ -100,7 +101,8 @@ public class Json5Map extends MarshalledMap {
* @serial exclude
*/
@SuppressWarnings({
- "java:S2386" // Public static final field accessed externally, cannot be protected
+ "java:S2386", // Public static final field accessed externally, cannot be protected
+ "java:S110" // Anonymous subclass of Json5Map inherits the MarshalledMap -> LinkedHashMap chain; intentional
})
public static final Json5Map EMPTY_MAP = new Json5Map() {
@@ -199,7 +201,7 @@ public class Json5Map extends MarshalledMap {
* @return A new map or <jk>null</jk> if the string was null.
* @throws ParseException Malformed input encountered.
*/
- public static Json5Map ofJson5(CharSequence json5) throws ParseException {
+ public static Json5Map ofText(CharSequence json5) throws ParseException {
return json5 == null ? null : new Json5Map(json5);
}
@@ -211,7 +213,7 @@ public class Json5Map extends MarshalledMap {
* @return A new map or <jk>null</jk> if the input was <jk>null</jk>.
* @throws ParseException Malformed input encountered.
*/
- public static Json5Map ofJson5(Reader json5) throws ParseException {
+ public static Json5Map ofText(Reader json5) throws ParseException {
return json5 == null ? null : new Json5Map(json5);
}
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/jsonschema/SchemaUtils.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/jsonschema/SchemaUtils.java
index 1b1a57edf2..fed5269fe1 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/jsonschema/SchemaUtils.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/jsonschema/SchemaUtils.java
@@ -78,7 +78,7 @@ public class SchemaUtils {
return JsonMap.of("ignore", true);
if (! isProbablyJsonObject(s, true))
s = "{" + s + "}";
- return new JsonMap(Json5Map.ofJson5(s));
+ return new JsonMap(Json5Map.ofText(s));
}
if (o instanceof JsonMap o2)
return o2;
@@ -105,7 +105,7 @@ public class SchemaUtils {
return null;
if (! isProbablyJsonObject(s, true))
s = "{" + s + "}";
- return new JsonMap(Json5Map.ofJson5(s));
+ return new JsonMap(Json5Map.ofText(s));
}
/**
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/objecttools/ObjectRest.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/objecttools/ObjectRest.java
index 7bb7514ecd..0afdbe8e53 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/objecttools/ObjectRest.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/objecttools/ObjectRest.java
@@ -63,7 +63,7 @@ import org.apache.juneau.parser.*;
* <h5 class='section'>Example:</h5>
* <p class='bjava'>
* <jc>// Construct an unstructured POJO model</jc>
- * JsonMap <jv>map</jv> = JsonMap.<jsm>ofJson</jsm>(<js>""</js>
+ * JsonMap <jv>map</jv> = JsonMap.<jsm>ofText</jsm>(<js>""</js>
* + <js>"{"</js>
* + <js>" name:'John Smith', "</js>
* + <js>" address:{ "</js>
@@ -111,7 +111,7 @@ import org.apache.juneau.parser.*;
* <jv>johnSmith</jv>.delete(<js>"fico score"</js>);
*
* <jc>// Add entirely new structures to the tree</jc>
- * JsonMap <jv>medicalInfo</jv> = JsonMap.<jsm>ofJson</jsm>(<js>""</js>
+ * JsonMap <jv>medicalInfo</jv> = JsonMap.<jsm>ofText</jsm>(<js>""</js>
* + <js>"{"</js>
* + <js>" currentStatus: 'deceased',"</js>
* + <js>" health: 'non-existent',"</js>
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/uon/UonParserSession.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/uon/UonParserSession.java
index 4bb1615b0e..83576ab95a 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/uon/UonParserSession.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/uon/UonParserSession.java
@@ -495,7 +495,7 @@ public class UonParserSession extends ReaderParserSession implements HttpPartPar
}
@SuppressWarnings({
- "java:S1168", // TODO: null for empty/EOF or parseAttrName('%00'). Parser state machine.
+ "java:S1168", // Intentionally returns null for empty/EOF or parseAttrName('%00') in this parser state machine.
"java:S2589", // Final if (state==S4) is always true given prior checks; exhaustive state error-reporting pattern
"java:S3776", // Cognitive complexity acceptable for this specific logic
"java:S6541", // Single-threaded session contexts do not require synchronization
@@ -618,7 +618,7 @@ public class UonParserSession extends ReaderParserSession implements HttpPartPar
}
@SuppressWarnings({
- "java:S1168", // TODO: null for EOF/AMP. Parser state machine.
+ "java:S1168", // Intentionally returns null for EOF/AMP in this parser state machine.
"java:S1854", // argIndex=0 is the valid starting arg index; Sonar FP on early-return paths that never read it
"java:S2583", // State variables persist across loop iterations
"java:S2589", // Final if (state==S3) is always true given prior check; exhaustive state error-reporting pattern
@@ -713,7 +713,7 @@ public class UonParserSession extends ReaderParserSession implements HttpPartPar
}
@SuppressWarnings({
- "java:S1168", // TODO: null for EOF/AMP. Parser state machine.
+ "java:S1168", // Intentionally returns null for EOF/AMP in this parser state machine.
"java:S2589", // Final if (state==S4) is always true given prior checks; exhaustive state error-reporting pattern
"java:S6541", // Brain method acceptable for parser state machine
"java:S3776" // Cognitive complexity acceptable for parser state machine
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/uon/UonSerializer.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/uon/UonSerializer.java
index 64d5fd1b02..72510acb43 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/uon/UonSerializer.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/uon/UonSerializer.java
@@ -112,7 +112,7 @@ import org.apache.juneau.commons.bean.BeanPropertyMeta;
* <h5 class='section'>Example:</h5>
* <p class='bjava'>
* <jc>// Serialize a Map</jc>
- * Map <jv>map</jv> = JsonMap.<jsm>ofJson</jsm>(<js>"{a:'b',c:1,d:false,e:['f',1,false],g:{h:'i'}}"</js>);
+ * Map <jv>map</jv> = JsonMap.<jsm>ofText</jsm>(<js>"{a:'b',c:1,d:false,e:['f',1,false],g:{h:'i'}}"</js>);
*
* <jc>// Serialize to value equivalent to JSON.</jc>
* <jc>// Produces "(a=b,c=1,d=false,e=@(f,1,false),g=(h=i))"</jc>
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/urlencoding/UrlEncodingSerializer.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/urlencoding/UrlEncodingSerializer.java
index c45a773ff4..75194f649a 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/urlencoding/UrlEncodingSerializer.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/urlencoding/UrlEncodingSerializer.java
@@ -97,7 +97,7 @@ import org.apache.juneau.commons.bean.BeanPropertyMeta;
* <h5 class='section'>Example:</h5>
* <p class='bjava'>
* <jc>// Serialize a Map</jc>
- * Map <jv>map</jv> = JsonMap.<jsm>ofJson</jsm>(<js>"{a:'b',c:1,d:false,e:['f',1,false],g:{h:'i'}}"</js>);
+ * Map <jv>map</jv> = JsonMap.<jsm>ofText</jsm>(<js>"{a:'b',c:1,d:false,e:['f',1,false],g:{h:'i'}}"</js>);
*
* <jc>// Serialize to value equivalent to JSON.</jc>
* <jc>// Produces "a=b&c=1&d=false&e=@(f,1,false)&g=(h=i)"</jc>
diff --git a/juneau-distrib/pom.xml b/juneau-distrib/pom.xml
index 273b361a80..273badcacb 100644
--- a/juneau-distrib/pom.xml
+++ b/juneau-distrib/pom.xml
@@ -533,29 +533,29 @@
<destFileName>org.apache.juneau.rest.mock_${project.version}.jar</destFileName>
</artifactItem>
- <!-- juneau-microservice-core -->
+ <!-- juneau-microservice -->
<artifactItem>
<outputDirectory>${project.build.directory}/src/lib</outputDirectory>
<groupId>org.apache.juneau</groupId>
- <artifactId>juneau-microservice-core</artifactId>
+ <artifactId>juneau-microservice</artifactId>
<version>${project.version}</version>
<type>jar</type>
<classifier>sources</classifier>
- <destFileName>apache-juneau-microservice-core-${project.version}-sources.jar</destFileName>
+ <destFileName>apache-juneau-microservice-${project.version}-sources.jar</destFileName>
</artifactItem>
<artifactItem>
<outputDirectory>${project.build.directory}/bin/lib</outputDirectory>
<groupId>org.apache.juneau</groupId>
- <artifactId>juneau-microservice-core</artifactId>
+ <artifactId>juneau-microservice</artifactId>
<version>${project.version}</version>
- <destFileName>apache-juneau-microservice-core-${project.version}.jar</destFileName>
+ <destFileName>apache-juneau-microservice-${project.version}.jar</destFileName>
</artifactItem>
<artifactItem>
<outputDirectory>${project.build.directory}/bin/osgi</outputDirectory>
<groupId>org.apache.juneau</groupId>
- <artifactId>juneau-microservice-core</artifactId>
+ <artifactId>juneau-microservice</artifactId>
<version>${project.version}</version>
- <destFileName>org.apache.juneau.microservice.core_${project.version}.jar</destFileName>
+ <destFileName>org.apache.juneau.microservice_${project.version}.jar</destFileName>
</artifactItem>
<!-- juneau-microservice-jetty -->
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
index d6e5f2ce53..9e73ccc997 100644
--- 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
@@ -19,17 +19,21 @@ package org.apache.juneau.examples.rest;
import java.net.*;
import java.util.*;
+import org.apache.juneau.commons.inject.*;
+import org.apache.juneau.microservice.*;
import org.apache.juneau.microservice.jetty.*;
import org.apache.juneau.parser.*;
import org.apache.juneau.rest.client.*;
import org.apache.juneau.serializer.*;
+import jakarta.servlet.*;
+
/**
* Utility class for starting up the examples microservice.
*/
@SuppressWarnings("resource")
public class SamplesMicroservice {
- static volatile JettyMicroservice microservice;
+ static volatile Microservice microservice;
static URI microserviceURI;
// Reusable HTTP clients that get created and shut down with the microservice.
@@ -46,8 +50,8 @@ public class SamplesMicroservice {
return false;
try {
Locale.setDefault(Locale.US);
- microservice = JettyMicroservice.create().workingDir("../juneau-examples-rest-jetty").configName("juneau-examples-rest-jetty.cfg").servlet(RootResources.class).build();
- microserviceURI = microservice.start().getURI();
+ 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;
@@ -107,4 +111,22 @@ public class SamplesMicroservice {
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.annotation.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/src/main/java/org/apache/juneau/examples/rest/jetty/App.java b/juneau-examples/juneau-examples-rest-jetty/src/main/java/org/apache/juneau/examples/rest/jetty/App.java
index c91ed57e07..b46b6cfa7c 100644
--- a/juneau-examples/juneau-examples-rest-jetty/src/main/java/org/apache/juneau/examples/rest/jetty/App.java
+++ b/juneau-examples/juneau-examples-rest-jetty/src/main/java/org/apache/juneau/examples/rest/jetty/App.java
@@ -16,20 +16,19 @@
*/
package org.apache.juneau.examples.rest.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.
*
* <p>
- * Subclasses can extend from {@link JettyMicroservice} to implement their own custom behavior.
- * However, this is optional and the {@link JettyMicroservice} class can be invoked directly.
- *
- * <p>
- * The {@link JettyMicroservice} class will locate the <c>examples.cfg</c> file in the home directory and initialize
+ * 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.
- *
*/
public class App {
@@ -40,13 +39,33 @@ public class App {
* @throws Exception General exception occurred.
*/
public static void main(String[] args) throws Exception {
- JettyMicroservice
+ // @formatter:off
+ Microservice
.create()
.args(args)
- .servlet(RootResources.class)
+ .configurations(JettyConfiguration.class, AppConfig.class)
.build()
.start()
.startConsole()
.join();
+ // @formatter:on
+ }
+
+ /**
+ * Application-specific configuration class contributing the top-level REST servlet.
+ */
+ @Configuration
+ public static class AppConfig {
+
+ /**
+ * Provides the top-level REST servlet, auto-mounted by {@link JettyServerComponent} at
+ * {@link org.apache.juneau.rest.annotation.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-springboot/build-overlay/pom.xml b/juneau-examples/juneau-examples-rest-springboot/build-overlay/pom.xml
index d8dc4c18bb..86dedf99d8 100644
--- a/juneau-examples/juneau-examples-rest-springboot/build-overlay/pom.xml
+++ b/juneau-examples/juneau-examples-rest-springboot/build-overlay/pom.xml
@@ -69,7 +69,7 @@
</dependency>
<dependency>
<groupId>org.apache.juneau</groupId>
- <artifactId>juneau-microservice-core</artifactId>
+ <artifactId>juneau-microservice</artifactId>
<version>\${juneau.version}</version>
</dependency>
<dependency>
diff --git a/juneau-microservice/juneau-microservice-jetty/pom.xml b/juneau-microservice/juneau-microservice-jetty/pom.xml
index 406c7ea78a..021df8ed18 100644
--- a/juneau-microservice/juneau-microservice-jetty/pom.xml
+++ b/juneau-microservice/juneau-microservice-jetty/pom.xml
@@ -21,7 +21,7 @@
<parent>
<groupId>org.apache.juneau</groupId>
- <artifactId>juneau-microservice</artifactId>
+ <artifactId>juneau-microservice-parent</artifactId>
<version>9.5.0-SNAPSHOT</version>
</parent>
@@ -46,7 +46,7 @@
<dependencies>
<dependency>
<groupId>org.apache.juneau</groupId>
- <artifactId>juneau-microservice-core</artifactId>
+ <artifactId>juneau-microservice</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
diff --git a/juneau-microservice/juneau-microservice-jetty/src/main/java/org/apache/juneau/microservice/jetty/BasicJettyMicroserviceListener.java b/juneau-microservice/juneau-microservice-jetty/src/main/java/org/apache/juneau/microservice/jetty/BasicJettyMicroserviceListener.java
deleted file mode 100644
index c3dda0b21d..0000000000
--- a/juneau-microservice/juneau-microservice-jetty/src/main/java/org/apache/juneau/microservice/jetty/BasicJettyMicroserviceListener.java
+++ /dev/null
@@ -1,54 +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.microservice.jetty;
-
-import org.apache.juneau.microservice.*;
-
-/**
- * Basic extensible microservice listener with default no-op method implementations.
- *
- * <h5 class='section'>See Also:</h5><ul>
- * <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/JuneauMicroserviceJettyBasics">juneau-microservice-jetty Basics</a>
- * </ul>
- */
-public class BasicJettyMicroserviceListener extends BasicMicroserviceListener implements JettyMicroserviceListener {
-
- @Override /* Overridden from JettyMicroserviceListener */
- public void onCreateServer(JettyMicroservice microservice) {
- // No-op: Intentional empty implementation for optional interface method
- }
-
- @Override /* Overridden from JettyMicroserviceListener */
- public void onPostStartServer(JettyMicroservice microservice) {
- // No-op: Intentional empty implementation for optional interface method
- }
-
- @Override /* Overridden from JettyMicroserviceListener */
- public void onPostStopServer(JettyMicroservice microservice) {
- // No-op: Intentional empty implementation for optional interface method
- }
-
- @Override /* Overridden from JettyMicroserviceListener */
- public void onStartServer(JettyMicroservice microservice) {
- // No-op: Intentional empty implementation for optional interface method
- }
-
- @Override /* Overridden from JettyMicroserviceListener */
- public void onStopServer(JettyMicroservice microservice) {
- // No-op: Intentional empty implementation for optional interface method
- }
-}
\ No newline at end of file
diff --git a/juneau-microservice/juneau-microservice-jetty/src/main/java/org/apache/juneau/microservice/jetty/JettyConfiguration.java b/juneau-microservice/juneau-microservice-jetty/src/main/java/org/apache/juneau/microservice/jetty/JettyConfiguration.java
new file mode 100644
index 0000000000..42dfe6859f
--- /dev/null
+++ b/juneau-microservice/juneau-microservice-jetty/src/main/java/org/apache/juneau/microservice/jetty/JettyConfiguration.java
@@ -0,0 +1,113 @@
+/*
+ * 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.jetty;
+
+import org.apache.juneau.commons.inject.*;
+import org.apache.juneau.microservice.*;
+
+/**
+ * <c>@Configuration</c> class that wires Jetty into a {@link Microservice} bootstrap.
+ *
+ * <p>
+ * Add this class to {@link org.apache.juneau.microservice.Microservice.Builder#configurations(Class...) configurations(...)} to enable a
+ * Jetty-backed microservice:
+ *
+ * <p class='bjava'>
+ * Microservice
+ * .<jsm>create</jsm>()
+ * .args(<jv>args</jv>)
+ * .configurations(JettyConfiguration.<jk>class</jk>, MyAppConfig.<jk>class</jk>)
+ * .build()
+ * .start()
+ * .startConsole()
+ * .join();
+ * </p>
+ *
+ * <p>
+ * Contributes the following beans (each gated on {@code @ConditionalOnMissingBean} so user-supplied beans of the
+ * same type win):
+ * <ul>
+ * <li>{@link JettyServerFactory} — defaults to {@link BasicJettyServerFactory}, used to build the Jetty
+ * {@link org.eclipse.jetty.server.Server Server} from <c>jetty.xml</c>.
+ * <li>{@link JettySettings} — empty defaults; user-supplied <c>@Bean JettySettings</c> can override ports,
+ * <c>jetty.xml</c> contents, and var-resolution.
+ * <li>{@link JettyServerComponent} (always contributed, also registered under {@link MicroserviceListener}) —
+ * drives the Jetty server lifecycle via the microservice's {@code start()} / {@code stop()} fan-out.
+ * </ul>
+ *
+ * <p>
+ * <c>@Bean Servlet</c> methods in user-supplied <c>@Configuration</c> classes are auto-mounted at
+ * {@link org.apache.juneau.rest.annotation.Rest#path()} during start-up. See {@link JettyServerComponent} for
+ * full details.
+ *
+ * <h5 class='section'>See Also:</h5><ul>
+ * <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/JuneauMicroserviceJettyBasics">juneau-microservice-jetty Basics</a>
+ * </ul>
+ *
+ * @since 9.5.0
+ */
+@Configuration
+public class JettyConfiguration {
+
+ private final JettyServerComponent component = new JettyServerComponent();
+
+ /**
+ * Contributes the default Jetty server factory used to build the {@link org.eclipse.jetty.server.Server Server}
+ * from a <c>jetty.xml</c> file.
+ *
+ * @return The default factory.
+ */
+ @Bean
+ @ConditionalOnMissingBean(JettyServerFactory.class)
+ public JettyServerFactory jettyServerFactory() {
+ return new BasicJettyServerFactory();
+ }
+
+ /**
+ * Contributes an empty default {@link JettySettings} so {@link JettyServerComponent} always finds one in the
+ * store. Users who need programmatic overrides supply their own <c>@Bean JettySettings</c>.
+ *
+ * @return The default empty settings.
+ */
+ @Bean
+ @ConditionalOnMissingBean(JettySettings.class)
+ public JettySettings jettySettings() {
+ return JettySettings.create().build();
+ }
+
+ /**
+ * Contributes the {@link JettyServerComponent} bean under its own type for direct lookup by external callers.
+ *
+ * @return The component instance.
+ */
+ @Bean
+ public JettyServerComponent jettyServerComponent() {
+ return component;
+ }
+
+ /**
+ * Contributes the same {@link JettyServerComponent} instance under {@link MicroserviceListener} (named
+ * <c>jettyServerListener</c>) so it participates in the {@link Microservice#start()} / {@link Microservice#stop()}
+ * fan-out without clobbering any user-supplied unnamed {@code MicroserviceListener}.
+ *
+ * @return The component instance.
+ */
+ @Bean(name = "jettyServerListener")
+ public MicroserviceListener jettyServerListener() {
+ return component;
+ }
+}
diff --git a/juneau-microservice/juneau-microservice-jetty/src/main/java/org/apache/juneau/microservice/jetty/JettyMicroservice.java b/juneau-microservice/juneau-microservice-jetty/src/main/java/org/apache/juneau/microservice/jetty/JettyMicroservice.java
deleted file mode 100644
index b924f00754..0000000000
--- a/juneau-microservice/juneau-microservice-jetty/src/main/java/org/apache/juneau/microservice/jetty/JettyMicroservice.java
+++ /dev/null
@@ -1,907 +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.microservice.jetty;
-
-import static org.apache.juneau.collections.JsonMap.*;
-import static org.apache.juneau.commons.reflect.ReflectionUtils.*;
-import static org.apache.juneau.commons.utils.CollectionUtils.*;
-import static org.apache.juneau.commons.utils.IoUtils.*;
-import static org.apache.juneau.commons.utils.StringUtils.*;
-import static org.apache.juneau.commons.utils.ThrowableUtils.*;
-import static org.apache.juneau.commons.utils.Utils.*;
-
-import java.io.*;
-import java.net.*;
-import java.nio.file.*;
-import java.util.*;
-import java.util.concurrent.atomic.AtomicReference;
-import java.util.logging.*;
-
-import org.apache.juneau.commons.inject.*;
-import org.apache.juneau.commons.reflect.*;
-import org.apache.juneau.commons.runtime.*;
-import org.apache.juneau.commons.svl.*;
-import org.apache.juneau.config.*;
-import org.apache.juneau.config.store.*;
-import org.apache.juneau.cp.*;
-import org.apache.juneau.microservice.*;
-import org.apache.juneau.microservice.console.*;
-import org.apache.juneau.parser.*;
-import org.apache.juneau.rest.annotation.*;
-import org.apache.juneau.rest.servlet.*;
-import org.eclipse.jetty.ee11.servlet.*;
-import org.eclipse.jetty.server.*;
-
-import jakarta.servlet.*;
-
-/**
- * Entry point for Juneau microservice that implements a REST interface using Jetty on a single port.
- *
- * <h5 class='topic'>Jetty Server Details</h5>
- *
- * The Jetty server is created by the {@link #createServer()} method and started with the {@link #startServer()} method.
- * These methods can be overridden to provided customized behavior.
- *
- * <h5 class='topic'>Defining REST Resources</h5>
- *
- * Top-level REST resources are defined in the <c>jetty.xml</c> file as normal servlets.
- *
- * <h5 class='section'>See Also:</h5><ul>
- * <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/JuneauMicroserviceJettyBasics">juneau-microservice-jetty Basics</a>
- * </ul>
- */
-@SuppressWarnings({
- "java:S115" // Constants use UPPER_snakeCase convention (e.g., KEY_SERVLET_CONTEXT_HANDLER)
-})
-public class JettyMicroservice extends Microservice {
-
- /**
- * Builder class.
- */
- public static class Builder extends Microservice.Builder {
-
- String jettyXml;
- int[] ports;
- Boolean jettyXmlResolveVars;
- Map<String,Servlet> servlets = map();
- Map<String,Object> servletAttributes = map();
- JettyMicroserviceListener listener2;
- JettyServerFactory factory;
-
- /**
- * Constructor.
- */
- protected Builder() {}
-
- /**
- * Copy constructor.
- *
- * @param copyFrom The builder to copy settings from.
- */
- protected Builder(Builder copyFrom) {
- super(copyFrom);
- this.jettyXml = copyFrom.jettyXml;
- this.ports = copyFrom.ports;
- this.jettyXmlResolveVars = copyFrom.jettyXmlResolveVars;
- this.servlets = copyOf(copyFrom.servlets);
- this.servletAttributes = copyOf(copyFrom.servletAttributes);
- this.listener2 = copyFrom.listener2;
- }
-
- @Override /* Overridden from MicroserviceBuilder */
- public Builder args(Args args) {
- super.args(args);
- return this;
- }
-
- @Override /* Overridden from MicroserviceBuilder */
- public Builder args(String...args) {
- super.args(args);
- return this;
- }
-
- @Override /* Overridden from MicroserviceBuilder */
- public JettyMicroservice build() throws Exception {
- return new JettyMicroservice(this);
- }
-
- @Override /* Overridden from MicroserviceBuilder */
- public Builder config(Config config) {
- super.config(config);
- return this;
- }
-
- @Override /* Overridden from MicroserviceBuilder */
- public Builder configName(String configName) {
- super.configName(configName);
- return this;
- }
-
- @Override /* Overridden from MicroserviceBuilder */
- public Builder configStore(ConfigStore configStore) {
- super.configStore(configStore);
- return this;
- }
-
- @Override /* Overridden from MicroserviceBuilder */
- public Builder console(Scanner consoleReader, PrintWriter consoleWriter) {
- super.console(consoleReader, consoleWriter);
- return this;
- }
-
- @Override /* Overridden from MicroserviceBuilder */
- public Builder consoleCommands(ConsoleCommand...consoleCommands) {
- super.consoleCommands(consoleCommands);
- return this;
- }
-
- @Override /* Overridden from MicroserviceBuilder */
- public Builder consoleEnabled(boolean consoleEnabled) {
- super.consoleEnabled(consoleEnabled);
- return this;
- }
-
- @Override /* Overridden from MicroserviceBuilder */
- public Builder copy() {
- return new Builder(this);
- }
-
- /**
- * Specifies the factory to use for creating the Jetty {@link Server} instance.
- *
- * <p>
- * If not specified, uses {@link BasicJettyServerFactory}.
- *
- * @param value The new value for this property.
- * @return This object.
- */
- public Builder jettyServerFactory(JettyServerFactory value) {
- factory = value;
- return this;
- }
-
- /**
- * Specifies the contents or location of the <c>jetty.xml</c> file used by the Jetty server.
- *
- * <p>
- * If you do not specify this value, it is pulled from the following in the specified order:
- * <ul class='spaced-list'>
- * <li>
- * <c>Jetty/config</c> setting in the config file.
- * <c>Jetty-Config</c> setting in the manifest file.
- * </ul>
- *
- * <p>
- * By default, we look for the <c>jetty.xml</c> file in the following locations:
- * <ul class='spaced-list'>
- * <li><c>jetty.xml</c> in home directory.
- * <li><c>files/jetty.xml</c> in home directory.
- * <li><c>/jetty.xml</c> in classpath.
- * <li><c>/files/jetty.xml</c> in classpath.
- * </ul>
- *
- * @param jettyXml
- * The contents or location of the file.
- * <br>Can be any of the following:
- * <ul>
- * <li>{@link String} - Relative path to file on file system or classpath.
- * <li>{@link File} - File on file system.
- * <li>{@link Path} - Path on file system.
- * <li>{@link InputStream} - Raw contents as <c>UTF-8</c> encoded stream.
- * <li>{@link Reader} - Raw contents.
- * </ul>
- *
- * @param resolveVars
- * If <jk>true</jk>, SVL variables in the file will automatically be resolved.
- * @return This object.
- * @throws IOException Thrown by underlying stream.
- */
- public Builder jettyXml(Object jettyXml, boolean resolveVars) throws IOException {
- if (jettyXml instanceof String jettyXml2)
- this.jettyXml = read(resolveFile(jettyXml2));
- else if (jettyXml instanceof File jettyXml2)
- this.jettyXml = read(jettyXml2);
- else if (jettyXml instanceof Path jettyXml2)
- this.jettyXml = read(jettyXml2);
- else if (jettyXml instanceof InputStream jettyXml2)
- this.jettyXml = read(jettyXml2);
- else if (jettyXml instanceof Reader jettyXml2)
- this.jettyXml = read(jettyXml2);
- else
- throw rex("Invalid object type passed to jettyXml(Object): {0}", cn(jettyXml));
- this.jettyXmlResolveVars = resolveVars;
- return this;
- }
-
- /**
- * Registers an event listener for this microservice.
- *
- * @param listener An event listener for this microservice.
- * @return This object.
- */
- public Builder listener(JettyMicroserviceListener listener) {
- super.listener(listener);
- this.listener2 = listener;
- return this;
- }
-
- @Override /* Overridden from MicroserviceBuilder */
- public Builder logger(Logger logger) {
- super.logger(logger);
- return this;
- }
-
- @Override /* Overridden from MicroserviceBuilder */
- public Builder manifest(Object manifest) throws IOException {
- super.manifest(manifest);
- return this;
- }
-
- /**
- * Specifies the ports to use for the web server.
- *
- * <p>
- * You can specify multiple ports. The first available will be used. <js>'0'</js> indicates to try a random port.
- * The resulting available port gets set as the system property <js>"availablePort"</js> which can be referenced in the
- * <c>jetty.xml</c> file as <js>"$S{availablePort}"</js> (assuming resolveVars is enabled).
- *
- * <p>
- * If you do not specify this value, it is pulled from the following in the specified order:
- * <ul class='spaced-list'>
- * <li>
- * <c>Jetty/port</c> setting in the config file.
- * <li>
- * <c>Jetty-Port</c> setting in the manifest file.
- * <li>
- * <c>8000</c>
- * </ul>
- *
- * Jetty/port", mf.getWithDefault("Jetty-Port", ints(8000)
- * @param ports The ports to use for the web server.
- * @return This object.
- */
- public Builder ports(int...ports) {
- this.ports = ports;
- return this;
- }
-
- /**
- * Adds a servlet to the servlet container.
- *
- * <p>
- * This method can only be used with servlets with no-arg constructors.
- * <br>The path is pulled from the {@link Rest#path()} annotation.
- *
- * @param c The servlet to add to the servlet container.
- * @return This object.
- * @throws ExecutableException Exception occurred on invoked constructor/method/field.
- */
- public Builder servlet(Class<? extends RestServlet> c) throws ExecutableException {
- RestServlet rs;
- try {
- rs = c.getDeclaredConstructor().newInstance();
- } catch (Exception e) {
- throw new ExecutableException(e);
- }
- return servlet(rs, '/' + rs.getPath());
- }
-
- /**
- * Adds a servlet to the servlet container.
- *
- * <p>
- * This method can only be used with servlets with no-arg constructors.
- *
- * @param c The servlet to add to the servlet container.
- * @param path The servlet path spec.
- * @return This object.
- * @throws ExecutableException Exception occurred on invoked constructor/method/field.
- */
- public Builder servlet(Class<? extends Servlet> c, String path) throws ExecutableException {
- try {
- return servlet(c.getDeclaredConstructor().newInstance(), path);
- } catch (Exception e) {
- throw new ExecutableException(e);
- }
- }
-
- /**
- * Adds a servlet instance to the servlet container.
- *
- * @param servlet The servlet to add to the servlet container.
- * @param path The servlet path spec.
- * @return This object.
- */
- public Builder servlet(Servlet servlet, String path) {
- servlets.put(path, servlet);
- return this;
- }
-
- /**
- * Adds a set of servlet attributes to the servlet container.
- *
- * @param values The map of attributes.
- * @return This object.
- */
- public Builder servletAttribute(Map<String,Object> values) {
- if (nn(values))
- this.servletAttributes.putAll(values);
- return this;
- }
-
- /**
- * Adds a servlet attribute to the servlet container.
- *
- * @param name The attribute name.
- * @param value The attribute value.
- * @return This object.
- */
- public Builder servletAttribute(String name, Object value) {
- this.servletAttributes.put(name, value);
- return this;
- }
-
- /**
- * Adds a set of servlets to the servlet container.
- *
- * @param servlets
- * A map of servlets to add to the servlet container.
- * <br>Keys are path specs for the servlet.
- * @return This object.
- */
- public Builder servlets(Map<String,Servlet> servlets) {
- if (nn(servlets))
- this.servlets.putAll(servlets);
- return this;
- }
-
- @Override /* Overridden from MicroserviceBuilder */
- public <T> Builder varBean(Class<T> c, T value) {
- super.varBean(c, value);
- return this;
- }
-
- @Override /* Overridden from MicroserviceBuilder */
- @SuppressWarnings({
- "unchecked" // Type erasure requires unchecked cast for varargs
- })
- public Builder vars(Class<? extends Var>...vars) {
- super.vars(vars);
- return this;
- }
-
- @Override /* Overridden from MicroserviceBuilder */
- public Builder workingDir(File path) {
- super.workingDir(path);
- return this;
- }
-
- @Override /* Overridden from MicroserviceBuilder */
- public Builder configurations(Class<?>...configurations) {
- super.configurations(configurations);
- return this;
- }
-
- @Override /* Overridden from MicroserviceBuilder */
- public Builder configurations(List<Class<?>> configurations) {
- super.configurations(configurations);
- return this;
- }
-
- @Override /* Overridden from MicroserviceBuilder */
- public Builder beanStore(WritableBeanStore beanStore) {
- super.beanStore(beanStore);
- return this;
- }
-
- @Override /* Overridden from MicroserviceBuilder */
- public Builder workingDir(String path) {
- super.workingDir(path);
- return this;
- }
- }
-
- private static final String KEY_SERVLET_CONTEXT_HANDLER = "ServletContextHandler";
- private static final Random RANDOM = new Random();
-
- private static final AtomicReference<JettyMicroservice> instance = new AtomicReference<>();
-
- /**
- * Creates a new microservice builder.
- *
- * @return A new microservice builder.
- */
- public static Builder create() {
- return new Builder();
- }
-
- /**
- * Returns the Microservice instance.
- * <p>
- * This method only works if there's only one Microservice instance in a JVM.
- * Otherwise, it's just overwritten by the last instantiated microservice.
- *
- * @return The Microservice instance, or <jk>null</jk> if there isn't one.
- */
- public static JettyMicroservice getInstance() {
- return instance.get();
- }
-
- /**
- * Entry-point method.
- *
- * @param args Command line arguments.
- * @throws Exception Error occurred.
- */
- public static void main(String[] args) throws Exception {
- // @formatter:off
- JettyMicroservice
- .create()
- .args(args)
- .build()
- .start()
- .startConsole()
- .join();
- // @formatter:on
- }
-
- private static int[] parseIntArray(String csv) {
- if (csv == null || csv.isEmpty())
- return new int[0];
- var parts = csv.split(",");
- var out = new int[parts.length];
- for (var i = 0; i < parts.length; i++)
- out[i] = Integer.parseInt(parts[i].trim());
- return out;
- }
-
- private static int findOpenPort(int[] ports) {
- for (var port : ports) {
- // If port is 0, try a random port between ports[0] and 32767.
- if (port == 0)
- port = RANDOM.nextInt(32767 - ports[0] + 1) + ports[0];
- try (var ss = new ServerSocket(port)) {
- return port;
- } catch (@SuppressWarnings("unused") IOException e) {
- // Port is in use, try next port in array
- }
- }
- return 0;
- }
-
- private static void setInstance(JettyMicroservice m) {
- instance.set(m);
- }
-
- final Messages messages2 = Messages.of(JettyMicroservice.class);
- private final Builder builder;
- final JettyMicroserviceListener listener;
-
- private final JettyServerFactory factory;
-
- private final AtomicReference<Server> server = new AtomicReference<>();
-
- /**
- * Constructor.
- *
- * @param builder The constructor arguments.
- * @throws IOException Problem occurred reading file.
- * @throws ParseException Malformed content found in config file.
- */
- @SuppressWarnings({
- "resource" // getBeanStore() is microservice-owned and closed in Microservice.stop(); fluent addBean() should not be auto-closed here.
- })
- protected JettyMicroservice(Builder builder) throws ParseException, IOException {
- super(builder);
- setInstance(this);
- this.builder = builder.copy();
- var store = getBeanStore();
- // Listener: explicit builder > @Bean (Jetty-specific first, then core) > default.
- this.listener = nn(builder.listener2)
- ? builder.listener2
- : store.getBean(JettyMicroserviceListener.class).orElseGet(BasicJettyMicroserviceListener::new);
- store.addBean(JettyMicroserviceListener.class, this.listener);
- // Factory: explicit builder > @Bean > default.
- this.factory = nn(builder.factory)
- ? builder.factory
- : store.getBean(JettyServerFactory.class).orElseGet(BasicJettyServerFactory::new);
- store.addBean(JettyServerFactory.class, this.factory);
- // Self-register so @Bean factory methods can take JettyMicroservice as a constructor/method param.
- store.addBean(JettyMicroservice.class, this);
- }
-
- /**
- * Adds an arbitrary servlet to this microservice.
- *
- * @param servlet The servlet instance.
- * @param pathSpec The context path of the servlet.
- * @return This object.
- * @throws RuntimeException if {@link #createServer()} has not previously been called.
- */
- public JettyMicroservice addServlet(Servlet servlet, String pathSpec) {
- var sh = new ServletHolder(servlet);
- if (nn(pathSpec) && ! pathSpec.endsWith("/*"))
- pathSpec = trimTrailingSlashes(pathSpec) + "/*";
- getServletContextHandler().addServlet(sh, pathSpec);
- return this;
- }
-
- /**
- * Adds a servlet attribute to the Jetty server.
- *
- * @param name The server attribute name.
- * @param value The context path of the servlet.
- * @return This object.
- * @throws RuntimeException if {@link #createServer()} has not previously been called.
- */
- public JettyMicroservice addServletAttribute(String name, Object value) {
- getServer().setAttribute(name, value);
- return this;
- }
-
- /**
- * Method used to create (but not start) an instance of a Jetty server.
- *
- * <p>
- * Subclasses can override this method to customize the Jetty server before it is started.
- *
- * <p>
- * The default implementation is configured by the following values in the config file
- * if a jetty.xml is not specified via a <c>REST/jettyXml</c> setting:
- * <p class='bini'>
- * <cc>#================================================================================
- * # Jetty settings
- * #================================================================================</cc>
- * <cs>[Jetty]</cs>
- *
- * <cc># Path of the jetty.xml file used to configure the Jetty server.</cc>
- * <ck>config</ck> = jetty.xml
- *
- * <cc># Resolve Juneau variables in the jetty.xml file.</cc>
- * <ck>resolveVars</ck> = true
- *
- * <cc># 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).</cc>
- * <ck>port</ck> = 10000,0,0,0
- * </p>
- *
- * @return The newly-created server.
- * @throws ParseException Configuration file contains malformed input.
- * @throws IOException File could not be read.
- * @throws ExecutableException Exception occurred on invoked constructor/method/field.
- */
- @SuppressWarnings({
- "java:S3776", // Cognitive complexity acceptable for server creation logic
- "resource" // getBeanStore() is owned by the microservice lifecycle; do not close in createServer().
- })
- public Server createServer() throws ParseException, IOException, ExecutableException {
- listener.onCreateServer(this);
-
- var cf = getConfig();
- var mf = getManifest();
- var vr = getVarResolver();
- var store = getBeanStore();
-
- var ports = firstNonNull(builder.ports, cf.get("Jetty/port").as(int[].class).orElseGet(() -> mf.get("Jetty-Port").map(JettyMicroservice::parseIntArray).orElseGet(() -> ints(8000))));
- var availablePort = findOpenPort(ports);
-
- if (env("availablePort").isEmpty())
- System.setProperty("availablePort", String.valueOf(availablePort));
-
- // Prefer a @Bean-supplied Server if one was contributed via @Configuration.
- // Otherwise build from jetty.xml via the configured factory.
- var injectedServer = store.getBean(Server.class).orElse(null);
- if (nn(injectedServer)) {
- server.set(injectedServer);
- } else {
- var jettyXml = builder.jettyXml;
- var jettyConfig = cf.get("Jetty/config").orElseGet(() -> mf.get("Jetty-Config").orElse("jetty.xml"));
- var resolveVars = firstNonNull(builder.jettyXmlResolveVars, cf.get("Jetty/resolveVars").asBoolean().orElse(false));
- boolean resolveVars2 = isTrue(resolveVars);
-
- if (jettyXml == null)
- jettyXml = loadSystemResourceAsString("jetty.xml", ".", "files");
- if (jettyXml == null)
- throw rex("jetty.xml file ''{0}'' was not found on the file system or classpath.", jettyConfig);
-
- if (resolveVars2)
- jettyXml = vr.resolve(jettyXml);
-
- getLogger().info(jettyXml);
-
- try {
- server.set(factory.create(jettyXml));
- } catch (Exception e2) {
- throw new ExecutableException(e2);
- }
- }
- // Publish the Server back to the store so @Bean factory methods of other beans can depend on it.
- store.addBean(Server.class, server.get());
-
- // Track each servlet pathSpec with its declaring source so we can fail loudly on collisions.
- var mountedPaths = new LinkedHashMap<String,String>();
-
- for (var s : cf.get("Jetty/servlets").asStringArray().orElse(new String[0])) {
- try {
- var c = info(Class.forName(s));
- if (c.isAssignableTo(RestServlet.class)) {
- var rs = (RestServlet)c.newInstance();
- mountWithCollisionCheck(rs, rs.getPath(), "Jetty/servlets[" + s + "]", mountedPaths);
- } else {
- throw rex("Invalid servlet specified in Jetty/servlets. Must be a subclass of RestServlet: {0}", s);
- }
- } catch (ClassNotFoundException e1) {
- throw new ExecutableException(e1);
- }
- }
-
- cf.get("Jetty/servletMap").asMap().orElse(EMPTY_MAP).forEach((k, v) -> {
- try {
- var c = info(Class.forName(v.toString()));
- if (c.isAssignableTo(Servlet.class)) {
- var rs = (Servlet)c.newInstance();
- mountWithCollisionCheck(rs, k, "Jetty/servletMap[" + k + "]", mountedPaths);
- } else {
- throw rex("Invalid servlet specified in Jetty/servletMap. Must be a subclass of Servlet: {0}", cn(v));
- }
- } catch (ClassNotFoundException e1) {
- throw new ExecutableException(e1);
- }
- });
-
- cf.get("Jetty/servletAttributes").asMap().orElse(EMPTY_MAP).forEach(this::addServletAttribute);
-
- builder.servlets.forEach((k, v) -> mountWithCollisionCheck(v, k, "Builder.servlet(" + cn(v) + ")", mountedPaths));
-
- builder.servletAttributes.forEach(this::addServletAttribute);
-
- // Auto-discover @Rest servlets contributed via @Configuration/@Bean methods.
- // Path source precedence: @Rest(path=...) on the resource class, else "/".
- // Builder-supplied servlets already won (registered above), so duplicate mount paths fail hard.
- for (var e : store.getBeansOfType(Servlet.class).entrySet()) {
- var servlet = e.getValue();
- var cls = servlet.getClass();
- if (cls.getAnnotation(Rest.class) == null)
- continue;
- var pathSpec = restPathFor(cls);
- mountWithCollisionCheck(servlet, pathSpec, "@Bean " + cls.getName() + (ne(e.getKey()) ? "[" + e.getKey() + "]" : ""), mountedPaths);
- }
-
- if (env("juneau.serverPort").isEmpty())
- System.setProperty("juneau.serverPort", String.valueOf(availablePort));
-
- return server.get();
- }
-
- private void mountWithCollisionCheck(Servlet servlet, String rawPath, String source, Map<String,String> mountedPaths) {
- var pathSpec = normalizePathSpec(rawPath);
- var prior = mountedPaths.get(pathSpec);
- if (nn(prior))
- throw rex("Servlet mount path collision: ''{0}'' is already mounted by {1}; refused by {2}.", pathSpec, prior, source);
- mountedPaths.put(pathSpec, source);
- addServlet(servlet, pathSpec);
- }
-
- private static String normalizePathSpec(String rawPath) {
- var p = rawPath == null ? "" : rawPath;
- if (p.isEmpty() || "/".equals(p))
- return "/*";
- if (! p.startsWith("/"))
- p = "/" + p;
- if (! p.endsWith("/*"))
- p = trimTrailingSlashes(p) + "/*";
- return p;
- }
-
- private static String restPathFor(Class<?> cls) {
- var r = cls.getAnnotation(Rest.class);
- if (r == null || r.path().isEmpty())
- return "/";
- return r.path();
- }
-
- /**
- * Calls {@link Server#destroy()} on the underlying Jetty server if it exists.
- *
- * @throws Exception Error occurred.
- */
- @SuppressWarnings({
- "java:S112" // throws Exception intentional - callback/lifecycle method
- })
- public void destroyServer() throws Exception {
- var s = server.getAndSet(null);
- if (nn(s))
- s.destroy();
- }
-
- /**
- * Returns the context path that this microservice is using.
- * <p>
- * The value is determined by looking at the <c>Server/Handlers[ServletContextHandler]/contextPath</c> value
- * in the Jetty configuration.
- *
- * @return The context path that this microservice is using.
- */
- public String getContextPath() { return getServletContextHandler().getContextPath(); }
-
- /**
- * Returns the hostname of this microservice.
- * <p>
- * Simply uses <c>InetAddress.getLocalHost().getHostName()</c>.
- *
- * @return The hostname of this microservice.
- */
- public String getHostName() {
- String hostname = "localhost";
- try {
- hostname = InetAddress.getLocalHost().getHostName();
- } catch (@SuppressWarnings("unused") UnknownHostException e) {
- // Cannot determine hostname, use default "localhost"
- }
- return hostname;
- }
-
- /**
- * Returns the port that this microservice started up on.
- * <p>
- * The value is determined by looking at the <c>Server/Connectors[ServerConnector]/port</c> value in the
- * Jetty configuration.
- *
- * @return The port that this microservice started up on.
- */
- public int getPort() {
- for (var c : getServer().getConnectors())
- if (c instanceof ServerConnector c2)
- return c2.getPort();
- throw new IllegalStateException("Could not locate ServerConnector in Jetty server.");
- }
-
- /**
- * Returns whether this microservice is using <js>"http"</js> or <js>"https"</js>.
- * <p>
- * The value is determined by looking for the existence of an SSL Connection Factorie by looking for the
- * <c>Server/Connectors[ServerConnector]/ConnectionFactories[SslConnectionFactory]</c> value in the Jetty
- * configuration.
- *
- * @return Whether this microservice is using <js>"http"</js> or <js>"https"</js>.
- */
- public String getProtocol() {
- for (var c : getServer().getConnectors())
- if (c instanceof ServerConnector c2)
- for (var cf : c2.getConnectionFactories())
- if (cf instanceof SslConnectionFactory)
- return "https";
- return "http";
- }
-
- /**
- * Returns the underlying Jetty server.
- *
- * @return The underlying Jetty server, or <jk>null</jk> if {@link #createServer()} has not yet been called.
- */
- public Server getServer() { return Objects.requireNonNull(server.get(), "Server not found. createServer() must be called first."); }
-
- /**
- * Finds and returns the servlet context handler defined in the Jetty container.
- *
- * @return The servlet context handler.
- * @throws RuntimeException if context handler is not defined.
- */
- public ServletContextHandler getServletContextHandler() {
- var obj = getServer().getAttribute(KEY_SERVLET_CONTEXT_HANDLER);
- if (obj instanceof ServletContextHandler obj2)
- return obj2;
- throw new IllegalStateException("Servlet context handler not found in jetty server or at attribute '" + KEY_SERVLET_CONTEXT_HANDLER + "'");
- }
-
- /**
- * Returns the URI where this microservice is listening on.
- *
- * @return The URI where this microservice is listening on.
- */
- public URI getURI() {
- var cp = getContextPath();
- try {
- return new URI(getProtocol(), null, getHostName(), getPort(), "/".equals(cp) ? null : cp, null, null);
- } catch (URISyntaxException e) {
- throw toRex(e);
- }
- }
-
- @Override /* Overridden from Microservice */
- public synchronized JettyMicroservice init() throws ParseException, IOException {
- super.init();
- return this;
- }
-
- @Override /* Overridden from Microservice */
- public JettyMicroservice join() throws Exception {
- server.get().join();
- return this;
- }
-
- @Override /* Overridden from Microservice */
- public synchronized JettyMicroservice start() throws Exception {
- super.start();
- createServer();
- startServer();
- return this;
- }
-
- @Override /* Overridden from Microservice */
- public synchronized JettyMicroservice startConsole() throws Exception {
- super.startConsole();
- return this;
- }
-
- @Override /* Overridden from Microservice */
- public synchronized JettyMicroservice stop() throws Exception {
- final Logger logger = getLogger();
- final Messages mb2 = messages2;
- var t = new Thread("JettyMicroserviceStop") {
- @Override /* Overridden from Thread */
- public void run() {
- try {
- var s = server.get();
- if (s == null || s.isStopping() || s.isStopped())
- return;
- listener.onStopServer(JettyMicroservice.this);
- out(mb2, "StoppingServer");
- s.stop();
- out(mb2, "ServerStopped");
- listener.onPostStopServer(JettyMicroservice.this);
- } catch (Exception e) {
- logger.log(Level.WARNING, lm(e), e);
- }
- }
- };
- t.start();
- try {
- t.join();
- } catch (@SuppressWarnings("unused") InterruptedException e) {
- Thread.currentThread().interrupt();
- }
- super.stop();
-
- return this;
- }
-
- @Override /* Overridden from Microservice */
- public synchronized JettyMicroservice stopConsole() throws Exception {
- super.stopConsole();
- return this;
- }
-
- /**
- * Method used to start the Jetty server created by {@link #createServer()}.
- *
- * <p>
- * Subclasses can override this method to customize server startup.
- *
- * @return The port that this server started on.
- * @throws Exception Error occurred.
- */
- protected int startServer() throws Exception {
- listener.onStartServer(this);
- server.get().start();
- out(messages2, "ServerStarted", getPort());
- listener.onPostStartServer(this);
- return getPort();
- }
-}
\ No newline at end of file
diff --git a/juneau-microservice/juneau-microservice-jetty/src/main/java/org/apache/juneau/microservice/jetty/JettyMicroserviceListener.java b/juneau-microservice/juneau-microservice-jetty/src/main/java/org/apache/juneau/microservice/jetty/JettyMicroserviceListener.java
deleted file mode 100644
index 4649e087c0..0000000000
--- a/juneau-microservice/juneau-microservice-jetty/src/main/java/org/apache/juneau/microservice/jetty/JettyMicroserviceListener.java
+++ /dev/null
@@ -1,64 +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.microservice.jetty;
-
-import org.apache.juneau.microservice.*;
-
-/**
- * Listener class for Jetty microservice lifecycle events.
- *
- * <h5 class='section'>See Also:</h5><ul>
- * <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/JuneauMicroserviceJettyBasics">juneau-microservice-jetty Basics</a>
- * </ul>
- */
-public interface JettyMicroserviceListener extends MicroserviceListener {
-
- /**
- * Called before the Jetty server is created.
- *
- * @param microservice Reference to microservice.
- */
- void onCreateServer(JettyMicroservice microservice);
-
- /**
- * Called after the Jetty server is started.
- *
- * @param microservice Reference to microservice.
- */
- void onPostStartServer(JettyMicroservice microservice);
-
- /**
- * Called after the Jetty server is stopped.
- *
- * @param microservice Reference to microservice.
- */
- void onPostStopServer(JettyMicroservice microservice);
-
- /**
- * Called before the Jetty server is started.
- *
- * @param microservice Reference to microservice.
- */
- void onStartServer(JettyMicroservice microservice);
-
- /**
- * Called before the Jetty server is stopped.
- *
- * @param microservice Reference to microservice.
- */
- void onStopServer(JettyMicroservice microservice);
-}
\ No newline at end of file
diff --git a/juneau-microservice/juneau-microservice-jetty/src/main/java/org/apache/juneau/microservice/jetty/JettyServerComponent.java b/juneau-microservice/juneau-microservice-jetty/src/main/java/org/apache/juneau/microservice/jetty/JettyServerComponent.java
new file mode 100644
index 0000000000..77458fd459
--- /dev/null
+++ b/juneau-microservice/juneau-microservice-jetty/src/main/java/org/apache/juneau/microservice/jetty/JettyServerComponent.java
@@ -0,0 +1,398 @@
+/*
+ * 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.jetty;
+
+import static org.apache.juneau.collections.JsonMap.*;
+import static org.apache.juneau.commons.reflect.ReflectionUtils.*;
+import static org.apache.juneau.commons.utils.CollectionUtils.*;
+import static org.apache.juneau.commons.utils.IoUtils.*;
+import static org.apache.juneau.commons.utils.StringUtils.*;
+import static org.apache.juneau.commons.utils.ThrowableUtils.*;
+import static org.apache.juneau.commons.utils.Utils.*;
+
+import java.io.*;
+import java.net.*;
+import java.util.*;
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.logging.*;
+
+import org.apache.juneau.config.event.*;
+import org.apache.juneau.cp.*;
+import org.apache.juneau.microservice.*;
+import org.apache.juneau.rest.annotation.*;
+import org.apache.juneau.rest.servlet.*;
+import org.eclipse.jetty.ee11.servlet.*;
+import org.eclipse.jetty.server.*;
+
+import jakarta.servlet.*;
+
+/**
+ * Drives the Jetty server lifecycle on behalf of the microservice via the {@link MicroserviceListener} fan-out.
+ *
+ * <p>
+ * Contributed by {@link JettyConfiguration} as a <c>@Bean</c>. The microservice's {@link Microservice#start()}
+ * call invokes {@link #onStart(Microservice)}, which:
+ * <ol>
+ * <li>Picks the first available port from the resolved {@link JettySettings#getPorts() ports} (falling back to
+ * <c>Jetty/port</c> config, then <c>Jetty-Port</c> manifest, then <c>8000</c>).
+ * <li>Resolves the Jetty {@link Server} — preferring an externally-supplied <c>@Bean Server</c>, otherwise
+ * building one from <c>jetty.xml</c> via the {@link JettyServerFactory}.
+ * <li>Mounts servlets from {@code Jetty/servlets}, {@code Jetty/servletMap}, {@code Jetty/servletAttributes}
+ * config sections, plus auto-mounts every {@code @Bean Servlet} whose runtime class is annotated with
+ * {@link Rest @Rest} (at {@link Rest#path()}, or <c>"/"</c> when no path is set).
+ * <li>Starts the server and publishes the bound port via the {@code availablePort} / {@code juneau.serverPort}
+ * system properties.
+ * </ol>
+ *
+ * <p>
+ * {@link #onStop(Microservice)} performs the inverse: stops the server gracefully in a worker thread.
+ *
+ * <p>
+ * External callers reach this component via
+ * {@code Microservice.getInstance().getBeanStore().getBean(JettyServerComponent.class).orElseThrow()}.
+ *
+ * <h5 class='section'>See Also:</h5><ul>
+ * <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/JuneauMicroserviceJettyBasics">juneau-microservice-jetty Basics</a>
+ * </ul>
+ *
+ * @since 9.5.0
+ */
+@SuppressWarnings({
+ "java:S115" // Constants use UPPER_snakeCase convention (e.g., KEY_SERVLET_CONTEXT_HANDLER)
+})
+public class JettyServerComponent implements MicroserviceListener {
+
+ private static final String KEY_SERVLET_CONTEXT_HANDLER = "ServletContextHandler";
+ private static final Random RANDOM = new Random();
+
+ private final Messages messages = Messages.of(JettyServerComponent.class);
+ private final AtomicReference<Server> server = new AtomicReference<>();
+ private final AtomicReference<Microservice> microservice = new AtomicReference<>();
+
+ private static int[] parseIntArray(String csv) {
+ if (csv == null || csv.isEmpty())
+ return new int[0];
+ var parts = csv.split(",");
+ var out = new int[parts.length];
+ for (var i = 0; i < parts.length; i++)
+ out[i] = Integer.parseInt(parts[i].trim());
+ return out;
+ }
+
+ private static int findOpenPort(int[] ports) {
+ for (var port : ports) {
+ if (port == 0)
+ port = RANDOM.nextInt(32767 - ports[0] + 1) + ports[0];
+ try (var ss = new ServerSocket(port)) {
+ return port;
+ } catch (@SuppressWarnings("unused") IOException e) {
+ // Port is in use, try next port in array
+ }
+ }
+ return 0;
+ }
+
+ private static String normalizePathSpec(String rawPath) {
+ var p = rawPath == null ? "" : rawPath;
+ if (p.isEmpty() || "/".equals(p))
+ return "/*";
+ if (! p.startsWith("/"))
+ p = "/" + p;
+ if (! p.endsWith("/*"))
+ p = trimTrailingSlashes(p) + "/*";
+ return p;
+ }
+
+ private static String restPathFor(Class<?> cls) {
+ var r = cls.getAnnotation(Rest.class);
+ if (r == null || r.path().isEmpty())
+ return "/";
+ return r.path();
+ }
+
+ /**
+ * Constructor.
+ */
+ @SuppressWarnings({
+ "java:S1186" // Empty constructor; all state is initialized via onStart(Microservice) when wired through the bean store.
+ })
+ public JettyServerComponent() {}
+
+ @Override /* Overridden from MicroserviceListener */
+ @SuppressWarnings({
+ "java:S3776", // Cognitive complexity acceptable for server creation logic
+ "java:S1141", // Nested try blocks scope checked-exception translation tightly to single call sites
+ "resource" // ms.getBeanStore() is owned by the microservice lifecycle; do not close here.
+ })
+ public void onStart(Microservice ms) {
+ try {
+ microservice.set(ms);
+ var store = ms.getBeanStore();
+ var cf = ms.getConfig();
+ var mf = ms.getManifest();
+ var vr = ms.getVarResolver();
+ var settings = store.getBean(JettySettings.class).orElseGet(() -> JettySettings.create().build());
+
+ // Port resolution: settings > Jetty/port config > Jetty-Port manifest > 8000
+ var ports = settings.getPorts();
+ if (ports == null)
+ ports = cf.get("Jetty/port").as(int[].class)
+ .orElseGet(() -> mf.get("Jetty-Port").map(JettyServerComponent::parseIntArray).orElseGet(() -> ints(8000)));
+ var availablePort = findOpenPort(ports);
+
+ if (env("availablePort").isEmpty())
+ System.setProperty("availablePort", String.valueOf(availablePort));
+
+ // Prefer a @Bean-supplied Server, else build one from jetty.xml.
+ var injectedServer = store.getBean(Server.class).orElse(null);
+ if (nn(injectedServer)) {
+ server.set(injectedServer);
+ } else {
+ var factory = store.getBean(JettyServerFactory.class).orElseGet(BasicJettyServerFactory::new);
+ var jettyXml = settings.getJettyXml();
+ var jettyConfig = cf.get("Jetty/config").orElseGet(() -> mf.get("Jetty-Config").orElse("jetty.xml"));
+ var resolveVars = firstNonNull(settings.getJettyXmlResolveVars(), cf.get("Jetty/resolveVars").asBoolean().orElse(false));
+ boolean resolveVars2 = isTrue(resolveVars);
+
+ if (jettyXml == null)
+ jettyXml = loadSystemResourceAsString("jetty.xml", ".", "files");
+ if (jettyXml == null)
+ throw rex("jetty.xml file ''{0}'' was not found on the file system or classpath.", jettyConfig);
+
+ if (resolveVars2)
+ jettyXml = vr.resolve(jettyXml);
+
+ ms.getLogger().info(jettyXml);
+
+ try {
+ server.set(factory.create(jettyXml));
+ } catch (Exception e) {
+ throw toRex(e);
+ }
+ }
+
+ // Publish back to the store for downstream beans / lookups.
+ store.addBean(Server.class, server.get());
+
+ // Track each servlet pathSpec with its declaring source so we can fail loudly on collisions.
+ var mountedPaths = new LinkedHashMap<String,String>();
+
+ for (var s : cf.get("Jetty/servlets").asStringArray().orElse(new String[0])) {
+ try {
+ var c = info(Class.forName(s));
+ if (c.isAssignableTo(RestServlet.class)) {
+ var rs = (RestServlet)c.newInstance();
+ mountWithCollisionCheck(rs, rs.getPath(), "Jetty/servlets[" + s + "]", mountedPaths);
+ } else {
+ throw rex("Invalid servlet specified in Jetty/servlets. Must be a subclass of RestServlet: {0}", s);
+ }
+ } catch (ClassNotFoundException e) {
+ throw toRex(e);
+ }
+ }
+
+ cf.get("Jetty/servletMap").asMap().orElse(EMPTY_MAP).forEach((k, v) -> {
+ try {
+ var c = info(Class.forName(v.toString()));
+ if (c.isAssignableTo(Servlet.class)) {
+ var rs = (Servlet)c.newInstance();
+ mountWithCollisionCheck(rs, k, "Jetty/servletMap[" + k + "]", mountedPaths);
+ } else {
+ throw rex("Invalid servlet specified in Jetty/servletMap. Must be a subclass of Servlet: {0}", cn(v));
+ }
+ } catch (ClassNotFoundException e) {
+ throw toRex(e);
+ }
+ });
+
+ cf.get("Jetty/servletAttributes").asMap().orElse(EMPTY_MAP).forEach(this::addServletAttribute);
+
+ // Auto-discover @Rest servlets contributed via @Configuration/@Bean methods.
+ // Path source precedence: @Rest(path=...) on the resource class, else "/".
+ for (var e : store.getBeansOfType(Servlet.class).entrySet()) {
+ var servlet = e.getValue();
+ var cls = servlet.getClass();
+ if (cls.getAnnotation(Rest.class) == null)
+ continue;
+ var pathSpec = restPathFor(cls);
+ mountWithCollisionCheck(servlet, pathSpec, "@Bean " + cls.getName() + (ne(e.getKey()) ? "[" + e.getKey() + "]" : ""), mountedPaths);
+ }
+
+ if (env("juneau.serverPort").isEmpty())
+ System.setProperty("juneau.serverPort", String.valueOf(availablePort));
+
+ server.get().start();
+ ms.out(messages, "ServerStarted", getPort());
+ } catch (Exception e) {
+ throw toRex(e);
+ }
+ }
+
+ @Override /* Overridden from MicroserviceListener */
+ public void onStop(Microservice ms) {
+ final Logger logger = ms.getLogger();
+ var t = new Thread("JettyServerComponentStop") {
+ @Override /* Overridden from Thread */
+ public void run() {
+ try {
+ var s = server.get();
+ if (s == null || s.isStopping() || s.isStopped())
+ return;
+ ms.out(messages, "StoppingServer");
+ s.stop();
+ ms.out(messages, "ServerStopped");
+ } catch (Exception e) {
+ logger.log(Level.WARNING, lm(e), e);
+ }
+ }
+ };
+ t.start();
+ try {
+ t.join();
+ } catch (@SuppressWarnings("unused") InterruptedException e) {
+ Thread.currentThread().interrupt();
+ }
+ }
+
+ @Override /* Overridden from MicroserviceListener */
+ public void onConfigChange(Microservice ms, ConfigEvents events) {
+ // No-op: Intentional empty implementation - this component is purely lifecycle-driven.
+ }
+
+ /**
+ * Adds an arbitrary servlet to this Jetty server.
+ *
+ * @param servlet The servlet instance.
+ * @param pathSpec The context path of the servlet.
+ * @return This object.
+ */
+ public JettyServerComponent addServlet(Servlet servlet, String pathSpec) {
+ var sh = new ServletHolder(servlet);
+ if (nn(pathSpec) && ! pathSpec.endsWith("/*"))
+ pathSpec = trimTrailingSlashes(pathSpec) + "/*";
+ getServletContextHandler().addServlet(sh, pathSpec);
+ return this;
+ }
+
+ /**
+ * Adds an attribute to the Jetty server.
+ *
+ * @param name The server attribute name.
+ * @param value The attribute value.
+ * @return This object.
+ */
+ public JettyServerComponent addServletAttribute(String name, Object value) {
+ getServer().setAttribute(name, value);
+ return this;
+ }
+
+ /**
+ * Returns the context path that this server is using.
+ *
+ * @return The context path.
+ */
+ public String getContextPath() {
+ return getServletContextHandler().getContextPath();
+ }
+
+ /**
+ * Returns the hostname of this microservice.
+ *
+ * @return The hostname.
+ */
+ public String getHostName() {
+ String hostname = "localhost";
+ try {
+ hostname = InetAddress.getLocalHost().getHostName();
+ } catch (@SuppressWarnings("unused") UnknownHostException e) {
+ // Cannot determine hostname, use default "localhost"
+ }
+ return hostname;
+ }
+
+ /**
+ * Returns the port that this server is listening on.
+ *
+ * @return The port.
+ */
+ public int getPort() {
+ for (var c : getServer().getConnectors())
+ if (c instanceof ServerConnector c2)
+ return c2.getPort();
+ throw new IllegalStateException("Could not locate ServerConnector in Jetty server.");
+ }
+
+ /**
+ * Returns whether this server is using <js>"http"</js> or <js>"https"</js>.
+ *
+ * @return The protocol.
+ */
+ public String getProtocol() {
+ for (var c : getServer().getConnectors())
+ if (c instanceof ServerConnector c2)
+ for (var cf : c2.getConnectionFactories())
+ if (cf instanceof SslConnectionFactory)
+ return "https";
+ return "http";
+ }
+
+ /**
+ * Returns the underlying Jetty server.
+ *
+ * @return The underlying Jetty server.
+ * @throws IllegalStateException If the server has not been created yet.
+ */
+ public Server getServer() {
+ return Objects.requireNonNull(server.get(), "Server not found. Microservice has not been started yet.");
+ }
+
+ /**
+ * Finds and returns the servlet context handler defined in the Jetty container.
+ *
+ * @return The servlet context handler.
+ * @throws IllegalStateException If the context handler is not defined.
+ */
+ public ServletContextHandler getServletContextHandler() {
+ var obj = getServer().getAttribute(KEY_SERVLET_CONTEXT_HANDLER);
+ if (obj instanceof ServletContextHandler obj2)
+ return obj2;
+ throw new IllegalStateException("Servlet context handler not found in jetty server or at attribute '" + KEY_SERVLET_CONTEXT_HANDLER + "'");
+ }
+
+ /**
+ * Returns the URI where this server is listening.
+ *
+ * @return The URI.
+ */
+ public URI getURI() {
+ var cp = getContextPath();
+ try {
+ return new URI(getProtocol(), null, getHostName(), getPort(), "/".equals(cp) ? null : cp, null, null);
+ } catch (URISyntaxException e) {
+ throw toRex(e);
+ }
+ }
+
+ private void mountWithCollisionCheck(Servlet servlet, String rawPath, String source, Map<String,String> mountedPaths) {
+ var pathSpec = normalizePathSpec(rawPath);
+ var prior = mountedPaths.get(pathSpec);
+ if (nn(prior))
+ throw rex("Servlet mount path collision: ''{0}'' is already mounted by {1}; refused by {2}.", pathSpec, prior, source);
+ mountedPaths.put(pathSpec, source);
+ addServlet(servlet, pathSpec);
+ }
+}
diff --git a/juneau-microservice/juneau-microservice-jetty/src/main/java/org/apache/juneau/microservice/jetty/JettySettings.java b/juneau-microservice/juneau-microservice-jetty/src/main/java/org/apache/juneau/microservice/jetty/JettySettings.java
new file mode 100644
index 0000000000..639641934d
--- /dev/null
+++ b/juneau-microservice/juneau-microservice-jetty/src/main/java/org/apache/juneau/microservice/jetty/JettySettings.java
@@ -0,0 +1,177 @@
+/*
+ * 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.jetty;
+
+import static org.apache.juneau.commons.utils.IoUtils.*;
+import static org.apache.juneau.commons.utils.ThrowableUtils.*;
+import static org.apache.juneau.commons.utils.Utils.*;
+
+import java.io.*;
+import java.nio.file.*;
+
+/**
+ * Programmatic settings for the Jetty server contributed by {@link JettyConfiguration}.
+ *
+ * <p>
+ * Users who need to override the defaults pulled from <c>Config</c> / <c>ManifestFile</c> should
+ * contribute a <c>@Bean JettySettings</c> from their own <c>@Configuration</c> class. Any value
+ * left {@code null} on this settings bean falls back to the corresponding <c>Config</c> / <c>ManifestFile</c>
+ * entry, then to a hard-coded default.
+ *
+ * <h5 class='section'>Example:</h5>
+ * <p class='bjava'>
+ * <ja>@Configuration</ja>
+ * <jk>public class</jk> MyAppConfig {
+ * <ja>@Bean</ja>
+ * <jk>public</jk> JettySettings jettySettings() {
+ * <jk>return</jk> JettySettings.<jsm>create</jsm>()
+ * .ports(8080, 0)
+ * .build();
+ * }
+ * }
+ * </p>
+ *
+ * <h5 class='section'>See Also:</h5><ul>
+ * <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/JuneauMicroserviceJettyBasics">juneau-microservice-jetty Basics</a>
+ * </ul>
+ *
+ * @since 9.5.0
+ */
+public class JettySettings {
+
+ /**
+ * Builder for {@link JettySettings}.
+ */
+ public static class Builder {
+
+ int[] ports;
+ String jettyXml;
+ Boolean jettyXmlResolveVars;
+
+ Builder() {}
+
+ /**
+ * Builds a new {@link JettySettings} from this builder.
+ *
+ * @return A new settings instance.
+ */
+ public JettySettings build() {
+ return new JettySettings(this);
+ }
+
+ /**
+ * Specifies the ports to try when binding the Jetty server.
+ *
+ * <p>
+ * The first available port is used. A value of <c>0</c> indicates "try a random port". When set, this
+ * value takes precedence over the <c>Jetty/port</c> config-file entry and the <c>Jetty-Port</c>
+ * manifest entry.
+ *
+ * @param value The candidate ports, in priority order. Can be <jk>null</jk> to defer to config / manifest.
+ * @return This object.
+ */
+ public Builder ports(int...value) {
+ ports = value;
+ return this;
+ }
+
+ /**
+ * Specifies the contents or location of the <c>jetty.xml</c> file used to build the Jetty server.
+ *
+ * <p>
+ * When set, this value takes precedence over the <c>Jetty/config</c> config-file entry and the
+ * <c>Jetty-Config</c> manifest entry. When not set, the component falls back to those values and
+ * finally to a <c>jetty.xml</c> file located on the file system or classpath.
+ *
+ * @param value The contents or location of the file. Can be any of:
+ * <ul>
+ * <li>{@link String} - Relative path to a file on the file system or classpath, or the raw XML content if it begins with <c><</c>.
+ * <li>{@link File} - File on the file system.
+ * <li>{@link Path} - Path on the file system.
+ * <li>{@link InputStream} - Raw contents as a <c>UTF-8</c> encoded stream.
+ * <li>{@link Reader} - Raw contents.
+ * </ul>
+ * @param resolveVars If <jk>true</jk>, SVL variables in the file will automatically be resolved.
+ * @return This object.
+ * @throws IOException Thrown by underlying stream.
+ */
+ public Builder jettyXml(Object value, boolean resolveVars) throws IOException {
+ if (value == null)
+ jettyXml = null;
+ else if (value instanceof String value2)
+ jettyXml = value2.startsWith("<") ? value2 : read(new File(value2));
+ else if (value instanceof File value2)
+ jettyXml = read(value2);
+ else if (value instanceof Path value2)
+ jettyXml = read(value2);
+ else if (value instanceof InputStream value2)
+ jettyXml = read(value2);
+ else if (value instanceof Reader value2)
+ jettyXml = read(value2);
+ else
+ throw rex("Invalid object type passed to jettyXml(Object): {0}", cn(value));
+ jettyXmlResolveVars = resolveVars;
+ return this;
+ }
+ }
+
+ /**
+ * Creates a new builder for this object.
+ *
+ * @return A new builder.
+ */
+ public static Builder create() {
+ return new Builder();
+ }
+
+ private final int[] ports;
+ private final String jettyXml;
+ private final Boolean jettyXmlResolveVars;
+
+ JettySettings(Builder b) {
+ ports = b.ports;
+ jettyXml = b.jettyXml;
+ jettyXmlResolveVars = b.jettyXmlResolveVars;
+ }
+
+ /**
+ * Returns the candidate ports to try when binding the Jetty server, in priority order.
+ *
+ * @return The ports, or <jk>null</jk> if not set.
+ */
+ public int[] getPorts() {
+ return ports == null ? null : ports.clone();
+ }
+
+ /**
+ * Returns the raw <c>jetty.xml</c> contents to use when building the server.
+ *
+ * @return The XML contents, or <jk>null</jk> if not set.
+ */
+ public String getJettyXml() {
+ return jettyXml;
+ }
+
+ /**
+ * Returns whether SVL variables in the <c>jetty.xml</c> file should be resolved.
+ *
+ * @return The resolve-vars flag, or <jk>null</jk> if not set.
+ */
+ public Boolean getJettyXmlResolveVars() {
+ return jettyXmlResolveVars;
+ }
+}
diff --git a/juneau-microservice/juneau-microservice-jetty/src/main/java/org/apache/juneau/microservice/jetty/resources/DebugResource.java b/juneau-microservice/juneau-microservice-jetty/src/main/java/org/apache/juneau/microservice/jetty/resources/DebugResource.java
index 0cc6e5a1d1..032ce79bed 100644
--- a/juneau-microservice/juneau-microservice-jetty/src/main/java/org/apache/juneau/microservice/jetty/resources/DebugResource.java
+++ b/juneau-microservice/juneau-microservice-jetty/src/main/java/org/apache/juneau/microservice/jetty/resources/DebugResource.java
@@ -20,6 +20,7 @@ import java.io.*;
import org.apache.juneau.html.annotation.*;
import org.apache.juneau.http.response.*;
+import org.apache.juneau.microservice.*;
import org.apache.juneau.microservice.jetty.*;
import org.apache.juneau.rest.*;
import org.apache.juneau.rest.annotation.*;
@@ -68,7 +69,7 @@ public class DebugResource extends BasicRestServlet {
"java:S112" // throws Exception intentional - callback/lifecycle method
})
public Ok createJettyDump(RestRequest req, RestResponse res) throws Exception {
- var dump = JettyMicroservice.getInstance().getServer().dump();
+ var dump = jettyServerComponent().getServer().dump();
try (var fw = new FileWriter(req.getConfig().get("Logging/logDir").orElse("") + "/jetty-thread-dump.log")) {
fw.write(dump);
}
@@ -99,6 +100,14 @@ public class DebugResource extends BasicRestServlet {
@RestGet(path = "/jetty/dump", description = "Generates and retrieves the jetty thread dump.")
public Reader getJettyDump(RestRequest req, RestResponse res) {
res.setContentType("text/plain");
- return new StringReader(JettyMicroservice.getInstance().getServer().dump());
+ return new StringReader(jettyServerComponent().getServer().dump());
+ }
+
+ @SuppressWarnings({
+ "resource" // BeanStore returned by Microservice.getBeanStore() is owned by the microservice lifecycle; do not close here.
+ })
+ private static JettyServerComponent jettyServerComponent() {
+ return Microservice.getInstance().getBeanStore().getBean(JettyServerComponent.class)
+ .orElseThrow(() -> new IllegalStateException("JettyServerComponent bean not found. Did you forget to add JettyConfiguration.class to Microservice.Builder.configurations(...)?"));
}
}
\ No newline at end of file
diff --git a/juneau-microservice/juneau-microservice-jetty/src/main/resources/org/apache/juneau/microservice/jetty/JettyMicroservice.properties b/juneau-microservice/juneau-microservice-jetty/src/main/resources/org/apache/juneau/microservice/jetty/JettyServerComponent.properties
similarity index 100%
rename from juneau-microservice/juneau-microservice-jetty/src/main/resources/org/apache/juneau/microservice/jetty/JettyMicroservice.properties
rename to juneau-microservice/juneau-microservice-jetty/src/main/resources/org/apache/juneau/microservice/jetty/JettyServerComponent.properties
diff --git a/juneau-microservice/juneau-microservice-core/.gitignore b/juneau-microservice/juneau-microservice/.gitignore
similarity index 100%
rename from juneau-microservice/juneau-microservice-core/.gitignore
rename to juneau-microservice/juneau-microservice/.gitignore
diff --git a/juneau-microservice/juneau-microservice-core/Dockerfile b/juneau-microservice/juneau-microservice/Dockerfile
similarity index 100%
rename from juneau-microservice/juneau-microservice-core/Dockerfile
rename to juneau-microservice/juneau-microservice/Dockerfile
diff --git a/juneau-microservice/juneau-microservice-core/pom.xml b/juneau-microservice/juneau-microservice/pom.xml
similarity index 92%
rename from juneau-microservice/juneau-microservice-core/pom.xml
rename to juneau-microservice/juneau-microservice/pom.xml
index 3f867c5c31..d79c98b73a 100644
--- a/juneau-microservice/juneau-microservice-core/pom.xml
+++ b/juneau-microservice/juneau-microservice/pom.xml
@@ -21,15 +21,15 @@
<parent>
<groupId>org.apache.juneau</groupId>
- <artifactId>juneau-microservice</artifactId>
+ <artifactId>juneau-microservice-parent</artifactId>
<version>9.5.0-SNAPSHOT</version>
</parent>
- <artifactId>juneau-microservice-core</artifactId>
+ <artifactId>juneau-microservice</artifactId>
<packaging>bundle</packaging>
- <name>Apache Juneau Microservice Core</name>
- <description>Apache Juneau Microservice Core API</description>
+ <name>Apache Juneau Microservice</name>
+ <description>Apache Juneau Microservice API</description>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
diff --git a/juneau-microservice/juneau-microservice-core/src/main/java/org/apache/juneau/microservice/BasicMicroserviceListener.java b/juneau-microservice/juneau-microservice/src/main/java/org/apache/juneau/microservice/BasicMicroserviceListener.java
similarity index 95%
rename from juneau-microservice/juneau-microservice-core/src/main/java/org/apache/juneau/microservice/BasicMicroserviceListener.java
rename to juneau-microservice/juneau-microservice/src/main/java/org/apache/juneau/microservice/BasicMicroserviceListener.java
index 82ddcf7898..ec561e22cd 100644
--- a/juneau-microservice/juneau-microservice-core/src/main/java/org/apache/juneau/microservice/BasicMicroserviceListener.java
+++ b/juneau-microservice/juneau-microservice/src/main/java/org/apache/juneau/microservice/BasicMicroserviceListener.java
@@ -22,7 +22,7 @@ import org.apache.juneau.config.event.*;
* Basic extensible microservice listener with default no-op method implementations.
*
* <h5 class='section'>See Also:</h5><ul>
- * <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/JuneauMicroserviceCoreBasics">juneau-microservice-core Basics</a>
+ * <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/JuneauMicroserviceBasics">juneau-microservice Basics</a>
* </ul>
*/
public class BasicMicroserviceListener implements MicroserviceListener {
diff --git a/juneau-microservice/juneau-microservice-core/src/main/java/org/apache/juneau/microservice/LogConfig.java b/juneau-microservice/juneau-microservice/src/main/java/org/apache/juneau/microservice/LogConfig.java
similarity index 100%
rename from juneau-microservice/juneau-microservice-core/src/main/java/org/apache/juneau/microservice/LogConfig.java
rename to juneau-microservice/juneau-microservice/src/main/java/org/apache/juneau/microservice/LogConfig.java
diff --git a/juneau-microservice/juneau-microservice-core/src/main/java/org/apache/juneau/microservice/Microservice.java b/juneau-microservice/juneau-microservice/src/main/java/org/apache/juneau/microservice/Microservice.java
similarity index 95%
rename from juneau-microservice/juneau-microservice-core/src/main/java/org/apache/juneau/microservice/Microservice.java
rename to juneau-microservice/juneau-microservice/src/main/java/org/apache/juneau/microservice/Microservice.java
index 150aa67fc9..573c576148 100755
--- a/juneau-microservice/juneau-microservice-core/src/main/java/org/apache/juneau/microservice/Microservice.java
+++ b/juneau-microservice/juneau-microservice/src/main/java/org/apache/juneau/microservice/Microservice.java
@@ -92,8 +92,7 @@ import org.apache.juneau.parser.ParseException;
* </ul>
*
* <h5 class='section'>See Also:</h5><ul>
- * <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/JuneauMicroserviceCoreBasics">juneau-microservice-core Basics</a>
-
+ * <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/JuneauMicroserviceBasics">juneau-microservice Basics</a>
* </ul>
*/
@SuppressWarnings({
@@ -620,7 +619,6 @@ public class Microservice implements ConfigEventListener {
private final Config config;
private final ManifestFile manifest;
private final VarResolver varResolver;
- private final MicroserviceListener listener;
private final Map<String,ConsoleCommand> consoleCommandMap = new ConcurrentHashMap<>();
private final boolean consoleEnabled;
private final Scanner consoleReader;
@@ -629,6 +627,7 @@ public class Microservice implements ConfigEventListener {
final File workingDir;
private final String configName;
private final WritableBeanStore beanStore;
+ private volatile boolean stopped;
private final AtomicReference<Logger> logger = new AtomicReference<>();
@@ -785,11 +784,15 @@ public class Microservice implements ConfigEventListener {
this.consoleWriter = null;
this.consoleThread = null;
}
- // Resolve listener: builder > @Bean > default.
- this.listener = nn(builder.listener)
- ? builder.listener
- : beanStore.getBean(MicroserviceListener.class).orElseGet(BasicMicroserviceListener::new);
- beanStore.addBean(MicroserviceListener.class, this.listener);
+ // Resolve listeners.
+ // If the builder supplies an explicit listener, register it under the unnamed key (overwriting any
+ // same-key @Bean MicroserviceListener); it joins the fan-out alongside any other @Bean-supplied listeners.
+ // If, after that, no MicroserviceListener exists in the store at all, register the default
+ // BasicMicroserviceListener so the fan-out has at least one no-op participant.
+ if (nn(builder.listener))
+ beanStore.addBean(MicroserviceListener.class, builder.listener);
+ if (beanStore.getBeansOfType(MicroserviceListener.class).isEmpty())
+ beanStore.addBean(MicroserviceListener.class, new BasicMicroserviceListener());
// Self-register so @Bean factory methods can take Microservice as a constructor/method param.
beanStore.addBean(Microservice.class, this);
@@ -1012,9 +1015,10 @@ public class Microservice implements ConfigEventListener {
* {@link Builder#configurations(Class...)}.
*
* <p>
- * Subclasses (e.g. <c>JettyMicroservice</c>) consult the store at start-up to discover additional
- * beans (servlets, listeners, factories) to register. External callers can query the store directly
- * to look up beans contributed by user-supplied <c>@Configuration</c> classes.
+ * Lifecycle integration beans (e.g. <c>JettyServerComponent</c> contributed by <c>JettyConfiguration</c>)
+ * implement {@link MicroserviceListener} and participate in the {@link #start()} / {@link #stop()}
+ * fan-out. External callers can query the store directly to look up beans contributed by user-supplied
+ * <c>@Configuration</c> classes.
*
* <p>
* The store is closed during {@link #stop()}, which triggers <c>@PreDestroy</c> hooks on resolved
@@ -1160,7 +1164,8 @@ public class Microservice implements ConfigEventListener {
@Override /* Overridden from ConfigChangeListener */
public void onConfigChange(ConfigEvents events) {
- listener.onConfigChange(this, events);
+ for (var l : beanStore.getBeansOfType(MicroserviceListener.class).values())
+ l.onConfigChange(this, events);
}
/**
@@ -1187,7 +1192,8 @@ public class Microservice implements ConfigEventListener {
* Start this application.
*
* <p>
- * Overridden methods MUST call this method FIRST so that the {@link MicroserviceListener#onStart(Microservice)} method is called.
+ * Iterates over every {@link MicroserviceListener} bean in the {@linkplain #getBeanStore() bean store} (in
+ * registration order) and calls {@link MicroserviceListener#onStart(Microservice)} on each.
*
* @return This object.
* @throws Exception Error occurred.
@@ -1214,7 +1220,8 @@ public class Microservice implements ConfigEventListener {
}
});
- listener.onStart(this);
+ for (var l : beanStore.getBeansOfType(MicroserviceListener.class).values())
+ l.onStart(this);
return this;
}
@@ -1238,7 +1245,9 @@ public class Microservice implements ConfigEventListener {
* Stop this application.
*
* <p>
- * Overridden methods MUST call this method LAST so that the {@link MicroserviceListener#onStop(Microservice)} method is called.
+ * Iterates over every {@link MicroserviceListener} bean in the {@linkplain #getBeanStore() bean store} in
+ * <i>reverse</i> registration order and calls {@link MicroserviceListener#onStop(Microservice)} on each, then
+ * closes the bean store (firing any {@code @PreDestroy} hooks).
*
* @return This object.
* @throws Exception Error occurred
@@ -1246,8 +1255,14 @@ public class Microservice implements ConfigEventListener {
@SuppressWarnings({
"java:S112" // throws Exception intentional - callback/lifecycle method
})
- public Microservice stop() throws Exception {
- listener.onStop(this);
+ public synchronized Microservice stop() throws Exception {
+ if (stopped)
+ return this;
+ stopped = true;
+ var listeners = new ArrayList<>(beanStore.getBeansOfType(MicroserviceListener.class).values());
+ Collections.reverse(listeners);
+ for (var l : listeners)
+ l.onStop(this);
try {
beanStore.close();
} catch (Exception e) {
diff --git a/juneau-microservice/juneau-microservice-core/src/main/java/org/apache/juneau/microservice/MicroserviceListener.java b/juneau-microservice/juneau-microservice/src/main/java/org/apache/juneau/microservice/MicroserviceListener.java
similarity index 95%
rename from juneau-microservice/juneau-microservice-core/src/main/java/org/apache/juneau/microservice/MicroserviceListener.java
rename to juneau-microservice/juneau-microservice/src/main/java/org/apache/juneau/microservice/MicroserviceListener.java
index e95b01d382..b46e3b3d68 100644
--- a/juneau-microservice/juneau-microservice-core/src/main/java/org/apache/juneau/microservice/MicroserviceListener.java
+++ b/juneau-microservice/juneau-microservice/src/main/java/org/apache/juneau/microservice/MicroserviceListener.java
@@ -22,7 +22,7 @@ import org.apache.juneau.config.event.*;
* Listener class for microservice lifecycle events.
*
* <h5 class='section'>See Also:</h5><ul>
- * <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/JuneauMicroserviceCoreBasics">juneau-microservice-core Basics</a>
+ * <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/JuneauMicroserviceBasics">juneau-microservice Basics</a>
* </ul>
*/
public interface MicroserviceListener {
diff --git a/juneau-microservice/juneau-microservice-core/src/main/java/org/apache/juneau/microservice/console/ConfigCommand.java b/juneau-microservice/juneau-microservice/src/main/java/org/apache/juneau/microservice/console/ConfigCommand.java
similarity index 97%
rename from juneau-microservice/juneau-microservice-core/src/main/java/org/apache/juneau/microservice/console/ConfigCommand.java
rename to juneau-microservice/juneau-microservice/src/main/java/org/apache/juneau/microservice/console/ConfigCommand.java
index db03b99b13..d1f037a713 100644
--- a/juneau-microservice/juneau-microservice-core/src/main/java/org/apache/juneau/microservice/console/ConfigCommand.java
+++ b/juneau-microservice/juneau-microservice/src/main/java/org/apache/juneau/microservice/console/ConfigCommand.java
@@ -29,7 +29,7 @@ import org.apache.juneau.microservice.*;
* Implements the 'config' console command to get or set configuration.
*
* <h5 class='section'>See Also:</h5><ul>
- * <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/JuneauMicroserviceCoreBasics">juneau-microservice-core Basics</a>
+ * <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/JuneauMicroserviceBasics">juneau-microservice Basics</a>
* </ul>
*/
@SuppressWarnings({
diff --git a/juneau-microservice/juneau-microservice-core/src/main/java/org/apache/juneau/microservice/console/ConsoleCommand.java b/juneau-microservice/juneau-microservice/src/main/java/org/apache/juneau/microservice/console/ConsoleCommand.java
similarity index 97%
rename from juneau-microservice/juneau-microservice-core/src/main/java/org/apache/juneau/microservice/console/ConsoleCommand.java
rename to juneau-microservice/juneau-microservice/src/main/java/org/apache/juneau/microservice/console/ConsoleCommand.java
index 8b246f6df4..fc7a20b984 100644
--- a/juneau-microservice/juneau-microservice-core/src/main/java/org/apache/juneau/microservice/console/ConsoleCommand.java
+++ b/juneau-microservice/juneau-microservice/src/main/java/org/apache/juneau/microservice/console/ConsoleCommand.java
@@ -42,7 +42,7 @@ import org.apache.juneau.commons.runtime.*;
* For example, the {@link HelpCommand} is used to provide help on other commands.
*
* <p class='bconsole'>
- * Running class 'JettyMicroservice' using config file 'examples.cfg'.
+ * Running class 'Microservice' using config file 'examples.cfg'.
* Server started on port 10000
*
* List of available commands:
@@ -97,7 +97,7 @@ import org.apache.juneau.commons.runtime.*;
* </p>
*
* <h5 class='section'>See Also:</h5><ul>
- * <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/JuneauMicroserviceCoreBasics">juneau-microservice-core Basics</a>
+ * <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/JuneauMicroserviceBasics">juneau-microservice Basics</a>
* </ul>
*/
public abstract class ConsoleCommand {
diff --git a/juneau-microservice/juneau-microservice-core/src/main/java/org/apache/juneau/microservice/console/ExitCommand.java b/juneau-microservice/juneau-microservice/src/main/java/org/apache/juneau/microservice/console/ExitCommand.java
similarity index 95%
rename from juneau-microservice/juneau-microservice-core/src/main/java/org/apache/juneau/microservice/console/ExitCommand.java
rename to juneau-microservice/juneau-microservice/src/main/java/org/apache/juneau/microservice/console/ExitCommand.java
index 46a8e4e97e..c70c6a6a7e 100644
--- a/juneau-microservice/juneau-microservice-core/src/main/java/org/apache/juneau/microservice/console/ExitCommand.java
+++ b/juneau-microservice/juneau-microservice/src/main/java/org/apache/juneau/microservice/console/ExitCommand.java
@@ -27,7 +27,7 @@ import org.apache.juneau.microservice.*;
* Implements the 'exit' console command to gracefully shut down the microservice and JVM.
*
* <h5 class='section'>See Also:</h5><ul>
- * <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/JuneauMicroserviceCoreBasics">juneau-microservice-core Basics</a>
+ * <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/JuneauMicroserviceBasics">juneau-microservice Basics</a>
* </ul>
*/
public class ExitCommand extends ConsoleCommand {
diff --git a/juneau-microservice/juneau-microservice-core/src/main/java/org/apache/juneau/microservice/console/HelpCommand.java b/juneau-microservice/juneau-microservice/src/main/java/org/apache/juneau/microservice/console/HelpCommand.java
similarity index 97%
rename from juneau-microservice/juneau-microservice-core/src/main/java/org/apache/juneau/microservice/console/HelpCommand.java
rename to juneau-microservice/juneau-microservice/src/main/java/org/apache/juneau/microservice/console/HelpCommand.java
index f0b99e9b02..b967f70f6b 100644
--- a/juneau-microservice/juneau-microservice-core/src/main/java/org/apache/juneau/microservice/console/HelpCommand.java
+++ b/juneau-microservice/juneau-microservice/src/main/java/org/apache/juneau/microservice/console/HelpCommand.java
@@ -29,7 +29,7 @@ import org.apache.juneau.microservice.*;
* Implements the 'restart' console command to gracefully shut down and restart the microservice.
*
* <h5 class='section'>See Also:</h5><ul>
- * <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/JuneauMicroserviceCoreBasics">juneau-microservice-core Basics</a>
+ * <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/JuneauMicroserviceBasics">juneau-microservice Basics</a>
* </ul>
*/
public class HelpCommand extends ConsoleCommand {
diff --git a/juneau-microservice/juneau-microservice-core/src/main/java/org/apache/juneau/microservice/console/RestartCommand.java b/juneau-microservice/juneau-microservice/src/main/java/org/apache/juneau/microservice/console/RestartCommand.java
similarity index 95%
rename from juneau-microservice/juneau-microservice-core/src/main/java/org/apache/juneau/microservice/console/RestartCommand.java
rename to juneau-microservice/juneau-microservice/src/main/java/org/apache/juneau/microservice/console/RestartCommand.java
index 2c95e40d17..4a5cb4e344 100644
--- a/juneau-microservice/juneau-microservice-core/src/main/java/org/apache/juneau/microservice/console/RestartCommand.java
+++ b/juneau-microservice/juneau-microservice/src/main/java/org/apache/juneau/microservice/console/RestartCommand.java
@@ -27,7 +27,7 @@ import org.apache.juneau.microservice.*;
* Implements the 'restart' console command to gracefully shut down and restart the microservice.
*
* <h5 class='section'>See Also:</h5><ul>
- * <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/JuneauMicroserviceCoreBasics">juneau-microservice-core Basics</a>
+ * <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/JuneauMicroserviceBasics">juneau-microservice Basics</a>
* </ul>
*/
public class RestartCommand extends ConsoleCommand {
diff --git a/juneau-microservice/juneau-microservice-core/src/main/java/org/apache/juneau/microservice/console/package-info.java b/juneau-microservice/juneau-microservice/src/main/java/org/apache/juneau/microservice/console/package-info.java
similarity index 100%
rename from juneau-microservice/juneau-microservice-core/src/main/java/org/apache/juneau/microservice/console/package-info.java
rename to juneau-microservice/juneau-microservice/src/main/java/org/apache/juneau/microservice/console/package-info.java
diff --git a/juneau-microservice/juneau-microservice-core/src/main/java/org/apache/juneau/microservice/package-info.java b/juneau-microservice/juneau-microservice/src/main/java/org/apache/juneau/microservice/package-info.java
similarity index 100%
rename from juneau-microservice/juneau-microservice-core/src/main/java/org/apache/juneau/microservice/package-info.java
rename to juneau-microservice/juneau-microservice/src/main/java/org/apache/juneau/microservice/package-info.java
diff --git a/juneau-microservice/juneau-microservice-core/src/main/java/org/apache/juneau/microservice/resources/ConfigEdit.html b/juneau-microservice/juneau-microservice/src/main/java/org/apache/juneau/microservice/resources/ConfigEdit.html
similarity index 100%
rename from juneau-microservice/juneau-microservice-core/src/main/java/org/apache/juneau/microservice/resources/ConfigEdit.html
rename to juneau-microservice/juneau-microservice/src/main/java/org/apache/juneau/microservice/resources/ConfigEdit.html
diff --git a/juneau-microservice/juneau-microservice-core/src/main/java/org/apache/juneau/microservice/resources/ConfigResource.java b/juneau-microservice/juneau-microservice/src/main/java/org/apache/juneau/microservice/resources/ConfigResource.java
similarity index 99%
rename from juneau-microservice/juneau-microservice-core/src/main/java/org/apache/juneau/microservice/resources/ConfigResource.java
rename to juneau-microservice/juneau-microservice/src/main/java/org/apache/juneau/microservice/resources/ConfigResource.java
index 14f57513a7..c5799ee9f5 100755
--- a/juneau-microservice/juneau-microservice-core/src/main/java/org/apache/juneau/microservice/resources/ConfigResource.java
+++ b/juneau-microservice/juneau-microservice/src/main/java/org/apache/juneau/microservice/resources/ConfigResource.java
@@ -34,7 +34,7 @@ import org.apache.juneau.rest.servlet.*;
* Shows contents of the microservice configuration file.
*
* <h5 class='section'>See Also:</h5><ul>
- * <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/JuneauMicroserviceCoreBasics">juneau-microservice-core Basics</a>
+ * <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/JuneauMicroserviceBasics">juneau-microservice Basics</a>
* </ul>
*
* @serial exclude
diff --git a/juneau-microservice/juneau-microservice-core/src/main/java/org/apache/juneau/microservice/resources/DirectoryResource.java b/juneau-microservice/juneau-microservice/src/main/java/org/apache/juneau/microservice/resources/DirectoryResource.java
similarity index 99%
rename from juneau-microservice/juneau-microservice-core/src/main/java/org/apache/juneau/microservice/resources/DirectoryResource.java
rename to juneau-microservice/juneau-microservice/src/main/java/org/apache/juneau/microservice/resources/DirectoryResource.java
index 1371638eb7..b118b46529 100755
--- a/juneau-microservice/juneau-microservice-core/src/main/java/org/apache/juneau/microservice/resources/DirectoryResource.java
+++ b/juneau-microservice/juneau-microservice/src/main/java/org/apache/juneau/microservice/resources/DirectoryResource.java
@@ -62,7 +62,7 @@ import org.apache.juneau.commons.bean.*;
* </ul>
*
* <h5 class='section'>See Also:</h5><ul>
- * <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/JuneauMicroserviceCoreBasics">juneau-microservice-core Basics</a>
+ * <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/JuneauMicroserviceBasics">juneau-microservice Basics</a>
* </ul>
*
* @serial exclude
diff --git a/juneau-microservice/juneau-microservice-core/src/main/java/org/apache/juneau/microservice/resources/LogEntryFormatter.java b/juneau-microservice/juneau-microservice/src/main/java/org/apache/juneau/microservice/resources/LogEntryFormatter.java
similarity index 100%
rename from juneau-microservice/juneau-microservice-core/src/main/java/org/apache/juneau/microservice/resources/LogEntryFormatter.java
rename to juneau-microservice/juneau-microservice/src/main/java/org/apache/juneau/microservice/resources/LogEntryFormatter.java
diff --git a/juneau-microservice/juneau-microservice-core/src/main/java/org/apache/juneau/microservice/resources/LogParser.java b/juneau-microservice/juneau-microservice/src/main/java/org/apache/juneau/microservice/resources/LogParser.java
similarity index 100%
rename from juneau-microservice/juneau-microservice-core/src/main/java/org/apache/juneau/microservice/resources/LogParser.java
rename to juneau-microservice/juneau-microservice/src/main/java/org/apache/juneau/microservice/resources/LogParser.java
diff --git a/juneau-microservice/juneau-microservice-core/src/main/java/org/apache/juneau/microservice/resources/LogsResource.java b/juneau-microservice/juneau-microservice/src/main/java/org/apache/juneau/microservice/resources/LogsResource.java
similarity index 100%
rename from juneau-microservice/juneau-microservice-core/src/main/java/org/apache/juneau/microservice/resources/LogsResource.java
rename to juneau-microservice/juneau-microservice/src/main/java/org/apache/juneau/microservice/resources/LogsResource.java
diff --git a/juneau-microservice/juneau-microservice-core/src/main/java/org/apache/juneau/microservice/resources/SampleRootResource.java b/juneau-microservice/juneau-microservice/src/main/java/org/apache/juneau/microservice/resources/SampleRootResource.java
similarity index 94%
rename from juneau-microservice/juneau-microservice-core/src/main/java/org/apache/juneau/microservice/resources/SampleRootResource.java
rename to juneau-microservice/juneau-microservice/src/main/java/org/apache/juneau/microservice/resources/SampleRootResource.java
index 9390ca274e..e9262bbbcf 100755
--- a/juneau-microservice/juneau-microservice-core/src/main/java/org/apache/juneau/microservice/resources/SampleRootResource.java
+++ b/juneau-microservice/juneau-microservice/src/main/java/org/apache/juneau/microservice/resources/SampleRootResource.java
@@ -23,7 +23,7 @@ import org.apache.juneau.rest.servlet.*;
* Sample root REST resource.
*
* <h5 class='section'>See Also:</h5><ul>
- * <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/JuneauMicroserviceCoreBasics">juneau-microservice-core Basics</a>
+ * <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/JuneauMicroserviceBasics">juneau-microservice Basics</a>
* </ul>
*
* @serial exclude
diff --git a/juneau-microservice/juneau-microservice-core/src/main/java/org/apache/juneau/microservice/resources/ShutdownResource.java b/juneau-microservice/juneau-microservice/src/main/java/org/apache/juneau/microservice/resources/ShutdownResource.java
similarity index 95%
rename from juneau-microservice/juneau-microservice-core/src/main/java/org/apache/juneau/microservice/resources/ShutdownResource.java
rename to juneau-microservice/juneau-microservice/src/main/java/org/apache/juneau/microservice/resources/ShutdownResource.java
index 327e52d155..b684e419fe 100755
--- a/juneau-microservice/juneau-microservice-core/src/main/java/org/apache/juneau/microservice/resources/ShutdownResource.java
+++ b/juneau-microservice/juneau-microservice/src/main/java/org/apache/juneau/microservice/resources/ShutdownResource.java
@@ -23,7 +23,7 @@ import org.apache.juneau.rest.servlet.*;
* Provides the capability to shut down this REST microservice through a REST call.
*
* <h5 class='section'>See Also:</h5><ul>
- * <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/JuneauMicroserviceCoreBasics">juneau-microservice-core Basics</a>
+ * <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/JuneauMicroserviceBasics">juneau-microservice Basics</a>
* </ul>
*
* @serial exclude
diff --git a/juneau-microservice/juneau-microservice-core/src/main/java/org/apache/juneau/microservice/resources/package-info.java b/juneau-microservice/juneau-microservice/src/main/java/org/apache/juneau/microservice/resources/package-info.java
similarity index 100%
rename from juneau-microservice/juneau-microservice-core/src/main/java/org/apache/juneau/microservice/resources/package-info.java
rename to juneau-microservice/juneau-microservice/src/main/java/org/apache/juneau/microservice/resources/package-info.java
diff --git a/juneau-microservice/juneau-microservice-core/src/main/resources/org/apache/juneau/microservice/Microservice.properties b/juneau-microservice/juneau-microservice/src/main/resources/org/apache/juneau/microservice/Microservice.properties
similarity index 100%
rename from juneau-microservice/juneau-microservice-core/src/main/resources/org/apache/juneau/microservice/Microservice.properties
rename to juneau-microservice/juneau-microservice/src/main/resources/org/apache/juneau/microservice/Microservice.properties
diff --git a/juneau-microservice/juneau-microservice-core/src/main/resources/org/apache/juneau/microservice/console/Messages.properties b/juneau-microservice/juneau-microservice/src/main/resources/org/apache/juneau/microservice/console/Messages.properties
similarity index 100%
rename from juneau-microservice/juneau-microservice-core/src/main/resources/org/apache/juneau/microservice/console/Messages.properties
rename to juneau-microservice/juneau-microservice/src/main/resources/org/apache/juneau/microservice/console/Messages.properties
diff --git a/juneau-microservice/juneau-my-jetty-microservice/pom.xml b/juneau-microservice/juneau-my-jetty-microservice/pom.xml
index 1ee41f7ef1..ded790f7ce 100644
--- a/juneau-microservice/juneau-my-jetty-microservice/pom.xml
+++ b/juneau-microservice/juneau-my-jetty-microservice/pom.xml
@@ -29,7 +29,7 @@
<parent>
<groupId>org.apache.juneau</groupId>
- <artifactId>juneau-microservice</artifactId>
+ <artifactId>juneau-microservice-parent</artifactId>
<version>9.5.0-SNAPSHOT</version>
</parent>
diff --git a/juneau-microservice/juneau-my-jetty-microservice/src/main/java/org/apache/juneau/microservice/jetty/template/App.java b/juneau-microservice/juneau-my-jetty-microservice/src/main/java/org/apache/juneau/microservice/jetty/template/App.java
index 99df365c0d..ab3a899e00 100644
--- a/juneau-microservice/juneau-my-jetty-microservice/src/main/java/org/apache/juneau/microservice/jetty/template/App.java
+++ b/juneau-microservice/juneau-my-jetty-microservice/src/main/java/org/apache/juneau/microservice/jetty/template/App.java
@@ -16,13 +16,17 @@
*/
package org.apache.juneau.microservice.jetty.template;
+import org.apache.juneau.commons.inject.*;
+import org.apache.juneau.microservice.*;
import org.apache.juneau.microservice.jetty.*;
+import jakarta.servlet.*;
+
/**
* Entry-point for your microservice.
*
* <p>
- * The {@link JettyMicroservice} class will locate the <code>my-microservice.cfg</code> file in the home directory and initialize
+ * The {@link Microservice} class will locate the <code>my-microservice.cfg</code> file in the home directory and initialize
* the resources and commands defined in that file.
*
* <h5 class='section'>See Also:</h5><ul>
@@ -39,14 +43,32 @@ public class App {
*/
public static void main(String[] args) throws Exception {
// @formatter:off
- JettyMicroservice
+ Microservice
.create()
.args(args)
- .servlet(RootResources.class)
+ .configurations(JettyConfiguration.class, AppConfig.class)
.build()
.start()
.startConsole()
.join();
// @formatter:on
}
-}
\ No newline at end of file
+
+ /**
+ * Application-specific configuration class contributing the top-level REST servlet.
+ */
+ @Configuration
+ public static class AppConfig {
+
+ /**
+ * Provides the top-level REST servlet, auto-mounted by {@link JettyServerComponent} at
+ * {@link org.apache.juneau.rest.annotation.Rest#path()}.
+ *
+ * @return The root servlet.
+ */
+ @Bean
+ public Servlet rootResources() {
+ return new RootResources();
+ }
+ }
+}
diff --git a/juneau-microservice/juneau-my-springboot-microservice/build-overlay/pom.xml.2 b/juneau-microservice/juneau-my-springboot-microservice/build-overlay/pom.xml.2
index 155295243b..d9fe3ef72e 100644
--- a/juneau-microservice/juneau-my-springboot-microservice/build-overlay/pom.xml.2
+++ b/juneau-microservice/juneau-my-springboot-microservice/build-overlay/pom.xml.2
@@ -63,7 +63,7 @@
</dependency>
<dependency>
<groupId>org.apache.juneau</groupId>
- <artifactId>juneau-microservice-core</artifactId>
+ <artifactId>juneau-microservice</artifactId>
<version>\${juneau.version}</version>
</dependency>
<dependency>
diff --git a/juneau-microservice/juneau-my-springboot-microservice/pom.xml b/juneau-microservice/juneau-my-springboot-microservice/pom.xml
index d7968e6089..a75353eea6 100644
--- a/juneau-microservice/juneau-my-springboot-microservice/pom.xml
+++ b/juneau-microservice/juneau-my-springboot-microservice/pom.xml
@@ -29,7 +29,7 @@
<parent>
<groupId>org.apache.juneau</groupId>
- <artifactId>juneau-microservice</artifactId>
+ <artifactId>juneau-microservice-parent</artifactId>
<version>9.5.0-SNAPSHOT</version>
</parent>
@@ -50,7 +50,7 @@
</dependency>
<dependency>
<groupId>org.apache.juneau</groupId>
- <artifactId>juneau-microservice-core</artifactId>
+ <artifactId>juneau-microservice</artifactId>
<version>${juneau.version}</version>
</dependency>
</dependencies>
diff --git a/juneau-microservice/pom.xml b/juneau-microservice/pom.xml
index f1d92163d6..db8ee3bafa 100644
--- a/juneau-microservice/pom.xml
+++ b/juneau-microservice/pom.xml
@@ -25,13 +25,13 @@
<version>9.5.0-SNAPSHOT</version>
</parent>
- <artifactId>juneau-microservice</artifactId>
+ <artifactId>juneau-microservice-parent</artifactId>
<packaging>pom</packaging>
<name>Apache Juneau Microservices</name>
<description>Apache Juneau Microservice APIs</description>
<modules>
- <module>juneau-microservice-core</module>
+ <module>juneau-microservice</module>
<module>juneau-microservice-jetty</module>
<module>juneau-my-jetty-microservice</module>
<module>juneau-my-springboot-microservice</module>
diff --git a/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestClient.java b/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestClient.java
index ad36d22617..11cd9646c4 100644
--- a/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestClient.java
+++ b/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestClient.java
@@ -6581,7 +6581,7 @@ public class RestClient extends MarshallingContextable implements HttpClient, Cl
try {
var req = request(method, uri, ne(content));
if (nn(headers))
- Json5Map.ofJson5(headers).forEach((k, v) -> req.header(stringHeader(k, s(v))));
+ Json5Map.ofText(headers).forEach((k, v) -> req.header(stringHeader(k, s(v))));
if (ne(content))
req.contentString(content);
return req;
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestContext.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestContext.java
index 61f9406fdf..cfd6c2485d 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestContext.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestContext.java
@@ -1750,11 +1750,6 @@ public class RestContext extends Context {
* Called during servlet destruction to invoke all {@link RestDestroy} methods.
*/
public void destroy() {
- // @RestDestroy hooks first, then children (recursive cleanup), then close this context's bean store.
- // Destroying children before closing the bean store is required: getRestChildren() reads from the bean
- // store and BasicBeanStore.getBean() rejects calls after close(), so the previous post-close lookup was
- // a latent bug that only surfaced when destroy() was invoked outside the JVM-shutdown happy path
- // (e.g. dynamic RestChildren.removeChild — see TODO-33).
for (var x : destroyInvokerPair.get().invokers) {
try {
x.invoke(beanStore, getResource());
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestDeleteAnnotation.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestDeleteAnnotation.java
index 962dae4c1a..96c18e31b0 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestDeleteAnnotation.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestDeleteAnnotation.java
@@ -326,7 +326,7 @@ public class RestDeleteAnnotation {
}
- // Phase D-2 (TODO-16, 2026-04-19): RestOpContextApply removed entirely. All previously-applied
+ // Phase D-2 (work item 16, 2026-04-19): RestOpContextApply removed entirely. All previously-applied
// settings are now resolved via direct annotation walking on the corresponding {@code findXxx()}
// memoizers in {@link org.apache.juneau.rest.RestOpContext}; the {@code @ContextApply} reference
// on {@code @RestDelete} has been dropped.
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestGetAnnotation.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestGetAnnotation.java
index 6baa5b2500..b083463e1b 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestGetAnnotation.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestGetAnnotation.java
@@ -366,7 +366,7 @@ public class RestGetAnnotation {
}
- // Phase D-2 (TODO-16, 2026-04-19): RestOpContextApply removed entirely. All previously-applied
+ // Phase D-2 (work item 16, 2026-04-19): RestOpContextApply removed entirely. All previously-applied
// settings (serializers/encoders/converters/guards/matchers/clientVersion/headers/attributes/path
// etc.) are now resolved via direct annotation walking on the corresponding {@code findXxx()}
// memoizers in {@link org.apache.juneau.rest.RestOpContext}; the {@code @ContextApply} reference
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestInit.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestInit.java
index dce6698d41..5955bcfddb 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestInit.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestInit.java
@@ -45,7 +45,7 @@ import jakarta.servlet.*;
*
* <p>
* <b>Note (9.5):</b> two related Builder-injection protocols have been removed in this release. They had zero
- * real-world callers across the codebase before deletion (TODO-16 Phase C-3):
+ * real-world callers across the codebase before deletion (work item 16 Phase C-3):
* <ul>
* <li><b>Per-operation:</b> {@code @RestInit public void init(RestOpContext.Builder b)} (invoked once per
* <code>@RestOp</code>-annotated method) — replaced by declarative <code>@RestOp(...)</code> attributes,
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestOpAnnotation.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestOpAnnotation.java
index 09340d05cb..18824f32b7 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestOpAnnotation.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestOpAnnotation.java
@@ -440,7 +440,7 @@ public class RestOpAnnotation {
}
- // Phase D-2 (TODO-16, 2026-04-19): RestOpContextApply removed entirely. All previously-applied
+ // Phase D-2 (work item 16, 2026-04-19): RestOpContextApply removed entirely. All previously-applied
// settings are now resolved via direct annotation walking on the corresponding {@code findXxx()}
// memoizers in {@link org.apache.juneau.rest.RestOpContext}; the {@code @ContextApply} reference
// on {@code @RestOp} has been dropped.
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestOptionsAnnotation.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestOptionsAnnotation.java
index b0f48aa24a..dda49c392d 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestOptionsAnnotation.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestOptionsAnnotation.java
@@ -366,7 +366,7 @@ public class RestOptionsAnnotation {
}
- // Phase D-2 (TODO-16, 2026-04-19): RestOpContextApply removed entirely. All previously-applied
+ // Phase D-2 (work item 16, 2026-04-19): RestOpContextApply removed entirely. All previously-applied
// settings are now resolved via direct annotation walking on the corresponding {@code findXxx()}
// memoizers in {@link org.apache.juneau.rest.RestOpContext}; the {@code @ContextApply} reference
// on {@code @RestOptions} has been dropped.
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestPatchAnnotation.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestPatchAnnotation.java
index f413203609..b746d90027 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestPatchAnnotation.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestPatchAnnotation.java
@@ -426,7 +426,7 @@ public class RestPatchAnnotation {
}
- // Phase D-2 (TODO-16, 2026-04-19): RestOpContextApply removed entirely. All previously-applied
+ // Phase D-2 (work item 16, 2026-04-19): RestOpContextApply removed entirely. All previously-applied
// settings are now resolved via direct annotation walking on the corresponding {@code findXxx()}
// memoizers in {@link org.apache.juneau.rest.RestOpContext}; the {@code @ContextApply} reference
// on {@code @RestPatch} has been dropped.
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestPostAnnotation.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestPostAnnotation.java
index 5bfaef7ce8..de4ae6a671 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestPostAnnotation.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestPostAnnotation.java
@@ -426,7 +426,7 @@ public class RestPostAnnotation {
}
- // Phase D-2 (TODO-16, 2026-04-19): RestOpContextApply removed entirely. All previously-applied
+ // Phase D-2 (work item 16, 2026-04-19): RestOpContextApply removed entirely. All previously-applied
// settings are now resolved via direct annotation walking on the corresponding {@code findXxx()}
// memoizers in {@link org.apache.juneau.rest.RestOpContext}; the {@code @ContextApply} reference
// on {@code @RestPost} has been dropped.
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestPutAnnotation.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestPutAnnotation.java
index 9854a9a815..87d971e456 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestPutAnnotation.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestPutAnnotation.java
@@ -426,7 +426,7 @@ public class RestPutAnnotation {
}
- // Phase D-2 (TODO-16, 2026-04-19): RestOpContextApply removed entirely. All previously-applied
+ // Phase D-2 (work item 16, 2026-04-19): RestOpContextApply removed entirely. All previously-applied
// settings are now resolved via direct annotation walking on the corresponding {@code findXxx()}
// memoizers in {@link org.apache.juneau.rest.RestOpContext}; the {@code @ContextApply} reference
// on {@code @RestPut} has been dropped.
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/processor/PlainTextPojoProcessor.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/processor/PlainTextPojoProcessor.java
index 51790a63be..e26bb1bbd1 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/processor/PlainTextPojoProcessor.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/processor/PlainTextPojoProcessor.java
@@ -57,10 +57,6 @@ public class PlainTextPojoProcessor implements ResponseProcessor {
if (o == null) {
w.append("null");
} else if (o instanceof Map || o instanceof Collection || o.getClass().isArray()) {
- // Historical contract: when no serializer matched and the response is a Map/Collection/array,
- // render it as JSON5 so callers that asserted on JsonMap/JsonList.toString() output before the
- // TODO-34 Phase C retargeting (which switched JsonMap/JsonList toString to strict JSON)
- // continue to see the same plain-text body.
w.append(Json5.of(o));
} else {
w.append(req.getMarshallingSession().getClassMetaForObject(o).toString(o));
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/swagger/BasicSwaggerProviderSession.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/swagger/BasicSwaggerProviderSession.java
index 4daa988677..6d03fee97d 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/swagger/BasicSwaggerProviderSession.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/swagger/BasicSwaggerProviderSession.java
@@ -1025,7 +1025,7 @@ public class BasicSwaggerProviderSession {
s = resolve(s);
if (! isProbablyJsonArray(s, true))
s = "[" + s + "]";
- return Json5List.ofJson5(s);
+ return Json5List.ofText(s);
} catch (ParseException e) {
throw new SwaggerException(e, "Malformed swagger JSON array encountered in " + location + ".", locationArgs);
}
@@ -1058,7 +1058,7 @@ public class BasicSwaggerProviderSession {
return Json5Map.of(SWAGGER_ignore, true);
if (! isProbablyJsonObject(o2, true))
o2 = "{" + o2 + "}";
- return Json5Map.ofJson5(o2);
+ return Json5Map.ofText(o2);
}
if (o instanceof Json5Map o2)
return o2;
diff --git a/juneau-sc/juneau-sc-server/src/main/java/org/apache/juneau/server/config/App.java b/juneau-sc/juneau-sc-server/src/main/java/org/apache/juneau/server/config/App.java
index 29782c9b37..47b7135f91 100644
--- a/juneau-sc/juneau-sc-server/src/main/java/org/apache/juneau/server/config/App.java
+++ b/juneau-sc/juneau-sc-server/src/main/java/org/apache/juneau/server/config/App.java
@@ -16,9 +16,13 @@
*/
package org.apache.juneau.server.config;
+import org.apache.juneau.commons.inject.*;
+import org.apache.juneau.microservice.*;
import org.apache.juneau.microservice.jetty.*;
import org.apache.juneau.server.config.rest.*;
+import jakarta.servlet.*;
+
/**
* Entry-point class.
*/
@@ -32,16 +36,32 @@ public class App {
*/
public static void main(String[] args) throws Exception {
// @formatter:off
- JettyMicroservice
- .create()
- .args(args)
- .servlet(LoadConfigResource.class)
- .build()
- .start()
- .startConsole()
- .join();
+ Microservice
+ .create()
+ .args(args)
+ .configurations(JettyConfiguration.class, AppConfig.class)
+ .build()
+ .start()
+ .startConsole()
+ .join();
// @formatter:on
}
+
+ /**
+ * Application-specific configuration class contributing the {@link LoadConfigResource} servlet.
+ */
+ @Configuration
+ public static class AppConfig {
+
+ /**
+ * Provides the {@link LoadConfigResource} REST servlet, auto-mounted by {@link JettyServerComponent} at
+ * {@link org.apache.juneau.rest.annotation.Rest#path()}.
+ *
+ * @return The servlet.
+ */
+ @Bean
+ public Servlet loadConfigResource() {
+ return new LoadConfigResource();
+ }
+ }
}
-// ter o xml do jetty padrão na aplicação
-// posibilitar a remoção do bin.xml
diff --git a/juneau-shaded/juneau-shaded-all/pom.xml b/juneau-shaded/juneau-shaded-all/pom.xml
index 3d1bf176db..68d3264f43 100644
--- a/juneau-shaded/juneau-shaded-all/pom.xml
+++ b/juneau-shaded/juneau-shaded-all/pom.xml
@@ -95,7 +95,7 @@
<!-- Microservice modules -->
<dependency>
<groupId>org.apache.juneau</groupId>
- <artifactId>juneau-microservice-core</artifactId>
+ <artifactId>juneau-microservice</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
diff --git a/juneau-utest/pom.xml b/juneau-utest/pom.xml
index 578748c105..42be9b65ca 100644
--- a/juneau-utest/pom.xml
+++ b/juneau-utest/pom.xml
@@ -150,7 +150,7 @@
</dependency>
<dependency>
<groupId>org.apache.juneau</groupId>
- <artifactId>juneau-microservice-core</artifactId>
+ <artifactId>juneau-microservice</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
diff --git a/juneau-utest/src/test/java/org/apache/juneau/BeanMap_Test.java b/juneau-utest/src/test/java/org/apache/juneau/BeanMap_Test.java
index 76fcd94c32..8599808d2c 100755
--- a/juneau-utest/src/test/java/org/apache/juneau/BeanMap_Test.java
+++ b/juneau-utest/src/test/java/org/apache/juneau/BeanMap_Test.java
@@ -223,11 +223,11 @@ class BeanMap_Test extends TestBase {
var m = bc.toBeanMap(t);
// Non-initialized list fields.
- m.put("l1", JsonList.ofJson("[1,2,3]"));
- m.put("al1", JsonList.ofJson("[1,2,3]"));
- m.put("ll1", JsonList.ofJson("[1,2,3]"));
- m.put("c1", JsonList.ofJson("[1,2,3]"));
- m.put("jl1", JsonList.ofJson("[1,2,3]"));
+ m.put("l1", JsonList.ofText("[1,2,3]"));
+ m.put("al1", JsonList.ofText("[1,2,3]"));
+ m.put("ll1", JsonList.ofText("[1,2,3]"));
+ m.put("c1", JsonList.ofText("[1,2,3]"));
+ m.put("jl1", JsonList.ofText("[1,2,3]"));
// al1 should be initialized with an ArrayList, since it's not a superclass of JsonList.
// The rest are proper superclasses of JsonList.
@@ -238,10 +238,10 @@ class BeanMap_Test extends TestBase {
);
// Non-initialized map fields.
- m.put("m1", JsonMap.ofJson("{\"foo\":\"bar\"}"));
- m.put("hm1", JsonMap.ofJson("{\"foo\":\"bar\"}"));
- m.put("jm1", JsonMap.ofJson("{\"foo\":\"bar\"}"));
- m.put("tm1", JsonMap.ofJson("{\"foo\":\"bar\"}"));
+ m.put("m1", JsonMap.ofText("{\"foo\":\"bar\"}"));
+ m.put("hm1", JsonMap.ofText("{\"foo\":\"bar\"}"));
+ m.put("jm1", JsonMap.ofText("{\"foo\":\"bar\"}"));
+ m.put("tm1", JsonMap.ofText("{\"foo\":\"bar\"}"));
// tm1 should be initialized with TreeMap, since it's not a superclass of JsonMap.
// The rest are proper superclasses of JsonMap
@@ -252,15 +252,15 @@ class BeanMap_Test extends TestBase {
);
// Initialized fields should reuse existing field value.
- m.put("l2", JsonList.ofJson("[1,2,3]"));
- m.put("al2", JsonList.ofJson("[1,2,3]"));
- m.put("ll2", JsonList.ofJson("[1,2,3]"));
- m.put("c2", JsonList.ofJson("[1,2,3]"));
- m.put("m2", JsonMap.ofJson("{\"foo\":\"bar\"}"));
- m.put("hm2", JsonMap.ofJson("{\"foo\":\"bar\"}"));
- m.put("tm2", JsonMap.ofJson("{\"foo\":\"bar\"}"));
- m.put("jm2", JsonMap.ofJson("{\"foo\":\"bar\"}"));
- m.put("jl2", JsonList.ofJson("[1,2,3]"));
+ m.put("l2", JsonList.ofText("[1,2,3]"));
+ m.put("al2", JsonList.ofText("[1,2,3]"));
+ m.put("ll2", JsonList.ofText("[1,2,3]"));
+ m.put("c2", JsonList.ofText("[1,2,3]"));
+ m.put("m2", JsonMap.ofText("{\"foo\":\"bar\"}"));
+ m.put("hm2", JsonMap.ofText("{\"foo\":\"bar\"}"));
+ m.put("tm2", JsonMap.ofText("{\"foo\":\"bar\"}"));
+ m.put("jm2", JsonMap.ofText("{\"foo\":\"bar\"}"));
+ m.put("jl2", JsonList.ofText("[1,2,3]"));
assertBean(
m,
@@ -298,11 +298,11 @@ class BeanMap_Test extends TestBase {
var m = bc.toBeanMap(t);
// Non-initialized list fields.
- m.put("l1", JsonList.ofJson("[1,2,3]"));
- m.put("al1", JsonList.ofJson("[1,2,3]"));
- m.put("ll1", JsonList.ofJson("[1,2,3]"));
- m.put("c1", JsonList.ofJson("[1,2,3]"));
- m.put("jl1", JsonList.ofJson("[1,2,3]"));
+ m.put("l1", JsonList.ofText("[1,2,3]"));
+ m.put("al1", JsonList.ofText("[1,2,3]"));
+ m.put("ll1", JsonList.ofText("[1,2,3]"));
+ m.put("c1", JsonList.ofText("[1,2,3]"));
+ m.put("jl1", JsonList.ofText("[1,2,3]"));
// al1 should be initialized with an ArrayList, since it's not a superclass of JsonList.
// The rest are proper superclasses of JsonList.
@@ -313,10 +313,10 @@ class BeanMap_Test extends TestBase {
);
// Non-initialized map fields.
- m.put("m1", JsonMap.ofJson("{\"foo\":\"bar\"}"));
- m.put("hm1", JsonMap.ofJson("{\"foo\":\"bar\"}"));
- m.put("jm1", JsonMap.ofJson("{\"foo\":\"bar\"}"));
- m.put("tm1", JsonMap.ofJson("{\"foo\":\"bar\"}"));
+ m.put("m1", JsonMap.ofText("{\"foo\":\"bar\"}"));
+ m.put("hm1", JsonMap.ofText("{\"foo\":\"bar\"}"));
+ m.put("jm1", JsonMap.ofText("{\"foo\":\"bar\"}"));
+ m.put("tm1", JsonMap.ofText("{\"foo\":\"bar\"}"));
// tm1 should be initialized with TreeMap, since it's not a superclass of JsonMap.
// The rest are proper superclasses of JsonMap
@@ -327,15 +327,15 @@ class BeanMap_Test extends TestBase {
);
// Initialized fields should reuse existing field value.
- m.put("l2", JsonList.ofJson("[1,2,3]"));
- m.put("al2", JsonList.ofJson("[1,2,3]"));
- m.put("ll2", JsonList.ofJson("[1,2,3]"));
- m.put("c2", JsonList.ofJson("[1,2,3]"));
- m.put("m2", JsonMap.ofJson("{\"foo\":\"bar\"}"));
- m.put("hm2", JsonMap.ofJson("{\"foo\":\"bar\"}"));
- m.put("tm2", JsonMap.ofJson("{\"foo\":\"bar\"}"));
- m.put("jm2", JsonMap.ofJson("{\"foo\":\"bar\"}"));
- m.put("jl2", JsonList.ofJson("[1,2,3]"));
+ m.put("l2", JsonList.ofText("[1,2,3]"));
+ m.put("al2", JsonList.ofText("[1,2,3]"));
+ m.put("ll2", JsonList.ofText("[1,2,3]"));
+ m.put("c2", JsonList.ofText("[1,2,3]"));
+ m.put("m2", JsonMap.ofText("{\"foo\":\"bar\"}"));
+ m.put("hm2", JsonMap.ofText("{\"foo\":\"bar\"}"));
+ m.put("tm2", JsonMap.ofText("{\"foo\":\"bar\"}"));
+ m.put("jm2", JsonMap.ofText("{\"foo\":\"bar\"}"));
+ m.put("jl2", JsonList.ofText("[1,2,3]"));
assertBean(
m,
@@ -424,7 +424,7 @@ class BeanMap_Test extends TestBase {
@Test void a05_arrayProperties() {
var t = new D1();
var m = bc.toBeanMap(t);
- m.put("b", JsonMap.ofJson("{\"s\":\"foo\"}"));
+ m.put("b", JsonMap.ofText("{\"s\":\"foo\"}"));
assertNotNull(t.b);
assertEquals("foo", t.b.s);
@@ -467,7 +467,7 @@ class BeanMap_Test extends TestBase {
@Test void a06_arrayProperties_usingConfig() {
var t = new D1c();
var m = bc.toBeanMap(t);
- m.put("b", JsonMap.ofJson("{\"s\":\"foo\"}"));
+ m.put("b", JsonMap.ofText("{\"s\":\"foo\"}"));
assertNotNull(t.b);
assertBean(t.b, "s", "foo");
@@ -517,13 +517,13 @@ class BeanMap_Test extends TestBase {
@Test void a07_arrayPropertiesInJsonList() {
var t = new E();
var m = bc.toBeanMap(t);
- m.put("s", JsonList.ofJson("[\"foo\"]"));
- m.put("s2", JsonList.ofJson("[[\"foo\"]]"));
- m.put("i", JsonList.ofJson("[1,2,3]"));
- m.put("i2", JsonList.ofJson("[[1,2,3],[4,5,6]]"));
+ m.put("s", JsonList.ofText("[\"foo\"]"));
+ m.put("s2", JsonList.ofText("[[\"foo\"]]"));
+ m.put("i", JsonList.ofText("[1,2,3]"));
+ m.put("i2", JsonList.ofText("[[1,2,3],[4,5,6]]"));
assertEquals("{s:['foo'],s2:[['foo']],i:[1,2,3],i2:[[1,2,3],[4,5,6]]}", Json5Serializer.DEFAULT.serialize(t));
- m.put("i", JsonList.ofJson("[null,null,null]"));
- m.put("i2", JsonList.ofJson("[[null,null,null],[null,null,null]]"));
+ m.put("i", JsonList.ofText("[null,null,null]"));
+ m.put("i2", JsonList.ofText("[[null,null,null],[null,null,null]]"));
assertEquals("{s:['foo'],s2:[['foo']],i:[0,0,0],i2:[[0,0,0],[0,0,0]]}", Json5Serializer.DEFAULT.serialize(t));
}
diff --git a/juneau-utest/src/test/java/org/apache/juneau/DataConversion_Test.java b/juneau-utest/src/test/java/org/apache/juneau/DataConversion_Test.java
index 1f5b0a7059..363d650506 100755
--- a/juneau-utest/src/test/java/org/apache/juneau/DataConversion_Test.java
+++ b/juneau-utest/src/test/java/org/apache/juneau/DataConversion_Test.java
@@ -71,7 +71,7 @@ class DataConversion_Test extends TestBase {
assertEquals("{}", m.getString("x"));
// *** JsonMap ***
- m.put("x", Json5Map.ofJson5("{foo:123}"));
+ m.put("x", Json5Map.ofText("{foo:123}"));
assertEquals("{foo:123}", m.getString("x"));
// *** Collection ***
@@ -81,7 +81,7 @@ class DataConversion_Test extends TestBase {
assertEquals("[123]", m.getString("x"));
// *** JsonList ***
- m.put("x", JsonList.ofJson("[123]"));
+ m.put("x", JsonList.ofText("[123]"));
assertEquals("[123]", m.getString("x"));
assertSize(1, m.getList("x"));
diff --git a/juneau-utest/src/test/java/org/apache/juneau/JsonList_Test.java b/juneau-utest/src/test/java/org/apache/juneau/JsonList_Test.java
index b2fdc0fdd2..d375b74c79 100755
--- a/juneau-utest/src/test/java/org/apache/juneau/JsonList_Test.java
+++ b/juneau-utest/src/test/java/org/apache/juneau/JsonList_Test.java
@@ -92,7 +92,7 @@ class JsonList_Test extends TestBase {
r = l.getAt("0/foo", String.class);
assertEquals("bing", r);
- l.postAt("", Json5Map.ofJson5("{a:'b'}"));
+ l.postAt("", Json5Map.ofText("{a:'b'}"));
r = l.getAt("2/a", String.class);
assertEquals("b", r);
diff --git a/juneau-utest/src/test/java/org/apache/juneau/JsonMap_Test.java b/juneau-utest/src/test/java/org/apache/juneau/JsonMap_Test.java
index 9241c16c86..33d6812a0f 100755
--- a/juneau-utest/src/test/java/org/apache/juneau/JsonMap_Test.java
+++ b/juneau-utest/src/test/java/org/apache/juneau/JsonMap_Test.java
@@ -37,207 +37,207 @@ class JsonMap_Test extends TestBase {
@Test void a01_basic() throws Exception {
var in = "{A:'asdf'}";
- checkStep(1, in, Json5Map.ofJson5(in).getString("A"), "asdf");
+ checkStep(1, in, Json5Map.ofText(in).getString("A"), "asdf");
in = "{A:{B:'asdf'}}";
- checkStep(2, in, getDeepString(Json5Map.ofJson5(in), "A/B"), "asdf");
- checkStep(3, in, Json5Map.ofJson5(in).getString("A"), "{B:'asdf'}");
+ checkStep(2, in, getDeepString(Json5Map.ofText(in), "A/B"), "asdf");
+ checkStep(3, in, Json5Map.ofText(in).getString("A"), "{B:'asdf'}");
in = "{A:{B:'asdf'+\"asdf\"}}";
- checkStep(4, in, getDeepString(Json5Map.ofJson5(in), "A/B"), "asdfasdf");
- checkStep(5, in, Json5Map.ofJson5(in).getString("A"), "{B:'asdfasdf'}");
+ checkStep(4, in, getDeepString(Json5Map.ofText(in), "A/B"), "asdfasdf");
+ checkStep(5, in, Json5Map.ofText(in).getString("A"), "{B:'asdfasdf'}");
in = "{A:{B:'asdf' + \n\t \"asdf\"}}";
- checkStep(6, in, getDeepString(Json5Map.ofJson5(in), "A/B"), "asdfasdf");
- checkStep(7, in, Json5Map.ofJson5(in).getString("A"), "{B:'asdfasdf'}");
+ checkStep(6, in, getDeepString(Json5Map.ofText(in), "A/B"), "asdfasdf");
+ checkStep(7, in, Json5Map.ofText(in).getString("A"), "{B:'asdfasdf'}");
in = "{A:{B:'asdf\"asdf', C:\"asdf'asdf\", D : \"asdf\\\"asdf\", E: 'asdf\\\'asdf', F:\"asdf\\\'asdf\", G:'asdf\\\"asdf'}}";
- checkStep(8, in, getDeepString(Json5Map.ofJson5(in), "A/B"), "asdf\"asdf");
- checkStep(9, in, getDeepString(Json5Map.ofJson5(in), "A/C"), "asdf'asdf");
- checkStep(10, in, getDeepString(Json5Map.ofJson5(in), "A/D"), "asdf\"asdf");
- checkStep(11, in, getDeepString(Json5Map.ofJson5(in), "A/E"), "asdf'asdf");
- checkStep(12, in, getDeepString(Json5Map.ofJson5(in), "A/F"), "asdf'asdf");
- checkStep(13, in, getDeepString(Json5Map.ofJson5(in), "A/G"), "asdf\"asdf");
+ checkStep(8, in, getDeepString(Json5Map.ofText(in), "A/B"), "asdf\"asdf");
+ checkStep(9, in, getDeepString(Json5Map.ofText(in), "A/C"), "asdf'asdf");
+ checkStep(10, in, getDeepString(Json5Map.ofText(in), "A/D"), "asdf\"asdf");
+ checkStep(11, in, getDeepString(Json5Map.ofText(in), "A/E"), "asdf'asdf");
+ checkStep(12, in, getDeepString(Json5Map.ofText(in), "A/F"), "asdf'asdf");
+ checkStep(13, in, getDeepString(Json5Map.ofText(in), "A/G"), "asdf\"asdf");
in = "{A:123, B: 123}";
- checkStep(16, in, Json5Map.ofJson5(in).getInt("A").toString(), "123");
- checkStep(17, in, Json5Map.ofJson5(in).getInt("B").toString(), "123");
+ checkStep(16, in, Json5Map.ofText(in).getInt("A").toString(), "123");
+ checkStep(17, in, Json5Map.ofText(in).getInt("B").toString(), "123");
in = "{A:true, B: true, C:false, D: false}";
- checkStep(18, in, Json5Map.ofJson5(in).getBoolean("A").toString(), "true");
- checkStep(19, in, Json5Map.ofJson5(in).getBoolean("B").toString(), "true");
- checkStep(20, in, Json5Map.ofJson5(in).getBoolean("C").toString(), "false");
- checkStep(21, in, Json5Map.ofJson5(in).getBoolean("D").toString(), "false");
+ checkStep(18, in, Json5Map.ofText(in).getBoolean("A").toString(), "true");
+ checkStep(19, in, Json5Map.ofText(in).getBoolean("B").toString(), "true");
+ checkStep(20, in, Json5Map.ofText(in).getBoolean("C").toString(), "false");
+ checkStep(21, in, Json5Map.ofText(in).getBoolean("D").toString(), "false");
in = "{'AAA':{\"BBB\":\"CCC\",'DDD':false}}";
- checkStep(31, in, getDeepString(Json5Map.ofJson5(in), "AAA/BBB"), "CCC");
- checkStep(32, in, getDeepBoolean(Json5Map.ofJson5(in), "AAA/DDD").toString(), "false");
+ checkStep(31, in, getDeepString(Json5Map.ofText(in), "AAA/BBB"), "CCC");
+ checkStep(32, in, getDeepBoolean(Json5Map.ofText(in), "AAA/DDD").toString(), "false");
in = " \n\n\t { 'AAA' : { \"BBB\" : \"CCC\" , 'DDD' : false } } \n\t";
- checkStep(33, in, getDeepString(Json5Map.ofJson5(in), "AAA/BBB"), "CCC");
- checkStep(34, in, getDeepBoolean(Json5Map.ofJson5(in), "AAA/DDD").toString(), "false");
+ checkStep(33, in, getDeepString(Json5Map.ofText(in), "AAA/BBB"), "CCC");
+ checkStep(34, in, getDeepBoolean(Json5Map.ofText(in), "AAA/DDD").toString(), "false");
in = "/*x*/{A:'B','C':1,\"E\":[1,2,3],G:['g1','g2','g3']}";
- checkStep(100, in, Json5Map.ofJson5(in).getString("A"), "B");
+ checkStep(100, in, Json5Map.ofText(in).getString("A"), "B");
in = "{/*x*/A:'B','C':1,\"E\":[1,2,3],G:['g1','g2','g3']}";
- checkStep(101, in, Json5Map.ofJson5(in).getString("A"), "B");
+ checkStep(101, in, Json5Map.ofText(in).getString("A"), "B");
in = "{A/*x*/:'B','C':1,\"E\":[1,2,3],G:['g1','g2','g3']}";
- checkStep(102, in, Json5Map.ofJson5(in).getString("A"), "B");
+ checkStep(102, in, Json5Map.ofText(in).getString("A"), "B");
in = "{A:/*x*/'B','C':1,\"E\":[1,2,3],G:['g1','g2','g3']}";
- checkStep(103, in, Json5Map.ofJson5(in).getString("A"), "B");
+ checkStep(103, in, Json5Map.ofText(in).getString("A"), "B");
in = "{A:'/*x*/B','C':1,\"E\":[1,2,3],G:['g1','g2','g3']}";
- checkStep(104, in, Json5Map.ofJson5(in).getString("A"), "/*x*/B");
+ checkStep(104, in, Json5Map.ofText(in).getString("A"), "/*x*/B");
in = "{A:'B/*x*/','C':1,\"E\":[1,2,3],G:['g1','g2','g3']}";
- checkStep(105, in, Json5Map.ofJson5(in).getString("A"), "B/*x*/");
+ checkStep(105, in, Json5Map.ofText(in).getString("A"), "B/*x*/");
in = "{A:'B'/*x*/,'C':1,\"E\":[1,2,3],G:['g1','g2','g3']}";
- checkStep(106, in, Json5Map.ofJson5(in).getString("A"), "B");
+ checkStep(106, in, Json5Map.ofText(in).getString("A"), "B");
in = "{A:'B',/*x*/'C':1,\"E\":[1,2,3],G:['g1','g2','g3']}";
- checkStep(107, in, Json5Map.ofJson5(in).getString("C"), "1");
+ checkStep(107, in, Json5Map.ofText(in).getString("C"), "1");
in = "{A:'B','C':/*x*/1,\"E\":[1,2,3],G:['g1','g2','g3']}";
- checkStep(108, in, Json5Map.ofJson5(in).getString("C"), "1");
+ checkStep(108, in, Json5Map.ofText(in).getString("C"), "1");
in = "{A:'B','C':1/*x*/,\"E\":[1,2,3],G:['g1','g2','g3']}";
- checkStep(109, in, Json5Map.ofJson5(in).getString("C"), "1");
+ checkStep(109, in, Json5Map.ofText(in).getString("C"), "1");
in = "{A:'B','C':1,/*x*/\"E\":[1,2,3],G:['g1','g2','g3']}";
- checkStep(110, in, Json5Map.ofJson5(in).getList("E").getString(0), "1");
+ checkStep(110, in, Json5Map.ofText(in).getList("E").getString(0), "1");
in = "{A:'B','C':1,\"/*x*/E\":[1,2,3],G:['g1','g2','g3']}";
- checkStep(111, in, Json5Map.ofJson5(in).getList("/*x*/E").getString(0), "1");
+ checkStep(111, in, Json5Map.ofText(in).getList("/*x*/E").getString(0), "1");
in = "{A:'B','C':1,\"E/*x*/\":[1,2,3],G:['g1','g2','g3']}";
- checkStep(112, in, Json5Map.ofJson5(in).getList("E/*x*/").getString(0), "1");
+ checkStep(112, in, Json5Map.ofText(in).getList("E/*x*/").getString(0), "1");
in = "{A:'B','C':1,\"E\"/*x*/:[1,2,3],G:['g1','g2','g3']}";
- checkStep(113, in, Json5Map.ofJson5(in).getList("E").getString(0), "1");
+ checkStep(113, in, Json5Map.ofText(in).getList("E").getString(0), "1");
in = "{A:'B','C':1,\"E\":/*x*/[1,2,3],G:['g1','g2','g3']}";
- checkStep(114, in, Json5Map.ofJson5(in).getList("E").getString(0), "1");
+ checkStep(114, in, Json5Map.ofText(in).getList("E").getString(0), "1");
in = "{A:'B','C':1,\"E\":[/*x*/1,2,3],G:['g1','g2','g3']}";
- checkStep(115, in, Json5Map.ofJson5(in).getList("E").getString(0), "1");
+ checkStep(115, in, Json5Map.ofText(in).getList("E").getString(0), "1");
in = "{A:'B','C':1,\"E\":[1/*x*/,2,3],G:['g1','g2','g3']}";
- checkStep(116, in, Json5Map.ofJson5(in).getList("E").getString(0), "1");
+ checkStep(116, in, Json5Map.ofText(in).getList("E").getString(0), "1");
in = "{A:'B','C':1,\"E\":[1,/*x*/2,3],G:['g1','g2','g3']}";
- checkStep(117, in, Json5Map.ofJson5(in).getList("E").getString(1), "2");
+ checkStep(117, in, Json5Map.ofText(in).getList("E").getString(1), "2");
in = "{A:'B','C':1,\"E\":[1,2/*x*/,3],G:['g1','g2','g3']}";
- checkStep(118, in, Json5Map.ofJson5(in).getList("E").getString(1), "2");
+ checkStep(118, in, Json5Map.ofText(in).getList("E").getString(1), "2");
in = "{A:'B','C':1,\"E\":[1,2,/*x*/3],G:['g1','g2','g3']}";
- checkStep(119, in, Json5Map.ofJson5(in).getList("E").getString(2), "3");
+ checkStep(119, in, Json5Map.ofText(in).getList("E").getString(2), "3");
in = "{A:'B','C':1,\"E\":[1,2,3]/*x*/,G:['g1','g2','g3']}";
- checkStep(120, in, Json5Map.ofJson5(in).getList("E").getString(2), "3");
+ checkStep(120, in, Json5Map.ofText(in).getList("E").getString(2), "3");
in = "{A:'B','C':1,\"E\":[1,2,3],/*x*/G:['g1','g2','g3']}";
- checkStep(121, in, Json5Map.ofJson5(in).getList("G").getString(0), "g1");
+ checkStep(121, in, Json5Map.ofText(in).getList("G").getString(0), "g1");
in = "{A:'B','C':1,\"E\":[1,2,3],G:[/*x*/'g1','g2','g3']}";
- checkStep(122, in, Json5Map.ofJson5(in).getList("G").getString(0), "g1");
+ checkStep(122, in, Json5Map.ofText(in).getList("G").getString(0), "g1");
in = "{A:'B','C':1,\"E\":[1,2,3],G:['/*x*/g1','g2','g3']}";
- checkStep(123, in, Json5Map.ofJson5(in).getList("G").getString(0), "/*x*/g1");
+ checkStep(123, in, Json5Map.ofText(in).getList("G").getString(0), "/*x*/g1");
in = "{A:'B','C':1,\"E\":[1,2,3],G:['g1'/*x*/,'g2','g3']}";
- checkStep(124, in, Json5Map.ofJson5(in).getList("G").getString(0), "g1");
+ checkStep(124, in, Json5Map.ofText(in).getList("G").getString(0), "g1");
in = "{A:'B','C':1,\"E\":[1,2,3],G:['g1',/*x*/'g2','g3']}";
- checkStep(125, in, Json5Map.ofJson5(in).getList("G").getString(1), "g2");
+ checkStep(125, in, Json5Map.ofText(in).getList("G").getString(1), "g2");
in = "{A:'B','C':1,\"E\":[1,2,3],G:['g1','g2'/*x*/,'g3']}";
- checkStep(126, in, Json5Map.ofJson5(in).getList("G").getString(1), "g2");
+ checkStep(126, in, Json5Map.ofText(in).getList("G").getString(1), "g2");
in = "{A:'B','C':1,\"E\":[1,2,3],G:['g1','g2',/*x*/'g3']}";
- checkStep(127, in, Json5Map.ofJson5(in).getList("G").getString(2), "g3");
+ checkStep(127, in, Json5Map.ofText(in).getList("G").getString(2), "g3");
in = "{A:'B','C':1,\"E\":[1,2,3],G:['g1','g2','g3'/*x*/]}";
- checkStep(128, in, Json5Map.ofJson5(in).getList("G").getString(2), "g3");
+ checkStep(128, in, Json5Map.ofText(in).getList("G").getString(2), "g3");
in = "{A:'B','C':1,\"E\":[1,2,3],G:['g1','g2','g3']/*x*/}";
- checkStep(129, in, Json5Map.ofJson5(in).getList("G").getString(2), "g3");
+ checkStep(129, in, Json5Map.ofText(in).getList("G").getString(2), "g3");
in = "{A:'B','C':1,\"E\":[1,2,3],G:['g1','g2','g3']}/*x*/";
- checkStep(130, in, Json5Map.ofJson5(in).getList("G").getString(2), "g3");
+ checkStep(130, in, Json5Map.ofText(in).getList("G").getString(2), "g3");
in = "/*\tx\t*///\tx\t\n\t/*\tx\t*/{A:'B','C':1,\"E\":[1,2,3],G:['g1','g2','g3']}";
- checkStep(201, in, Json5Map.ofJson5(in).getString("A"), "B");
+ checkStep(201, in, Json5Map.ofText(in).getString("A"), "B");
in = "{/*\tx\t*///\tx\t\n\t/*\tx\t*/A:'B','C':1,\"E\":[1,2,3],G:['g1','g2','g3']}";
- checkStep(202, in, Json5Map.ofJson5(in).getString("A"), "B");
+ checkStep(202, in, Json5Map.ofText(in).getString("A"), "B");
in = "{A/*\tx\t*///\tx\t\n\t/*\tx\t*/:'B','C':1,\"E\":[1,2,3],G:['g1','g2','g3']}";
- checkStep(203, in, Json5Map.ofJson5(in).getString("A"), "B");
+ checkStep(203, in, Json5Map.ofText(in).getString("A"), "B");
in = "{A:/*\tx\t*///\tx\t\n\t/*\tx\t*/'B','C':1,\"E\":[1,2,3],G:['g1','g2','g3']}";
- checkStep(204, in, Json5Map.ofJson5(in).getString("A"), "B");
+ checkStep(204, in, Json5Map.ofText(in).getString("A"), "B");
in = "{A:'/*\tx\t*///\tx\t\n\t/*\tx\t*/B','C':1,\"E\":[1,2,3],G:['g1','g2','g3']}";
- checkStep(205, in, Json5Map.ofJson5(in).getString("A"), "/*\tx\t*///\tx\t\n\t/*\tx\t*/B");
+ checkStep(205, in, Json5Map.ofText(in).getString("A"), "/*\tx\t*///\tx\t\n\t/*\tx\t*/B");
in = "{A:'B/*\tx\t*///\tx\t\n\t/*\tx\t*/','C':1,\"E\":[1,2,3],G:['g1','g2','g3']}";
- checkStep(206, in, Json5Map.ofJson5(in).getString("A"), "B/*\tx\t*///\tx\t\n\t/*\tx\t*/");
+ checkStep(206, in, Json5Map.ofText(in).getString("A"), "B/*\tx\t*///\tx\t\n\t/*\tx\t*/");
in = "{A:'B'/*\tx\t*///\tx\t\n\t/*\tx\t*/,'C':1,\"E\":[1,2,3],G:['g1','g2','g3']}";
- checkStep(207, in, Json5Map.ofJson5(in).getString("A"), "B");
+ checkStep(207, in, Json5Map.ofText(in).getString("A"), "B");
in = "{A:'B',/*\tx\t*///\tx\t\n\t/*\tx\t*/'C':1,\"E\":[1,2,3],G:['g1','g2','g3']}";
- checkStep(208, in, Json5Map.ofJson5(in).getString("C"), "1");
+ checkStep(208, in, Json5Map.ofText(in).getString("C"), "1");
in = "{A:'B','C':/*\tx\t*///\tx\t\n\t/*\tx\t*/1,\"E\":[1,2,3],G:['g1','g2','g3']}";
- checkStep(209, in, Json5Map.ofJson5(in).getString("C"), "1");
+ checkStep(209, in, Json5Map.ofText(in).getString("C"), "1");
in = "{A:'B','C':1/*\tx\t*///\tx\t\n\t/*\tx\t*/,\"E\":[1,2,3],G:['g1','g2','g3']}";
- checkStep(210, in, Json5Map.ofJson5(in).getString("C"), "1");
+ checkStep(210, in, Json5Map.ofText(in).getString("C"), "1");
in = "{A:'B','C':1,/*\tx\t*///\tx\t\n\t/*\tx\t*/\"E\":[1,2,3],G:['g1','g2','g3']}";
- checkStep(211, in, Json5Map.ofJson5(in).getList("E").getString(0), "1");
+ checkStep(211, in, Json5Map.ofText(in).getList("E").getString(0), "1");
in = "{A:'B','C':1,\"/*\tx\t*///\tx\t\n\t/*\tx\t*/E\":[1,2,3],G:['g1','g2','g3']}";
- checkStep(212, in, Json5Map.ofJson5(in).getList("/*\tx\t*///\tx\t\n\t/*\tx\t*/E").getString(0), "1");
+ checkStep(212, in, Json5Map.ofText(in).getList("/*\tx\t*///\tx\t\n\t/*\tx\t*/E").getString(0), "1");
in = "{A:'B','C':1,\"E/*\tx\t*///\tx\t\n\t/*\tx\t*/\":[1,2,3],G:['g1','g2','g3']}";
- checkStep(213, in, Json5Map.ofJson5(in).getList("E/*\tx\t*///\tx\t\n\t/*\tx\t*/").getString(0), "1");
+ checkStep(213, in, Json5Map.ofText(in).getList("E/*\tx\t*///\tx\t\n\t/*\tx\t*/").getString(0), "1");
in = "{A:'B','C':1,\"E\"/*\tx\t*///\tx\t\n\t/*\tx\t*/:[1,2,3],G:['g1','g2','g3']}";
- checkStep(214, in, Json5Map.ofJson5(in).getList("E").getString(0), "1");
+ checkStep(214, in, Json5Map.ofText(in).getList("E").getString(0), "1");
in = "{A:'B','C':1,\"E\":/*\tx\t*///\tx\t\n\t/*\tx\t*/[1,2,3],G:['g1','g2','g3']}";
- checkStep(215, in, Json5Map.ofJson5(in).getList("E").getString(0), "1");
+ checkStep(215, in, Json5Map.ofText(in).getList("E").getString(0), "1");
in = "{A:'B','C':1,\"E\":[/*\tx\t*///\tx\t\n\t/*\tx\t*/1,2,3],G:['g1','g2','g3']}";
- checkStep(216, in, Json5Map.ofJson5(in).getList("E").getString(0), "1");
+ checkStep(216, in, Json5Map.ofText(in).getList("E").getString(0), "1");
in = "{A:'B','C':1,\"E\":[1/*\tx\t*///\tx\t\n\t/*\tx\t*/,2,3],G:['g1','g2','g3']}";
- checkStep(217, in, Json5Map.ofJson5(in).getList("E").getString(0), "1");
+ checkStep(217, in, Json5Map.ofText(in).getList("E").getString(0), "1");
in = "{A:'B','C':1,\"E\":[1,/*\tx\t*///\tx\t\n\t/*\tx\t*/2,3],G:['g1','g2','g3']}";
- checkStep(218, in, Json5Map.ofJson5(in).getList("E").getString(1), "2");
+ checkStep(218, in, Json5Map.ofText(in).getList("E").getString(1), "2");
in = "{A:'B','C':1,\"E\":[1,2/*\tx\t*///\tx\t\n\t/*\tx\t*/,3],G:['g1','g2','g3']}";
- checkStep(219, in, Json5Map.ofJson5(in).getList("E").getString(1), "2");
+ checkStep(219, in, Json5Map.ofText(in).getList("E").getString(1), "2");
in = "{A:'B','C':1,\"E\":[1,2,/*\tx\t*///\tx\t\n\t/*\tx\t*/3],G:['g1','g2','g3']}";
- checkStep(220, in, Json5Map.ofJson5(in).getList("E").getString(2), "3");
+ checkStep(220, in, Json5Map.ofText(in).getList("E").getString(2), "3");
in = "{A:'B','C':1,\"E\":[1,2,3]/*\tx\t*///\tx\t\n\t/*\tx\t*/,G:['g1','g2','g3']}";
- checkStep(221, in, Json5Map.ofJson5(in).getList("E").getString(2), "3");
+ checkStep(221, in, Json5Map.ofText(in).getList("E").getString(2), "3");
in = "{A:'B','C':1,\"E\":[1,2,3],/*\tx\t*///\tx\t\n\t/*\tx\t*/G:['g1','g2','g3']}";
- checkStep(222, in, Json5Map.ofJson5(in).getList("G").getString(0), "g1");
+ checkStep(222, in, Json5Map.ofText(in).getList("G").getString(0), "g1");
in = "{A:'B','C':1,\"E\":[1,2,3],G:[/*\tx\t*///\tx\t\n\t/*\tx\t*/'g1','g2','g3']}";
- checkStep(223, in, Json5Map.ofJson5(in).getList("G").getString(0), "g1");
+ checkStep(223, in, Json5Map.ofText(in).getList("G").getString(0), "g1");
in = "{A:'B','C':1,\"E\":[1,2,3],G:['/*\tx\t*///\tx\t\n\t/*\tx\t*/g1','g2','g3']}";
- checkStep(224, in, Json5Map.ofJson5(in).getList("G").getString(0), "/*\tx\t*///\tx\t\n\t/*\tx\t*/g1");
+ checkStep(224, in, Json5Map.ofText(in).getList("G").getString(0), "/*\tx\t*///\tx\t\n\t/*\tx\t*/g1");
in = "{A:'B','C':1,\"E\":[1,2,3],G:['g1'/*\tx\t*///\tx\t\n\t/*\tx\t*/,'g2','g3']}";
- checkStep(225, in, Json5Map.ofJson5(in).getList("G").getString(0), "g1");
+ checkStep(225, in, Json5Map.ofText(in).getList("G").getString(0), "g1");
in = "{A:'B','C':1,\"E\":[1,2,3],G:['g1',/*\tx\t*///\tx\t\n\t/*\tx\t*/'g2','g3']}";
- checkStep(226, in, Json5Map.ofJson5(in).getList("G").getString(1), "g2");
+ checkStep(226, in, Json5Map.ofText(in).getList("G").getString(1), "g2");
in = "{A:'B','C':1,\"E\":[1,2,3],G:['g1','g2'/*\tx\t*///\tx\t\n\t/*\tx\t*/,'g3']}";
- checkStep(227, in, Json5Map.ofJson5(in).getList("G").getString(1), "g2");
+ checkStep(227, in, Json5Map.ofText(in).getList("G").getString(1), "g2");
in = "{A:'B','C':1,\"E\":[1,2,3],G:['g1','g2',/*\tx\t*///\tx\t\n\t/*\tx\t*/'g3']}";
- checkStep(228, in, Json5Map.ofJson5(in).getList("G").getString(2), "g3");
+ checkStep(228, in, Json5Map.ofText(in).getList("G").getString(2), "g3");
in = "{A:'B','C':1,\"E\":[1,2,3],G:['g1','g2','g3'/*\tx\t*///\tx\t\n\t/*\tx\t*/]}";
- checkStep(229, in, Json5Map.ofJson5(in).getList("G").getString(2), "g3");
+ checkStep(229, in, Json5Map.ofText(in).getList("G").getString(2), "g3");
in = "{A:'B','C':1,\"E\":[1,2,3],G:['g1','g2','g3']/*\tx\t*///\tx\t\n\t/*\tx\t*/}";
- checkStep(230, in, Json5Map.ofJson5(in).getList("G").getString(2), "g3");
+ checkStep(230, in, Json5Map.ofText(in).getList("G").getString(2), "g3");
in = "{A:'B','C':1,\"E\":[1,2,3],G:['g1','g2','g3']}/*\tx\t*///\tx\t\n\t/*\tx\t*/";
- checkStep(231, in, Json5Map.ofJson5(in).getList("G").getString(2), "g3");
+ checkStep(231, in, Json5Map.ofText(in).getList("G").getString(2), "g3");
in = "{ /* x */ // x \n /* x */ A:'B','C':1,\"E\":[1,2,3],G:['g1','g2','g3']}";
- checkStep(240, in, Json5Map.ofJson5(in).getString("A"), "B");
+ checkStep(240, in, Json5Map.ofText(in).getString("A"), "B");
in = "{A:'B','C':1,\"E\":[1,2,3],G:['g1','g2','g3']}";
- checkStep(301, in, Json5Map.ofJson5(in).getString("A", "default"), "B");
+ checkStep(301, in, Json5Map.ofText(in).getString("A", "default"), "B");
in = "{/*A:'B',*/'C':1,\"E\":[1,2,3],G:['g1','g2','g3']}";
- checkStep(302, in, Json5Map.ofJson5(in).getString("A", "default"), "default");
+ checkStep(302, in, Json5Map.ofText(in).getString("A", "default"), "default");
in = "{A:'B',/*'C':1,*/\"E\":[1,2,3],G:['g1','g2','g3']}";
- checkStep(303, in, Json5Map.ofJson5(in).getString("C", "default"), "default");
+ checkStep(303, in, Json5Map.ofText(in).getString("C", "default"), "default");
in = "{A:'B','C':1,/*\"E\":[1,2,3],*/G:['g1','g2','g3']}";
- checkStep(304, in, Json5Map.ofJson5(in).getString("E", "default"), "default");
+ checkStep(304, in, Json5Map.ofText(in).getString("E", "default"), "default");
in = "{A:'B','C':1,\"E\":[/*1,*/2,3],G:['g1','g2','g3']}";
- checkStep(305, in, Json5Map.ofJson5(in).getList("E").getString(0), "2");
+ checkStep(305, in, Json5Map.ofText(in).getList("E").getString(0), "2");
in = "{A:'B','C':1,\"E\":[1,/*2,*/3],G:['g1','g2','g3']}";
- checkStep(306, in, Json5Map.ofJson5(in).getList("E").getString(1), "3");
+ checkStep(306, in, Json5Map.ofText(in).getList("E").getString(1), "3");
in = "{A:'B','C':1,\"E\":[1,2/*,3*/],G:['g1','g2','g3']}";
- checkStep(307, in, Json5Map.ofJson5(in).getList("E").getString(1), "2");
+ checkStep(307, in, Json5Map.ofText(in).getList("E").getString(1), "2");
in = "{A:'B','C':1,\"E\":[1,2,3],G:[/*'g1',*/'g2','g3']}";
- checkStep(308, in, Json5Map.ofJson5(in).getList("G").getString(0), "g2");
+ checkStep(308, in, Json5Map.ofText(in).getList("G").getString(0), "g2");
in = "{A:'B','C':1,\"E\":[1,2,3],G:['g1'/*,'g2'*/,'g3']}";
- checkStep(309, in, Json5Map.ofJson5(in).getList("G").getString(1), "g3");
+ checkStep(309, in, Json5Map.ofText(in).getList("G").getString(1), "g3");
in = "{A:'B','C':1,\"E\":[1,2,3],G:['g1','g2'/*,'g3'*/]}";
- checkStep(310, in, Json5Map.ofJson5(in).getList("G").getString(1), "g2");
+ checkStep(310, in, Json5Map.ofText(in).getList("G").getString(1), "g2");
in = "{A:'B','C':1,\"E\":[1,2,3],G:['g1','g2','g3']}";
- checkStep(310, in, Json5Map.ofJson5(in).getList("G").getString(1), "g2");
+ checkStep(310, in, Json5Map.ofText(in).getList("G").getString(1), "g2");
// Check keys that contain array indexes
in = "{A:{B:[{C:'c0'},{C:'c1'},{C:'c2'}]}}";
- checkStep(401, in, getDeepString(Json5Map.ofJson5(in), "A/B/0/C"), "c0");
- checkStep(402, in, getDeepString(Json5Map.ofJson5(in), "A/B/1/C"), "c1");
- checkStep(403, in, getDeepString(Json5Map.ofJson5(in), "A/B/2/C"), "c2");
+ checkStep(401, in, getDeepString(Json5Map.ofText(in), "A/B/0/C"), "c0");
+ checkStep(402, in, getDeepString(Json5Map.ofText(in), "A/B/1/C"), "c1");
+ checkStep(403, in, getDeepString(Json5Map.ofText(in), "A/B/2/C"), "c2");
// Check extended unicode characters.
in = "{'𤭢𤭢':'𤭢𤭢'}";
- checkStep(1, in, Json5Map.ofJson5(in).getString("𤭢𤭢"), "𤭢𤭢");
+ checkStep(1, in, Json5Map.ofText(in).getString("𤭢𤭢"), "𤭢𤭢");
}
private static String getDeepString(Json5Map m, String url) {
@@ -261,8 +261,8 @@ class JsonMap_Test extends TestBase {
// testComparison
//====================================================================================================
@Test void a02_comparison() throws Exception {
- var m1 = Json5Map.ofJson5("{ firstName:'John', lastName:'Smith', age:123, isDeceased:false }");
- var m2 = Json5Map.ofJson5("{ age:123, isDeceased:false, lastName:'Smith', firstName:'John' }");
+ var m1 = Json5Map.ofText("{ firstName:'John', lastName:'Smith', age:123, isDeceased:false }");
+ var m2 = Json5Map.ofText("{ age:123, isDeceased:false, lastName:'Smith', firstName:'John' }");
assertEquals(m1, m2);
}
@@ -271,8 +271,8 @@ class JsonMap_Test extends TestBase {
// testParent
//====================================================================================================
@Test void a03_parent() throws Exception {
- var m1 = Json5Map.ofJson5("{a:1}");
- var m2 = Json5Map.ofJson5("{b:2}").inner(m1);
+ var m1 = Json5Map.ofText("{a:1}");
+ var m2 = Json5Map.ofText("{b:2}").inner(m1);
assertEquals(Integer.valueOf(1), m2.getInt("a"));
}
@@ -281,13 +281,13 @@ class JsonMap_Test extends TestBase {
// testUpdatability
//====================================================================================================
@Test void a04_updatability() throws Exception {
- var m = Json5Map.ofJson5("{a:[{b:'c'}]}");
+ var m = Json5Map.ofText("{a:[{b:'c'}]}");
var l = m.getList("a");
var m2 = l.getMap(0);
m2.put("b", "x");
assertBean(m, "a", "[{b=x}]");
- m = Json5Map.ofJson5("{a:[{b:'c'}]}");
+ m = Json5Map.ofText("{a:[{b:'c'}]}");
for (var m3 : m.getList("a").elements(Json5Map.class))
m3.put("b", "y");
@@ -298,7 +298,7 @@ class JsonMap_Test extends TestBase {
// testAtMethods
//====================================================================================================
@Test void a05_atMethods() throws Exception {
- var m = Json5Map.ofJson5("{a:[{b:'c'}]}");
+ var m = Json5Map.ofText("{a:[{b:'c'}]}");
var r = m.getAt("a/0/b", String.class);
assertEquals("c", r);
@@ -319,14 +319,14 @@ class JsonMap_Test extends TestBase {
// JsonMap(Reader)
//====================================================================================================
@Test void a06_fromReader() throws Exception {
- assertBean(Json5Map.ofJson5(reader("{foo:'bar'}")), "foo", "bar");
+ assertBean(Json5Map.ofText(reader("{foo:'bar'}")), "foo", "bar");
}
//====================================================================================================
// testGetMap
//====================================================================================================
@Test void a07_getMap() throws Exception {
- var m = Json5Map.ofJson5("{a:{1:'true',2:'false'}}");
+ var m = Json5Map.ofText("{a:{1:'true',2:'false'}}");
var m2 = m.getMap("a", Integer.class, Boolean.class, null);
assertJson("{'1':true,'2':false}", m2);
assertEquals(Integer.class, m2.keySet().iterator().next().getClass());
@@ -348,7 +348,7 @@ class JsonMap_Test extends TestBase {
// testGetList
//====================================================================================================
@Test void a08_getList() throws Exception {
- var m = Json5Map.ofJson5("{a:['123','456']}");
+ var m = Json5Map.ofText("{a:['123','456']}");
var l2 = m.getList("a", Integer.class, null);
assertList(l2, "123", "456");
assertEquals(Integer.class, l2.iterator().next().getClass());
@@ -368,7 +368,7 @@ class JsonMap_Test extends TestBase {
// toX serialization methods
//====================================================================================================
@Test void a09_toX() {
- var m = Json5Map.ofJson5("{b:'2',a:'1'}");
+ var m = Json5Map.ofText("{b:'2',a:'1'}");
// toJson5 — JSON5 (unquoted keys where possible), same as toString()
assertString("{b:'2',a:'1'}", m.toJson5());
diff --git a/juneau-utest/src/test/java/org/apache/juneau/MarshalledConfig_Test.java b/juneau-utest/src/test/java/org/apache/juneau/MarshalledConfig_Test.java
index 586110f836..e9f866d09b 100755
--- a/juneau-utest/src/test/java/org/apache/juneau/MarshalledConfig_Test.java
+++ b/juneau-utest/src/test/java/org/apache/juneau/MarshalledConfig_Test.java
@@ -314,7 +314,7 @@ class MarshalledConfig_Test extends TestBase {
assertEquals("{name:'x',age:123}", bc.convertToType(o, String.class));
// List of Maps to array of beans.
- var o2 = JsonList.of(JsonMap.ofJson("{\"name\":\"x\",\"age\":1}"), JsonMap.ofJson("{\"name\":\"y\",\"age\":2}"));
+ var o2 = JsonList.of(JsonMap.ofText("{\"name\":\"x\",\"age\":1}"), JsonMap.ofText("{\"name\":\"y\",\"age\":2}"));
assertEquals(1, bc.convertToType(o2, ReadOnlyPerson[].class)[0].getAge());
}
@@ -346,7 +346,7 @@ class MarshalledConfig_Test extends TestBase {
assertEquals("{name:'x',age:123}", bc.convertToType(o, String.class));
// List of Maps to array of beans.
- var o2 = JsonList.of(JsonMap.ofJson("{\"name\":\"x\",\"age\":1}"), JsonMap.ofJson("{\"name\":\"y\",\"age\":2}"));
+ var o2 = JsonList.of(JsonMap.ofText("{\"name\":\"x\",\"age\":1}"), JsonMap.ofText("{\"name\":\"y\",\"age\":2}"));
assertEquals(1, bc.convertToType(o2, ReadOnlyPerson2[].class)[0].getAge());
}
diff --git a/juneau-utest/src/test/java/org/apache/juneau/ObjectSwap_Test.java b/juneau-utest/src/test/java/org/apache/juneau/ObjectSwap_Test.java
index 2040dd1612..3f1ad2ba59 100755
--- a/juneau-utest/src/test/java/org/apache/juneau/ObjectSwap_Test.java
+++ b/juneau-utest/src/test/java/org/apache/juneau/ObjectSwap_Test.java
@@ -39,7 +39,7 @@ class ObjectSwap_Test extends TestBase {
r = p.parse(r, String.class);
assertEquals("foobar", r);
- var m = Json5Map.ofJson5("{foo:'bar'}");
+ var m = Json5Map.ofText("{foo:'bar'}");
r = s.serialize(m);
assertEquals("{xfoox:'xbarx'}", r);
}
diff --git a/juneau-utest/src/test/java/org/apache/juneau/a/rttests/JsonMaps_RoundTripTest.java b/juneau-utest/src/test/java/org/apache/juneau/a/rttests/JsonMaps_RoundTripTest.java
index 7e8f247a3b..26ddf62bad 100755
--- a/juneau-utest/src/test/java/org/apache/juneau/a/rttests/JsonMaps_RoundTripTest.java
+++ b/juneau-utest/src/test/java/org/apache/juneau/a/rttests/JsonMaps_RoundTripTest.java
@@ -42,7 +42,7 @@ class JsonMaps_RoundTripTest extends RoundTripTest_Base {
@ParameterizedTest
@MethodSource("testers")
void a01_basic(RoundTrip_Tester t) throws Exception {
- var x1 = new A(JsonMap.ofJson("{\"f1\":\"a\",\"f2\":2}"));
+ var x1 = new A(JsonMap.ofText("{\"f1\":\"a\",\"f2\":2}"));
x1 = t.roundTrip(x1, A.class);
assertBean(x1, "f1,f2", "a,2");
@@ -50,11 +50,11 @@ class JsonMaps_RoundTripTest extends RoundTripTest_Base {
x2 = t.roundTrip(x2, A[].class);
assertBean(x2, "length,#{f1,f2}", "1,[{a,2}]");
- var x3 = l(new A(JsonMap.ofJson("{\"f1\":\"a\",\"f2\":2}")));
+ var x3 = l(new A(JsonMap.ofText("{\"f1\":\"a\",\"f2\":2}")));
x3 = t.roundTrip(x3, List.class, A.class);
assertBean(x3, "size,0{f1,f2}", "1,{a,2}");
- var x4 = m("a",new A(JsonMap.ofJson("{\"f1\":\"a\",\"f2\":2}")));
+ var x4 = m("a",new A(JsonMap.ofText("{\"f1\":\"a\",\"f2\":2}")));
x4 = t.roundTrip(x4, Map.class, String.class, A.class);
assertBean(x4, "size,a{f1,f2}", "1,{a,2}");
}
diff --git a/juneau-utest/src/test/java/org/apache/juneau/a/rttests/ParentProperty_RoundTripTest.java b/juneau-utest/src/test/java/org/apache/juneau/a/rttests/ParentProperty_RoundTripTest.java
index 229aef1b95..9fdded2b01 100644
--- a/juneau-utest/src/test/java/org/apache/juneau/a/rttests/ParentProperty_RoundTripTest.java
+++ b/juneau-utest/src/test/java/org/apache/juneau/a/rttests/ParentProperty_RoundTripTest.java
@@ -35,7 +35,6 @@ class ParentProperty_RoundTripTest extends RoundTripTest_Base {
@ParameterizedTest
@MethodSource("testers")
void a01_parentProperty(RoundTrip_Tester t) throws Exception {
- // @ParentProperty not supported for inline JSON5 beans in Markdown (see TODO-9-markdown-remaining-issues.md #9)
if (t.label.contains("Markdown"))
return;
var x = new ParentPropertyMethodContainer().init();
@@ -78,7 +77,7 @@ class ParentProperty_RoundTripTest extends RoundTripTest_Base {
@ParameterizedTest
@MethodSource("testers")
void a02_parentPropertyField(RoundTrip_Tester t) throws Exception {
- // @ParentProperty not supported for inline JSON5 beans in Markdown (see TODO-9-markdown-remaining-issues.md #9)
+ // @ParentProperty not supported for inline JSON5 beans in Markdown (see work-item-9 markdown remaining issues, item 9)
if (t.label.contains("Markdown"))
return;
var x = new ParentPropertyFieldContainer().init();
diff --git a/juneau-utest/src/test/java/org/apache/juneau/a/rttests/SimpleObjects_RoundTripTest.java b/juneau-utest/src/test/java/org/apache/juneau/a/rttests/SimpleObjects_RoundTripTest.java
index aa7620456f..e0b2b494d0 100755
--- a/juneau-utest/src/test/java/org/apache/juneau/a/rttests/SimpleObjects_RoundTripTest.java
+++ b/juneau-utest/src/test/java/org/apache/juneau/a/rttests/SimpleObjects_RoundTripTest.java
@@ -450,7 +450,7 @@ class SimpleObjects_RoundTripTest extends RoundTripTest_Base {
void a51_jsonMap(RoundTrip_Tester t) throws Exception {
if (isRdf(t))
return;
- var x = JsonMap.ofJson("{\"a\":\"b\",\"c\":123,\"d\":false,\"e\":null,\"f\":[123,\"abc\",true,false,null]}");
+ var x = JsonMap.ofText("{\"a\":\"b\",\"c\":123,\"d\":false,\"e\":null,\"f\":[123,\"abc\",true,false,null]}");
x = t.roundTrip(x);
assertEquals("b", x.get("a"));
assertEquals(123, ((Number)x.get("c")).intValue());
diff --git a/juneau-utest/src/test/java/org/apache/juneau/a/rttests/TrimStrings_RoundTripTest.java b/juneau-utest/src/test/java/org/apache/juneau/a/rttests/TrimStrings_RoundTripTest.java
index adbadc70d6..9c7faafe7a 100755
--- a/juneau-utest/src/test/java/org/apache/juneau/a/rttests/TrimStrings_RoundTripTest.java
+++ b/juneau-utest/src/test/java/org/apache/juneau/a/rttests/TrimStrings_RoundTripTest.java
@@ -54,8 +54,8 @@ class TrimStrings_RoundTripTest extends RoundTripTest_Base {
a = p2.parse(s.serialize(in), String.class);
assertEquals(json(a), json(e));
- in = JsonMap.ofJson("{\" foo \": \" bar \"}");
- e = JsonMap.ofJson("{\"foo\":\"bar\"}");
+ in = JsonMap.ofText("{\" foo \": \" bar \"}");
+ e = JsonMap.ofText("{\"foo\":\"bar\"}");
a = p.parse(s2.serialize(in), JsonMap.class);
assertEquals(json(a), json(e));
a = p2.parse(s.serialize(in), JsonMap.class);
@@ -89,16 +89,16 @@ class TrimStrings_RoundTripTest extends RoundTripTest_Base {
public A init1() throws Exception {
f1 = " f1 ";
f2 = a(" f2a ", " f2b ");
- f3 = JsonList.ofJson("[\" f3a \",\" f3b \"]");
- f4 = JsonMap.ofJson("{\" foo \":\" bar \"}");
+ f3 = JsonList.ofText("[\" f3a \",\" f3b \"]");
+ f4 = JsonMap.ofText("{\" foo \":\" bar \"}");
return this;
}
public A init2() throws Exception {
f1 = "f1";
f2 = a("f2a", "f2b");
- f3 = JsonList.ofJson("[\"f3a\",\"f3b\"]");
- f4 = JsonMap.ofJson("{\"foo\":\"bar\"}");
+ f3 = JsonList.ofText("[\"f3a\",\"f3b\"]");
+ f4 = JsonMap.ofText("{\"foo\":\"bar\"}");
return this;
}
}
diff --git a/juneau-utest/src/test/java/org/apache/juneau/bean/jsonschema/JsonSchemaBeanGenerator_Test.java b/juneau-utest/src/test/java/org/apache/juneau/bean/jsonschema/JsonSchemaBeanGenerator_Test.java
index 5ce495f007..7b0929b4b7 100644
--- a/juneau-utest/src/test/java/org/apache/juneau/bean/jsonschema/JsonSchemaBeanGenerator_Test.java
+++ b/juneau-utest/src/test/java/org/apache/juneau/bean/jsonschema/JsonSchemaBeanGenerator_Test.java
@@ -96,7 +96,7 @@ class JsonSchemaBeanGenerator_Test extends TestBase {
}
@Test void a08_toBeanConversion() {
- var map = new JsonMap(Json5Map.ofJson5("{type:'integer',format:'int32','$comment':'c',deprecated:true}"));
+ var map = new JsonMap(Json5Map.ofText("{type:'integer',format:'int32','$comment':'c',deprecated:true}"));
var bean = JsonSchemaBeanGenerator.toBean(map);
assertEquals("integer", bean.getTypeAsJsonType().toString().toLowerCase(Locale.ROOT));
assertEquals("int32", bean.getFormat());
diff --git a/juneau-utest/src/test/java/org/apache/juneau/cbor/CborCompliance_Test.java b/juneau-utest/src/test/java/org/apache/juneau/cbor/CborCompliance_Test.java
index c7e5212012..22fc4a79ef 100644
--- a/juneau-utest/src/test/java/org/apache/juneau/cbor/CborCompliance_Test.java
+++ b/juneau-utest/src/test/java/org/apache/juneau/cbor/CborCompliance_Test.java
@@ -90,7 +90,7 @@ class CborCompliance_Test extends TestBase {
void g17_simpleArray() throws Exception { enc(ints(1, 2, 3), "83 01 02 03"); }
@Test
- void g18_emptyMap() throws Exception { enc(JsonMap.ofJson("{}"), "A0"); }
+ void g18_emptyMap() throws Exception { enc(JsonMap.ofText("{}"), "A0"); }
@Test
void g19_false() throws Exception { enc(false, "F4"); }
diff --git a/juneau-utest/src/test/java/org/apache/juneau/cbor/CborOutputStream_Test.java b/juneau-utest/src/test/java/org/apache/juneau/cbor/CborOutputStream_Test.java
index b907df0be8..3666a90edc 100644
--- a/juneau-utest/src/test/java/org/apache/juneau/cbor/CborOutputStream_Test.java
+++ b/juneau-utest/src/test/java/org/apache/juneau/cbor/CborOutputStream_Test.java
@@ -219,12 +219,12 @@ class CborOutputStream_Test extends TestBase {
@Test
void a29_emptyMap() throws Exception {
- enc(JsonMap.ofJson("{}"), "A0");
+ enc(JsonMap.ofText("{}"), "A0");
}
@Test
void a30_shortMap() throws Exception {
- enc(JsonMap.ofJson("{\"a\":1,\"b\":2}"), "A2 61 61 01 61 62 02");
+ enc(JsonMap.ofText("{\"a\":1,\"b\":2}"), "A2 61 61 01 61 62 02");
}
@Test
diff --git a/juneau-utest/src/test/java/org/apache/juneau/cbor/CborRoundTrip_Test.java b/juneau-utest/src/test/java/org/apache/juneau/cbor/CborRoundTrip_Test.java
index f3d21accb6..9c1f4a737f 100644
--- a/juneau-utest/src/test/java/org/apache/juneau/cbor/CborRoundTrip_Test.java
+++ b/juneau-utest/src/test/java/org/apache/juneau/cbor/CborRoundTrip_Test.java
@@ -130,7 +130,7 @@ class CborRoundTrip_Test extends TestBase {
void e13_emptyCollectionsRoundTrip() throws Exception {
var emptyList = CborParser.DEFAULT.parse(CborSerializer.DEFAULT.serialize(list()), JsonList.class);
assertTrue(emptyList.isEmpty());
- var emptyMap = CborParser.DEFAULT.parse(CborSerializer.DEFAULT.serialize(JsonMap.ofJson("{}")), JsonMap.class);
+ var emptyMap = CborParser.DEFAULT.parse(CborSerializer.DEFAULT.serialize(JsonMap.ofText("{}")), JsonMap.class);
assertTrue(emptyMap.isEmpty());
}
diff --git a/juneau-utest/src/test/java/org/apache/juneau/cbor/CborSerializer_Test.java b/juneau-utest/src/test/java/org/apache/juneau/cbor/CborSerializer_Test.java
index efe6e9616b..a9f69d806b 100644
--- a/juneau-utest/src/test/java/org/apache/juneau/cbor/CborSerializer_Test.java
+++ b/juneau-utest/src/test/java/org/apache/juneau/cbor/CborSerializer_Test.java
@@ -55,7 +55,7 @@ class CborSerializer_Test extends TestBase {
test("a", "61 61");
test(ints(), "80");
test(ints(1, 2, 3), "83 01 02 03");
- test(JsonMap.ofJson("{}"), "A0");
+ test(JsonMap.ofText("{}"), "A0");
}
public static class Person {
@@ -190,7 +190,7 @@ class CborSerializer_Test extends TestBase {
@Test
void c13_emptyBean() throws Exception {
- var bytes = CborSerializer.DEFAULT.serialize(JsonMap.ofJson("{}"));
+ var bytes = CborSerializer.DEFAULT.serialize(JsonMap.ofText("{}"));
assertEquals("A0", toSpacedHex(bytes));
var parsed = CborParser.DEFAULT.parse(bytes, JsonMap.class);
assertTrue(parsed.isEmpty());
@@ -199,7 +199,7 @@ class CborSerializer_Test extends TestBase {
@Test
void c14_emptyCollections() throws Exception {
test(ints(), "80");
- test(JsonMap.ofJson("{}"), "A0");
+ test(JsonMap.ofText("{}"), "A0");
}
@Test
diff --git a/juneau-utest/src/test/java/org/apache/juneau/commons/inject/BasicBeanStore_Test.java b/juneau-utest/src/test/java/org/apache/juneau/commons/inject/BasicBeanStore_Test.java
index 29cf2d1086..4c0a005e10 100644
--- a/juneau-utest/src/test/java/org/apache/juneau/commons/inject/BasicBeanStore_Test.java
+++ b/juneau-utest/src/test/java/org/apache/juneau/commons/inject/BasicBeanStore_Test.java
@@ -1525,10 +1525,6 @@ class BasicBeanStore_Test extends TestBase {
assertSame(cause, ex.getCause());
}
- //------------------------------------------------------------------------------------------------
- // Coverage gap fillers — targeted tests added during the TODO-24 coverage pass.
- //------------------------------------------------------------------------------------------------
-
@Test
void z01_trackResolved_nullSupplierResult_isNotTracked() {
// A supplier that returns null exercises BasicBeanStore.trackResolved(null) — most easily
diff --git a/juneau-utest/src/test/java/org/apache/juneau/httppart/OpenApiPartSerializer_Test.java b/juneau-utest/src/test/java/org/apache/juneau/httppart/OpenApiPartSerializer_Test.java
index e4db0e9820..09c9e7b640 100644
--- a/juneau-utest/src/test/java/org/apache/juneau/httppart/OpenApiPartSerializer_Test.java
+++ b/juneau-utest/src/test/java/org/apache/juneau/httppart/OpenApiPartSerializer_Test.java
@@ -799,8 +799,8 @@ class OpenApiPartSerializer_Test extends TestBase {
var ps = tObject().allowEmptyValue().build();
assertEquals("f1=1,f2=2,f3=true", serialize(ps, new H1("1",2,true)));
assertEquals("", serialize(ps, new H1(null,null,null)));
- assertEquals("f1=1,f2=2,f3=true", serialize(ps, Json5Map.ofJson5("{f1:'1',f2:2,f3:true}")));
- assertEquals("f1=null,f2=null,f3=null", serialize(ps, Json5Map.ofJson5("{f1:null,f2:null,f3:null}")));
+ assertEquals("f1=1,f2=2,f3=true", serialize(ps, Json5Map.ofText("{f1:'1',f2:2,f3:true}")));
+ assertEquals("f1=null,f2=null,f3=null", serialize(ps, Json5Map.ofText("{f1:null,f2:null,f3:null}")));
assertEquals("null", serialize(ps, null));
}
@@ -808,8 +808,8 @@ class OpenApiPartSerializer_Test extends TestBase {
var ps = T_OBJECT_UON;
assertEquals("(f1='1',f2=2,f3=true)", serialize(ps, new H1("1",2,true)));
assertEquals("()", serialize(ps, new H1(null,null,null)));
- assertEquals("(f1='1',f2=2,f3=true)", serialize(ps, Json5Map.ofJson5("{f1:'1',f2:2,f3:true}")));
- assertEquals("(f1=null,f2=null,f3=null)", serialize(ps, Json5Map.ofJson5("{f1:null,f2:null,f3:null}")));
+ assertEquals("(f1='1',f2=2,f3=true)", serialize(ps, Json5Map.ofText("{f1:'1',f2:2,f3:true}")));
+ assertEquals("(f1=null,f2=null,f3=null)", serialize(ps, Json5Map.ofText("{f1:null,f2:null,f3:null}")));
assertEquals("null", serialize(ps, null));
}
@@ -817,30 +817,30 @@ class OpenApiPartSerializer_Test extends TestBase {
var ps = tArray(tObject().allowEmptyValue()).build();
assertEquals("f1=1\\,f2=2\\,f3=true,,null", serialize(ps, a(new H1("1",2,true),new H1(null,null,null),null)));
assertEquals("f1=1\\,f2=2\\,f3=true,,null", serialize(ps, l(new H1("1",2,true),new H1(null,null,null),null)));
- assertEquals("f1=1\\,f2=2\\,f3=true,f1=null\\,f2=null\\,f3=null,null", serialize(ps, a(Json5Map.ofJson5("{f1:'1',f2:2,f3:true}"),Json5Map.ofJson5("{f1:null,f2:null,f3:null}"),null)));
- assertEquals("f1=1\\,f2=2\\,f3=true,f1=null\\,f2=null\\,f3=null,null", serialize(ps, l(Json5Map.ofJson5("{f1:'1',f2:2,f3:true}"),Json5Map.ofJson5("{f1:null,f2:null,f3:null}"),null)));
- assertEquals("f1=1\\,f2=2\\,f3=true,f1=1\\,f2=2\\,f3=true,null", serialize(ps, ao(new H1("1",2,true),Json5Map.ofJson5("{f1:'1',f2:2,f3:true}"),null)));
- assertEquals("f1=1\\,f2=2\\,f3=true,f1=1\\,f2=2\\,f3=true,null", serialize(ps, l(new H1("1",2,true),Json5Map.ofJson5("{f1:'1',f2:2,f3:true}"),null)));
+ assertEquals("f1=1\\,f2=2\\,f3=true,f1=null\\,f2=null\\,f3=null,null", serialize(ps, a(Json5Map.ofText("{f1:'1',f2:2,f3:true}"),Json5Map.ofText("{f1:null,f2:null,f3:null}"),null)));
+ assertEquals("f1=1\\,f2=2\\,f3=true,f1=null\\,f2=null\\,f3=null,null", serialize(ps, l(Json5Map.ofText("{f1:'1',f2:2,f3:true}"),Json5Map.ofText("{f1:null,f2:null,f3:null}"),null)));
+ assertEquals("f1=1\\,f2=2\\,f3=true,f1=1\\,f2=2\\,f3=true,null", serialize(ps, ao(new H1("1",2,true),Json5Map.ofText("{f1:'1',f2:2,f3:true}"),null)));
+ assertEquals("f1=1\\,f2=2\\,f3=true,f1=1\\,f2=2\\,f3=true,null", serialize(ps, l(new H1("1",2,true),Json5Map.ofText("{f1:'1',f2:2,f3:true}"),null)));
}
@Test void h03_objectType_2d_pipes() throws Exception {
var ps = tArrayPipes(tObject().allowEmptyValue()).build();
assertEquals("f1=1,f2=2,f3=true||null", serialize(ps, a(new H1("1",2,true),new H1(null,null,null),null)));
assertEquals("f1=1,f2=2,f3=true||null", serialize(ps, l(new H1("1",2,true),new H1(null,null,null),null)));
- assertEquals("f1=1,f2=2,f3=true|f1=null,f2=null,f3=null|null", serialize(ps, a(Json5Map.ofJson5("{f1:'1',f2:2,f3:true}"),Json5Map.ofJson5("{f1:null,f2:null,f3:null}"),null)));
- assertEquals("f1=1,f2=2,f3=true|f1=null,f2=null,f3=null|null", serialize(ps, l(Json5Map.ofJson5("{f1:'1',f2:2,f3:true}"),Json5Map.ofJson5("{f1:null,f2:null,f3:null}"),null)));
- assertEquals("f1=1,f2=2,f3=true|f1=1,f2=2,f3=true|null", serialize(ps, ao(new H1("1",2,true),Json5Map.ofJson5("{f1:'1',f2:2,f3:true}"),null)));
- assertEquals("f1=1,f2=2,f3=true|f1=1,f2=2,f3=true|null", serialize(ps, l(new H1("1",2,true),Json5Map.ofJson5("{f1:'1',f2:2,f3:true}"),null)));
+ assertEquals("f1=1,f2=2,f3=true|f1=null,f2=null,f3=null|null", serialize(ps, a(Json5Map.ofText("{f1:'1',f2:2,f3:true}"),Json5Map.ofText("{f1:null,f2:null,f3:null}"),null)));
+ assertEquals("f1=1,f2=2,f3=true|f1=null,f2=null,f3=null|null", serialize(ps, l(Json5Map.ofText("{f1:'1',f2:2,f3:true}"),Json5Map.ofText("{f1:null,f2:null,f3:null}"),null)));
+ assertEquals("f1=1,f2=2,f3=true|f1=1,f2=2,f3=true|null", serialize(ps, ao(new H1("1",2,true),Json5Map.ofText("{f1:'1',f2:2,f3:true}"),null)));
+ assertEquals("f1=1,f2=2,f3=true|f1=1,f2=2,f3=true|null", serialize(ps, l(new H1("1",2,true),Json5Map.ofText("{f1:'1',f2:2,f3:true}"),null)));
}
@Test void h04_objectType_2d_uon() throws Exception {
var ps = tArrayUon(tObject()).build();
assertEquals("@((f1='1',f2=2,f3=true),(),null)", serialize(ps, a(new H1("1",2,true),new H1(null,null,null),null)));
assertEquals("@((f1='1',f2=2,f3=true),(),null)", serialize(ps, l(new H1("1",2,true),new H1(null,null,null),null)));
- assertEquals("@((f1='1',f2=2,f3=true),(f1=null,f2=null,f3=null),null)", serialize(ps, a(Json5Map.ofJson5("{f1:'1',f2:2,f3:true}"),Json5Map.ofJson5("{f1:null,f2:null,f3:null}"),null)));
- assertEquals("@((f1='1',f2=2,f3=true),(f1=null,f2=null,f3=null),null)", serialize(ps, l(Json5Map.ofJson5("{f1:'1',f2:2,f3:true}"),Json5Map.ofJson5("{f1:null,f2:null,f3:null}"),null)));
- assertEquals("@((f1='1',f2=2,f3=true),(f1='1',f2=2,f3=true),null)", serialize(ps, ao(new H1("1",2,true),Json5Map.ofJson5("{f1:'1',f2:2,f3:true}"),null)));
- assertEquals("@((f1='1',f2=2,f3=true),(f1='1',f2=2,f3=true),null)", serialize(ps, l(new H1("1",2,true),Json5Map.ofJson5("{f1:'1',f2:2,f3:true}"),null)));
+ assertEquals("@((f1='1',f2=2,f3=true),(f1=null,f2=null,f3=null),null)", serialize(ps, a(Json5Map.ofText("{f1:'1',f2:2,f3:true}"),Json5Map.ofText("{f1:null,f2:null,f3:null}"),null)));
+ assertEquals("@((f1='1',f2=2,f3=true),(f1=null,f2=null,f3=null),null)", serialize(ps, l(Json5Map.ofText("{f1:'1',f2:2,f3:true}"),Json5Map.ofText("{f1:null,f2:null,f3:null}"),null)));
+ assertEquals("@((f1='1',f2=2,f3=true),(f1='1',f2=2,f3=true),null)", serialize(ps, ao(new H1("1",2,true),Json5Map.ofText("{f1:'1',f2:2,f3:true}"),null)));
+ assertEquals("@((f1='1',f2=2,f3=true),(f1='1',f2=2,f3=true),null)", serialize(ps, l(new H1("1",2,true),Json5Map.ofText("{f1:'1',f2:2,f3:true}"),null)));
}
@Test void h03_objectType_3d() throws Exception {
@@ -848,12 +848,12 @@ class OpenApiPartSerializer_Test extends TestBase {
assertEquals("f1=1\\\\\\,f2=2\\\\\\,f3=true\\,f1=x\\\\\\,f2=3\\\\\\,f3=false,\\,null,null", serialize(ps, a(a(new H1("1",2,true),new H1("x",3,false)),a(new H1(null,null,null),null),null)));
assertEquals("f1=1\\\\\\,f2=2\\\\\\,f3=true\\,f1=x\\\\\\,f2=3\\\\\\,f3=false,\\,null,null", serialize(ps, l(a(new H1("1",2,true),new H1("x",3,false)),a(new H1(null,null,null),null),null)));
assertEquals("f1=1\\\\\\,f2=2\\\\\\,f3=true\\,f1=x\\\\\\,f2=3\\\\\\,f3=false,\\,null,null", serialize(ps, l(l(new H1("1",2,true),new H1("x",3,false)),l(new H1(null,null,null),null),null)));
- assertEquals("f1=1\\\\\\,f2=2\\\\\\,f3=true\\,f1=x\\\\\\,f2=4\\\\\\,f3=false,f1=null\\\\\\,f2=null\\\\\\,f3=null\\,null,null", serialize(ps, a(a(Json5Map.ofJson5("{f1:'1',f2:2,f3:true}"),Json5Map.ofJson5("{f1:'x',f2:4,f3:false}")),a(Json5Map.ofJson5("{f1:null,f2:null,f3:null}"),null),null)));
- assertEquals("f1=1\\\\\\,f2=2\\\\\\,f3=true\\,f1=x\\\\\\,f2=4\\\\\\,f3=false,f1=null\\\\\\,f2=null\\\\\\,f3=null\\,null,null", serialize(ps, l(a(Json5Map.ofJson5("{f1:'1',f2:2,f3:true}"),Json5Map.ofJson5("{f1:'x',f2:4,f3:false}")),a(Json5Map.ofJson5("{f1:null,f2:null,f3:null}"),null),null)));
- assertEquals("f1=1\\\\\\,f2=2\\\\\\,f3=true\\,f1=x\\\\\\,f2=4\\\\\\,f3=false,f1=null\\\\\\,f2=null\\\\\\,f3=null\\,null,null", serialize(ps, l(l(Json5Map.ofJson5("{f1:'1',f2:2,f3:true}"),Json5Map.ofJson5("{f1:'x',f2:4,f3:false}")),l(Json5Map.ofJson5("{f1:null,f2:null,f3:null}"),null),null)));
- assertEquals("f1=1\\\\\\,f2=2\\\\\\,f3=true\\,f1=1\\\\\\,f2=2\\\\\\,f3=true,\\,f1=null\\\\\\,f2=null\\\\\\,f3=null\\,null,null", serialize(ps, a2(ao(new H1("1",2,true),Json5Map.ofJson5("{f1:'1',f2:2,f3:true}")),ao(new H1(null,null,null),Json5Map.ofJson5("{f1:null,f2:null,f3:null}"),null),null)));
- assertEquals("f1=1\\\\\\,f2=2\\\\\\,f3=true\\,f1=1\\\\\\,f2=2\\\\\\,f3=true,\\,f1=null\\\\\\,f2=null\\\\\\,f3=null\\,null,null", serialize(ps, l(ao(new H1("1",2,true),Json5Map.ofJson5("{f1:'1',f2:2,f3:true}")),ao(new H1(null,null,null),Json5Map.ofJson5("{f1:null,f2:null,f3:null}"),null),null)));
- assertEquals("f1=1\\\\\\,f2=2\\\\\\,f3=true\\,f1=1\\\\\\,f2=2\\\\\\,f3=true,\\,f1=null\\\\\\,f2=null\\\\\\,f3=null\\,null,null", serialize(ps, l(l(new H1("1",2,true),Json5Map.ofJson5("{f1:'1',f2:2,f3:true}")),l(new H1(null,null,null),Json5Map.ofJson5("{f1:null,f2:null,f3:null}"),null),null)));
+ assertEquals("f1=1\\\\\\,f2=2\\\\\\,f3=true\\,f1=x\\\\\\,f2=4\\\\\\,f3=false,f1=null\\\\\\,f2=null\\\\\\,f3=null\\,null,null", serialize(ps, a(a(Json5Map.ofText("{f1:'1',f2:2,f3:true}"),Json5Map.ofText("{f1:'x',f2:4,f3:false}")),a(Json5Map.ofText("{f1:null,f2:null,f3:null}"),null),null)));
+ assertEquals("f1=1\\\\\\,f2=2\\\\\\,f3=true\\,f1=x\\\\\\,f2=4\\\\\\,f3=false,f1=null\\\\\\,f2=null\\\\\\,f3=null\\,null,null", serialize(ps, l(a(Json5Map.ofText("{f1:'1',f2:2,f3:true}"),Json5Map.ofText("{f1:'x',f2:4,f3:false}")),a(Json5Map.ofText("{f1:null,f2:null,f3:null}"),null),null)));
+ assertEquals("f1=1\\\\\\,f2=2\\\\\\,f3=true\\,f1=x\\\\\\,f2=4\\\\\\,f3=false,f1=null\\\\\\,f2=null\\\\\\,f3=null\\,null,null", serialize(ps, l(l(Json5Map.ofText("{f1:'1',f2:2,f3:true}"),Json5Map.ofText("{f1:'x',f2:4,f3:false}")),l(Json5Map.ofText("{f1:null,f2:null,f3:null}"),null),null)));
+ assertEquals("f1=1\\\\\\,f2=2\\\\\\,f3=true\\,f1=1\\\\\\,f2=2\\\\\\,f3=true,\\,f1=null\\\\\\,f2=null\\\\\\,f3=null\\,null,null", serialize(ps, a2(ao(new H1("1",2,true),Json5Map.ofText("{f1:'1',f2:2,f3:true}")),ao(new H1(null,null,null),Json5Map.ofText("{f1:null,f2:null,f3:null}"),null),null)));
+ assertEquals("f1=1\\\\\\,f2=2\\\\\\,f3=true\\,f1=1\\\\\\,f2=2\\\\\\,f3=true,\\,f1=null\\\\\\,f2=null\\\\\\,f3=null\\,null,null", serialize(ps, l(ao(new H1("1",2,true),Json5Map.ofText("{f1:'1',f2:2,f3:true}")),ao(new H1(null,null,null),Json5Map.ofText("{f1:null,f2:null,f3:null}"),null),null)));
+ assertEquals("f1=1\\\\\\,f2=2\\\\\\,f3=true\\,f1=1\\\\\\,f2=2\\\\\\,f3=true,\\,f1=null\\\\\\,f2=null\\\\\\,f3=null\\,null,null", serialize(ps, l(l(new H1("1",2,true),Json5Map.ofText("{f1:'1',f2:2,f3:true}")),l(new H1(null,null,null),Json5Map.ofText("{f1:null,f2:null,f3:null}"),null),null)));
}
@Test void h03_objectType_3d_ssvAndPipes() throws Exception {
@@ -863,12 +863,12 @@ class OpenApiPartSerializer_Test extends TestBase {
assertEquals("f1=1,f2=2,f3=true|f1=x,f2=3,f3=false |null null", serialize(ps, a(a(new H1("1",2,true),new H1("x",3,false)),a(new H1(null,null,null),null),null)));
assertEquals("f1=1,f2=2,f3=true|f1=x,f2=3,f3=false |null null", serialize(ps, l(a(new H1("1",2,true),new H1("x",3,false)),a(new H1(null,null,null),null),null)));
assertEquals("f1=1,f2=2,f3=true|f1=x,f2=3,f3=false |null null", serialize(ps, l(l(new H1("1",2,true),new H1("x",3,false)),l(new H1(null,null,null),null),null)));
- assertEquals("f1=1,f2=2,f3=true|f1=x,f2=4,f3=false f1=null,f2=null,f3=null|null null", serialize(ps, a(a(Json5Map.ofJson5("{f1:'1',f2:2,f3:true}"),Json5Map.ofJson5("{f1:'x',f2:4,f3:false}")),a(Json5Map.ofJson5("{f1:null,f2:null,f3:null}"),null),null)));
- assertEquals("f1=1,f2=2,f3=true|f1=x,f2=4,f3=false f1=null,f2=null,f3=null|null null", serialize(ps, l(a(Json5Map.ofJson5("{f1:'1',f2:2,f3:true}"),Json5Map.ofJson5("{f1:'x',f2:4,f3:false}")),a(Json5Map.ofJson5("{f1:null,f2:null,f3:null}"),null),null)));
- assertEquals("f1=1,f2=2,f3=true|f1=x,f2=4,f3=false f1=null,f2=null,f3=null|null null", serialize(ps, l(l(Json5Map.ofJson5("{f1:'1',f2:2,f3:true}"),Json5Map.ofJson5("{f1:'x',f2:4,f3:false}")),l(Json5Map.ofJson5("{f1:null,f2:null,f3:null}"),null),null)));
- assertEquals("f1=1,f2=2,f3=true|f1=1,f2=2,f3=true |f1=null,f2=null,f3=null|null null", serialize(ps, a2(ao(new H1("1",2,true),Json5Map.ofJson5("{f1:'1',f2:2,f3:true}")),ao(new H1(null,null,null),Json5Map.ofJson5("{f1:null,f2:null,f3:null}"),null),null)));
- assertEquals("f1=1,f2=2,f3=true|f1=1,f2=2,f3=true |f1=null,f2=null,f3=null|null null", serialize(ps, l(ao(new H1("1",2,true),Json5Map.ofJson5("{f1:'1',f2:2,f3:true}")),ao(new H1(null,null,null),Json5Map.ofJson5("{f1:null,f2:null,f3:null}"),null),null)));
- assertEquals("f1=1,f2=2,f3=true|f1=1,f2=2,f3=true |f1=null,f2=null,f3=null|null null", serialize(ps, l(l(new H1("1",2,true),Json5Map.ofJson5("{f1:'1',f2:2,f3:true}")),l(new H1(null,null,null),Json5Map.ofJson5("{f1:null,f2:null,f3:null}"),null),null)));
+ assertEquals("f1=1,f2=2,f3=true|f1=x,f2=4,f3=false f1=null,f2=null,f3=null|null null", serialize(ps, a(a(Json5Map.ofText("{f1:'1',f2:2,f3:true}"),Json5Map.ofText("{f1:'x',f2:4,f3:false}")),a(Json5Map.ofText("{f1:null,f2:null,f3:null}"),null),null)));
+ assertEquals("f1=1,f2=2,f3=true|f1=x,f2=4,f3=false f1=null,f2=null,f3=null|null null", serialize(ps, l(a(Json5Map.ofText("{f1:'1',f2:2,f3:true}"),Json5Map.ofText("{f1:'x',f2:4,f3:false}")),a(Json5Map.ofText("{f1:null,f2:null,f3:null}"),null),null)));
+ assertEquals("f1=1,f2=2,f3=true|f1=x,f2=4,f3=false f1=null,f2=null,f3=null|null null", serialize(ps, l(l(Json5Map.ofText("{f1:'1',f2:2,f3:true}"),Json5Map.ofText("{f1:'x',f2:4,f3:false}")),l(Json5Map.ofText("{f1:null,f2:null,f3:null}"),null),null)));
+ assertEquals("f1=1,f2=2,f3=true|f1=1,f2=2,f3=true |f1=null,f2=null,f3=null|null null", serialize(ps, a2(ao(new H1("1",2,true),Json5Map.ofText("{f1:'1',f2:2,f3:true}")),ao(new H1(null,null,null),Json5Map.ofText("{f1:null,f2:null,f3:null}"),null),null)));
+ assertEquals("f1=1,f2=2,f3=true|f1=1,f2=2,f3=true |f1=null,f2=null,f3=null|null null", serialize(ps, l(ao(new H1("1",2,true),Json5Map.ofText("{f1:'1',f2:2,f3:true}")),ao(new H1(null,null,null),Json5Map.ofText("{f1:null,f2:null,f3:null}"),null),null)));
+ assertEquals("f1=1,f2=2,f3=true|f1=1,f2=2,f3=true |f1=null,f2=null,f3=null|null null", serialize(ps, l(l(new H1("1",2,true),Json5Map.ofText("{f1:'1',f2:2,f3:true}")),l(new H1(null,null,null),Json5Map.ofText("{f1:null,f2:null,f3:null}"),null),null)));
}
@Test void h03_objectType_3d_uon() throws Exception {
@@ -876,12 +876,12 @@ class OpenApiPartSerializer_Test extends TestBase {
assertEquals("@(@((f1='1',f2=2,f3=true),(f1=x,f2=3,f3=false)),@((),null),null)", serialize(ps, a(a(new H1("1",2,true),new H1("x",3,false)),a(new H1(null,null,null),null),null)));
assertEquals("@(@((f1='1',f2=2,f3=true),(f1=x,f2=3,f3=false)),@((),null),null)", serialize(ps, l(a(new H1("1",2,true),new H1("x",3,false)),a(new H1(null,null,null),null),null)));
assertEquals("@(@((f1='1',f2=2,f3=true),(f1=x,f2=3,f3=false)),@((),null),null)", serialize(ps, l(l(new H1("1",2,true),new H1("x",3,false)),l(new H1(null,null,null),null),null)));
- assertEquals("@(@((f1='1',f2=2,f3=true),(f1=x,f2=4,f3=false)),@((f1=null,f2=null,f3=null),null),null)", serialize(ps, a(a(Json5Map.ofJson5("{f1:'1',f2:2,f3:true}"),Json5Map.ofJson5("{f1:'x',f2:4,f3:false}")),a(Json5Map.ofJson5("{f1:null,f2:null,f3:null}"),null),null)));
- assertEquals("@(@((f1='1',f2=2,f3=true),(f1=x,f2=4,f3=false)),@((f1=null,f2=null,f3=null),null),null)", serialize(ps, l(a(Json5Map.ofJson5("{f1:'1',f2:2,f3:true}"),Json5Map.ofJson5("{f1:'x',f2:4,f3:false}")),a(Json5Map.ofJson5("{f1:null,f2:null,f3:null}"),null),null)));
- assertEquals("@(@((f1='1',f2=2,f3=true),(f1=x,f2=4,f3=false)),@((f1=null,f2=null,f3=null),null),null)", serialize(ps, l(l(Json5Map.ofJson5("{f1:'1',f2:2,f3:true}"),Json5Map.ofJson5("{f1:'x',f2:4,f3:false}")),l(Json5Map.ofJson5("{f1:null,f2:null,f3:null}"),null),null)));
- assertEquals("@(@((f1='1',f2=2,f3=true),(f1='1',f2=2,f3=true)),@((),(f1=null,f2=null,f3=null),null),null)", serialize(ps, a2(ao(new H1("1",2,true),Json5Map.ofJson5("{f1:'1',f2:2,f3:true}")),ao(new H1(null,null,null),Json5Map.ofJson5("{f1:null,f2:null,f3:null}"),null),null)));
- assertEquals("@(@((f1='1',f2=2,f3=true),(f1='1',f2=2,f3=true)),@((),(f1=null,f2=null,f3=null),null),null)", serialize(ps, l(ao(new H1("1",2,true),Json5Map.ofJson5("{f1:'1',f2:2,f3:true}")),ao(new H1(null,null,null),Json5Map.ofJson5("{f1:null,f2:null,f3:null}"),null),null)));
- assertEquals("@(@((f1='1',f2=2,f3=true),(f1='1',f2=2,f3=true)),@((),(f1=null,f2=null,f3=null),null),null)", serialize(ps, l(l(new H1("1",2,true),Json5Map.ofJson5("{f1:'1',f2:2,f3:true}")),l(new H1(null,null,null),Json5Map.ofJson5("{f1:null,f2:null,f3:null}"),null),null)));
+ assertEquals("@(@((f1='1',f2=2,f3=true),(f1=x,f2=4,f3=false)),@((f1=null,f2=null,f3=null),null),null)", serialize(ps, a(a(Json5Map.ofText("{f1:'1',f2:2,f3:true}"),Json5Map.ofText("{f1:'x',f2:4,f3:false}")),a(Json5Map.ofText("{f1:null,f2:null,f3:null}"),null),null)));
+ assertEquals("@(@((f1='1',f2=2,f3=true),(f1=x,f2=4,f3=false)),@((f1=null,f2=null,f3=null),null),null)", serialize(ps, l(a(Json5Map.ofText("{f1:'1',f2:2,f3:true}"),Json5Map.ofText("{f1:'x',f2:4,f3:false}")),a(Json5Map.ofText("{f1:null,f2:null,f3:null}"),null),null)));
+ assertEquals("@(@((f1='1',f2=2,f3=true),(f1=x,f2=4,f3=false)),@((f1=null,f2=null,f3=null),null),null)", serialize(ps, l(l(Json5Map.ofText("{f1:'1',f2:2,f3:true}"),Json5Map.ofText("{f1:'x',f2:4,f3:false}")),l(Json5Map.ofText("{f1:null,f2:null,f3:null}"),null),null)));
+ assertEquals("@(@((f1='1',f2=2,f3=true),(f1='1',f2=2,f3=true)),@((),(f1=null,f2=null,f3=null),null),null)", serialize(ps, a2(ao(new H1("1",2,true),Json5Map.ofText("{f1:'1',f2:2,f3:true}")),ao(new H1(null,null,null),Json5Map.ofText("{f1:null,f2:null,f3:null}"),null),null)));
+ assertEquals("@(@((f1='1',f2=2,f3=true),(f1='1',f2=2,f3=true)),@((),(f1=null,f2=null,f3=null),null),null)", serialize(ps, l(ao(new H1("1",2,true),Json5Map.ofText("{f1:'1',f2:2,f3:true}")),ao(new H1(null,null,null),Json5Map.ofText("{f1:null,f2:null,f3:null}"),null),null)));
+ assertEquals("@(@((f1='1',f2=2,f3=true),(f1='1',f2=2,f3=true)),@((),(f1=null,f2=null,f3=null),null),null)", serialize(ps, l(l(new H1("1",2,true),Json5Map.ofText("{f1:'1',f2:2,f3:true}")),l(new H1(null,null,null),Json5Map.ofText("{f1:null,f2:null,f3:null}"),null),null)));
}
public static class H2 {
diff --git a/juneau-utest/src/test/java/org/apache/juneau/json/Json_Test.java b/juneau-utest/src/test/java/org/apache/juneau/json/Json_Test.java
index 368f07213f..41993c1000 100755
--- a/juneau-utest/src/test/java/org/apache/juneau/json/Json_Test.java
+++ b/juneau-utest/src/test/java/org/apache/juneau/json/Json_Test.java
@@ -62,7 +62,7 @@ class Json_Test extends TestBase{
var r = "\\w[\\w\\-\\.]{3,}\\w";
m.put("x", r);
assertEquals("{\"x\":\"\\\\w[\\\\w\\\\-\\\\.]{3,}\\\\w\"}", s2.serialize(m));
- assertEquals(r, JsonMap.ofJson(s2.serialize(m)).getString("x"));
+ assertEquals(r, JsonMap.ofText(s2.serialize(m)).getString("x"));
// String = [foo\bar]
m.clear();
@@ -138,7 +138,7 @@ class Json_Test extends TestBase{
// Indentation
//====================================================================================================
@Test void a04_indentation() throws Exception {
- var m = Json5Map.ofJson5("{J:{B:['c',{D:'e'},['f',{G:'h'},1,false]]},I:'j'}");
+ var m = Json5Map.ofText("{J:{B:['c',{D:'e'},['f',{G:'h'},1,false]]},I:'j'}");
var e = """
{
J: {
diff --git a/juneau-utest/src/test/java/org/apache/juneau/json5/Json5List_Test.java b/juneau-utest/src/test/java/org/apache/juneau/json5/Json5List_Test.java
index 671cecca50..21b32ae3b0 100644
--- a/juneau-utest/src/test/java/org/apache/juneau/json5/Json5List_Test.java
+++ b/juneau-utest/src/test/java/org/apache/juneau/json5/Json5List_Test.java
@@ -39,8 +39,8 @@ class Json5List_Test extends TestBase {
assertEquals("[1,'two',true]", l.toString());
}
- @Test void a03_factoryOfJson5() throws Exception {
- var l = Json5List.ofJson5("[1,'two',true]");
+ @Test void a03_factoryOfText() throws Exception {
+ var l = Json5List.ofText("[1,'two',true]");
assertNotNull(l);
assertEquals(3, l.size());
assertEquals(1, l.getInt(0));
@@ -48,8 +48,8 @@ class Json5List_Test extends TestBase {
assertTrue(l.getBoolean(2));
}
- @Test void a04_factoryOfJson5NullInput() throws Exception {
- assertNull(Json5List.ofJson5((CharSequence)null));
+ @Test void a04_factoryOfTextNullInput() throws Exception {
+ assertNull(Json5List.ofText((CharSequence)null));
}
@Test void a05_factoryCreateAndAppend() {
@@ -139,7 +139,7 @@ class Json5List_Test extends TestBase {
@Test void a17_roundTripJson5() throws Exception {
var original = Json5List.of(1, "two", true);
var serialized = original.toString();
- var parsed = Json5List.ofJson5(serialized);
+ var parsed = Json5List.ofText(serialized);
assertEquals(1, parsed.getInt(0));
assertEquals("two", parsed.getString(1));
assertTrue(parsed.getBoolean(2));
diff --git a/juneau-utest/src/test/java/org/apache/juneau/json5/Json5Map_Test.java b/juneau-utest/src/test/java/org/apache/juneau/json5/Json5Map_Test.java
index 5b0d50b59c..2b07a3dc28 100644
--- a/juneau-utest/src/test/java/org/apache/juneau/json5/Json5Map_Test.java
+++ b/juneau-utest/src/test/java/org/apache/juneau/json5/Json5Map_Test.java
@@ -31,7 +31,7 @@ import org.junit.jupiter.api.*;
* These confirm that:
* <ul>
* <li>{@link Json5Map#toString()} produces JSON5 form.
- * <li>JSON5 default-parser constructors and {@code ofJson5} factories work.
+ * <li>JSON5 default-parser constructors and {@code ofText} factories work.
* <li>Covariant overrides on the get/fluent surface return {@code Json5Map} / {@code Json5List}, not the neutral base.
* <li>{@code writeTo(Writer)} uses {@link Json5Serializer#DEFAULT}.
* </ul>
@@ -49,15 +49,15 @@ class Json5Map_Test extends TestBase {
assertEquals("{a:1,b:'two'}", m.toString());
}
- @Test void a03_factoryOfJson5() throws Exception {
- var m = Json5Map.ofJson5("{a:1,b:'two'}");
+ @Test void a03_factoryOfText() throws Exception {
+ var m = Json5Map.ofText("{a:1,b:'two'}");
assertNotNull(m);
assertEquals(1, m.getInt("a"));
assertEquals("two", m.getString("b"));
}
- @Test void a04_factoryOfJson5NullInput() throws Exception {
- assertNull(Json5Map.ofJson5((CharSequence)null));
+ @Test void a04_factoryOfTextNullInput() throws Exception {
+ assertNull(Json5Map.ofText((CharSequence)null));
}
@Test void a05_factoryOfCreateAppend() {
@@ -180,7 +180,7 @@ class Json5Map_Test extends TestBase {
@Test void a21_roundTripJson5() throws Exception {
var original = Json5Map.of("a", 1, "b", "two", "c", true);
var serialized = original.toString();
- var parsed = Json5Map.ofJson5(serialized);
+ var parsed = Json5Map.ofText(serialized);
assertEquals(1, parsed.getInt("a"));
assertEquals("two", parsed.getString("b"));
assertTrue(parsed.getBoolean("c"));
diff --git a/juneau-utest/src/test/java/org/apache/juneau/jsonschema/JsonSchemaGeneratorTest.java b/juneau-utest/src/test/java/org/apache/juneau/jsonschema/JsonSchemaGeneratorTest.java
index 56ae6ec6c7..62dbac8a21 100755
--- a/juneau-utest/src/test/java/org/apache/juneau/jsonschema/JsonSchemaGeneratorTest.java
+++ b/juneau-utest/src/test/java/org/apache/juneau/jsonschema/JsonSchemaGeneratorTest.java
@@ -1522,10 +1522,6 @@ class JsonSchemaGeneratorTest extends TestBase {
public int value;
}
- //====================================================================================================
- // summary (TODO-6, since 9.5.0)
- //====================================================================================================
-
@Test void summary_typeLevel() throws Exception {
var s = JsonSchemaGenerator.DEFAULT.getSession();
assertBean(s.getSchema(SummaryBean.class), "type,summary,description", "object,A pet,Long description");
diff --git a/juneau-utest/src/test/java/org/apache/juneau/jsonschema/annotation/SchemaAnnotation_Test.java b/juneau-utest/src/test/java/org/apache/juneau/jsonschema/annotation/SchemaAnnotation_Test.java
index 29f145b9b5..e441d8193c 100644
--- a/juneau-utest/src/test/java/org/apache/juneau/jsonschema/annotation/SchemaAnnotation_Test.java
+++ b/juneau-utest/src/test/java/org/apache/juneau/jsonschema/annotation/SchemaAnnotation_Test.java
@@ -447,10 +447,6 @@ class SchemaAnnotation_Test extends TestBase {
assertBean(mixed, "exclusiveMaximum,exclusiveMinimum,exclusiveMaximumValue,exclusiveMinimumValue", "false,false,100,0");
}
- //------------------------------------------------------------------------------------------------------------------
- // summary / su (TODO-6, since 9.5.0)
- //------------------------------------------------------------------------------------------------------------------
-
@Test void g01_summary_asMap_emptyAnnotationOmitsKey() throws Exception {
assertFalse(SchemaAnnotation.asMap(SchemaAnnotation.DEFAULT).containsKey("summary"));
}
diff --git a/juneau-utest/src/test/java/org/apache/juneau/microservice/MicroserviceTestFixture.java b/juneau-utest/src/test/java/org/apache/juneau/microservice/MicroserviceTestFixture.java
index 931d4a6694..3d0b7f1033 100644
--- a/juneau-utest/src/test/java/org/apache/juneau/microservice/MicroserviceTestFixture.java
+++ b/juneau-utest/src/test/java/org/apache/juneau/microservice/MicroserviceTestFixture.java
@@ -26,7 +26,8 @@ import org.eclipse.jetty.server.*;
import org.junit.jupiter.api.extension.*;
/**
- * JUnit 5 extension that boots a {@link JettyMicroservice} on an ephemeral port for the duration of a test class.
+ * 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:
@@ -50,15 +51,14 @@ import org.junit.jupiter.api.extension.*;
*
* <h5 class='section'>How it works:</h5>
* <ul>
- * <li>The fixture supplies its own {@link Server} {@link Bean} factory ({@link EphemeralJettyServerConfig}) that
- * binds to port {@code 0} (OS-assigned ephemeral port). User-supplied configurations should typically
- * contribute {@code @Bean Servlet} definitions (which the {@link JettyMicroservice} auto-mounts at
- * {@code @Rest(path=...)}); a user-supplied {@code @Bean Server} will conflict and is not supported here.
- * <li>{@link #beforeAll(ExtensionContext) beforeAll} builds the microservice, calls
- * {@link JettyMicroservice#createServer() createServer()}, and then
- * {@link JettyMicroservice#start() start()}.
- * <li>{@link #afterAll(ExtensionContext) afterAll} calls {@link JettyMicroservice#stop() stop()} so the bound
- * port is released and {@code @PreDestroy} hooks on bean-store beans fire.
+ * <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>
@@ -69,7 +69,7 @@ import org.junit.jupiter.api.extension.*;
public final class MicroserviceTestFixture implements BeforeAllCallback, AfterAllCallback {
private final List<Class<?>> configurations = new ArrayList<>();
- private JettyMicroservice microservice;
+ private Microservice microservice;
private URI rootUrl;
private MicroserviceTestFixture() {}
@@ -118,26 +118,38 @@ public final class MicroserviceTestFixture implements BeforeAllCallback, AfterAl
*
* @return The microservice.
*/
- public JettyMicroservice getMicroservice() {
+ 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). Our default Server
- // factory is registered last via configurations() — JettyMicroservice resolves Server from the bean
- // store by type, and BeanStore.getBean(...) returns the first registered match.
+ // 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);
- microservice = JettyMicroservice.create()
+ classes.add(JettyConfiguration.class);
+ microservice = Microservice.create()
.configurations(classes.toArray(new Class<?>[0]))
.build();
microservice.start();
- // JettyMicroservice.getURI() uses InetAddress.getLocalHost().getHostName() (may resolve to a non-loopback
+ // 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 : microservice.getServer().getConnectors()) {
+ for (var c : server.getConnectors()) {
if (c instanceof ServerConnector sc) {
localPort = sc.getLocalPort();
break;
@@ -159,15 +171,15 @@ public final class MicroserviceTestFixture implements BeforeAllCallback, AfterAl
*
* <p>
* The server has a single {@link ServerConnector} on port 0 (OS-assigned) and a single root
- * {@link ServletContextHandler} at context path {@code "/"}. {@code JettyMicroservice} discovers the handler
+ * {@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 the microservice consumes during
- * {@link JettyMicroservice#createServer()}.
+ * Provides the bean-supplied Jetty {@link Server} that {@link JettyServerComponent} consumes during
+ * {@code onStart()}.
*
* @return A configured {@link Server} bound to port 0.
*/
diff --git a/juneau-utest/src/test/java/org/apache/juneau/microservice/Microservice_Listener_Fanout_Test.java b/juneau-utest/src/test/java/org/apache/juneau/microservice/Microservice_Listener_Fanout_Test.java
new file mode 100644
index 0000000000..04d8b9ce18
--- /dev/null
+++ b/juneau-utest/src/test/java/org/apache/juneau/microservice/Microservice_Listener_Fanout_Test.java
@@ -0,0 +1,141 @@
+/*
+ * 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 static org.junit.jupiter.api.Assertions.*;
+
+import java.util.*;
+
+import org.apache.juneau.*;
+import org.apache.juneau.commons.inject.*;
+import org.apache.juneau.config.event.*;
+import org.junit.jupiter.api.*;
+
+/**
+ * Verifies the {@link MicroserviceListener} fan-out behavior in {@link Microservice}.
+ *
+ * <p>
+ * Listeners contributed via {@link Microservice.Builder#listener(MicroserviceListener)} and any
+ * {@code @Bean MicroserviceListener} methods supplied by {@code @Configuration} classes are all invoked
+ * for each lifecycle event ({@link Microservice#start()}, {@link Microservice#stop()}, and config-change
+ * notifications). {@code onStart} runs in registration order; {@code onStop} runs in the reverse order.
+ */
+class Microservice_Listener_Fanout_Test extends TestBase {
+
+ /**
+ * Recording listener that captures invocation order across instances.
+ */
+ static final class Recorder implements MicroserviceListener {
+ final String name;
+ final List<String> log;
+
+ Recorder(String name, List<String> log) {
+ this.name = name;
+ this.log = log;
+ }
+
+ @Override
+ public void onStart(Microservice ms) {
+ log.add("start:" + name);
+ }
+
+ @Override
+ public void onStop(Microservice ms) {
+ log.add("stop:" + name);
+ }
+
+ @Override
+ public void onConfigChange(Microservice ms, ConfigEvents events) {
+ log.add("config:" + name);
+ }
+ }
+
+ //-----------------------------------------------------------------------------------------------------------------
+ // A. Fan-out: explicit + @Bean listeners both fire in registration order on start, reverse on stop.
+ //-----------------------------------------------------------------------------------------------------------------
+
+ static final List<String> A_LOG = Collections.synchronizedList(new ArrayList<>());
+
+ @Configuration
+ static class A_TwoBeanListeners {
+ @Bean(name = "first") MicroserviceListener first() { return new Recorder("first", A_LOG); }
+ @Bean(name = "second") MicroserviceListener second() { return new Recorder("second", A_LOG); }
+ }
+
+ @Test void a01_fanOut_startThenReverseStop() throws Exception {
+ A_LOG.clear();
+ var explicit = new Recorder("explicit", A_LOG);
+ var ms = Microservice.create()
+ .listener(explicit)
+ .configurations(A_TwoBeanListeners.class)
+ .build();
+ try {
+ ms.start();
+ } finally {
+ ms.stop();
+ }
+ // All three listeners must fire once for start and once for stop.
+ assertEquals(6, A_LOG.size(), () -> "log=" + A_LOG);
+ var startLog = A_LOG.subList(0, 3);
+ var stopLog = A_LOG.subList(3, 6);
+ assertTrue(startLog.stream().allMatch(s -> s.startsWith("start:")));
+ assertTrue(stopLog.stream().allMatch(s -> s.startsWith("stop:")));
+ // Each listener fired in both phases.
+ for (var who : List.of("first", "second", "explicit")) {
+ assertTrue(startLog.contains("start:" + who), () -> "missing start:" + who + " in " + startLog);
+ assertTrue(stopLog.contains("stop:" + who), () -> "missing stop:" + who + " in " + stopLog);
+ }
+ // stop order is the exact reverse of start order — this is the lifecycle contract.
+ var startNames = startLog.stream().map(s -> s.substring("start:".length())).toList();
+ var stopNames = stopLog.stream().map(s -> s.substring("stop:".length())).toList();
+ var reversed = new ArrayList<>(startNames);
+ Collections.reverse(reversed);
+ assertEquals(reversed, stopNames, "stop order must be reverse of start order");
+ }
+
+ //-----------------------------------------------------------------------------------------------------------------
+ // B. Default listener: registered iff no listeners exist after configurations + builder are processed.
+ //-----------------------------------------------------------------------------------------------------------------
+
+ @Test void b01_noListeners_defaultBasicListenerRegistered() throws Exception {
+ var ms = Microservice.create().build();
+ try {
+ var listeners = ms.getBeanStore().getBeansOfType(MicroserviceListener.class).values();
+ assertEquals(1, listeners.size());
+ assertInstanceOf(BasicMicroserviceListener.class, listeners.iterator().next());
+ } finally {
+ ms.stop();
+ }
+ }
+
+ @Configuration
+ static class B_NamedListenerOnly {
+ @Bean(name = "only") MicroserviceListener only() { return new BasicMicroserviceListener(); }
+ }
+
+ @Test void b02_namedListenerPresent_noDefaultAdded() throws Exception {
+ var ms = Microservice.create().configurations(B_NamedListenerOnly.class).build();
+ try {
+ // Only the named listener should be present; no unnamed default added.
+ var listeners = ms.getBeanStore().getBeansOfType(MicroserviceListener.class);
+ assertEquals(1, listeners.size());
+ assertEquals("only", listeners.keySet().iterator().next());
+ } finally {
+ ms.stop();
+ }
+ }
+}
diff --git a/juneau-utest/src/test/java/org/apache/juneau/microservice/jetty/BasicJettyMicroserviceListener_Test.java b/juneau-utest/src/test/java/org/apache/juneau/microservice/jetty/BasicJettyMicroserviceListener_Test.java
deleted file mode 100644
index bfe7f0b71c..0000000000
--- a/juneau-utest/src/test/java/org/apache/juneau/microservice/jetty/BasicJettyMicroserviceListener_Test.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.microservice.jetty;
-
-import static org.junit.jupiter.api.Assertions.*;
-
-import org.apache.juneau.*;
-import org.junit.jupiter.api.*;
-
-/**
- * Tests for {@link BasicJettyMicroserviceListener}.
- */
-class BasicJettyMicroserviceListener_Test extends TestBase {
-
- @Test void a01_instantiate() {
- assertDoesNotThrow(() -> new BasicJettyMicroserviceListener());
- }
-
- @Test void a02_onCreateServer() {
- assertDoesNotThrow(() -> new BasicJettyMicroserviceListener().onCreateServer(null));
- }
-
- @Test void a03_onPostStartServer() {
- assertDoesNotThrow(() -> new BasicJettyMicroserviceListener().onPostStartServer(null));
- }
-
- @Test void a04_onPostStopServer() {
- assertDoesNotThrow(() -> new BasicJettyMicroserviceListener().onPostStopServer(null));
- }
-
- @Test void a05_onStartServer() {
- assertDoesNotThrow(() -> new BasicJettyMicroserviceListener().onStartServer(null));
- }
-
- @Test void a06_onStopServer() {
- assertDoesNotThrow(() -> new BasicJettyMicroserviceListener().onStopServer(null));
- }
-}
diff --git a/juneau-utest/src/test/java/org/apache/juneau/microservice/jetty/JettyMicroservice_Inject_Test.java b/juneau-utest/src/test/java/org/apache/juneau/microservice/jetty/JettyConfiguration_Test.java
similarity index 67%
rename from juneau-utest/src/test/java/org/apache/juneau/microservice/jetty/JettyMicroservice_Inject_Test.java
rename to juneau-utest/src/test/java/org/apache/juneau/microservice/jetty/JettyConfiguration_Test.java
index 5f3fcfe947..d15b8c0cbd 100644
--- a/juneau-utest/src/test/java/org/apache/juneau/microservice/jetty/JettyMicroservice_Inject_Test.java
+++ b/juneau-utest/src/test/java/org/apache/juneau/microservice/jetty/JettyConfiguration_Test.java
@@ -20,6 +20,7 @@ import static org.junit.jupiter.api.Assertions.*;
import org.apache.juneau.*;
import org.apache.juneau.commons.inject.*;
+import org.apache.juneau.microservice.*;
import org.apache.juneau.rest.annotation.*;
import org.apache.juneau.rest.servlet.*;
import org.eclipse.jetty.ee11.servlet.*;
@@ -30,40 +31,47 @@ import jakarta.servlet.*;
import jakarta.servlet.http.*;
/**
- * Tests for the inject-aware {@link JettyMicroservice} bootstrap.
+ * Tests for the inject-aware Jetty microservice bootstrap via {@link JettyConfiguration}.
*
* <p>
- * Verifies that <c>@Configuration</c>-supplied <c>JettyServerFactory</c> /
- * <c>JettyMicroserviceListener</c> / <c>Server</c> / <c>Servlet</c> beans are picked up,
- * that explicit builder calls take precedence, that auto-discovered <c>@Rest</c> servlets
- * are mounted at <c>@Rest(path=...)</c>, and that duplicate mount paths fail fast.
+ * Verifies that <c>@Configuration</c>-supplied <c>JettyServerFactory</c> / <c>JettyServerComponent</c>
+ * / <c>Server</c> / <c>Servlet</c> beans are picked up via the {@link JettyConfiguration} bean wiring,
+ * that auto-discovered <c>@Rest</c> servlets are mounted at <c>@Rest(path=...)</c>, and that duplicate
+ * mount paths fail fast.
*/
-class JettyMicroservice_Inject_Test extends TestBase {
+class JettyConfiguration_Test extends TestBase {
+
+ private static Microservice create(Class<?>... configurations) throws Exception {
+ var classes = new Class<?>[configurations.length + 1];
+ System.arraycopy(configurations, 0, classes, 0, configurations.length);
+ classes[configurations.length] = JettyConfiguration.class;
+ return Microservice.create().configurations(classes).build();
+ }
//-----------------------------------------------------------------------------------------------------------------
// A. Bean store presence + self-registration of Jetty-specific beans.
//-----------------------------------------------------------------------------------------------------------------
- @Test void a01_beanStore_containsJettyMicroservice() throws Exception {
- var ms = JettyMicroservice.create().build();
+ @Test void a01_beanStore_containsMicroservice() throws Exception {
+ var ms = create();
try {
- assertSame(ms, ms.getBeanStore().getBean(JettyMicroservice.class).orElse(null));
+ assertSame(ms, ms.getBeanStore().getBean(Microservice.class).orElse(null));
} finally {
ms.stop();
}
}
- @Test void a02_beanStore_containsJettyListener() throws Exception {
- var ms = JettyMicroservice.create().build();
+ @Test void a02_beanStore_containsJettyServerComponent() throws Exception {
+ var ms = create();
try {
- assertNotNull(ms.getBeanStore().getBean(JettyMicroserviceListener.class).orElse(null));
+ assertNotNull(ms.getBeanStore().getBean(JettyServerComponent.class).orElse(null));
} finally {
ms.stop();
}
}
@Test void a03_beanStore_containsJettyServerFactory() throws Exception {
- var ms = JettyMicroservice.create().build();
+ var ms = create();
try {
assertNotNull(ms.getBeanStore().getBean(JettyServerFactory.class).orElse(null));
} finally {
@@ -71,8 +79,17 @@ class JettyMicroservice_Inject_Test extends TestBase {
}
}
+ @Test void a04_beanStore_containsJettySettings() throws Exception {
+ var ms = create();
+ try {
+ assertNotNull(ms.getBeanStore().getBean(JettySettings.class).orElse(null));
+ } finally {
+ ms.stop();
+ }
+ }
+
//-----------------------------------------------------------------------------------------------------------------
- // B. Resolution priority: explicit builder > @Bean > default.
+ // B. Resolution priority: user-supplied @Bean beats JettyConfiguration default.
//-----------------------------------------------------------------------------------------------------------------
static class TestFactory extends BasicJettyServerFactory {
@@ -84,23 +101,8 @@ class JettyMicroservice_Inject_Test extends TestBase {
@Bean JettyServerFactory factory() { return new TestFactory(); }
}
- @Test void b01_explicitFactory_beatsConfigurationFactory() throws Exception {
- var explicit = new BasicJettyServerFactory();
- var ms = JettyMicroservice.create()
- .jettyServerFactory(explicit)
- .configurations(B_FactoryConfig.class)
- .build();
- try {
- assertSame(explicit, ms.getBeanStore().getBean(JettyServerFactory.class).orElse(null));
- } finally {
- ms.stop();
- }
- }
-
- @Test void b02_configurationFactory_usedWhenNoBuilderFactory() throws Exception {
- var ms = JettyMicroservice.create()
- .configurations(B_FactoryConfig.class)
- .build();
+ @Test void b01_userFactory_beatsConfigurationDefault() throws Exception {
+ var ms = create(B_FactoryConfig.class);
try {
assertInstanceOf(TestFactory.class, ms.getBeanStore().getBean(JettyServerFactory.class).orElse(null));
} finally {
@@ -109,19 +111,15 @@ class JettyMicroservice_Inject_Test extends TestBase {
}
@Configuration
- static class B_ListenerConfig {
- @Bean JettyMicroserviceListener listener() { return new BasicJettyMicroserviceListener() {}; }
+ static class B_SettingsConfig {
+ @Bean JettySettings jettySettings() { return JettySettings.create().ports(9999).build(); }
}
- @Test void b03_configurationListener_usedWhenNoBuilderListener() throws Exception {
- var ms = JettyMicroservice.create()
- .configurations(B_ListenerConfig.class)
- .build();
+ @Test void b02_userSettings_beatsConfigurationDefault() throws Exception {
+ var ms = create(B_SettingsConfig.class);
try {
- // The contributed listener bean should be the resolved one.
- var configured = ms.getBeanStore().getBeansOfType(JettyMicroserviceListener.class).values().iterator().next();
- assertNotNull(configured);
- assertNotSame(BasicJettyMicroserviceListener.class, configured.getClass()); // it's the anonymous subclass
+ var resolved = ms.getBeanStore().getBean(JettySettings.class).orElseThrow();
+ assertArrayEquals(new int[]{9999}, resolved.getPorts());
} finally {
ms.stop();
}
@@ -144,6 +142,9 @@ class JettyMicroservice_Inject_Test extends TestBase {
static class C_AutoMountConfig {
@Bean Server jettyServer() {
var server = new Server();
+ var connector = new ServerConnector(server);
+ connector.setPort(0);
+ server.addConnector(connector);
var ctx = new ServletContextHandler();
ctx.setContextPath("/");
server.setAttribute("ServletContextHandler", ctx);
@@ -156,12 +157,10 @@ class JettyMicroservice_Inject_Test extends TestBase {
}
@Test void c01_restServletAutoMounted_atRestPath() throws Exception {
- var ms = JettyMicroservice.create()
- .configurations(C_AutoMountConfig.class)
- .build();
+ var ms = create(C_AutoMountConfig.class);
try {
- ms.createServer();
- var ctx = ms.getServletContextHandler();
+ ms.start();
+ var ctx = ms.getBeanStore().getBean(JettyServerComponent.class).orElseThrow().getServletContextHandler();
var mounted = false;
for (var h : ctx.getServletHandler().getServletMappings()) {
for (var p : h.getPathSpecs()) {
@@ -181,6 +180,9 @@ class JettyMicroservice_Inject_Test extends TestBase {
static class C_NoRestServletConfig {
@Bean Server jettyServer() {
var server = new Server();
+ var connector = new ServerConnector(server);
+ connector.setPort(0);
+ server.addConnector(connector);
var ctx = new ServletContextHandler();
ctx.setContextPath("/");
server.setAttribute("ServletContextHandler", ctx);
@@ -191,15 +193,16 @@ class JettyMicroservice_Inject_Test extends TestBase {
}
@Test void c02_servletWithoutRestAnnotation_isNotAutoMounted() throws Exception {
- var ms = JettyMicroservice.create()
- .configurations(C_NoRestServletConfig.class)
- .build();
+ var ms = create(C_NoRestServletConfig.class);
try {
- ms.createServer();
- var ctx = ms.getServletContextHandler();
- // PlainServlet has no @Rest, so it should NOT be auto-mounted.
- assertEquals(0, ctx.getServletHandler().getServletMappings().length,
- "plain Servlet without @Rest should not be auto-mounted");
+ ms.start();
+ var ctx = ms.getBeanStore().getBean(JettyServerComponent.class).orElseThrow().getServletContextHandler();
+ // PlainServlet has no @Rest, so its class name should not appear in any servlet mapping.
+ var plainName = PlainServlet.class.getName();
+ for (var holder : ctx.getServletHandler().getServlets()) {
+ assertNotEquals(plainName, holder.getClassName(),
+ "plain Servlet without @Rest should not be auto-mounted");
+ }
} finally {
ms.stop();
}
@@ -213,6 +216,9 @@ class JettyMicroservice_Inject_Test extends TestBase {
static class D_CollisionConfig {
@Bean Server jettyServer() {
var server = new Server();
+ var connector = new ServerConnector(server);
+ connector.setPort(0);
+ server.addConnector(connector);
var ctx = new ServletContextHandler();
ctx.setContextPath("/");
server.setAttribute("ServletContextHandler", ctx);
@@ -224,11 +230,9 @@ class JettyMicroservice_Inject_Test extends TestBase {
}
@Test void d01_pathCollision_failsHard() throws Exception {
- var ms = JettyMicroservice.create()
- .configurations(D_CollisionConfig.class)
- .build();
+ var ms = create(D_CollisionConfig.class);
try {
- var ex = assertThrows(Exception.class, ms::createServer);
+ var ex = assertThrows(Exception.class, ms::start);
var root = ThrowableUtils.getCause(ex);
assertTrue(root.getMessage().contains("Servlet mount path collision"),
"expected path-collision error, got: " + root.getMessage());
diff --git a/juneau-utest/src/test/java/org/apache/juneau/microservice/jetty/JettyMicroservice_Builder_Test.java b/juneau-utest/src/test/java/org/apache/juneau/microservice/jetty/JettyMicroservice_Builder_Test.java
deleted file mode 100644
index 2deafbcbf6..0000000000
--- a/juneau-utest/src/test/java/org/apache/juneau/microservice/jetty/JettyMicroservice_Builder_Test.java
+++ /dev/null
@@ -1,181 +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.microservice.jetty;
-
-import static org.junit.jupiter.api.Assertions.*;
-
-import java.io.*;
-import java.util.*;
-
-import org.apache.juneau.*;
-import org.apache.juneau.microservice.console.*;
-import org.junit.jupiter.api.*;
-
-import jakarta.servlet.*;
-
-/**
- * Tests for {@link JettyMicroservice.Builder} methods.
- */
-class JettyMicroservice_Builder_Test extends TestBase {
-
- @Test void a01_create() {
- var b = JettyMicroservice.create();
- assertNotNull(b);
- }
-
- @Test void a02_getInstance_noInstance() {
- assertDoesNotThrow(() -> JettyMicroservice.getInstance());
- }
-
- @Test void a03_builder_args_array() {
- // Just verify the call doesn't throw - field is package-private in parent
- assertDoesNotThrow(() -> JettyMicroservice.create().args("--port", "8080"));
- }
-
- @Test void a04_builder_configName() {
- // Just verify fluent return works - field is package-private in parent
- var b = JettyMicroservice.create().configName("myapp.cfg");
- assertNotNull(b);
- }
-
- @Test void a05_builder_consoleEnabled() {
- var b = JettyMicroservice.create().consoleEnabled(true);
- assertNotNull(b);
- }
-
- @Test void a06_builder_consoleCommands() {
- var cmd = new ExitCommand();
- var b = JettyMicroservice.create().consoleCommands(cmd);
- assertNotNull(b);
- }
-
- @Test void a07_builder_listener() {
- var listener = new BasicJettyMicroserviceListener();
- var b = JettyMicroservice.create().listener(listener);
- // listener2 is accessible from within the jetty package
- assertSame(listener, b.listener2);
- }
-
- @Test void a08_builder_jettyServerFactory() {
- var factory = new BasicJettyServerFactory();
- var b = JettyMicroservice.create().jettyServerFactory(factory);
- assertSame(factory, b.factory);
- }
-
- @Test void a09_builder_ports() {
- var b = JettyMicroservice.create().ports(8080, 8443);
- assertArrayEquals(new int[]{8080, 8443}, b.ports);
- }
-
- @Test void a10_builder_servlet_instance() {
- var servlet = new MockServlet();
- var b = JettyMicroservice.create().servlet(servlet, "/test");
- assertTrue(b.servlets.containsKey("/test"));
- assertSame(servlet, b.servlets.get("/test"));
- }
-
- @Test void a11_builder_servletAttribute_nameValue() {
- var b = JettyMicroservice.create().servletAttribute("key1", "value1");
- assertEquals("value1", b.servletAttributes.get("key1"));
- }
-
- @Test void a12_builder_servletAttribute_map() {
- var b = JettyMicroservice.create().servletAttribute(Map.of("key2", "value2", "key3", "value3"));
- assertEquals("value2", b.servletAttributes.get("key2"));
- assertEquals("value3", b.servletAttributes.get("key3"));
- }
-
- @Test void a13_builder_servletAttribute_nullMap() {
- var b = JettyMicroservice.create().servletAttribute(null);
- assertTrue(b.servletAttributes.isEmpty());
- }
-
- @Test void a14_builder_servlets_map() {
- var servlet = new MockServlet();
- var b = JettyMicroservice.create().servlets(Map.of("/path", servlet));
- assertSame(servlet, b.servlets.get("/path"));
- }
-
- @Test void a15_builder_servlets_nullMap() {
- var b = JettyMicroservice.create().servlets(null);
- assertTrue(b.servlets.isEmpty());
- }
-
- @Test void a16_builder_workingDir_file() {
- assertDoesNotThrow(() -> JettyMicroservice.create().workingDir(new File("/tmp")));
- }
-
- @Test void a17_builder_workingDir_string() {
- assertDoesNotThrow(() -> JettyMicroservice.create().workingDir("/tmp"));
- }
-
- @Test void a18_builder_copy() {
- var b = JettyMicroservice.create()
- .ports(9090)
- .servletAttribute("attr1", "val1");
- var copy = b.copy();
- assertNotSame(b, copy);
- assertArrayEquals(new int[]{9090}, copy.ports);
- assertEquals("val1", copy.servletAttributes.get("attr1"));
- }
-
- @Test void a19_builder_jettyXml_reader() throws Exception {
- var xml = "<Configure />";
- var b = JettyMicroservice.create().jettyXml(new StringReader(xml), false);
- assertEquals(xml, b.jettyXml);
- assertEquals(Boolean.FALSE, b.jettyXmlResolveVars);
- }
-
- @Test void a20_builder_jettyXml_inputStream() throws Exception {
- var xml = "<Configure />";
- var b = JettyMicroservice.create().jettyXml(new ByteArrayInputStream(xml.getBytes()), false);
- assertEquals(xml, b.jettyXml);
- }
-
- @Test void a21_builder_jettyXml_invalidType() {
- assertThrows(RuntimeException.class, () -> JettyMicroservice.create().jettyXml(42, false));
- }
-
- @Test void a22_builder_jettyXml_resolveVars_true() throws Exception {
- var xml = "<Configure />";
- var b = JettyMicroservice.create().jettyXml(new StringReader(xml), true);
- assertEquals(Boolean.TRUE, b.jettyXmlResolveVars);
- }
-
- @Test void a23_builder_console() {
- var reader = new java.util.Scanner(System.in);
- var writer = new PrintWriter(System.out);
- assertDoesNotThrow(() -> JettyMicroservice.create().console(reader, writer));
- }
-
- @Test void a24_builder_logger() {
- assertDoesNotThrow(() -> JettyMicroservice.create().logger(java.util.logging.Logger.getLogger("test")));
- }
-
- @Test void a25_builder_manifest_null() {
- assertDoesNotThrow(() -> JettyMicroservice.create().manifest((Object)null));
- }
-
- // Minimal no-op servlet for testing.
- static class MockServlet implements Servlet {
- @Override public void init(ServletConfig config) {}
- @Override public ServletConfig getServletConfig() { return null; }
- @Override public void service(ServletRequest req, ServletResponse res) {}
- @Override public String getServletInfo() { return "mock"; }
- @Override public void destroy() {}
- }
-}
diff --git a/juneau-utest/src/test/java/org/apache/juneau/msgpack/MsgPackSerializerTest.java b/juneau-utest/src/test/java/org/apache/juneau/msgpack/MsgPackSerializerTest.java
index b65bffa494..a3e029a4dc 100755
--- a/juneau-utest/src/test/java/org/apache/juneau/msgpack/MsgPackSerializerTest.java
+++ b/juneau-utest/src/test/java/org/apache/juneau/msgpack/MsgPackSerializerTest.java
@@ -206,10 +206,10 @@ class MsgPackSerializerTest extends TestBase {
// * odd elements in objects are keys of a map
// * the next element of a key is its associated value
- test(Json5Map.ofJson5("{}"), "80");
- test(Json5Map.ofJson5("{1:1}"), "81 A1 31 01");
- test(Json5Map.ofJson5("{1:1,2:1,3:1,4:1,5:1,6:1,7:1,8:1,9:1,a:1,b:1,c:1,d:1,e:1,f:1}"), "8F A1 31 01 A1 32 01 A1 33 01 A1 34 01 A1 35 01 A1 36 01 A1 37 01 A1 38 01 A1 39 01 A1 61 01 A1 62 01 A1 63 01 A1 64 01 A1 65 01 A1 66 01");
- test(Json5Map.ofJson5("{1:1,2:1,3:1,4:1,5:1,6:1,7:1,8:1,9:1,a:1,b:1,c:1,d:1,e:1,f:1,g:1}"), "DE 00 10 A1 31 01 A1 32 01 A1 33 01 A1 34 01 A1 35 01 A1 36 01 A1 37 01 A1 38 01 A1 39 01 A1 61 01 A1 62 01 A1 63 01 A1 64 01 A1 65 01 A1 66 01 A1 67 01");
+ test(Json5Map.ofText("{}"), "80");
+ test(Json5Map.ofText("{1:1}"), "81 A1 31 01");
+ test(Json5Map.ofText("{1:1,2:1,3:1,4:1,5:1,6:1,7:1,8:1,9:1,a:1,b:1,c:1,d:1,e:1,f:1}"), "8F A1 31 01 A1 32 01 A1 33 01 A1 34 01 A1 35 01 A1 36 01 A1 37 01 A1 38 01 A1 39 01 A1 61 01 A1 62 01 A1 63 01 A1 64 01 A1 65 01 A1 66 01");
+ test(Json5Map.ofText("{1:1,2:1,3:1,4:1,5:1,6:1,7:1,8:1,9:1,a:1,b:1,c:1,d:1,e:1,f:1,g:1}"), "DE 00 10 A1 31 01 A1 32 01 A1 33 01 A1 34 01 A1 35 01 A1 36 01 A1 37 01 A1 38 01 A1 39 01 A1 61 01 A1 62 01 A1 63 01 A1 64 01 A1 65 01 A1 66 01 A1 67 01");
}
public static class Person {
diff --git a/juneau-utest/src/test/java/org/apache/juneau/objecttools/ObjectRest_Test.java b/juneau-utest/src/test/java/org/apache/juneau/objecttools/ObjectRest_Test.java
index 71d4d0e14f..d1448ace77 100755
--- a/juneau-utest/src/test/java/org/apache/juneau/objecttools/ObjectRest_Test.java
+++ b/juneau-utest/src/test/java/org/apache/juneau/objecttools/ObjectRest_Test.java
@@ -174,11 +174,11 @@ class ObjectRest_Test extends TestBase {
assertEquals("{}", s);
// Make sure doing a PUT against "" or "/" replaces the root object.
- var m2 = Json5Map.ofJson5("{x:1}");
+ var m2 = Json5Map.ofText("{x:1}");
model.put("", m2);
s = model.get("").toString();
assertEquals("{x:1}", s);
- m2 = Json5Map.ofJson5("{x:2}");
+ m2 = Json5Map.ofText("{x:2}");
model.put("/", m2);
s = model.get("").toString();
assertEquals("{x:2}", s);
@@ -325,8 +325,8 @@ class ObjectRest_Test extends TestBase {
//====================================================================================================
@Test void f01_getMethods() throws Exception {
var model = ObjectRest.create(new A());
- var l = Json5List.ofJson5("[{a:'b'}]");
- var m = Json5Map.ofJson5("{a:'b'}");
+ var l = Json5List.ofText("[{a:'b'}]");
+ var m = Json5Map.ofText("{a:'b'}");
var jm = new JsonMap(m);
var jl = new JsonList(l);
@@ -719,10 +719,10 @@ class ObjectRest_Test extends TestBase {
f3a = 3L;
f4a = true;
try {
- f5 = Json5Map.ofJson5("{f5a:'a'}");
- f6 = Json5List.ofJson5("[{f6a:'a'}]");
- f7 = Json5Map.ofJson5("{f5a:'a'}");
- f8 = Json5List.ofJson5("[{f6a:'a'}]");
+ f5 = Json5Map.ofText("{f5a:'a'}");
+ f6 = Json5List.ofText("[{f6a:'a'}]");
+ f7 = Json5Map.ofText("{f5a:'a'}");
+ f8 = Json5List.ofText("[{f6a:'a'}]");
} catch (ParseException e) {
throw new RuntimeException(e);
}
diff --git a/juneau-utest/src/test/java/org/apache/juneau/rest/annotation/RestInit_Test.java b/juneau-utest/src/test/java/org/apache/juneau/rest/annotation/RestInit_Test.java
index 2420b59671..533cf381cd 100644
--- a/juneau-utest/src/test/java/org/apache/juneau/rest/annotation/RestInit_Test.java
+++ b/juneau-utest/src/test/java/org/apache/juneau/rest/annotation/RestInit_Test.java
@@ -26,16 +26,6 @@ import jakarta.servlet.*;
class RestInit_Test extends TestBase {
- //------------------------------------------------------------------------------------------------------------------
- // @RestInit
- //
- // Pre-9.5 this test also covered `@RestInit public void initX(RestContext.Builder b)` — the framework
- // injected the in-flight RestContext.Builder so user code could imperatively configure the context.
- // That protocol was deleted in TODO-16 Phase C-3 (Builder is no longer a user-visible bean), so the
- // `init1c(RestContext.Builder)` cases were dropped along with it. The remaining cases still cover
- // no-arg invocation, ServletConfig injection, and inheritance / override ordering.
- //------------------------------------------------------------------------------------------------------------------
-
@Rest(children={A_Super.class,A_Sub.class})
public static class A {}
diff --git a/juneau-utest/src/test/java/org/apache/juneau/rest/annotation/Rest_BeanCreatorOverrides_Test.java b/juneau-utest/src/test/java/org/apache/juneau/rest/annotation/Rest_BeanCreatorOverrides_Test.java
index 1203a338b5..af55f150fb 100644
--- a/juneau-utest/src/test/java/org/apache/juneau/rest/annotation/Rest_BeanCreatorOverrides_Test.java
+++ b/juneau-utest/src/test/java/org/apache/juneau/rest/annotation/Rest_BeanCreatorOverrides_Test.java
@@ -35,10 +35,6 @@ import org.junit.jupiter.api.*;
* walks the `@Rest` hierarchy via `getRestAnnotationsForProperty(...)` and picks the first
* non-{@code Void} class. This test exercises the "non-Void annotation wins" branch that was
* previously uncovered by tests.
- *
- * <p>
- * See {@code todo/TODO-16-restcontext-memoized-fields.md} (Decision #21) for the coverage
- * mandate.
*/
class Rest_BeanCreatorOverrides_Test extends TestBase {
diff --git a/juneau-utest/src/test/java/org/apache/juneau/uon/UonSerializer_Test.java b/juneau-utest/src/test/java/org/apache/juneau/uon/UonSerializer_Test.java
index a0e65bd68d..1dbff17c94 100755
--- a/juneau-utest/src/test/java/org/apache/juneau/uon/UonSerializer_Test.java
+++ b/juneau-utest/src/test/java/org/apache/juneau/uon/UonSerializer_Test.java
@@ -43,26 +43,26 @@ class UonSerializer_Test {
assertEquals("a", sr.serialize(t));
// 2nd level
- t = Json5Map.ofJson5("{a:'a'}");
+ t = Json5Map.ofText("{a:'a'}");
assertEquals("(a=a)", s.serialize(t));
assertEquals("(a=a)", su.serialize(t));
assertEquals("(\n\ta=a\n)", sr.serialize(t));
// Simple map
// Top level
- t = Json5Map.ofJson5("{a:'b',c:123,d:false,e:true,f:null}");
+ t = Json5Map.ofText("{a:'b',c:123,d:false,e:true,f:null}");
assertEquals("(a=b,c=123,d=false,e=true,f=null)", s.serialize(t));
assertEquals("(a=b,c=123,d=false,e=true,f=null)", su.serialize(t));
assertEquals("(\n\ta=b,\n\tc=123,\n\td=false,\n\te=true,\n\tf=null\n)", sr.serialize(t));
// 2nd level
- t = Json5Map.ofJson5("{a:{a:'b',c:123,d:false,e:true,f:null}}");
+ t = Json5Map.ofText("{a:{a:'b',c:123,d:false,e:true,f:null}}");
assertEquals("(a=(a=b,c=123,d=false,e=true,f=null))", s.serialize(t));
assertEquals("(a=(a=b,c=123,d=false,e=true,f=null))", su.serialize(t));
assertEquals("(\n\ta=(\n\t\ta=b,\n\t\tc=123,\n\t\td=false,\n\t\te=true,\n\t\tf=null\n\t)\n)", sr.serialize(t));
// Simple map with primitives as literals
- t = Json5Map.ofJson5("{a:'b',c:'123',d:'false',e:'true',f:'null'}");
+ t = Json5Map.ofText("{a:'b',c:'123',d:'false',e:'true',f:'null'}");
assertEquals("(a=b,c='123',d='false',e='true',f='null')", s.serialize(t));
assertEquals("(a=b,c='123',d='false',e='true',f='null')", su.serialize(t));
assertEquals("(\n\ta=b,\n\tc='123',\n\td='false',\n\te='true',\n\tf='null'\n)", sr.serialize(t));
@@ -76,13 +76,13 @@ class UonSerializer_Test {
assertEquals("null", sr.serialize(t));
// 2nd level
- t = Json5Map.ofJson5("{null:null}");
+ t = Json5Map.ofText("{null:null}");
assertEquals("(null=null)", s.serialize(t));
assertEquals("(null=null)", su.serialize(t));
assertEquals("(\n\tnull=null\n)", sr.serialize(t));
// 3rd level
- t = Json5Map.ofJson5("{null:{null:null}}");
+ t = Json5Map.ofText("{null:{null:null}}");
assertEquals("(null=(null=null))", s.serialize(t));
assertEquals("(null=(null=null))", su.serialize(t));
assertEquals("(\n\tnull=(\n\t\tnull=null\n\t)\n)", sr.serialize(t));
@@ -95,7 +95,7 @@ class UonSerializer_Test {
assertEquals("@()", sr.serialize(t));
// 2nd level in map
- t = Json5Map.ofJson5("{x:[]}");
+ t = Json5Map.ofText("{x:[]}");
assertEquals("(x=@())", s.serialize(t));
assertEquals("(x=@())", su.serialize(t));
assertEquals("(\n\tx=@()\n)", sr.serialize(t));
@@ -114,7 +114,7 @@ class UonSerializer_Test {
assertEquals("@(\n\t''\n)", sr.serialize(t));
// 2nd level
- t = Json5Map.ofJson5("{x:['']}");
+ t = Json5Map.ofText("{x:['']}");
assertEquals("(x=@(''))", s.serialize(t));
assertEquals("(x=@(''))", su.serialize(t));
assertEquals("(\n\tx=@(\n\t\t''\n\t)\n)", sr.serialize(t));
@@ -133,7 +133,7 @@ class UonSerializer_Test {
assertEquals("\u0000", sr.serialize(t));
// 2nd level
- t = Json5Map.ofJson5("{'\u0000':'\u0000'}");
+ t = Json5Map.ofText("{'\u0000':'\u0000'}");
assertEquals("(%00=%00)", s.serialize(t));
assertEquals("(\u0000=\u0000)", su.serialize(t));
assertEquals("(\n\t\u0000=\u0000\n)", sr.serialize(t));
@@ -146,7 +146,7 @@ class UonSerializer_Test {
assertEquals("false", sr.serialize(t));
// 2nd level
- t = Json5Map.ofJson5("{x:false}");
+ t = Json5Map.ofText("{x:false}");
assertEquals("(x=false)", s.serialize(t));
assertEquals("(x=false)", su.serialize(t));
assertEquals("(\n\tx=false\n)", sr.serialize(t));
@@ -159,7 +159,7 @@ class UonSerializer_Test {
assertEquals("123", sr.serialize(t));
// 2nd level
- t = Json5Map.ofJson5("{x:123}");
+ t = Json5Map.ofText("{x:123}");
assertEquals("(x=123)", s.serialize(t));
assertEquals("(x=123)", su.serialize(t));
assertEquals("(\n\tx=123\n)", sr.serialize(t));
@@ -172,7 +172,7 @@ class UonSerializer_Test {
assertEquals("x;/?:@-_.!*~'", sr.serialize(t));
// 2nd level
- t = Json5Map.ofJson5("{x:'x;/?:@-_.!*\\''}");
+ t = Json5Map.ofText("{x:'x;/?:@-_.!*\\''}");
assertEquals("(x=x;/?:@-_.!*~')", s.serialize(t));
assertEquals("(x=x;/?:@-_.!*~')", su.serialize(t));
assertEquals("(\n\tx=x;/?:@-_.!*~'\n)", sr.serialize(t));
@@ -185,7 +185,7 @@ class UonSerializer_Test {
assertEquals("x{}|\\^[]`<>#%\"&+", sr.serialize(t));
// 2nd level
- t = Json5Map.ofJson5("{'x{}|\\\\^[]`<>#%\"&+':'x{}|\\\\^[]`<>#%\"&+'}");
+ t = Json5Map.ofText("{'x{}|\\\\^[]`<>#%\"&+':'x{}|\\\\^[]`<>#%\"&+'}");
assertEquals("(x%7B%7D%7C%5C%5E%5B%5D%60%3C%3E%23%25%22%26%2B=x%7B%7D%7C%5C%5E%5B%5D%60%3C%3E%23%25%22%26%2B)", s.serialize(t));
assertEquals("(x{}|\\^[]`<>#%\"&+=x{}|\\^[]`<>#%\"&+)", su.serialize(t));
assertEquals("(\n\tx{}|\\^[]`<>#%\"&+=x{}|\\^[]`<>#%\"&+\n)", sr.serialize(t));
@@ -199,14 +199,14 @@ class UonSerializer_Test {
// 2nd level
// Note behavior on serializeParams() is different since 2nd-level is top level.
- t = Json5Map.ofJson5("{'x$,()~':'x$,()~'}");
+ t = Json5Map.ofText("{'x$,()~':'x$,()~'}");
assertEquals("('x$,()~~'='x$,()~~')", s.serialize(t));
assertEquals("('x$,()~~'='x$,()~~')", su.serialize(t));
assertEquals("(\n\t'x$,()~~'='x$,()~~'\n)", sr.serialize(t));
// 3rd level
// Note behavior on serializeParams().
- t = Json5Map.ofJson5("{'x$,()~':{'x$,()~':'x$,()~'}}");
+ t = Json5Map.ofText("{'x$,()~':{'x$,()~':'x$,()~'}}");
assertEquals("('x$,()~~'=('x$,()~~'='x$,()~~'))", s.serialize(t));
assertEquals("('x$,()~~'=('x$,()~~'='x$,()~~'))", su.serialize(t));
assertEquals("(\n\t'x$,()~~'=(\n\t\t'x$,()~~'='x$,()~~'\n\t)\n)", sr.serialize(t));
@@ -220,13 +220,13 @@ class UonSerializer_Test {
assertEquals("'x='", sr.serialize(t));
// 2nd level
- t = Json5Map.ofJson5("{'x=':'x='}");
+ t = Json5Map.ofText("{'x=':'x='}");
assertEquals("('x='='x=')", s.serialize(t));
assertEquals("('x='='x=')", su.serialize(t));
assertEquals("(\n\t'x='='x='\n)", sr.serialize(t));
// 3rd level
- t = Json5Map.ofJson5("{'x=':{'x=':'x='}}");
+ t = Json5Map.ofText("{'x=':{'x=':'x='}}");
assertEquals("('x='=('x='='x='))", s.serialize(t));
assertEquals("('x='=('x='='x='))", su.serialize(t));
assertEquals("(\n\t'x='=(\n\t\t'x='='x='\n\t)\n)", sr.serialize(t));
@@ -239,7 +239,7 @@ class UonSerializer_Test {
assertEquals("'()'", sr.serialize(t));
// 2nd level
- t = Json5Map.ofJson5("{'()':'()'}");
+ t = Json5Map.ofText("{'()':'()'}");
assertEquals("('()'='()')", s.serialize(t));
assertEquals("('()'='()')", su.serialize(t));
assertEquals("(\n\t'()'='()'\n)", sr.serialize(t));
@@ -252,7 +252,7 @@ class UonSerializer_Test {
assertEquals("$a", sr.serialize(t));
// 2nd level
- t = Json5Map.ofJson5("{$a:'$a'}");
+ t = Json5Map.ofText("{$a:'$a'}");
assertEquals("($a=$a)", s.serialize(t));
assertEquals("($a=$a)", su.serialize(t));
assertEquals("(\n\t$a=$a\n)", sr.serialize(t));
@@ -265,13 +265,13 @@ class UonSerializer_Test {
assertEquals("''", sr.serialize(t));
// 2nd level
- t = Json5Map.ofJson5("{'':''}");
+ t = Json5Map.ofText("{'':''}");
assertEquals("(''='')", s.serialize(t));
assertEquals("(''='')", su.serialize(t));
assertEquals("(\n\t''=''\n)", sr.serialize(t));
// 3rd level
- t = Json5Map.ofJson5("{'':{'':''}}");
+ t = Json5Map.ofText("{'':{'':''}}");
assertEquals("(''=(''=''))", s.serialize(t));
assertEquals("(''=(''=''))", su.serialize(t));
assertEquals("(\n\t''=(\n\t\t''=''\n\t)\n)", sr.serialize(t));
@@ -284,13 +284,13 @@ class UonSerializer_Test {
assertEquals("'\n'", sr.serialize(t));
// 2nd level
- t = Json5Map.ofJson5("{'\n':'\n'}");
+ t = Json5Map.ofText("{'\n':'\n'}");
assertEquals("('%0A'='%0A')", s.serialize(t));
assertEquals("('\n'='\n')", su.serialize(t));
assertEquals("(\n\t'\n'='\n'\n)", sr.serialize(t));
// 3rd level
- t = Json5Map.ofJson5("{'\n':{'\n':'\n'}}");
+ t = Json5Map.ofText("{'\n':{'\n':'\n'}}");
assertEquals("('%0A'=('%0A'='%0A'))", s.serialize(t));
assertEquals("('\n'=('\n'='\n'))", su.serialize(t));
assertEquals("(\n\t'\n'=(\n\t\t'\n'='\n'\n\t)\n)", sr.serialize(t));
@@ -309,13 +309,13 @@ class UonSerializer_Test {
assertEquals("¢", sr.serialize(t));
// 2nd level
- t = Json5Map.ofJson5("{'¢':'¢'}");
+ t = Json5Map.ofText("{'¢':'¢'}");
assertEquals("(%C2%A2=%C2%A2)", s.serialize(t));
assertEquals("(¢=¢)", su.serialize(t));
assertEquals("(\n\t¢=¢\n)", sr.serialize(t));
// 3rd level
- t = Json5Map.ofJson5("{'¢':{'¢':'¢'}}");
+ t = Json5Map.ofText("{'¢':{'¢':'¢'}}");
assertEquals("(%C2%A2=(%C2%A2=%C2%A2))", s.serialize(t));
assertEquals("(¢=(¢=¢))", su.serialize(t));
assertEquals("(\n\t¢=(\n\t\t¢=¢\n\t)\n)", sr.serialize(t));
@@ -328,13 +328,13 @@ class UonSerializer_Test {
assertEquals("€", sr.serialize(t));
// 2nd level
- t = Json5Map.ofJson5("{'€':'€'}");
+ t = Json5Map.ofText("{'€':'€'}");
assertEquals("(%E2%82%AC=%E2%82%AC)", s.serialize(t));
assertEquals("(€=€)", su.serialize(t));
assertEquals("(\n\t€=€\n)", sr.serialize(t));
// 3rd level
- t = Json5Map.ofJson5("{'€':{'€':'€'}}");
+ t = Json5Map.ofText("{'€':{'€':'€'}}");
assertEquals("(%E2%82%AC=(%E2%82%AC=%E2%82%AC))", s.serialize(t));
assertEquals("(€=(€=€))", su.serialize(t));
assertEquals("(\n\t€=(\n\t\t€=€\n\t)\n)", sr.serialize(t));
@@ -347,13 +347,13 @@ class UonSerializer_Test {
assertEquals("𤭢", sr.serialize(t));
// 2nd level
- t = Json5Map.ofJson5("{'𤭢':'𤭢'}");
+ t = Json5Map.ofText("{'𤭢':'𤭢'}");
assertEquals("(%F0%A4%AD%A2=%F0%A4%AD%A2)", s.serialize(t));
assertEquals("(𤭢=𤭢)", su.serialize(t));
assertEquals("(\n\t𤭢=𤭢\n)", sr.serialize(t));
// 3rd level
- t = Json5Map.ofJson5("{'𤭢':{'𤭢':'𤭢'}}");
+ t = Json5Map.ofText("{'𤭢':{'𤭢':'𤭢'}}");
assertEquals("(%F0%A4%AD%A2=(%F0%A4%AD%A2=%F0%A4%AD%A2))", s.serialize(t));
assertEquals("(𤭢=(𤭢=𤭢))", su.serialize(t));
assertEquals("(\n\t𤭢=(\n\t\t𤭢=𤭢\n\t)\n)", sr.serialize(t));
diff --git a/juneau-utest/src/test/java/org/apache/juneau/urlencoding/UrlEncodingSerializer_Test.java b/juneau-utest/src/test/java/org/apache/juneau/urlencoding/UrlEncodingSerializer_Test.java
index 0138d753ce..e5bd922856 100755
--- a/juneau-utest/src/test/java/org/apache/juneau/urlencoding/UrlEncodingSerializer_Test.java
+++ b/juneau-utest/src/test/java/org/apache/juneau/urlencoding/UrlEncodingSerializer_Test.java
@@ -44,23 +44,23 @@ class UrlEncodingSerializer_Test extends TestBase {
assertEquals("_value=a", s.serialize(t));
// 2nd level
- t = Json5Map.ofJson5("{a:'a'}");
+ t = Json5Map.ofText("{a:'a'}");
assertEquals("a=a", s.serialize(t));
assertEquals("a=a", sr.serialize(t));
// Simple map
// Top level
- t = Json5Map.ofJson5("{a:'b',c:123,d:false,e:true,f:null}");
+ t = Json5Map.ofText("{a:'b',c:123,d:false,e:true,f:null}");
assertEquals("a=b&c=123&d=false&e=true&f=null", s.serialize(t));
assertEquals("a=b\n&c=123\n&d=false\n&e=true\n&f=null", sr.serialize(t));
// 2nd level
- t = Json5Map.ofJson5("{a:{a:'b',c:123,d:false,e:true,f:null}}");
+ t = Json5Map.ofText("{a:{a:'b',c:123,d:false,e:true,f:null}}");
assertEquals("a=(a=b,c=123,d=false,e=true,f=null)", s.serialize(t));
assertEquals("a=(\n\ta=b,\n\tc=123,\n\td=false,\n\te=true,\n\tf=null\n)", sr.serialize(t));
// Simple map with primitives as literals
- t = Json5Map.ofJson5("{a:'b',c:'123',d:'false',e:'true',f:'null'}");
+ t = Json5Map.ofText("{a:'b',c:'123',d:'false',e:'true',f:'null'}");
assertEquals("a=b&c='123'&d='false'&e='true'&f='null'", s.serialize(t));
assertEquals("a=b\n&c='123'\n&d='false'\n&e='true'\n&f='null'", sr.serialize(t));
@@ -72,12 +72,12 @@ class UrlEncodingSerializer_Test extends TestBase {
assertEquals("_value=null", sr.serialize(t));
// 2nd level
- t = Json5Map.ofJson5("{null:null}");
+ t = Json5Map.ofText("{null:null}");
assertEquals("null=null", s.serialize(t));
assertEquals("null=null", sr.serialize(t));
// 3rd level
- t = Json5Map.ofJson5("{null:{null:null}}");
+ t = Json5Map.ofText("{null:{null:null}}");
assertEquals("null=(null=null)", s.serialize(t));
assertEquals("null=(\n\tnull=null\n)", sr.serialize(t));
@@ -88,7 +88,7 @@ class UrlEncodingSerializer_Test extends TestBase {
assertEquals("", sr.serialize(t));
// 2nd level in map
- t = Json5Map.ofJson5("{x:[]}");
+ t = Json5Map.ofText("{x:[]}");
assertEquals("x=@()", s.serialize(t));
assertEquals("x=@()", sr.serialize(t));
@@ -104,7 +104,7 @@ class UrlEncodingSerializer_Test extends TestBase {
assertEquals("0=''", sr.serialize(t));
// 2nd level
- t = Json5Map.ofJson5("{x:['']}");
+ t = Json5Map.ofText("{x:['']}");
assertEquals("x=@('')", s.serialize(t));
assertEquals("x=@(\n\t''\n)", sr.serialize(t));
@@ -120,7 +120,7 @@ class UrlEncodingSerializer_Test extends TestBase {
assertEquals("_value=%00", sr.serialize(t));
// 2nd level
- t = Json5Map.ofJson5("{'\u0000':'\u0000'}");
+ t = Json5Map.ofText("{'\u0000':'\u0000'}");
assertEquals("%00=%00", s.serialize(t));
assertEquals("%00=%00", sr.serialize(t));
@@ -131,7 +131,7 @@ class UrlEncodingSerializer_Test extends TestBase {
assertEquals("_value=false", sr.serialize(t));
// 2nd level
- t = Json5Map.ofJson5("{x:false}");
+ t = Json5Map.ofText("{x:false}");
assertEquals("x=false", s.serialize(t));
assertEquals("x=false", sr.serialize(t));
@@ -142,7 +142,7 @@ class UrlEncodingSerializer_Test extends TestBase {
assertEquals("_value=123", sr.serialize(t));
// 2nd level
- t = Json5Map.ofJson5("{x:123}");
+ t = Json5Map.ofText("{x:123}");
assertEquals("x=123", s.serialize(t));
assertEquals("x=123", sr.serialize(t));
@@ -153,7 +153,7 @@ class UrlEncodingSerializer_Test extends TestBase {
assertEquals("_value=x;/?:@-_.!*~'", sr.serialize(t));
// 2nd level
- t = Json5Map.ofJson5("{x:'x;/?:@-_.!*\\''}");
+ t = Json5Map.ofText("{x:'x;/?:@-_.!*\\''}");
assertEquals("x=x;/?:@-_.!*~'", s.serialize(t));
assertEquals("x=x;/?:@-_.!*~'", sr.serialize(t));
@@ -164,7 +164,7 @@ class UrlEncodingSerializer_Test extends TestBase {
assertEquals("_value=x%7B%7D%7C%5C%5E%5B%5D%60%3C%3E%23%25%22%26%2B", sr.serialize(t));
// 2nd level
- t = Json5Map.ofJson5("{'x{}|\\\\^[]`<>#%\"&+':'x{}|\\\\^[]`<>#%\"&+'}");
+ t = Json5Map.ofText("{'x{}|\\\\^[]`<>#%\"&+':'x{}|\\\\^[]`<>#%\"&+'}");
assertEquals("x%7B%7D%7C%5C%5E%5B%5D%60%3C%3E%23%25%22%26%2B=x%7B%7D%7C%5C%5E%5B%5D%60%3C%3E%23%25%22%26%2B", s.serialize(t));
assertEquals("x%7B%7D%7C%5C%5E%5B%5D%60%3C%3E%23%25%22%26%2B=x%7B%7D%7C%5C%5E%5B%5D%60%3C%3E%23%25%22%26%2B", sr.serialize(t));
@@ -175,12 +175,12 @@ class UrlEncodingSerializer_Test extends TestBase {
assertEquals("_value='x$,()~~'", sr.serialize(t));
// 2nd level
- t = Json5Map.ofJson5("{'x$,()~':'x$,()~'}");
+ t = Json5Map.ofText("{'x$,()~':'x$,()~'}");
assertEquals("'x$,()~~'='x$,()~~'", s.serialize(t));
assertEquals("'x$,()~~'='x$,()~~'", sr.serialize(t));
// 3rd level
- t = Json5Map.ofJson5("{'x$,()~':{'x$,()~':'x$,()~'}}");
+ t = Json5Map.ofText("{'x$,()~':{'x$,()~':'x$,()~'}}");
assertEquals("'x$,()~~'=('x$,()~~'='x$,()~~')", s.serialize(t));
assertEquals("'x$,()~~'=(\n\t'x$,()~~'='x$,()~~'\n)", sr.serialize(t));
@@ -192,12 +192,12 @@ class UrlEncodingSerializer_Test extends TestBase {
assertEquals("_value='x='", sr.serialize(t));
// 2nd level
- t = Json5Map.ofJson5("{'x=':'x='}");
+ t = Json5Map.ofText("{'x=':'x='}");
assertEquals("'x%3D'='x='", s.serialize(t));
assertEquals("'x%3D'='x='", sr.serialize(t));
// 3rd level
- t = Json5Map.ofJson5("{'x=':{'x=':'x='}}");
+ t = Json5Map.ofText("{'x=':{'x=':'x='}}");
assertEquals("'x%3D'=('x='='x=')", s.serialize(t));
assertEquals("'x%3D'=(\n\t'x='='x='\n)", sr.serialize(t));
@@ -208,7 +208,7 @@ class UrlEncodingSerializer_Test extends TestBase {
assertEquals("_value='()'", sr.serialize(t));
// 2nd level
- t = Json5Map.ofJson5("{'()':'()'}");
+ t = Json5Map.ofText("{'()':'()'}");
assertEquals("'()'='()'", s.serialize(t));
assertEquals("'()'='()'", sr.serialize(t));
@@ -219,7 +219,7 @@ class UrlEncodingSerializer_Test extends TestBase {
assertEquals("_value=$a", sr.serialize(t));
// 2nd level
- t = Json5Map.ofJson5("{$a:'$a'}");
+ t = Json5Map.ofText("{$a:'$a'}");
assertEquals("$a=$a", s.serialize(t));
assertEquals("$a=$a", sr.serialize(t));
@@ -230,12 +230,12 @@ class UrlEncodingSerializer_Test extends TestBase {
assertEquals("_value=''", sr.serialize(t));
// 2nd level
- t = Json5Map.ofJson5("{'':''}");
+ t = Json5Map.ofText("{'':''}");
assertEquals("''=''", s.serialize(t));
assertEquals("''=''", sr.serialize(t));
// 3rd level
- t = Json5Map.ofJson5("{'':{'':''}}");
+ t = Json5Map.ofText("{'':{'':''}}");
assertEquals("''=(''='')", s.serialize(t));
assertEquals("''=(\n\t''=''\n)", sr.serialize(t));
@@ -246,12 +246,12 @@ class UrlEncodingSerializer_Test extends TestBase {
assertEquals("_value='%0A'", sr.serialize(t));
// 2nd level
- t = Json5Map.ofJson5("{'\n':'\n'}");
+ t = Json5Map.ofText("{'\n':'\n'}");
assertEquals("'%0A'='%0A'", s.serialize(t));
assertEquals("'%0A'='%0A'", sr.serialize(t));
// 3rd level
- t = Json5Map.ofJson5("{'\n':{'\n':'\n'}}");
+ t = Json5Map.ofText("{'\n':{'\n':'\n'}}");
assertEquals("'%0A'=('%0A'='%0A')", s.serialize(t));
assertEquals("'%0A'=(\n\t'%0A'='%0A'\n)", sr.serialize(t));
}
@@ -268,12 +268,12 @@ class UrlEncodingSerializer_Test extends TestBase {
assertEquals("_value=%C2%A2", sr.serialize(t));
// 2nd level
- t = Json5Map.ofJson5("{'¢':'¢'}");
+ t = Json5Map.ofText("{'¢':'¢'}");
assertEquals("%C2%A2=%C2%A2", s.serialize(t));
assertEquals("%C2%A2=%C2%A2", sr.serialize(t));
// 3rd level
- t = Json5Map.ofJson5("{'¢':{'¢':'¢'}}");
+ t = Json5Map.ofText("{'¢':{'¢':'¢'}}");
assertEquals("%C2%A2=(%C2%A2=%C2%A2)", s.serialize(t));
assertEquals("%C2%A2=(\n\t%C2%A2=%C2%A2\n)", sr.serialize(t));
@@ -284,12 +284,12 @@ class UrlEncodingSerializer_Test extends TestBase {
assertEquals("_value=%E2%82%AC", sr.serialize(t));
// 2nd level
- t = Json5Map.ofJson5("{'€':'€'}");
+ t = Json5Map.ofText("{'€':'€'}");
assertEquals("%E2%82%AC=%E2%82%AC", s.serialize(t));
assertEquals("%E2%82%AC=%E2%82%AC", sr.serialize(t));
// 3rd level
- t = Json5Map.ofJson5("{'€':{'€':'€'}}");
+ t = Json5Map.ofText("{'€':{'€':'€'}}");
assertEquals("%E2%82%AC=(%E2%82%AC=%E2%82%AC)", s.serialize(t));
assertEquals("%E2%82%AC=(\n\t%E2%82%AC=%E2%82%AC\n)", sr.serialize(t));
@@ -300,12 +300,12 @@ class UrlEncodingSerializer_Test extends TestBase {
assertEquals("_value=%F0%A4%AD%A2", sr.serialize(t));
// 2nd level
- t = Json5Map.ofJson5("{'𤭢':'𤭢'}");
+ t = Json5Map.ofText("{'𤭢':'𤭢'}");
assertEquals("%F0%A4%AD%A2=%F0%A4%AD%A2", s.serialize(t));
assertEquals("%F0%A4%AD%A2=%F0%A4%AD%A2", sr.serialize(t));
// 3rd level
- t = Json5Map.ofJson5("{'𤭢':{'𤭢':'𤭢'}}");
+ t = Json5Map.ofText("{'𤭢':{'𤭢':'𤭢'}}");
assertEquals("%F0%A4%AD%A2=(%F0%A4%AD%A2=%F0%A4%AD%A2)", s.serialize(t));
assertEquals("%F0%A4%AD%A2=(\n\t%F0%A4%AD%A2=%F0%A4%AD%A2\n)", sr.serialize(t));
}
diff --git a/juneau-utest/src/test/java/org/apache/juneau/utils/FilteredMapTest.java b/juneau-utest/src/test/java/org/apache/juneau/utils/FilteredMapTest.java
index 3aa5189ff4..90b4a08c5d 100755
--- a/juneau-utest/src/test/java/org/apache/juneau/utils/FilteredMapTest.java
+++ b/juneau-utest/src/test/java/org/apache/juneau/utils/FilteredMapTest.java
@@ -35,7 +35,7 @@ class FilteredMapTest extends TestBase {
// testBasic
//====================================================================================================
@Test void a01_basic() throws Exception {
- var m = Json5Map.ofJson5("{a:'1',b:'2'}");
+ var m = Json5Map.ofText("{a:'1',b:'2'}");
ClassMeta<Map<String,Object>> cm = MarshallingContext.DEFAULT.getClassMeta(Map.class, String.class, Object.class);
ClassMeta<Map<String,String>> cm2 = MarshallingContext.DEFAULT.getClassMeta(Map.class, String.class, String.class);
diff --git a/scripts/apply-eclipse-prefs.py b/scripts/apply-eclipse-prefs.py
index 39aa576ff9..07d187a0a1 100755
--- a/scripts/apply-eclipse-prefs.py
+++ b/scripts/apply-eclipse-prefs.py
@@ -51,7 +51,7 @@ SOURCE_PROJECTS = [
"juneau-examples/juneau-examples-rest",
"juneau-examples/juneau-examples-rest-jetty",
"juneau-examples/juneau-examples-rest-springboot",
- "juneau-microservice/juneau-microservice-core",
+ "juneau-microservice/juneau-microservice",
"juneau-microservice/juneau-microservice-jetty",
"juneau-microservice/juneau-my-jetty-microservice",
"juneau-microservice/juneau-my-springboot-microservice",
diff --git a/todo/TODO-36-jetty-as-bean.md b/todo/FINISHED-36-jetty-as-bean.md
similarity index 100%
rename from todo/TODO-36-jetty-as-bean.md
rename to todo/FINISHED-36-jetty-as-bean.md
diff --git a/todo/TODO.md b/todo/TODO.md
index 112080d651..08a8a2d80b 100644
--- a/todo/TODO.md
+++ b/todo/TODO.md
@@ -23,8 +23,6 @@
- [TODO-35] Add support for overriding injected beans for tests (test-time replacement/override of beans in the inject/DI container so tests can swap real beans for stubs/mocks).
-- [TODO-36] Rework `juneau-microservice-jetty` as a predefined `@Configuration` bean on top of a single `Microservice` class (rename `juneau-microservice-core` → `juneau-microservice`, delete `JettyMicroservice`, drive Jetty lifecycle through a fanned-out `MicroserviceListener`). See `todo/TODO-36-jetty-as-bean.md`.
-
- [TODO-38] Rename `juneau-rest-client` → `juneau-rest-client-classic` and promote the `juneau-ng-rest-client-*` family + `org.apache.juneau.ng.*` packages to the canonical `juneau-rest-client` / `org.apache.juneau.*` names. See `todo/TODO-38-rename-rest-client-to-classic.md`.
- [TODO-39] Add a `/sonarqube` Cursor command (and matching `scripts/sonarqube.py` helper) that runs SonarQube analysis against a given source file, package, or module — analogous to `/coverage` / `scripts/coverage.py`. Should auto-detect the Maven module from the path, invoke the SonarQube/SonarLint scanner, and print a concise per-file summary of issues (rule id, severity, line, message) so the user can quickly triage Sonar findings the same way they do JaCoCo coverage.