This is an automated email from the ASF dual-hosted git repository.
jamesbognar pushed a commit to branch docs
in repository https://gitbox.apache.org/repos/asf/juneau.git
The following commit(s) were added to refs/heads/docs by this push:
new 54df16965e Fix docs from TODO-297 audit: Spring bean-precedence,
NG-client conflation, high-value page rewrites
54df16965e is described below
commit 54df16965e3a5919de9e94ca3f2caae8e6b26957
Author: James Bognar <[email protected]>
AuthorDate: Mon Jul 27 07:51:40 2026 -0400
Fix docs from TODO-297 audit: Spring bean-precedence, NG-client conflation,
high-value page rewrites
Closes TODO-298 (12.00/12.01/19 - real local-Juneau-wins-first bean
precedence,
removed fabricated overridingParent API, sample-app examples), TODO-300 (12
NG-client
pages - classic->NG API corrections + wrong-sibling-class fixes), TODO-309
(01.01
reframe to feature-presence,
01.02/05.04/03.26.07/06.03.01/03.03.06/10.31.02 rewrites,
03.14 nine-row *Apply completion, sidebar label). Completes all 13 ROLLUP
slices of
the TODO-297 documentation audit.
Co-authored-by: Cursor <[email protected]>
---
pages/topics/01.01.FrameworkComparisons.md | 133 +++++++++++----------
pages/topics/01.02.WhyJuneau.md | 16 ++-
pages/topics/03.03.06.BeanIgnoreAnnotation.md | 108 +++++++++++++----
.../topics/03.14.DynamicallyAppliedAnnotations.md | 2 +-
pages/topics/03.26.07.XmlNamespaces.md | 13 +-
pages/topics/05.04.JuneauBeanOpenApi3.md | 52 +++++---
pages/topics/06.03.01.LogicVariables.md | 89 ++++++--------
pages/topics/09.01.HelperClasses.md | 123 +++++++++++--------
pages/topics/09.03.HttpHeaders.md | 20 +++-
pages/topics/09.04.HttpParts.md | 32 +++--
pages/topics/10.31.02.HtmlWidgets.md | 8 +-
pages/topics/10.56.RestRpc.md | 23 +++-
pages/topics/12.00.JuneauRestServerSpringboot.md | 64 ++++++----
pages/topics/12.01.SpringBootOverview.md | 18 ++-
pages/topics/13.14.NextGenRestClient.md | 102 ++++++++--------
pages/topics/13.15.00.HttpTransportAdapters.md | 22 ++--
.../13.15.01.RestClientApacheHttpClient45.md | 35 +++---
.../13.15.02.RestClientApacheHttpClient50.md | 33 ++---
pages/topics/13.15.03.RestClientOkHttp.md | 31 +++--
pages/topics/13.15.04.RestClientJetty.md | 30 +++--
pages/topics/13.16.StreamingCursors.md | 47 ++++----
pages/topics/13.17.ContentTypeNegotiation.md | 19 +--
pages/topics/19.JuneauPetstore.md | 6 +
sidebars.ts | 2 +-
24 files changed, 594 insertions(+), 434 deletions(-)
diff --git a/pages/topics/01.01.FrameworkComparisons.md
b/pages/topics/01.01.FrameworkComparisons.md
index 4c3d7acde7..8e7da74b41 100644
--- a/pages/topics/01.01.FrameworkComparisons.md
+++ b/pages/topics/01.01.FrameworkComparisons.md
@@ -4,93 +4,94 @@ slug: FrameworkComparisons
---
-This page provides detailed comparisons between Juneau and popular
alternatives to help you choose the right tool for your needs.
+This page describes how Juneau's feature set lines up against a few popular
alternatives. Rather than declaring
+an overall "winner", each table below simply notes whether a given capability
is present, built-in, or requires
+extra setup — the goal is to help you evaluate whether Juneau's particular
trade-offs fit your project, not to
+score points.
## Juneau vs Jackson
-| Feature | Juneau | Jackson | Winner |
-|---------|--------|---------|--------|
-| **Multi-format support** | JSON, XML, HTML, URL-Encoding, UON, OpenAPI,
PlainText, CSV, SOAP, MessagePack, RDF | Primarily JSON (with modules for XML,
YAML, etc.) | **Juneau** - Built-in multi-format support |
-| **Zero dependencies** | Core marshalling has zero external dependencies |
Requires additional modules for different formats | **Juneau** - Truly
zero-dependency |
-| **REST API integration** | Built-in REST server and client with automatic
content negotiation | Requires separate REST framework | **Juneau** -
Integrated solution |
-| **Self-documenting APIs** | Automatic Swagger/OpenAPI generation | Requires
additional tools | **Juneau** - Built-in documentation |
-| **Testing support** | MockRestClient for serverless testing | Requires
external testing frameworks | **Juneau** - Integrated testing |
-| **Configuration files** | Built-in INI-style config with POJO support | No
built-in configuration support | **Juneau** - Comprehensive config API |
-| **Performance** | ~20% faster than Jackson, optimized for memory efficiency
| Highly optimized for JSON | **Juneau** - Better performance in benchmarks |
-| **Ecosystem maturity** | Smaller community, newer project | Large community,
extensive ecosystem | **Jackson** - More mature ecosystem |
-
-**Choose Juneau when:** You need multi-format serialization, REST APIs, or
want an integrated solution with minimal dependencies.
-
-**Choose Jackson when:** You only need JSON serialization, want maximum
performance, or need extensive community support.
+| Feature | Juneau | Jackson |
+|---------|--------|---------|
+| **Multi-format support** | JSON, XML, HTML, URL-Encoding, UON, OpenAPI,
PlainText, CSV, SOAP, MessagePack, RDF, and more, in one library | JSON
natively; other formats (XML, YAML, CSV, etc.) require separate
`jackson-dataformat-*` modules |
+| **Zero external dependencies** | Core marshalling module has none | Core
(`jackson-databind`) has none either; additional formats pull in their own
modules |
+| **REST server/client integration** | Built-in
(`juneau-rest-server`/`juneau-rest-client`) with automatic content negotiation
| Not provided; typically paired with a separate REST framework (Spring MVC,
JAX-RS, etc.) |
+| **Automatic OpenAPI/Swagger generation** | Built-in via `@Rest`/`@RestOp`
annotations | Not provided directly; typically added via `springdoc-openapi` or
similar |
+| **Serverless REST testing** | Built-in (`MockRestClient`) | Not applicable —
Jackson isn't a REST framework |
+| **Built-in configuration file support** | Yes (`juneau-config`, INI-style
with POJO binding) | No — not in scope for a data-binding library |
+| **Streaming/token-level parsing API** | Yes (`TokenReader`/`RecordReader`) |
Yes (`JsonParser` streaming API, Jackson's original design center) |
+| **Community size / ecosystem maturity** | Smaller community, Apache project
| Large community, extensive third-party module ecosystem |
+
+**Juneau tends to fit well when:** you need more than JSON out of a single
library, want REST server/client and
+config-file support integrated with the same annotations, or want to avoid
assembling several separate
+dependencies to cover serialization + REST + docs + testing.
+
+**Jackson tends to fit well when:** your scope is JSON-only (or JSON-first
with a small number of additional
+formats), you're already invested in its ecosystem (e.g. Spring Boot's default
integration), or you need its
+specific plugin/module surface.
## Juneau REST APIs vs Spring Boot Web Controllers
-| Feature | Juneau REST APIs | Spring Boot Web Controllers | Winner |
-|---------|------------------|----------------------------|--------|
-| **REST API creation** | Annotation-based with automatic content negotiation
| Requires @RestController, @RequestMapping, etc. | **Juneau** - Simpler REST
API setup |
-| **Self-documenting APIs** | Automatic Swagger generation | Requires
SpringDoc or similar | **Juneau** - Built-in documentation |
-| **Content negotiation** | Automatic support for all formats (JSON, XML,
HTML, etc.) with single method | Must define separate methods for each content
type | **Juneau** - Single method handles all formats |
-| **Serialization** | Built-in multi-format support | Requires additional
configuration | **Juneau** - Integrated serialization |
-| **Testing** | MockRestClient for serverless testing | Requires
@SpringBootTest with embedded containers | **Juneau** - Faster testing |
-| **Dependencies** | Minimal additional dependencies | Uses Spring's
dependency injection | **Juneau** - Lighter footprint |
-| **Integration** | Works seamlessly with Spring Boot | Native Spring Boot
feature | **Spring Boot** - Native integration |
-| **Ecosystem** | Focused on REST and serialization | Full Spring ecosystem |
**Spring Boot** - Larger ecosystem |
-
-**Use Juneau REST APIs when:** You want automatic content negotiation,
built-in documentation, or need multi-format serialization in your Spring Boot
application.
-
-**Use Spring Boot Web Controllers when:** You prefer standard Spring patterns,
need complex request handling, or want to leverage existing Spring knowledge.
+| Feature | Juneau REST APIs | Spring Boot Web Controllers |
+|---------|------------------|----------------------------|
+| **REST endpoint declaration** | Annotation-based (`@Rest`, `@RestGet`, etc.)
with automatic content negotiation | Annotation-based (`@RestController`,
`@RequestMapping`, etc.) |
+| **Automatic OpenAPI/Swagger generation** | Built-in | Requires an add-on
such as SpringDoc |
+| **Multi-format content negotiation from a single method** | Built-in — one
method handles JSON/XML/HTML/etc. based on `Accept` | Requires separate methods
or `HttpMessageConverter` configuration per format |
+| **Serverless testing** | Built-in (`MockRestClient`) | Requires
`@SpringBootTest`/`@WebMvcTest` or embedded containers |
+| **Dependency footprint for a minimal REST service** | Small —
`juneau-rest-server` plus a servlet container | Larger — full Spring Boot
starter web stack |
+| **Native Spring ecosystem integration** (DI, Security, Actuator, etc.) | Can
be layered alongside Spring Boot, but isn't a Spring-native component | Native |
+| **Ecosystem breadth beyond REST** (batch, messaging, data, etc.) | Focused
on REST/serialization | Full Spring ecosystem |
-**Note:** Juneau works perfectly with Spring Boot! You can use Juneau REST
APIs alongside Spring Boot's dependency injection, security, and other features.
+**Note:** Juneau REST APIs and Spring Boot aren't mutually exclusive — you can
run Juneau `@Rest` resources
+alongside Spring Boot's dependency injection, security, and other features in
the same application.
## Juneau vs JAX-RS
-| Feature | Juneau | JAX-RS | Winner |
-|---------|--------|--------|--------|
-| **API simplicity** | POJO-based with automatic serialization | Requires
explicit serialization handling | **Juneau** - Simpler API |
-| **Content negotiation** | Automatic based on Accept headers | Manual content
negotiation | **Juneau** - Automatic negotiation |
-| **Documentation** | Automatic Swagger generation | Requires additional tools
| **Juneau** - Built-in documentation |
-| **Testing** | MockRestClient for unit testing | Requires external testing
frameworks | **Juneau** - Integrated testing |
-| **Dependencies** | Minimal dependencies | Requires JAX-RS implementation |
**Juneau** - Fewer dependencies |
-| **Standards compliance** | Proprietary but simple | Industry standard |
**JAX-RS** - Standard compliance |
-| **Ecosystem** | Smaller ecosystem | Large ecosystem with many
implementations | **JAX-RS** - Larger ecosystem |
-
-**Choose Juneau when:** You want simplicity, automatic features, and minimal
configuration.
-
-**Choose JAX-RS when:** You need standards compliance, extensive ecosystem, or
enterprise integration.
-
-## Performance Benchmarks
+| Feature | Juneau | JAX-RS |
+|---------|--------|--------|
+| **Serialization model** | POJO-based; serialization is automatic once a bean
is returned | Requires explicit `MessageBodyWriter`/`MessageBodyReader` wiring
for non-trivial types |
+| **Content negotiation** | Automatic based on `Accept` header | Supported via
`@Produces`/`@Consumes`, but format-specific handling is manual |
+| **Automatic OpenAPI/Swagger generation** | Built-in | Not part of the spec;
typically added via a separate library (e.g. MicroProfile OpenAPI) |
+| **Serverless testing** | Built-in (`MockRestClient`) | Not part of the spec;
depends on the implementation and test tooling used |
+| **Standardization** | Apache project, not a JCP/Jakarta specification |
Jakarta EE specification with multiple competing implementations (Jersey,
RESTEasy, CXF) |
+| **Implementation portability** | Single implementation | Multiple
implementations to choose from, each spec-compliant |
-### Serialization Performance
-Juneau has been shown to be approximately **20% faster** than Jackson in
performance tests, while maintaining excellent memory efficiency.
+**Juneau tends to fit well when:** you want POJO-in/POJO-out simplicity
without wiring up message body
+providers by hand, and don't need portability across multiple JAX-RS
implementations.
-### Memory Usage
-Juneau is optimized for memory efficiency, making it ideal for:
-- High-throughput applications
-- Memory-constrained environments
-- Microservices with limited resources
-
-### Startup Time
-Juneau's minimal dependencies and lightweight design result in faster
application startup times compared to heavier frameworks.
+**JAX-RS tends to fit well when:** standards compliance, implementation
portability, or existing enterprise
+JAX-RS investment matters for your project.
## Migration Considerations
### From Jackson to Juneau
-- **Easy migration** for basic serialization use cases
-- **Annotation mapping** available (see [Jackson
Comparison](/docs/topics/JacksonComparison))
-- **Performance benefits** with minimal code changes
+
+- Basic POJO serialization use cases usually migrate with minimal code changes.
+- An annotation-mapping reference is available at [Jackson
Comparison](/docs/topics/JacksonComparison), covering
+ the common `@Json*` annotations and their closest Juneau equivalents.
+- Evaluate your own workload if performance is a deciding factor — see the
note below.
### From Spring Boot Controllers to Juneau REST APIs
-- **Gradual migration** possible - use alongside existing controllers
-- **Automatic content negotiation** reduces boilerplate code
-- **Built-in documentation** eliminates need for additional tools
+
+- Migration can be gradual — Juneau `@Rest` resources can run alongside
existing Spring MVC controllers in the
+ same application.
+- Automatic content negotiation and built-in Swagger generation reduce
boilerplate compared to a from-scratch
+ Spring MVC + SpringDoc setup.
### From JAX-RS to Juneau
-- **Simplified API** with fewer annotations required
-- **Automatic serialization** reduces manual configuration
-- **Integrated testing** improves development workflow
+
+- Juneau requires fewer annotations for the common case since serialization is
automatic rather than explicit.
+- If standards compliance or JAX-RS implementation portability is a
requirement for your organization, factor
+ that into the decision — Juneau does not implement the JAX-RS specification.
+
+## A Note on Performance
+
+Juneau does not currently publish a reproducible, methodology-documented
benchmark comparing its serialization
+performance against Jackson or other libraries. If raw JSON serialization
throughput is your primary decision
+criterion, benchmark both libraries against your own representative payloads
and hardware rather than relying on
+a general claim — JVM warm-up, payload shape, and object-graph complexity all
materially affect results in ways
+that don't generalize well across projects.
## Getting Started
Ready to try Juneau? Check out the [Ecosystem
Overview](/docs/topics/JuneauEcosystemOverview) or explore our
[examples](/docs/topics/JuneauExamples).
-
-For detailed feature comparisons, see our [Jackson
Comparison](/docs/topics/JacksonComparison) page.
diff --git a/pages/topics/01.02.WhyJuneau.md b/pages/topics/01.02.WhyJuneau.md
index bc5e1f9b4c..51a6ea5775 100644
--- a/pages/topics/01.02.WhyJuneau.md
+++ b/pages/topics/01.02.WhyJuneau.md
@@ -133,17 +133,21 @@ public void testUserAPI() throws Exception {
Juneau 10 introduces a low-level streaming API for processing large datasets
without buffering the entire document:
```java
-// Stream a large JSONL file record-by-record — O(1) memory
-try (RecordReader r = Json5l.DEFAULT.fromRecords(inputStream)) {
+// Stream a large JSON5L (JSON5 Lines) file record-by-record — O(1) memory
+try (RecordReader r = Json5l.DEFAULT.readRecords(inputStream)) {
while (r.canRead())
process(r.read(Person.class));
}
// Fine-grained structural token cursor (JSON, CBOR, MsgPack)
-try (TokenReader tokens = JsonParser.DEFAULT.readTokens(inputStream)) {
- tokens.startObject();
- while (tokens.hasMoreFields())
- System.out.println(tokens.fieldName() + " = " + tokens.string());
+try (TokenReader r = Json.DEFAULT.readTokens(inputStream)) {
+ while (r.next() != TokenType.END_OF_STREAM) {
+ switch (r.getCurrentToken()) {
+ case FIELD_NAME -> System.out.print(r.getFieldName() + " = ");
+ case VALUE_STRING -> System.out.println(r.getString());
+ default -> { /* structural token, e.g. START_OBJECT/END_OBJECT */ }
+ }
+ }
}
```
diff --git a/pages/topics/03.03.06.BeanIgnoreAnnotation.md
b/pages/topics/03.03.06.BeanIgnoreAnnotation.md
index cd32a87b3d..fabcb625fb 100644
--- a/pages/topics/03.03.06.BeanIgnoreAnnotation.md
+++ b/pages/topics/03.03.06.BeanIgnoreAnnotation.md
@@ -1,41 +1,74 @@
---
-title: "@MarshalledIgnore Annotation"
+title: "@BeanIgnore Annotation"
slug: BeanIgnoreAnnotation
---
-The <a href="/site/apidocs/org/apache/juneau/marshall/MarshalledIgnore.html"
target="_blank">@MarshalledIgnore</a> annotation is used to ignore fields and
-methods from being interpreted as bean components, and to suppress
serialization of a class entirely.
+The <a href="/site/apidocs/org/apache/juneau/commons/bean/BeanIgnore.html"
target="_blank">@BeanIgnore</a> annotation
+(`org.apache.juneau.commons.bean`) excludes a class, field, method, or
constructor from **bean introspection** —
+the model-side decision about whether something participates in bean detection
at all.
-When applied to **fields and getters/setters**, they will be ignored as bean
properties.
+This is the **model-side** annotation. Format-side concerns — skipping a type
entirely at the wire-format layer
+regardless of whether it's a bean — live on the sibling annotation
+<a href="/site/apidocs/org/apache/juneau/marshall/MarshalledIgnore.html"
target="_blank">@MarshalledIgnore</a>
+(`org.apache.juneau.marshall`), described at the end of this page. The two
annotations are independent and may
+be combined.
+
+## Fields and Methods
+
+When applied to a **field or method**, `@BeanIgnore` excludes it from bean
property discovery.
```java
public class MyBean {
// Not a bean property!
- @MarshalledIgnore
+ @BeanIgnore
public String foo;
// Not a bean property!
- @MarshalledIgnore
+ @BeanIgnore
public String getBar() {...}
}
```
-When applied to a **class**, objects of that type are suppressed during
serialization (output as `null`).
+## Constructors
+
+When applied to a **constructor**, `@BeanIgnore` excludes it from constructor
detection (i.e. it won't be
+considered a candidate bean constructor).
```java
-// Suppressed entirely — serializes as null.
-@MarshalledIgnore
+public class MyBean {
+
+ public MyBean() {...}
+
+ // Excluded from constructor detection.
+ @BeanIgnore
+ public MyBean(String foo) {...}
+}
+```
+
+## Classes
+
+When applied to a **class**, `@BeanIgnore` marks the class as *not a bean* for
modeling purposes. The marshaller
+falls through to its other type-detection logic (object swaps,
`@BeanType`-style hints,
+`@Marshalled(as=MarshalledAs.STRING)`, etc.) instead of treating the class as
a bean — it does **not** by itself
+suppress output the way `@MarshalledIgnore` does.
+
+```java
+// Not treated as a bean for modeling purposes.
+// The marshaller still tries to render it, e.g. via toString() or an
installed swap.
+@BeanIgnore
public class MyType {...}
```
:::note Migration
-In versions prior to 9.5, `@BeanIgnore` on a class caused the object to be
serialized via `toString()` rather than as a bean. The new `@MarshalledIgnore`
on a class instead outputs `null`.
-
-If you want the old `toString()` serialization behavior, use
`@Marshalled(as=MarshalledAs.STRING)` instead:
+In versions prior to 9.5, `@BeanIgnore` on a class caused the object to be
serialized via `toString()` rather
+than as a bean — that historical behavior is what the current
`@BeanIgnore`-on-class semantics above describe.
+If you specifically want the wire format to render `null` for a type
regardless of bean-modeling status, use
+`@MarshalledIgnore` (see below) instead. If you want the explicit `toString()`
serialization behavior, use
+`@Marshalled(as=MarshalledAs.STRING)`:
```java
-// Serialize as toString() value (old @BeanIgnore-on-class behavior)
+// Serialize as toString() value.
@Marshalled(as=MarshalledAs.STRING)
public class MyType {
@Override public String toString() { return "my-value"; }
@@ -45,9 +78,13 @@ public class MyType {
## Private fields and accessors (`ignoreAccessors`)
-By default, `@MarshalledIgnore` on a **field** only excludes that field from
**field-based** bean discovery. Public (or otherwise visible)
**getters/setters** can still expose the same logical property—for example when
`beanFieldVisibility` is `NONE` and only methods are used. That matches
patterns such as `@MarshalledIgnore` on private `f5`…`f8` with public `getF5()`
while still serializing `f5` via the getter.
+By default, `@BeanIgnore` on a **field** only excludes that field from
**field-based** bean discovery. Public (or
+otherwise visible) **getters/setters** can still expose the same logical
property — for example when
+`beanFieldVisibility` is `NONE` and only methods are used. That matches
patterns such as `@BeanIgnore` on private
+`f5`…`f8` with public `getF5()` while still serializing `f5` via the getter.
-To **also** exclude the matching JavaBean accessor pair from metadata (so the
property does not appear in serialization or parsing), set **`ignoreAccessors =
true`** on the field annotation:
+To **also** exclude the matching JavaBean accessor pair from metadata (so the
property does not appear in
+serialization or parsing), set **`ignoreAccessors = true`** on the field
annotation:
```java
public class MyBean {
@@ -55,7 +92,7 @@ public class MyBean {
public String visible = "ok";
// Hidden from Juneau bean metadata: no "foo" in serialization/parsing
- @MarshalledIgnore(ignoreAccessors = true)
+ @BeanIgnore(ignoreAccessors = true)
private String foo = "secret";
public String getFoo() {
@@ -68,19 +105,44 @@ public class MyBean {
}
```
-The logical property name is derived from the field the same way as for
visible fields: `@MarshalledProp` / `@Name` on the field, if present, otherwise
the marshalling context's `PropertyNamer` applied to the field name. That name
must match the accessor-derived property name (e.g. field `foo` with
`getFoo`/`setFoo`).
+The logical property name is derived from the field the same way as for
visible fields: `@MarshalledProp` /
+`@Name` on the field, if present, otherwise the marshalling context's
`PropertyNamer` applied to the field name.
+That name must match the accessor-derived property name (e.g. field `foo` with
`getFoo`/`setFoo`).
## Java Records
-Ignoring individual record components is not supported during parsing.
Because records are immutable, all components
-must be provided to the canonical constructor. Applying `@MarshalledIgnore`
to a record component's accessor method or
-field will exclude it from serialization output, but the parser will be unable
to instantiate the record if the
-component value is missing from the input.
+Ignoring individual record components is not supported during parsing. Because
records are immutable, all
+components must be provided to the canonical constructor. Applying
`@BeanIgnore` to a record component's
+accessor method or field will exclude it from serialization output, but the
parser will be unable to instantiate
+the record if the component value is missing from the input.
If you need to omit components during parsing, use
-<a href="/site/apidocs/org/apache/juneau/commons/bean/BeanCtor.html"
target="_blank">@BeanCtor</a> with a non-canonical
-constructor that provides defaults for the omitted components.
+<a href="/site/apidocs/org/apache/juneau/commons/bean/BeanCtor.html"
target="_blank">@BeanCtor</a> with a
+non-canonical constructor that provides defaults for the omitted components.
+
+## Format Side: `@MarshalledIgnore`
+
+<a href="/site/apidocs/org/apache/juneau/marshall/MarshalledIgnore.html"
target="_blank">@MarshalledIgnore</a>
+(`org.apache.juneau.marshall`) is a **type-level-only** annotation (it has no
field/method target and no
+`ignoreAccessors` attribute). Serializers output `null` for instances of the
annotated type, and parsers return
+`null` when asked to instantiate it — this is a wire-format concern
independent of whatever the bean-modeling
+layer would otherwise do with the type.
+
+```java
+// Suppressed entirely at the wire-format layer — serializes as null.
+@MarshalledIgnore
+public class MyType {...}
+```
+
+Because the two annotations are independent, they combine as follows:
+
+- **`@MarshalledIgnore` alone** — the class still participates in bean
detection (it may be treated as a bean by
+ the modeling layer), but the marshaller emits `null`.
+- **`@BeanIgnore` alone** — the class is not a bean for modeling purposes, but
the marshaller still tries to
+ render it (typically via `toString()` or an installed swap).
+- **Both** — the class is not a bean and the marshaller emits `null`.
:::info See Also
- [Java Records Support](/docs/topics/JavaRecordsSupport) - Full documentation
on Java records support.
+- [@BeanType Annotation](/docs/topics/BeanTypeAnnotation) - The
model-side/format-side split pattern this page follows.
:::
diff --git a/pages/topics/03.14.DynamicallyAppliedAnnotations.md
b/pages/topics/03.14.DynamicallyAppliedAnnotations.md
index 255e032f58..addd10f4c8 100644
--- a/pages/topics/03.14.DynamicallyAppliedAnnotations.md
+++ b/pages/topics/03.14.DynamicallyAppliedAnnotations.md
@@ -49,7 +49,7 @@ Each `*Apply` annotation has an `on()`/`onClass()` targeting
method and applies
specified targets. The available `*Apply` annotations are:
<tree>
-<node-0><javac-annotation><a
href="/site/apidocs/org/apache/juneau/marshall/BeanTypeApply.html"
target="_blank">BeanTypeApply</a></javac-annotation> <javac-annotation><a
href="/site/apidocs/org/apache/juneau/marshall/MarshalledApply.html"
target="_blank">MarshalledApply</a></javac-annotation> <javac-annotation><a
href="/site/apidocs/org/apache/juneau/marshall/BeanCtorApply.html"
target="_blank">BeanCtorApply</a></javac-annotation> <javac-annotation><a
href="/site/apidocs/org/apache/junea [...]
+<node-0><javac-annotation><a
href="/site/apidocs/org/apache/juneau/marshall/BeanTypeApply.html"
target="_blank">BeanTypeApply</a></javac-annotation> <javac-annotation><a
href="/site/apidocs/org/apache/juneau/marshall/MarshalledApply.html"
target="_blank">MarshalledApply</a></javac-annotation> <javac-annotation><a
href="/site/apidocs/org/apache/juneau/marshall/BeanCtorApply.html"
target="_blank">BeanCtorApply</a></javac-annotation> <javac-annotation><a
href="/site/apidocs/org/apache/junea [...]
</tree>
The valid pattern matches are:
diff --git a/pages/topics/03.26.07.XmlNamespaces.md
b/pages/topics/03.26.07.XmlNamespaces.md
index edd4ede870..7a63db699a 100644
--- a/pages/topics/03.26.07.XmlNamespaces.md
+++ b/pages/topics/03.26.07.XmlNamespaces.md
@@ -73,7 +73,7 @@ Person person = new Person()
// Note that this is identical to XmlSerializer.DEFAULT_NS_SQ_READABLE.
XmlSerializer serializer = XmlSerializer.create().ns().ws().sq().build();
-String xml = serializer.write(p);
+String xml = serializer.write(person);
```
Now when we run this code, we'll see namespaces added to our output:
@@ -94,7 +94,7 @@ Now when we run this code, we'll see namespaces added to our
output:
</per:person>
```
-Enabling the `XmlSerializer.XML_addNamespaceUrisToRoot` setting results in the
namespace URLs being added to the root
+Enabling the <a
href="/site/apidocs/org/apache/juneau/marshall/xml/XmlSerializer.Builder.html#addNamespaceUrisToRoot()"
target="_blank">XmlSerializer.Builder.addNamespaceUrisToRoot()</a> setting
results in the namespace URLs being added to the root
node:
```xml
@@ -125,8 +125,8 @@ prefixed:
```java
// Create a new serializer with readable output, this time with namespaces
enabled.
XmlSerializer serializer = XmlSerializer.create().ws().sq().ns()
- .defaultNamespaceUri("http://www.apache.org/person/")
-
+ .defaultNamespace(Namespace.of("per", "http://www.apache.org/person/"))
+ .build();
```
This produces the following equivalent where the elements don't need prefixes
since they're already in the default
document namespace:
@@ -163,9 +163,10 @@ step.
```java
// Create a new serializer with readable output, this time with namespaces
enabled.
XmlSerializer serializer = XmlSerializer.create()
+ .ns()
.ws()
.sq()
- .autoDetectNamespaces(false)
- .namespaces("{per:'http://www.apache.org/person/'}")
+ .disableAutoDetectNamespaces()
+ .namespaces(Namespace.of("per", "http://www.apache.org/person/"))
.build();
```
diff --git a/pages/topics/05.04.JuneauBeanOpenApi3.md
b/pages/topics/05.04.JuneauBeanOpenApi3.md
index 1326a45340..a80c7b9ed0 100644
--- a/pages/topics/05.04.JuneauBeanOpenApi3.md
+++ b/pages/topics/05.04.JuneauBeanOpenApi3.md
@@ -83,6 +83,9 @@ This document can be generated by the following Java code:
```java
import static org.apache.juneau.bean.openapi3.OpenApiBuilder.*;
+import java.net.URI;
+import java.util.Map;
+
OpenApi openApi = openApi()
.setOpenapi("3.0.0")
.setInfo(
@@ -92,31 +95,32 @@ OpenApi openApi = openApi()
contact().setEmail("[email protected]")
)
.setLicense(
- license("Apache
2.0").setUrl("http://www.apache.org/licenses/LICENSE-2.0.html")
+ license("Apache
2.0").setUrl(URI.create("http://www.apache.org/licenses/LICENSE-2.0.html"))
)
)
.setServers(
- server("https://petstore.example.com/v2")
+ server(URI.create("https://petstore.example.com/v2"))
)
.setTags(
tag("pet").setDescription("Everything about your Pets")
)
- .setPath("/pet", "post",
- operation()
- .setTags("pet")
- .setSummary("Add a new pet to the store")
- .setDescription("")
- .setOperationId("addPet")
- .setRequestBody(
- requestBody()
- .setDescription("Pet object that needs to be added to the
store")
- .setRequired(true)
- .setContent(
- content("application/json")
- .setSchema(schema().setType("object"))
- )
- )
- .setResponse(405, response("Invalid input"))
+ .addPath("/pet",
+ pathItem().setPost(
+ operation()
+ .addTags("pet")
+ .setSummary("Add a new pet to the store")
+ .setDescription("")
+ .setOperationId("addPet")
+ .setRequestBody(
+ requestBodyInfo()
+ .setDescription("Pet object that needs to be added to
the store")
+ .setRequired(true)
+ .setContent(
+ Map.of("application/json",
mediaType().setSchema(schemaInfo().setType("object")))
+ )
+ )
+ .addResponse("405", response("Invalid input"))
+ )
);
// Serialize using JSON serializer.
@@ -126,6 +130,18 @@ String openApiJson = Json.of(openApi);
openApiJson = openApi.toString();
```
+A few things to note when comparing this to the (superficially similar)
Swagger 2.0 API on
+[juneau-bean-swagger2](/docs/topics/JuneauBeanSwagger2):
+
+- OpenAPI v3 paths are added with `OpenApi.addPath(String path, PathItem
pathItem)` — a 2-argument method that
+ takes a fully-built `PathItem`. This differs from Swagger v2's
`Swagger.addPath(String path, String method,
+ Operation operation)`, a 3-argument method that adds a single operation
directly. Individual HTTP methods on an
+ OpenAPI v3 `PathItem` are set via
`setGet(Operation)`/`setPost(Operation)`/etc.
+- Request bodies use `RequestBodyInfo` (via the `requestBodyInfo()` factory),
not `requestBody()`/`schema()`
+ static factories — those don't exist in this package.
+- `RequestBodyInfo.setContent(...)` and `Response.setContent(...)` both take a
`Map<String,MediaType>`, keyed by
+ media type string, with each `MediaType` built via
`mediaType().setSchema(SchemaInfo)`.
+
## OpenAPI UI
The <a href="/site/apidocs/org/apache/juneau/bean/openapi3/ui/OpenApiUI.html"
target="_blank">OpenApiUI</a> class is a DTO bean class for generating OpenAPI
user interfaces from <a
href="/site/apidocs/org/apache/juneau/bean/openapi3/OpenApi.html"
target="_blank">OpenApi</a> beans.
diff --git a/pages/topics/06.03.01.LogicVariables.md
b/pages/topics/06.03.01.LogicVariables.md
index 6457d12d5f..096b21dbf0 100644
--- a/pages/topics/06.03.01.LogicVariables.md
+++ b/pages/topics/06.03.01.LogicVariables.md
@@ -3,84 +3,67 @@ title: "Logic Variables"
slug: LogicVariables
---
-The default variable resolver also provides the following logic variables for
performing simple logical operations:
-
-<tree>
-<node-0>Logic Variables</node-0>
-<node-1><java-class><a
href="/site/apidocs/org/apache/juneau/commons/svl/vars/IfVar.html"
target="_blank">IfVar</a></java-class> - `$IF{arg,then[,else]}`</node-1>
-<node-1><java-class><a
href="/site/apidocs/org/apache/juneau/commons/svl/vars/SwitchVar.html"
target="_blank">SwitchVar</a></java-class> -
`$SW{arg,pattern1:then1[,pattern2:then2...]}`</node-1>
-<node-1><java-class><a
href="/site/apidocs/org/apache/juneau/commons/svl/vars/CoalesceVar.html"
target="_blank">CoalesceVar</a></java-class> - `$CO{arg1[,arg2...]}`</node-1>
-<node-1><java-class><a
href="/site/apidocs/org/apache/juneau/commons/svl/vars/PatternMatchVar.html"
target="_blank">PatternMatchVar</a></java-class> - `$PM{arg,pattern}`</node-1>
-<node-1><java-class><a
href="/site/apidocs/org/apache/juneau/commons/svl/vars/NotEmptyVar.html"
target="_blank">NotEmptyVar</a></java-class> - `$NE{arg}`</node-1>
-<node-1><java-class><a
href="/site/apidocs/org/apache/juneau/commons/svl/vars/UpperCaseVar.html"
target="_blank">UpperCaseVar</a></java-class> - `$UC{arg}`</node-1>
-<node-1><java-class><a
href="/site/apidocs/org/apache/juneau/commons/svl/vars/LowerCaseVar.html"
target="_blank">LowerCaseVar</a></java-class> - `$LC{arg}`</node-1>
-</tree>
-
-The `$IF` variable can be used for simple if/else logic:
+:::note Migration
+The dedicated `$IF{}`/`$SW{}`/`$CO{}`/`$PM{}`/`$NE{}`/`$UC{}`/`$LC{}` variable
classes described in earlier
+versions of this page (`IfVar`, `SwitchVar`, `CoalesceVar`, `PatternMatchVar`,
`NotEmptyVar`, `UpperCaseVar`,
+`LowerCaseVar`) were removed in the 10.0.0 cycle. They were replaced by a
unified `#{name(args...)}`
+function-call syntax backed by
`org.apache.juneau.commons.svl.functions.ConditionalFunctions`
+(`if`/`switch`/`coalesce`/`notEmpty`) and
`org.apache.juneau.commons.svl.functions.StringFunctions`
+(`upper`/`lower`). See [Simple Variable
Language](/docs/topics/SimpleVariableLanguage) for the full, current
+function catalog and syntax — this page shows the config-file equivalents of
the old `$IF`/`$SW`/`$CO`/`$PM`
+examples using the current syntax.
+:::
+
+Config files can use the `#{...}` function-call syntax anywhere a `$Var{...}`
variable is valid, including nested
+inside other variables such as `$S{...}` (system property lookup).
+
+The `#{if(cond,then,else)}` function can be used for simple if/else logic.
Unlike the old `$IF{}` variable, the
+`else` argument is required (pass an empty string if no "else" value is
needed):
```ini
-# Value set to 'foo' if myBooleanProperty is true
+# Value set to 'foo' if myBooleanProperty is true, empty otherwise.
-key1 =
- $IF{
- $S{myBooleanProperty},
- foo
- }
+key1 = #{if($S{myBooleanProperty}, foo, "")}
# Value set to 'foo' if myBooleanProperty is true, 'bar' if false.
-key2 =
- $IF{
- $S{myBooleanProperty},
- foo,
- bar
- }
+key2 = #{if($S{myBooleanProperty}, foo, bar)}
# Value set to key1 value if myBooleanProperty is true, key2 value if false.
-key3 =
- $IF{
- $S{myBooleanProperty},
- $C{key1},
- $C{key2}
- }
+key3 = #{if($S{myBooleanProperty}, $C{key1}, $C{key2})}
```
-The `$SW` variable can be used for switch blocks based on pattern matching:
+The `#{switch(...)}` function can be used for switch blocks based on pattern
matching. Arguments are flat and
+comma-delimited: `value, pattern1, result1, pattern2, result2, ..., default`.
Patterns support `*`/`?` glob
+wildcards (matched against the whole value):
```ini
# Shell command depends on the OS
-shellCommand =
- $SW{
- $LC{$S{os.name}},
- *win*: bat,
- linux: bash,
- *: sh
- }
+shellCommand = #{switch(#{lower($S{os.name})}, *win*, bat, linux, bash, sh)}
```
-The `$CO` variable can be used for coalescing of values (finding the first
non-null/empty match):
+The `#{coalesce(...)}` function can be used for coalescing of values (finding
the first non-null/empty match):
```ini
# Debug flag can be enabled by system property or environment variable.
-debug =
- $CO{
- $S{debug},
- $E{DEBUG},
- false
- }
+debug = #{coalesce($S{debug}, $E{DEBUG}, false)}
```
-The `$PM` variable can be used for calculating boolean values:
+The `#{match(s,regex)}` function is the direct replacement for the old
`$PM{arg,pattern}` pattern-match variable,
+returning `"true"`/`"false"`:
```ini
# Debug flag can be enabled by system property or environment variable.
-isWindows =
- $PM{
- $LC{$S{os.name}},
- *win*
- }
+isWindows = #{match(#{lower($S{os.name})}, .*win.*)}
```
+
+:::info See Also
+- [Simple Variable Language](/docs/topics/SimpleVariableLanguage) — the
canonical reference for the full
+ `#{name(args...)}` function catalog (string, type-conversion, arithmetic,
boolean, conditional, regex,
+ encoding, date/time, random/UUID, and JSON-navigation functions), plus the
`$Var{...}` syntax these functions
+ compose with.
+:::
diff --git a/pages/topics/09.01.HelperClasses.md
b/pages/topics/09.01.HelperClasses.md
index dada7e1092..a17072e23f 100644
--- a/pages/topics/09.01.HelperClasses.md
+++ b/pages/topics/09.01.HelperClasses.md
@@ -7,8 +7,8 @@ The <a
href="/site/apidocs/org/apache/juneau/http/header/package-summary.html" t
standard HTTP components using static imports.
<tree>
-<node-0><java-class><a
href="/site/apidocs/org/apache/juneau/http/HttpHeaders.html"
target="_blank">HttpHeaders</a></java-class> - Utility class for standard HTTP
headers.</node-0>
-<node-0><java-class><a
href="/site/apidocs/org/apache/juneau/http/HttpParts.html"
target="_blank">HttpParts</a></java-class> - Utility class for standard HTTP
parts.</node-0>
+<node-0><java-class><a
href="/site/apidocs/org/apache/juneau/http/classic/HttpHeaders.html"
target="_blank">HttpHeaders</a></java-class> - Utility class for standard HTTP
headers.</node-0>
+<node-0><java-class><a
href="/site/apidocs/org/apache/juneau/http/classic/HttpParts.html"
target="_blank">HttpParts</a></java-class> - Utility class for standard HTTP
parts.</node-0>
<node-0><java-class><a
href="/site/apidocs/org/apache/juneau/http/classic/HttpEntities.html"
target="_blank">HttpEntities</a></java-class> - Utility class for standard HTTP
entities.</node-0>
<node-0><java-class><a
href="/site/apidocs/org/apache/juneau/http/classic/HttpResources.html"
target="_blank">HttpResources</a></java-class> - Utility class for standard
HTTP resources.</node-0>
<node-0><java-class><a
href="/site/apidocs/org/apache/juneau/http/HttpResponses.html"
target="_blank">HttpResponses</a></java-class> - Utility class for standard
HTTP responses.</node-0>
@@ -16,19 +16,29 @@ standard HTTP components using static imports.
## HttpHeaders
-The <a href="/site/apidocs/org/apache/juneau/http/HttpHeaders.html"
target="_blank">HttpHeaders</a> class contains many convenience static methods
+:::info
+There are two `HttpHeaders` classes: the transport-neutral NG
+<a href="/site/apidocs/org/apache/juneau/http/HttpHeaders.html"
target="_blank">org.apache.juneau.http.HttpHeaders</a>
+(strongly-typed creators only, e.g. `accept(String)`, `contentType(String)`;
see
+<a href="/docs/topics/HttpHeaders">HTTP Headers</a>) and the classic
+<a href="/site/apidocs/org/apache/juneau/http/classic/HttpHeaders.html"
target="_blank">org.apache.juneau.http.classic.HttpHeaders</a>
+documented below, which adds free-form header creators and `HeaderList`
builders on top of the
+Apache HttpCore-based header types.
+:::
+
+The <a href="/site/apidocs/org/apache/juneau/http/classic/HttpHeaders.html"
target="_blank">HttpHeaders</a> class contains many convenience static methods
and fields for working with standard HTTP request and response headers and
header lists.
:::tip Example
```java
-import static org.apache.juneau.http.HttpHeaders.*;
+import static org.apache.juneau.http.classic.HttpHeaders.*;
HeaderList headers =
headerList( // Arbitrary list of headers
CONTENTTYPE_TEXT_XML, // Static constants
- contentType("text/xml") // Predefined headers
- contentType(() -> "text/xml") // Predefined headers with supplied
values
- stringHeader("Content-Type", "text/xml") // Freeform headers
+ contentType("text/xml"), // Predefined headers
+ contentType(() -> "text/xml"), // Predefined headers with supplied
values
+ stringHeader("Content-Type", "text/xml"), // Freeform headers
stringHeader("Content-Type", () -> "text/xml") // Freeform headers
with supplied values
);
```
@@ -39,37 +49,37 @@ In addition to the predefined headers, various methods are
provided for free-for
Each accepts either static values or values from <a
href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/function/Supplier.html"
target="_blank">Suppliers</a>:
<tree>
-<node-0><java-class><a
href="/site/apidocs/org/apache/juneau/http/HttpHeaders.html"
target="_blank">HttpHeaders</a></java-class></node-0>
-<node-1><java-method><a
href="/site/apidocs/org/apache/juneau/http/HttpHeaders.html#basicHeader(java.lang.String,java.lang.Object)"
target="_blank">basicHeader(String,Object)</a></java-method></node-1>
-<node-1><java-method><a
href="/site/apidocs/org/apache/juneau/http/HttpHeaders.html#booleanHeader(java.lang.String,java.lang.Boolean)"
target="_blank">booleanHeader(String,String)</a></java-method></node-1>
-<node-1><java-method><a
href="/site/apidocs/org/apache/juneau/http/HttpHeaders.html#csvHeader(java.lang.String,java.lang.String)"
target="_blank">csvHeader(String,String)</a></java-method></node-1>
-<node-1><java-method><a
href="/site/apidocs/org/apache/juneau/http/HttpHeaders.html#dateHeader(java.lang.String,java.lang.String)"
target="_blank">dateHeader(String,String)</a></java-method></node-1>
-<node-1><java-method><a
href="/site/apidocs/org/apache/juneau/http/HttpHeaders.html#entityTagsHeader(java.lang.String,java.lang.String)"
target="_blank">entityTagsHeader(String,String)</a></java-method></node-1>
-<node-1><java-method><a
href="/site/apidocs/org/apache/juneau/http/HttpHeaders.html#entityTagHeader(java.lang.String,java.lang.String)"
target="_blank">entityTagHeader(String,String)</a></java-method></node-1>
-<node-1><java-method><a
href="/site/apidocs/org/apache/juneau/http/HttpHeaders.html#integerHeader(java.lang.String,java.lang.Integer)"
target="_blank">integerHeader(String,String)</a></java-method></node-1>
-<node-1><java-method><a
href="/site/apidocs/org/apache/juneau/http/HttpHeaders.html#longHeader(java.lang.String,java.lang.Long)"
target="_blank">longHeader(String,String)</a></java-method></node-1>
-<node-1><java-method><a
href="/site/apidocs/org/apache/juneau/http/HttpHeaders.html#mediaRangesHeader(java.lang.String,java.lang.String)"
target="_blank">mediaRangesHeader(String,String)</a></java-method></node-1>
-<node-1><java-method><a
href="/site/apidocs/org/apache/juneau/http/HttpHeaders.html#mediaTypeHeader(java.lang.String,java.lang.String)"
target="_blank">mediaTypeHeader(String,String)</a></java-method></node-1>
-<node-1><java-method><a
href="/site/apidocs/org/apache/juneau/http/HttpHeaders.html#stringHeader(java.lang.String)"
target="_blank">stringHeader(String,String)</a></java-method></node-1>
-<node-1><java-method><a
href="/site/apidocs/org/apache/juneau/http/HttpHeaders.html#serializedHeader(java.lang.String,java.lang.Object)"
target="_blank">serializedHeader(String,Object)</a></java-method></node-1>
-<node-1><java-method><a
href="/site/apidocs/org/apache/juneau/http/HttpHeaders.html#stringRangesHeader(java.lang.String,java.lang.String)"
target="_blank">stringRangesHeader(String,String)</a></java-method></node-1>
-<node-1><java-method><a
href="/site/apidocs/org/apache/juneau/http/HttpHeaders.html#uriHeader(java.lang.String,java.lang.String)"
target="_blank">uriHeader(String,String)</a></java-method></node-1>
+<node-0><java-class><a
href="/site/apidocs/org/apache/juneau/http/classic/HttpHeaders.html"
target="_blank">HttpHeaders</a></java-class></node-0>
+<node-1><java-method><a
href="/site/apidocs/org/apache/juneau/http/classic/HttpHeaders.html#basicHeader(java.lang.String,java.lang.Object)"
target="_blank">basicHeader(String,Object)</a></java-method></node-1>
+<node-1><java-method><a
href="/site/apidocs/org/apache/juneau/http/classic/HttpHeaders.html#booleanHeader(java.lang.String,java.lang.String)"
target="_blank">booleanHeader(String,String)</a></java-method></node-1>
+<node-1><java-method><a
href="/site/apidocs/org/apache/juneau/http/classic/HttpHeaders.html#csvHeader(java.lang.String,java.lang.String)"
target="_blank">csvHeader(String,String)</a></java-method></node-1>
+<node-1><java-method><a
href="/site/apidocs/org/apache/juneau/http/classic/HttpHeaders.html#dateHeader(java.lang.String,java.lang.String)"
target="_blank">dateHeader(String,String)</a></java-method></node-1>
+<node-1><java-method><a
href="/site/apidocs/org/apache/juneau/http/classic/HttpHeaders.html#entityTagsHeader(java.lang.String,java.lang.String)"
target="_blank">entityTagsHeader(String,String)</a></java-method></node-1>
+<node-1><java-method><a
href="/site/apidocs/org/apache/juneau/http/classic/HttpHeaders.html#entityTagHeader(java.lang.String,java.lang.String)"
target="_blank">entityTagHeader(String,String)</a></java-method></node-1>
+<node-1><java-method><a
href="/site/apidocs/org/apache/juneau/http/classic/HttpHeaders.html#integerHeader(java.lang.String,java.lang.String)"
target="_blank">integerHeader(String,String)</a></java-method></node-1>
+<node-1><java-method><a
href="/site/apidocs/org/apache/juneau/http/classic/HttpHeaders.html#longHeader(java.lang.String,java.lang.String)"
target="_blank">longHeader(String,String)</a></java-method></node-1>
+<node-1><java-method><a
href="/site/apidocs/org/apache/juneau/http/classic/HttpHeaders.html#mediaRangesHeader(java.lang.String,java.lang.String)"
target="_blank">mediaRangesHeader(String,String)</a></java-method></node-1>
+<node-1><java-method><a
href="/site/apidocs/org/apache/juneau/http/classic/HttpHeaders.html#mediaTypeHeader(java.lang.String,java.lang.String)"
target="_blank">mediaTypeHeader(String,String)</a></java-method></node-1>
+<node-1><java-method><a
href="/site/apidocs/org/apache/juneau/http/classic/HttpHeaders.html#stringHeader(java.lang.String,java.lang.String)"
target="_blank">stringHeader(String,String)</a></java-method></node-1>
+<node-1><java-method><a
href="/site/apidocs/org/apache/juneau/http/classic/HttpHeaders.html#serializedHeader(java.lang.String,java.lang.Object)"
target="_blank">serializedHeader(String,Object)</a></java-method></node-1>
+<node-1><java-method><a
href="/site/apidocs/org/apache/juneau/http/classic/HttpHeaders.html#stringRangesHeader(java.lang.String,java.lang.String)"
target="_blank">stringRangesHeader(String,String)</a></java-method></node-1>
+<node-1><java-method><a
href="/site/apidocs/org/apache/juneau/http/classic/HttpHeaders.html#uriHeader(java.lang.String,java.lang.String)"
target="_blank">uriHeader(String,String)</a></java-method></node-1>
</tree>
-The <a
href="/site/apidocs/org/apache/juneau/http/HttpHeaders.html#serializedHeader(java.lang.String,java.lang.Object)"
target="_blank">serializedHeader</a> methods
+The <a
href="/site/apidocs/org/apache/juneau/http/classic/HttpHeaders.html#serializedHeader(java.lang.String,java.lang.Object)"
target="_blank">serializedHeader</a> methods
allows for headers serialized using schema-based serializers such as the
OpenAPI serializer.
Static methods are also provided for instantiating <a
href="/site/apidocs/org/apache/juneau/http/Header.html"
target="_blank">Header</a>-annotated or other `HttpComponent`-defined header
classes:
<tree>
-<node-0><java-class><a
href="/site/apidocs/org/apache/juneau/http/HttpHeaders.html"
target="_blank">HttpHeaders</a></java-class></node-0>
-<node-1><java-method><a
href="/site/apidocs/org/apache/juneau/http/HttpHeaders.html#eTag(org.apache.juneau.http.header.EntityTag)"
target="_blank">header(Class,String,Object)</a></java-method></node-1>
-<node-1><java-method><a
href="/site/apidocs/org/apache/juneau/http/HttpHeaders.html#eTag(org.apache.juneau.http.header.EntityTag)"
target="_blank">header(Class,Object)</a></java-method></node-1>
+<node-0><java-class><a
href="/site/apidocs/org/apache/juneau/http/classic/HttpHeaders.html"
target="_blank">HttpHeaders</a></java-class></node-0>
+<node-1><java-method><a
href="/site/apidocs/org/apache/juneau/http/classic/HttpHeaders.html#header(java.lang.Class,java.lang.String,java.lang.Object)"
target="_blank">header(Class,String,Object)</a></java-method></node-1>
+<node-1><java-method><a
href="/site/apidocs/org/apache/juneau/http/classic/HttpHeaders.html#header(java.lang.Class,java.lang.Object)"
target="_blank">header(Class,Object)</a></java-method></node-1>
</tree>
:::tip Example
```java
-import static org.apache.juneau.http.HttpHeaders.*;
+import static org.apache.juneau.http.classic.HttpHeaders.*;
ContentType contentType = header(ContentType.class, "text/xml");
```
@@ -78,11 +88,11 @@ ContentType contentType = header(ContentType.class,
"text/xml");
Lists of headers can be produced with the following methods:
<tree>
-<node-0><java-class><a
href="/site/apidocs/org/apache/juneau/http/HttpHeaders.html"
target="_blank">HttpHeaders</a></java-class></node-0>
-<node-1><java-method><a
href="/site/apidocs/org/apache/juneau/http/HttpHeaders.html#headerList()"
target="_blank">headerList()</a></java-method></node-1>
-<node-1><java-method><a
href="/site/apidocs/org/apache/juneau/http/HttpHeaders.html#headerList()"
target="_blank">headerList(Header...)</a></java-method></node-1>
-<node-1><java-method><a
href="/site/apidocs/org/apache/juneau/http/HttpHeaders.html#headerList()"
target="_blank">headerList(List)</a></java-method></node-1>
-<node-1><java-method><a
href="/site/apidocs/org/apache/juneau/http/HttpHeaders.html#headerList()"
target="_blank">headerList(String...)</a></java-method></node-1>
+<node-0><java-class><a
href="/site/apidocs/org/apache/juneau/http/classic/HttpHeaders.html"
target="_blank">HttpHeaders</a></java-class></node-0>
+<node-1><java-method><a
href="/site/apidocs/org/apache/juneau/http/classic/HttpHeaders.html#headerList()"
target="_blank">headerList()</a></java-method></node-1>
+<node-1><java-method><a
href="/site/apidocs/org/apache/juneau/http/classic/HttpHeaders.html#headerList()"
target="_blank">headerList(Header...)</a></java-method></node-1>
+<node-1><java-method><a
href="/site/apidocs/org/apache/juneau/http/classic/HttpHeaders.html#headerList()"
target="_blank">headerList(List)</a></java-method></node-1>
+<node-1><java-method><a
href="/site/apidocs/org/apache/juneau/http/classic/HttpHeaders.html#headerList()"
target="_blank">headerList(String...)</a></java-method></node-1>
</tree>
The capabilities of the <a
href="/site/apidocs/org/apache/juneau/http/classic/header/HeaderList.html"
target="_blank">HeaderList</a> class is described
@@ -90,16 +100,25 @@ later.
## HttpParts
-The <a href="/site/apidocs/org/apache/juneau/http/HttpParts.html"
target="_blank">HttpParts</a> class contains convenience static methods for
+:::info
+There are two `HttpParts` classes: the transport-neutral NG
+<a href="/site/apidocs/org/apache/juneau/http/HttpParts.html"
target="_blank">org.apache.juneau.http.HttpParts</a>
+(minimal surface: `part(String,String)`, `partList(HttpPart...)`,
`partListOfPairs(String...)`) and
+the classic <a
href="/site/apidocs/org/apache/juneau/http/classic/HttpParts.html"
target="_blank">org.apache.juneau.http.classic.HttpParts</a>
+documented below, which adds typed free-form part creators on top of the
Apache HttpCore-based
+`NameValuePair` types.
+:::
+
+The <a href="/site/apidocs/org/apache/juneau/http/classic/HttpParts.html"
target="_blank">HttpParts</a> class contains convenience static methods for
generating query/form-data/path parts and part lists.
:::tip Example
```java
-import static org.apache.juneau.http.HttpParts.*;
+import static org.apache.juneau.http.classic.HttpParts.*;
PartList formData =
partList( // Arbitrary list of parts
- stringPart("Name", "Bill") // Freeform part
+ stringPart("Name", "Bill"), // Freeform part
integerPart("Age", () -> calculateAge()) // Freeform part with
supplied value
);
```
@@ -109,32 +128,32 @@ The following methods are provided for creating parts.
Each accepts either static values or values from <a
href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/function/Supplier.html"
target="_blank">Suppliers</a>:
<tree>
-<node-0><java-class><a
href="/site/apidocs/org/apache/juneau/http/HttpParts.html"
target="_blank">HttpParts</a></java-class></node-0>
-<node-1><java-method><a
href="/site/apidocs/org/apache/juneau/http/HttpParts.html#basicPart(java.lang.String)"
target="_blank">basicPart(String,Object)</a></java-method></node-1>
-<node-1><java-method><a
href="/site/apidocs/org/apache/juneau/http/HttpParts.html#booleanPart(java.lang.String,java.lang.Boolean)"
target="_blank">booleanPart(String,Boolean)</a></java-method></node-1>
-<node-1><java-method><a
href="/site/apidocs/org/apache/juneau/http/HttpParts.html#csvArrayPart(java.lang.String,java.lang.String...)"
target="_blank">csvArrayPart(String,String...)</a></java-method></node-1>
-<node-1><java-method><a
href="/site/apidocs/org/apache/juneau/http/HttpParts.html#datePart(java.lang.String,java.time.ZonedDateTime)"
target="_blank">datePart(String,ZonedDateTime)</a></java-method></node-1>
-<node-1><java-method><a
href="/site/apidocs/org/apache/juneau/http/HttpParts.html#integerPart(java.lang.String,java.lang.Integer)"
target="_blank">integerPart(String,Integer)</a></java-method></node-1>
-<node-1><java-method><a
href="/site/apidocs/org/apache/juneau/http/HttpParts.html#longPart(java.lang.String,java.lang.Long)"
target="_blank">longPart(String,Long)</a></java-method></node-1>
-<node-1><java-method><a
href="/site/apidocs/org/apache/juneau/http/HttpParts.html#serializedPart(java.lang.String,java.lang.Object)"
target="_blank">serializedPart(String,Object)</a></java-method></node-1>
-<node-1><java-method><a
href="/site/apidocs/org/apache/juneau/http/HttpParts.html#stringPart(java.lang.String,java.lang.String)"
target="_blank">stringPart(String,String)</a></java-method></node-1>
-<node-1><java-method><a
href="/site/apidocs/org/apache/juneau/http/HttpParts.html#uriPart(java.lang.String,java.net.URI)"
target="_blank">uriPart(String,URI)</a></java-method></node-1>
+<node-0><java-class><a
href="/site/apidocs/org/apache/juneau/http/classic/HttpParts.html"
target="_blank">HttpParts</a></java-class></node-0>
+<node-1><java-method><a
href="/site/apidocs/org/apache/juneau/http/classic/HttpParts.html#basicPart(java.lang.String,java.lang.Object)"
target="_blank">basicPart(String,Object)</a></java-method></node-1>
+<node-1><java-method><a
href="/site/apidocs/org/apache/juneau/http/classic/HttpParts.html#booleanPart(java.lang.String,java.lang.Boolean)"
target="_blank">booleanPart(String,Boolean)</a></java-method></node-1>
+<node-1><java-method><a
href="/site/apidocs/org/apache/juneau/http/classic/HttpParts.html#csvArrayPart(java.lang.String,java.lang.String...)"
target="_blank">csvArrayPart(String,String...)</a></java-method></node-1>
+<node-1><java-method><a
href="/site/apidocs/org/apache/juneau/http/classic/HttpParts.html#datePart(java.lang.String,java.time.ZonedDateTime)"
target="_blank">datePart(String,ZonedDateTime)</a></java-method></node-1>
+<node-1><java-method><a
href="/site/apidocs/org/apache/juneau/http/classic/HttpParts.html#integerPart(java.lang.String,java.lang.Integer)"
target="_blank">integerPart(String,Integer)</a></java-method></node-1>
+<node-1><java-method><a
href="/site/apidocs/org/apache/juneau/http/classic/HttpParts.html#longPart(java.lang.String,java.lang.Long)"
target="_blank">longPart(String,Long)</a></java-method></node-1>
+<node-1><java-method><a
href="/site/apidocs/org/apache/juneau/http/classic/HttpParts.html#serializedPart(java.lang.String,java.lang.Object)"
target="_blank">serializedPart(String,Object)</a></java-method></node-1>
+<node-1><java-method><a
href="/site/apidocs/org/apache/juneau/http/classic/HttpParts.html#stringPart(java.lang.String,java.lang.String)"
target="_blank">stringPart(String,String)</a></java-method></node-1>
+<node-1><java-method><a
href="/site/apidocs/org/apache/juneau/http/classic/HttpParts.html#uriPart(java.lang.String,java.net.URI)"
target="_blank">uriPart(String,URI)</a></java-method></node-1>
</tree>
-The <a
href="/site/apidocs/org/apache/juneau/http/HttpParts.html#serializedPart(java.lang.String,java.lang.Object)"
target="_blank">serializedPart</a> methods allows
+The <a
href="/site/apidocs/org/apache/juneau/http/classic/HttpParts.html#serializedPart(java.lang.String,java.lang.Object)"
target="_blank">serializedPart</a> methods allows
for parts serialized using schema-based serializers such as the OpenAPI
serializer.
Lists of parts can be produced with the following methods:
<tree>
-<node-0><java-class><a
href="/site/apidocs/org/apache/juneau/http/HttpParts.html"
target="_blank">HttpParts</a></java-class></node-0>
-<node-1><java-method><a
href="/site/apidocs/org/apache/juneau/http/HttpParts.html#partList()"
target="_blank">partList()</a></java-method></node-1>
-<node-1><java-method><a
href="/site/apidocs/org/apache/juneau/http/HttpParts.html#partList()"
target="_blank">partList(List)</a></java-method></node-1>
-<node-1><java-method><a
href="/site/apidocs/org/apache/juneau/http/HttpParts.html#partList()"
target="_blank">partList(NameValuePair...)</a></java-method></node-1>
-<node-1><java-method><a
href="/site/apidocs/org/apache/juneau/http/HttpParts.html#partList()"
target="_blank">partList(String...)</a></java-method></node-1>
+<node-0><java-class><a
href="/site/apidocs/org/apache/juneau/http/classic/HttpParts.html"
target="_blank">HttpParts</a></java-class></node-0>
+<node-1><java-method><a
href="/site/apidocs/org/apache/juneau/http/classic/HttpParts.html#partList()"
target="_blank">partList()</a></java-method></node-1>
+<node-1><java-method><a
href="/site/apidocs/org/apache/juneau/http/classic/HttpParts.html#partList()"
target="_blank">partList(List)</a></java-method></node-1>
+<node-1><java-method><a
href="/site/apidocs/org/apache/juneau/http/classic/HttpParts.html#partList()"
target="_blank">partList(NameValuePair...)</a></java-method></node-1>
+<node-1><java-method><a
href="/site/apidocs/org/apache/juneau/http/classic/HttpParts.html#partList()"
target="_blank">partList(String...)</a></java-method></node-1>
</tree>
-The capabilities of the <a
href="/site/apidocs/org/apache/juneau/http/part/PartList.html"
target="_blank">PartList</a> class is described later.
+The capabilities of the <a
href="/site/apidocs/org/apache/juneau/http/classic/part/PartList.html"
target="_blank">PartList</a> class is described later.
## HttpEntities
diff --git a/pages/topics/09.03.HttpHeaders.md
b/pages/topics/09.03.HttpHeaders.md
index 6e3c229cdf..cc8dbaae9c 100644
--- a/pages/topics/09.03.HttpHeaders.md
+++ b/pages/topics/09.03.HttpHeaders.md
@@ -39,17 +39,26 @@ These subclasses provide various convenience methods to
allow for easy fluent-st
:::tip Examples
```java
+import static org.apache.juneau.http.HttpHeaders.*;
+import java.time.*;
+
// Validates the response body content is not expired.
-restClient
+String expiresValue = restClient
.get(URL)
.run()
- .getHeader("Expires").asDateHeader().assertZonedDateTime().isLessThan(new
Date());
+ .header("Expires").getValue();
+
+boolean expired = date(expiresValue).asZonedDateTime()
+ .map(d -> d.isBefore(ZonedDateTime.now()))
+ .orElse(false);
```
:::
## HeaderList
The <a
href="/site/apidocs/org/apache/juneau/http/classic/header/HeaderList.html"
target="_blank">HeaderList</a> class is a list of HTTP headers.
+It is part of the classic (`org.apache.juneau.http.classic`) API; the NG
header beans documented
+above can be added to it individually, but the container itself has no NG
equivalent.
:::tip Example
```java
@@ -64,11 +73,12 @@ HeaderList headers = HeaderList.of(Accept.TEXT_XML,
ContentType.TEXT_XML);
```
:::
-Static methods are provided on <a
href="/site/apidocs/org/apache/juneau/http/HttpHeaders.html"
target="_blank">HttpHeaders</a> to further simplify
-creation of header lists.
+`HeaderList` is part of the classic (`org.apache.juneau.http.classic`) API, so
its `headerList(...)`
+convenience creator is provided on the classic <a
href="/site/apidocs/org/apache/juneau/http/classic/HttpHeaders.html"
target="_blank">HttpHeaders</a>
+class (not the NG class documented above) to further simplify creation of
header lists.
```java
-import static org.apache.juneau.http.HttpHeaders.*;
+import static org.apache.juneau.http.classic.HttpHeaders.*;
HeaderList headers = headerList(accept("text/xml"), contentType("text/xml"));
```
diff --git a/pages/topics/09.04.HttpParts.md b/pages/topics/09.04.HttpParts.md
index de5c7fa7cc..86e65c3bdc 100644
--- a/pages/topics/09.04.HttpParts.md
+++ b/pages/topics/09.04.HttpParts.md
@@ -21,7 +21,16 @@ The <a
href="/site/apidocs/org/apache/juneau/http/part/package-summary.html" tar
## PartList
-The <a href="/site/apidocs/org/apache/juneau/http/part/PartList.html"
target="_blank">PartList</a> class is a list of HTTP parts (form-data,
+:::info
+There are two `PartList` classes: the transport-neutral NG
+<a href="/site/apidocs/org/apache/juneau/http/part/PartList.html"
target="_blank">org.apache.juneau.http.part.PartList</a>
+(an immutable, `final` list of `HttpPart` beans created via
`of(...)`/`ofPairs(...)`) and the
+classic <a
href="/site/apidocs/org/apache/juneau/http/classic/part/PartList.html"
target="_blank">org.apache.juneau.http.classic.part.PartList</a>
+documented below, which is a mutable, extensible `ArrayList<NameValuePair>`
subclass with a
+fluent builder API.
+:::
+
+The <a href="/site/apidocs/org/apache/juneau/http/classic/part/PartList.html"
target="_blank">PartList</a> class is a list of HTTP parts (form-data,
query-parameters, path-parameters).
:::tip Example
@@ -39,11 +48,12 @@ Convenience creators are provided for creating lists with
minimal code:
PartList parts = PartList.of(BasicIntegerPart.of("foo", 1));
```
-Static methods are provided on <a
href="/site/apidocs/org/apache/juneau/http/HttpParts.html"
target="_blank">HttpParts</a> to further simplify
-creation of part lists.
+Static methods are provided on the classic <a
href="/site/apidocs/org/apache/juneau/http/classic/HttpParts.html"
target="_blank">HttpParts</a>
+class (not the NG class, which has a minimal
`part(String,String)`/`partList(HttpPart...)`
+surface) to further simplify creation of part lists.
```java
-import static org.apache.juneau.http.HttpParts.*;
+import static org.apache.juneau.http.classic.HttpParts.*;
PartList parts = partList(integerPart("foo", 1), booleanPart("bar", false));
```
@@ -69,14 +79,14 @@ assertObject(parts).isString("foo=bar");
Various methods are provided for iterating over the parts in this list to
avoid array copies.
-- <a
href="/site/apidocs/org/apache/juneau/http/part/PartList.html#forEach(java.lang.String,java.util.function.Consumer)"
target="_blank">forEach(Consumer)</a> / <a
href="/site/apidocs/org/apache/juneau/http/part/PartList.html#forEach(java.lang.String,java.util.function.Consumer)"
target="_blank">forEach(String,Consumer)</a> / <a
href="/site/apidocs/org/apache/juneau/http/part/PartList.html#forEach(java.lang.String,java.util.function.Consumer)"
target="_blank">forEach(Predicate,Consumer) [...]
-- <a
href="/site/apidocs/org/apache/juneau/http/part/PartList.html#partIterator()"
target="_blank">partIterator()</a> / <a
href="/site/apidocs/org/apache/juneau/http/part/PartList.html#partIterator()"
target="_blank">partIterator(String)</a> - Use an <a
href="/site/apidocs/org/apache/juneau/http/classic/part/PartIterator.html"
target="_blank">PartIterator</a> to process parts.
-- <a
href="/site/apidocs/org/apache/juneau/http/part/PartList.html#stream(java.lang.String)"
target="_blank">stream()</a> / <a
href="/site/apidocs/org/apache/juneau/http/part/PartList.html#stream(java.lang.String)"
target="_blank">stream(String)</a> - Use a stream.
+- <a
href="/site/apidocs/org/apache/juneau/http/classic/part/PartList.html#forEach(java.lang.String,java.util.function.Consumer)"
target="_blank">forEach(Consumer)</a> / <a
href="/site/apidocs/org/apache/juneau/http/classic/part/PartList.html#forEach(java.lang.String,java.util.function.Consumer)"
target="_blank">forEach(String,Consumer)</a> / <a
href="/site/apidocs/org/apache/juneau/http/classic/part/PartList.html#forEach(java.lang.String,java.util.function.Consumer)"
target="_blank">for [...]
+- <a
href="/site/apidocs/org/apache/juneau/http/classic/part/PartList.html#partIterator()"
target="_blank">partIterator()</a> / <a
href="/site/apidocs/org/apache/juneau/http/classic/part/PartList.html#partIterator()"
target="_blank">partIterator(String)</a> - Use an <a
href="/site/apidocs/org/apache/juneau/http/classic/part/PartIterator.html"
target="_blank">PartIterator</a> to process parts.
+- <a
href="/site/apidocs/org/apache/juneau/http/classic/part/PartList.html#stream(java.lang.String)"
target="_blank">stream()</a> / <a
href="/site/apidocs/org/apache/juneau/http/classic/part/PartList.html#stream(java.lang.String)"
target="_blank">stream(String)</a> - Use a stream.
-In general, try to use these over the <a
href="/site/apidocs/org/apache/juneau/http/part/PartList.html#getAll()"
target="_blank">getAll()</a> / <a
href="/site/apidocs/org/apache/juneau/http/part/PartList.html#getAll()"
target="_blank">getAll(String)</a> methods that require array copies.
-Similar to the way multiple headers can be collapsed into a single value, the
<a
href="/site/apidocs/org/apache/juneau/http/part/PartList.html#get(java.lang.Class)"
target="_blank">get(String)</a> method is special in that it will collapse
multiple parts with the same name into a single comma-delimited list.
+In general, try to use these over the <a
href="/site/apidocs/org/apache/juneau/http/classic/part/PartList.html#getAll()"
target="_blank">getAll()</a> / <a
href="/site/apidocs/org/apache/juneau/http/classic/part/PartList.html#getAll()"
target="_blank">getAll(String)</a> methods that require array copies.
+Similar to the way multiple headers can be collapsed into a single value, the
<a
href="/site/apidocs/org/apache/juneau/http/classic/part/PartList.html#get(java.lang.Class)"
target="_blank">get(String)</a> method is special in that it will collapse
multiple parts with the same name into a single comma-delimited list.
-The <a
href="/site/apidocs/org/apache/juneau/http/part/PartList.html#get(java.lang.Class)"
target="_blank">get(Class)</a> and <a
href="/site/apidocs/org/apache/juneau/http/part/PartList.html#get(java.lang.Class)"
target="_blank">get(String,Class)</a> methods are provided for working with <a
href="/site/apidocs/org/apache/juneau/http/FormData.html"
target="_blank">FormData</a> / <a
href="/site/apidocs/org/apache/juneau/http/Query.html"
target="_blank">Query</a> / <a href="/site/apidocs/or [...]
+The <a
href="/site/apidocs/org/apache/juneau/http/classic/part/PartList.html#get(java.lang.Class)"
target="_blank">get(Class)</a> and <a
href="/site/apidocs/org/apache/juneau/http/classic/part/PartList.html#get(java.lang.Class)"
target="_blank">get(String,Class)</a> methods are provided for working with <a
href="/site/apidocs/org/apache/juneau/http/FormData.html"
target="_blank">FormData</a> / <a
href="/site/apidocs/org/apache/juneau/http/Query.html"
target="_blank">Query</a> / <a href=" [...]
:::tip Example
```java
@@ -103,7 +113,7 @@ assertObject(parts).isString("X1=bar&X2=bar");
```
:::
-The <a href="/site/apidocs/org/apache/juneau/http/part/PartList.html"
target="_blank">PartList</a> object can be extended to defined pre-packaged
+The <a href="/site/apidocs/org/apache/juneau/http/classic/part/PartList.html"
target="_blank">PartList</a> object can be extended to defined pre-packaged
lists of parts which can be used in various annotations throughout the
framework.
:::tip Example
diff --git a/pages/topics/10.31.02.HtmlWidgets.md
b/pages/topics/10.31.02.HtmlWidgets.md
index 6f964521dd..9e8c21171a 100644
--- a/pages/topics/10.31.02.HtmlWidgets.md
+++ b/pages/topics/10.31.02.HtmlWidgets.md
@@ -52,13 +52,13 @@ It shows an example of a widget that renders an image
located in the `htdocs` st
public class MyWidget extends Widget {
@Override /* Widget */
- public String getHtml(RestRequest req) throws Exception {
+ public String getHtml(RestRequest req, RestResponse res) {
UriResolver resolver = req.getUriResolver(); // API used for resolving
URIs.
- return "";
+ return "<img src='" + resolver.resolve("servlet:/htdocs/myimage.png")
+ "' class='myimage'>";
}
@Override /* Widget */
- public String getScript(RestRequest req) throws Exception {
+ public String getScript(RestRequest req, RestResponse res) {
return ""
+ "\n function myalert(imageElement) {"
+ "\n alert('cool!');"
@@ -67,7 +67,7 @@ public class MyWidget extends Widget {
}
@Override /* Widget */
- public String getStyle(RestRequest req) throws Exception {
+ public String getStyle(RestRequest req, RestResponse res) {
return ""
+ "\n .myimage {"
+ "\n border: 10px solid red;"
diff --git a/pages/topics/10.56.RestRpc.md b/pages/topics/10.56.RestRpc.md
index 69faed5f3c..f770191567 100644
--- a/pages/topics/10.56.RestRpc.md
+++ b/pages/topics/10.56.RestRpc.md
@@ -50,16 +50,25 @@ thrown on the server side.
## Client side
+:::note
+REST/RPC is a **classic-client-only** feature. It is implemented on
+<a href="/site/apidocs/org/apache/juneau/rest/client/classic/RestClient.html"
target="_blank">org.apache.juneau.rest.client.classic.RestClient</a>
+(the Apache HttpClient 4.5-based client); the next-generation,
transport-agnostic
+<a href="/docs/topics/NextGenRestClient">NG REST client</a>
(`org.apache.juneau.rest.client.RestClient`) has no
+`getRrpcInterface(...)` method and no equivalent. If you're building against
the NG client, use standard
+REST calls with the server-side `@RestOp(method=RRPC)`/`RrpcServlet` endpoints
instead of a generated proxy.
+:::
+
Remote Interface proxies are instantiated on the client side using one of the
following methods:
<tree>
-<node-0><java-class><a
href="/site/apidocs/org/apache/juneau/rest/client/RestClient.html"
target="_blank">RestClient</a></java-class></node-0>
-<node-1><java-method><a
href="/site/apidocs/org/apache/juneau/rest/client/RestClient.html#getRrpcInterface(java.lang.Class)"
target="_blank">getRrpcInterface(Class)</a></java-method></node-1>
-<node-1><java-method><a
href="/site/apidocs/org/apache/juneau/rest/client/RestClient.html#getRrpcInterface(java.lang.Class)"
target="_blank">getRrpcInterface(Class,Object)</a></java-method></node-1>
-<node-1><java-method><a
href="/site/apidocs/org/apache/juneau/rest/client/RestClient.html#getRrpcInterface(java.lang.Class)"
target="_blank">getRrpcInterface(Class,Object,Serializer,Parser)</a></java-method></node-1>
+<node-0><java-class><a
href="/site/apidocs/org/apache/juneau/rest/client/classic/RestClient.html"
target="_blank">RestClient</a></java-class></node-0>
+<node-1><java-method><a
href="/site/apidocs/org/apache/juneau/rest/client/classic/RestClient.html#getRrpcInterface(java.lang.Class)"
target="_blank">getRrpcInterface(Class)</a></java-method></node-1>
+<node-1><java-method><a
href="/site/apidocs/org/apache/juneau/rest/client/classic/RestClient.html#getRrpcInterface(java.lang.Class,java.lang.Object)"
target="_blank">getRrpcInterface(Class,Object)</a></java-method></node-1>
+<node-1><java-method><a
href="/site/apidocs/org/apache/juneau/rest/client/classic/RestClient.html#getRrpcInterface(java.lang.Class,java.lang.Object,org.apache.juneau.marshall.serializer.Serializer,org.apache.juneau.marshall.parser.Parser)"
target="_blank">getRrpcInterface(Class,Object,Serializer,Parser)</a></java-method></node-1>
</tree>
-Since we build upon the existing `RestClient` API, we inherit all of it's
features.
+Since we build upon the existing classic `RestClient` API, we inherit all of
it's features.
For example, convenience methods for setting POJO filters and properties to
customize the behavior of the serializers
and parsers, and the ability to provide your own customized Apache
`HttpClient` for handling various scenarios involving
authentication and Internet proxies.
@@ -67,7 +76,9 @@ authentication and Internet proxies.
Here's an example of the above interface being used:
```java
-// Create a RestClient using JSON for serialization, and point to the
server-side remote interface servlet.
+import org.apache.juneau.rest.client.classic.RestClient;
+
+// Create a classic RestClient using JSON for serialization, and point to the
server-side remote interface servlet.
RestClient client = RestClient.create()
.json()
.rootUrl("http://localhost:10000/remote")
diff --git a/pages/topics/12.00.JuneauRestServerSpringboot.md
b/pages/topics/12.00.JuneauRestServerSpringboot.md
index 6012d83ab0..2f6e3d3670 100644
--- a/pages/topics/12.00.JuneauRestServerSpringboot.md
+++ b/pages/topics/12.00.JuneauRestServerSpringboot.md
@@ -15,32 +15,48 @@ Spring and Spring Boot.
When a Juneau REST resource runs inside a Spring Boot application,
framework-managed beans on `RestContext`
(`CallLogger`, `EncoderSet`, `SerializerSet`, `ParserSet`, `ThrownStore`,
`Config`, `VarResolver`,
-`HttpPartSerializer`, `HttpPartParser`, etc.) are resolved in the following
order — the first match wins:
+`HttpPartSerializer`, `HttpPartParser`, etc.) are resolved through the
resource's `SpringBeanStore` in the
+following order — the first match wins:
-1. **Spring `@Bean`** — any bean of the matching type (and name, where
applicable) reachable through the
- Spring `ApplicationContext` via `SpringBeanStore`.
-2. **`@Bean` method/field on the resource class**
(`org.apache.juneau.commons.inject.Bean`) — treated as a
- *programmable default*, analogous to Spring's `@ConditionalOnMissingBean`.
Use this to supply a
- framework bean directly on the REST resource class when you do not want to
expose it as a Spring bean.
+1. **Local entries** — beans registered directly on the resource's own bean
store, most commonly a
+ `@Bean` method/field on the `@Rest`-annotated resource class
(`org.apache.juneau.commons.inject.Bean`),
+ or anything added programmatically via `addBean(...)` / `addSupplier(...)`.
+2. **Regular parent bean store**, if any — the store passed as the `parent`
constructor argument when the
+ `SpringBeanStore` was created (`SpringBeanStore(ApplicationContext,
BeanStore)`).
3. **Memoizer-backed framework default** — Juneau's built-in implementation
(`BasicCallLogger`,
- `BasicEncoderSet`, etc.).
-
-This is a behavior change from 9.4 and earlier, where the resource-class bean
supplier won over Spring.
-Migration tips:
-
-- **Preferred — let Spring win.** Remove the `@Bean` method from the resource
class and lean on the Spring
- bean. The `@Bean` method is effectively a "default", which Spring already
provides through the bean factory.
-- **Skip the Spring `@Bean`.** Don't expose the type as a Spring `@Bean` and
the `@Bean` method on the
- resource class will continue to win over the framework default.
-- **Use Spring-native overrides.** Mark the relevant Spring bean with
`@Primary`, `@MockBean`, or a
- `@ConditionalOn...` predicate so Spring itself picks the right candidate;
that candidate then becomes the
- one Juneau sees through `SpringBeanStore`.
-
-Internally, this is implemented by installing `SpringBeanStore` as the
**overriding parent** of the
-`RestContext`'s bean store (via
`BasicBeanStore.Builder.overridingParent(...)`), and by registering every
-framework default as a `addDefaultSupplier(...)` entry on the same store — so
Spring beans are consulted
-before any local registration, and built-in defaults fire only when nothing
higher up has bound the type.
-See the 9.5.0 release notes for the full per-tier breakdown.
+ `BasicEncoderSet`, etc.), registered via `addDefaultSupplier(...)`.
+4. **Spring `@Bean`** — reached only if none of the above resolved the type
(and name, where applicable),
+ via the Spring `ApplicationContext`.
+
+This is a fallback relationship, not an override: `SpringBeanStore` extends
`BasicBeanStore`, and its
+overridden `getBean()` / `getBeanSupplier()` / `hasBean()` /
`getBeansOfType()` methods each call
+`super.getBean(...)` (which resolves tiers 1–3 above) *first*, and only query
Spring's
+`ApplicationContext.getBeanProvider(...)` / `getBean(...)` when that returns
empty. Concretely, a `@Bean`
+method declared directly on the resource class **always** wins over an
identically-typed Spring bean — this
+is confirmed directly by
`SpringBeanStore_Test.c05_getBean_localOverridesSpring`, which registers a local
+bean, stubs an identically-typed bean on a mocked `ApplicationContext`,
asserts that the *local* bean is
+returned, and asserts `verifyNoInteractions(mockAppContext)` — proving Spring
is never even queried once the
+local lookup succeeds.
+
+Practical implications:
+
+- **To let a Spring bean take effect**, don't declare a competing `@Bean`
method/field of the same type
+ (and name) on the resource class — a local declaration always shadows the
Spring bean, regardless of any
+ `@Primary`/`@ConditionalOn...` annotations on the Spring side.
+- **To force your resource-class `@Bean` to win**, no action is needed — this
is the default behavior.
+- **Spring-native qualifiers still matter, but only among Spring candidates.**
`@Primary`, `@Qualifier`,
+ and `@ConditionalOn...` control *which* Spring bean `SpringBeanStore` sees
when it falls back to Spring
+ (step 4) — they have no effect if a local entry, parent-store entry, or
framework default already
+ satisfied the lookup.
+
+`BasicBeanStore` separately supports a real *overriding*-parent slot — a store
consulted **before** local
+entries — via the `BasicBeanStore(BeanStore parent, BeanStore
overridingParent)` constructor or, for
+builder-style consumers, the
`BeanStoreOverridable<B>.overridingBeanStore(BeanStore)` interface (implemented
+by builders such as `SerializerSet.Builder`, `ParserSet.Builder`,
`EncoderSet.Builder`, and
+`MockRestClient.Builder` — mainly for test-time bean substitution).
`SpringRestServlet.createBeanStore(...)`
+does **not** use this slot for the Spring bridge: it always constructs `new
SpringBeanStore(appContext,
+parent)` with `parent` as the regular (non-overriding) parent, so Spring is
layered in only as the
+last-resort fallback described above, never as a true override.
## Property Resolution
diff --git a/pages/topics/12.01.SpringBootOverview.md
b/pages/topics/12.01.SpringBootOverview.md
index 846b7ae28f..3beee27f47 100644
--- a/pages/topics/12.01.SpringBootOverview.md
+++ b/pages/topics/12.01.SpringBootOverview.md
@@ -34,10 +34,10 @@ public class App {
return new HelloMessageProvider("Hello from Spring-injected bean!");
}
- // Returns HelloResource as a Spring bean so @Autowired fields resolve.
+ // Returns HelloResource as a Spring bean with its dependency injected via
constructor.
@Bean
- public HelloResource helloResource() {
- return new HelloResource();
+ public HelloResource helloResource(HelloMessageProvider
helloMessageProvider) {
+ return new HelloResource(helloMessageProvider);
}
// Returns the root router as a Spring bean so child resources resolve as
Spring beans.
@@ -73,6 +73,8 @@ It extends `BasicSpringRestServletGroup` so child resources
resolve as Spring be
PetMustacheViewResource.class,
PetFreemarkerViewResource.class,
PetstoreUiResource.class,
+ PetInfoResource.class,
+ PetHtmlResource.class,
HelloResource.class
}
)
@@ -92,8 +94,12 @@ as an injected bean, demonstrating Spring `@Autowired`
injection into a Juneau `
)
public class HelloResource extends BasicRestResource {
+ private final HelloMessageProvider messageProvider;
+
@Autowired
- private HelloMessageProvider messageProvider;
+ public HelloResource(HelloMessageProvider messageProvider) {
+ this.messageProvider = messageProvider;
+ }
@RestGet(path="/*", summary="Responds with the Spring-injected message.")
public String sayHello() {
@@ -103,8 +109,8 @@ public class HelloResource extends BasicRestResource {
```
The POJO serialized is a simple String, but the message is resolved from the
Spring-injected `HelloMessageProvider` bean.
-Resolution works because the parent router extends
`BasicSpringRestServletGroup` (i.e. `SpringRestServlet`), which lets
-child resources be Spring beans.
+Resolution works because the parent router extends
`BasicSpringRestServletGroup` (which extends `BasicSpringRestServlet`,
+which extends `SpringRestServlet`), which lets child resources be Spring beans.
## Choosing the right base class
diff --git a/pages/topics/13.14.NextGenRestClient.md
b/pages/topics/13.14.NextGenRestClient.md
index 4e54601bbd..4169e8319b 100644
--- a/pages/topics/13.14.NextGenRestClient.md
+++ b/pages/topics/13.14.NextGenRestClient.md
@@ -72,32 +72,34 @@ Each optional module ships three classes:
## Quick Start
```java
+import org.apache.http.impl.client.*;
import org.apache.juneau.marshall.json5.*;
import org.apache.juneau.rest.client.*;
import org.apache.juneau.rest.client.apachehttpclient45.*;
-import java.time.*;
// Pre-build the serializer/parser — configure marshalling externally
var serializer = Json5Serializer.create().build();
var parser = Json5Parser.create().build();
-// Choose a transport explicitly and configure it
-RestClient client = RestClient.create()
- .transportBuilder(ApacheHc45Transport.create()
- .connectTimeout(Duration.ofSeconds(10))
- .maxConnections(50))
+// Choose a transport explicitly and configure the underlying native client
+HttpTransport transport = ApacheHc45Transport.builder()
+ .httpClient(HttpClients.custom().setMaxConnTotal(50).build())
+ .build();
+
+RestClient client = RestClient.builder()
+ .transport(transport)
.serializer(serializer)
.parser(parser)
.rootUrl("https://api.example.com")
.build();
-// Always use try-with-resources on the request — close releases the connection
-try (var req = client.get("/users/{id}").pathData("id", 42)) {
- var user = req.run().as(User.class);
+// Always use try-with-resources on the response — close() releases the
connection
+try (var resp = client.get("/users/{id}").pathData("id", 42).run()) {
+ var user = resp.body().as(User.class);
}
// At application shutdown
-client.shutdown();
+client.close();
```
### Auto-Discovery
@@ -106,8 +108,9 @@ If you don't pass an explicit transport, `RestClient` uses
`ServiceLoader` to pi
highest-priority `HttpTransportProvider` on the classpath:
```java
-RestClient zeroConfig = RestClient.create()
- .marshaller(Json5.DEFAULT)
+RestClient zeroConfig = RestClient.builder()
+ .serializer(Json5Serializer.DEFAULT)
+ .parser(Json5Parser.DEFAULT)
.rootUrl("https://api.example.com")
.build();
```
@@ -119,10 +122,10 @@ RestClient zeroConfig = RestClient.create()
| Concern | Classic `RestClient` (`...client.classic`) | Canonical
`RestClient` (`...client`) |
|---|---|---|
| HTTP integration | Implements `org.apache.http.client.HttpClient`; bound to
Apache HC 4.5 | Composes an `HttpTransport`; transport-agnostic |
-| Serialization model | Multi-language marshallers / format shortcuts
(`json()`, `xml()`, …) | **One pre-built serializer/parser/marshaller per
client**; no multi-language mode |
+| Serialization model | Multi-language marshallers / format shortcuts
(`json()`, `xml()`, …) | **One pre-built serializer/parser pair per client**;
no multi-language mode |
| Builder surface | 40+ Apache HC passthrough methods | Small builder with
only Juneau-specific concerns |
-| Lifecycle | `RestClient.close()` | Explicit `shutdown()` (not `Closeable`) —
signalling app-lifecycle vs per-call |
-| Per-request lifecycle | `RestClient` and `RestResponse` were `Closeable` |
**Only `RestRequest` is `Closeable`**; `close()` releases the connection |
+| Lifecycle | `RestClient.close()` | `RestClient.close()` — same idiom; both
implement `Closeable` |
+| Per-request lifecycle | `RestRequest` and `RestResponse` are both
`Closeable` | **Only `RestResponse` is `Closeable`**; `close()` releases the
connection |
| Header/part types | Implement `org.apache.http.Header` / `NameValuePair` |
Implement JDK-only `HttpHeader` / `HttpPart` interfaces |
| Schema validation on `@Query`/`@Header`/`@FormData`/`@Path` | Supported |
**Not supported** — `toString()` + `CollectionFormat` only |
@@ -130,20 +133,21 @@ RestClient zeroConfig = RestClient.create()
## Resource Lifecycle
-`RestRequest` is the single `Closeable` in the user-facing API. Close it to
release the
-underlying connection and stream:
+`RestResponse` — returned by `RestRequest.run()` — is the single `Closeable`
in the user-facing
+per-call API. Close it to release the underlying connection and stream:
```java
-// Correct — try-with-resources releases the connection even if run() or as()
throws
-try (var req = client.get("/users")) {
- return req.run().as(UserList.class);
+// Correct — try-with-resources releases the connection even if run() or
body() throws
+try (var resp = client.get("/users").run()) {
+ return resp.body().as(UserList.class);
}
// At application shutdown
-client.shutdown();
+client.close();
```
-`RestResponse` does **not** implement `Closeable` — its lifecycle is owned by
the request.
+`RestRequest` does **not** implement `Closeable` — it is a disposable fluent
builder for a single
+call, and `run()` transfers ownership of the connection to the returned
`RestResponse`.
---
@@ -347,8 +351,8 @@ Only `http` / `https` schemes are permitted on a URL/base
override. Other scheme
### Declarative Multipart
-Beyond the [fluent multipart API](#multipart-file-uploads), the next-gen
engine supports a
-Retrofit-style **declarative** `multipart/form-data` surface:
+Beyond [manually building a multipart body](#multipart-file-uploads), the
next-gen engine supports
+a Retrofit-style **declarative** `multipart/form-data` surface:
- `@Multipart` (`org.apache.juneau.http.remote.Multipart`) — a method-level
marker. The
`multipart/form-data` `Content-Type` (with a generated boundary) is applied
automatically.
@@ -466,28 +470,22 @@ try (InputStream in = api.export()) {
## Multipart File Uploads
-`multipart/form-data` is a first-class body type:
+`multipart/form-data` is a first-class body type. Build a `MultipartBody`
explicitly and send it
+like any other request body via `RestRequest.body(HttpBody)`:
```java
-// Fluent multipart upload
-try (var req = client.multipartPost("/upload")
- .multipartField("album", "vacation")
- .multipartFile("photo", Path.of("/tmp/beach.jpg"), "image/jpeg")) {
- req.run();
-}
-
-// Pre-built body (e.g. shared across requests)
var mp = MultipartBody.builder()
.field("note", "hello")
- .file("attachment", Path.of("report.pdf"), "application/pdf")
+ .file("attachment", new File("report.pdf"), "application/pdf")
.build();
-try (var req = client.post("/cases/123/attachments").body(mp)) {
- req.run();
+
+try (var resp = client.post("/cases/123/attachments").body(mp).run()) {
+ resp.assertOk();
}
```
-`formPost()` and `PartList` continue to produce
`application/x-www-form-urlencoded`
-and should **not** be used for binary uploads.
+`RestRequest.formData(...)` continues to produce
`application/x-www-form-urlencoded` and should
+**not** be used for binary uploads.
---
@@ -496,14 +494,15 @@ and should **not** be used for binary uploads.
Logging is framework-agnostic via `java.lang.System.Logger`:
```java
-RestClient client = RestClient.create()
- .marshaller(Json5.DEFAULT)
+RestClient client = RestClient.builder()
+ .serializer(Json5Serializer.DEFAULT)
+ .parser(Json5Parser.DEFAULT)
.logger(BasicRestLogger.of(System.getLogger("myapp.http")))
.build(); // uses the built-in JavaHttpTransport by default
// Per-request verbose logging
-try (var req = client.get("/users/123").debug()) {
- req.run();
+try (var resp = client.get("/users/123").debug().run()) {
+ resp.assertOk();
}
```
@@ -522,13 +521,9 @@ serialization, remote proxies, interceptors, and
assertions:
```java
import org.apache.juneau.rest.mock.MockRestClient;
-RestClient mock = MockRestClient.create(MyRestResource.class)
- .marshaller(Json5.DEFAULT)
- .pathData("tenantId", "acme")
- .build();
-
-try (var req = mock.get("/users/123")) {
- var user = req.run().as(User.class);
+try (MockRestClient mock = MockRestClient.create(MyRestResource.class);
+ var resp = mock.get("/users/123").run()) {
+ var user = resp.body().as(User.class);
}
```
@@ -550,10 +545,11 @@ The classic `RestClient` and its supporting
`juneau-rest-common` Apache HttpCore
`juneau-rest-client-classic`. No behavioral change.
2. **Adopt the canonical stack** — add the NG transport module for your
preferred HTTP stack
as a Maven dependency. Replace `RestClient.create()` with the canonical
- `org.apache.juneau.rest.client.RestClient.create()` and adapt builder calls
— most builder
- methods map 1:1 (`rootUrl`, default headers/query/form/path, interceptors,
marshaller,
- `errorCodes`, `executorService`).
-3. Wrap each request in **try-with-resources**. Call `shutdown()` on the
client at
+ `org.apache.juneau.rest.client.RestClient.builder()` and adapt builder
calls — some map 1:1
+ (`rootUrl`, default headers/query, interceptors, logger); `marshaller`,
`errorCodes`, and
+ `executorService` have **no NG equivalent** — configure marshalling via the
discrete
+ `serializer(...)`/`parser(...)` builder methods instead.
+3. Wrap each call's `RestResponse` in **try-with-resources**. Call `close()`
on the client at
application shutdown.
4. If you customized Apache HttpClient through `httpClientBuilder()` /
`connectionManager()` /
`defaultRequestConfig()`, move those calls onto the **transport builder**
diff --git a/pages/topics/13.15.00.HttpTransportAdapters.md
b/pages/topics/13.15.00.HttpTransportAdapters.md
index 6cd191238a..ebe59e4296 100644
--- a/pages/topics/13.15.00.HttpTransportAdapters.md
+++ b/pages/topics/13.15.00.HttpTransportAdapters.md
@@ -32,11 +32,13 @@ default. It is part of the `juneau-rest-client` artifact
and requires no additio
on Java 11+. For most applications it is the right starting point.
```java
+import org.apache.juneau.marshall.json5.*;
import org.apache.juneau.rest.client.*;
// No transport module needed — JavaHttpTransport is picked up automatically.
-RestClient client = RestClient.create()
- .marshaller(Json5.DEFAULT)
+RestClient client = RestClient.builder()
+ .serializer(Json5Serializer.DEFAULT)
+ .parser(Json5Parser.DEFAULT)
.rootUrl("https://api.example.com")
.build();
```
@@ -59,7 +61,7 @@ To set a transport explicitly:
import org.apache.juneau.rest.client.*;
import org.apache.juneau.rest.client.apachehttpclient45.*;
-RestClient client = RestClient.create()
+RestClient client = RestClient.builder()
.transport(ApacheHc45Transport.create())
.build();
```
@@ -103,7 +105,7 @@ HttpTransport myTransport = request ->
TransportResponse.builder()
.body(new ByteArrayInputStream("{}".getBytes()))
.build();
-RestClient client = RestClient.create()
+RestClient client = RestClient.builder()
.transport(myTransport)
.build();
```
@@ -112,19 +114,19 @@ RestClient client = RestClient.create()
## Resource Lifecycle
-`RestRequest` is the only `Closeable` in the user-facing API. Always wrap
calls in
-try-with-resources to release the underlying connection promptly:
+`RestResponse` — returned by `RestRequest.run()` — is the only `Closeable` in
the user-facing
+per-call API. Always wrap it in try-with-resources to release the underlying
connection promptly:
```java
-try (var req = client.get("/users/123")) {
- var user = req.run().as(User.class);
+try (var resp = client.get("/users/123").run()) {
+ var user = resp.body().as(User.class);
}
// At application shutdown
-client.shutdown();
+client.close();
```
-`client.shutdown()` delegates to `HttpTransport.close()`, which releases
connection pools, threads,
+`client.close()` delegates to `HttpTransport.close()`, which releases
connection pools, threads,
and other resources held by the native HTTP client.
---
diff --git a/pages/topics/13.15.01.RestClientApacheHttpClient45.md
b/pages/topics/13.15.01.RestClientApacheHttpClient45.md
index 16f5396ea7..67fe91871a 100644
--- a/pages/topics/13.15.01.RestClientApacheHttpClient45.md
+++ b/pages/topics/13.15.01.RestClientApacheHttpClient45.md
@@ -54,20 +54,22 @@ explicit `.transport(...)` call always wins over
auto-discovery.
### Zero-configuration default
```java
+import org.apache.juneau.marshall.json5.*;
import org.apache.juneau.rest.client.*;
import org.apache.juneau.rest.client.apachehttpclient45.*;
-RestClient client = RestClient.create()
+RestClient client = RestClient.builder()
.transport(ApacheHc45Transport.create()) // wraps
HttpClients.createDefault()
- .marshaller(Json5.DEFAULT)
+ .serializer(Json5Serializer.DEFAULT)
+ .parser(Json5Parser.DEFAULT)
.rootUrl("https://api.example.com")
.build();
-try (var req = client.get("/users/123")) {
- var user = req.run().as(User.class);
+try (var resp = client.get("/users/123").run()) {
+ var user = resp.body().as(User.class);
}
-client.shutdown();
+client.close();
```
`ApacheHc45Transport.create()` is shorthand for
`ApacheHc45Transport.builder().build()`. It
@@ -79,8 +81,9 @@ Simply add the module to the classpath and omit the
`.transport(...)` call:
```java
// The ApacheHc45TransportProvider registered via ServiceLoader takes over
automatically.
-RestClient client = RestClient.create()
- .marshaller(Json5.DEFAULT)
+RestClient client = RestClient.builder()
+ .serializer(Json5Serializer.DEFAULT)
+ .parser(Json5Parser.DEFAULT)
.rootUrl("https://api.example.com")
.build();
```
@@ -91,11 +94,12 @@ RestClient client = RestClient.create()
Use `ApacheHc45TransportBuilder.httpClient(CloseableHttpClient)` to supply
your own
pre-configured `CloseableHttpClient`. The transport takes ownership of the
client and closes it
-when `RestClient.shutdown()` is called.
+when `RestClient.close()` is called.
```java
import org.apache.http.impl.client.*;
import org.apache.http.impl.conn.*;
+import org.apache.juneau.marshall.json5.*;
import org.apache.juneau.rest.client.*;
import org.apache.juneau.rest.client.apachehttpclient45.*;
@@ -105,11 +109,12 @@ CloseableHttpClient apacheClient = HttpClients.custom()
.setMaxConnTotal(100)
.build();
-RestClient client = RestClient.create()
+RestClient client = RestClient.builder()
.transport(ApacheHc45Transport.builder()
.httpClient(apacheClient)
.build())
- .marshaller(Json5.DEFAULT)
+ .serializer(Json5Serializer.DEFAULT)
+ .parser(Json5Parser.DEFAULT)
.rootUrl("https://api.example.com")
.build();
```
@@ -177,17 +182,17 @@ The `RestClient` lifecycle maps directly to the
underlying `CloseableHttpClient`
```java
// Build once at application startup
-RestClient client = RestClient.create()
+RestClient client = RestClient.builder()
.transport(ApacheHc45Transport.builder().httpClient(myClient).build())
.build();
-// Use throughout the application lifetime; wrap each call in
try-with-resources
-try (var req = client.get("/items")) {
- return req.run().as(ItemList.class);
+// Use throughout the application lifetime; wrap each response in
try-with-resources
+try (var resp = client.get("/items").run()) {
+ return resp.body().as(ItemList.class);
}
// At application shutdown — closes the CloseableHttpClient
-client.shutdown();
+client.close();
```
---
diff --git a/pages/topics/13.15.02.RestClientApacheHttpClient50.md
b/pages/topics/13.15.02.RestClientApacheHttpClient50.md
index 1ff55f3f2c..ed1df567c0 100644
--- a/pages/topics/13.15.02.RestClientApacheHttpClient50.md
+++ b/pages/topics/13.15.02.RestClientApacheHttpClient50.md
@@ -51,20 +51,22 @@ explicit `.transport(...)` call always wins over
auto-discovery.
### Zero-configuration default
```java
+import org.apache.juneau.marshall.json5.*;
import org.apache.juneau.rest.client.*;
import org.apache.juneau.rest.client.apachehttpclient50.*;
-RestClient client = RestClient.create()
+RestClient client = RestClient.builder()
.transport(ApacheHc5Transport.create()) // wraps
HttpClients.createDefault()
- .marshaller(Json5.DEFAULT)
+ .serializer(Json5Serializer.DEFAULT)
+ .parser(Json5Parser.DEFAULT)
.rootUrl("https://api.example.com")
.build();
-try (var req = client.get("/users/123")) {
- var user = req.run().as(User.class);
+try (var resp = client.get("/users/123").run()) {
+ var user = resp.body().as(User.class);
}
-client.shutdown();
+client.close();
```
`ApacheHc5Transport.create()` is shorthand for
`ApacheHc5Transport.builder().build()`. It
@@ -75,8 +77,9 @@ creates a default `CloseableHttpClient` via
`org.apache.hc.client5.http.impl.cla
Add the module to the classpath and omit the `.transport(...)` call:
```java
-RestClient client = RestClient.create()
- .marshaller(Json5.DEFAULT)
+RestClient client = RestClient.builder()
+ .serializer(Json5Serializer.DEFAULT)
+ .parser(Json5Parser.DEFAULT)
.rootUrl("https://api.example.com")
.build();
```
@@ -87,20 +90,22 @@ RestClient client = RestClient.create()
Use `ApacheHc5TransportBuilder.httpClient(CloseableHttpClient)` to supply your
own
`CloseableHttpClient`. The transport takes ownership of the client and closes
it when
-`RestClient.shutdown()` is called.
+`RestClient.close()` is called.
```java
import org.apache.hc.client5.http.impl.classic.*;
+import org.apache.juneau.marshall.json5.*;
import org.apache.juneau.rest.client.*;
import org.apache.juneau.rest.client.apachehttpclient50.*;
CloseableHttpClient apacheClient = HttpClients.createDefault();
-RestClient client = RestClient.create()
+RestClient client = RestClient.builder()
.transport(ApacheHc5Transport.builder()
.httpClient(apacheClient)
.build())
- .marshaller(Json5.DEFAULT)
+ .serializer(Json5Serializer.DEFAULT)
+ .parser(Json5Parser.DEFAULT)
.rootUrl("https://api.example.com")
.build();
```
@@ -185,15 +190,15 @@ CloseableHttpClient timedClient = HttpClients.custom()
## Lifecycle
```java
-RestClient client = RestClient.create()
+RestClient client = RestClient.builder()
.transport(ApacheHc5Transport.builder().httpClient(myClient).build())
.build();
-try (var req = client.get("/items")) {
- return req.run().as(ItemList.class);
+try (var resp = client.get("/items").run()) {
+ return resp.body().as(ItemList.class);
}
-client.shutdown();
+client.close();
```
---
diff --git a/pages/topics/13.15.03.RestClientOkHttp.md
b/pages/topics/13.15.03.RestClientOkHttp.md
index 8bd8b08ae6..02a3f76157 100644
--- a/pages/topics/13.15.03.RestClientOkHttp.md
+++ b/pages/topics/13.15.03.RestClientOkHttp.md
@@ -55,20 +55,22 @@ explicit `.transport(...)` call always wins over
auto-discovery.
### Zero-configuration default
```java
+import org.apache.juneau.marshall.json5.*;
import org.apache.juneau.rest.client.*;
import org.apache.juneau.rest.client.okhttp.*;
-RestClient client = RestClient.create()
+RestClient client = RestClient.builder()
.transport(OkHttpTransport.create()) // wraps new OkHttpClient()
- .marshaller(Json5.DEFAULT)
+ .serializer(Json5Serializer.DEFAULT)
+ .parser(Json5Parser.DEFAULT)
.rootUrl("https://api.example.com")
.build();
-try (var req = client.get("/users/123")) {
- var user = req.run().as(User.class);
+try (var resp = client.get("/users/123").run()) {
+ var user = resp.body().as(User.class);
}
-client.shutdown();
+client.close();
```
`OkHttpTransport.create()` is shorthand for
`OkHttpTransport.builder().build()`. It creates a
@@ -79,8 +81,9 @@ new `OkHttpClient` with default settings.
Add the module to the classpath and omit the `.transport(...)` call:
```java
-RestClient client = RestClient.create()
- .marshaller(Json5.DEFAULT)
+RestClient client = RestClient.builder()
+ .serializer(Json5Serializer.DEFAULT)
+ .parser(Json5Parser.DEFAULT)
.rootUrl("https://api.example.com")
.build();
```
@@ -91,10 +94,11 @@ RestClient client = RestClient.create()
Use `OkHttpTransportBuilder.httpClient(OkHttpClient)` to supply your own
`OkHttpClient`. The
transport will call `dispatcher().executorService().shutdown()` and
-`connectionPool().evictAll()` on it when `RestClient.shutdown()` is called.
+`connectionPool().evictAll()` on it when `RestClient.close()` is called.
```java
import okhttp3.*;
+import org.apache.juneau.marshall.json5.*;
import org.apache.juneau.rest.client.*;
import org.apache.juneau.rest.client.okhttp.*;
@@ -103,11 +107,12 @@ OkHttpClient okClient = new OkHttpClient.Builder()
.readTimeout(java.time.Duration.ofSeconds(30))
.build();
-RestClient client = RestClient.create()
+RestClient client = RestClient.builder()
.transport(OkHttpTransport.builder()
.httpClient(okClient)
.build())
- .marshaller(Json5.DEFAULT)
+ .serializer(Json5Serializer.DEFAULT)
+ .parser(Json5Parser.DEFAULT)
.rootUrl("https://api.example.com")
.build();
```
@@ -121,12 +126,12 @@ each adapter:
```java
OkHttpClient shared = new OkHttpClient();
-RestClient users = RestClient.create()
+RestClient users = RestClient.builder()
.transport(OkHttpTransport.builder().httpClient(shared).build())
.rootUrl("https://users.example.com")
.build();
-RestClient orders = RestClient.create()
+RestClient orders = RestClient.builder()
.transport(OkHttpTransport.builder().httpClient(shared).build())
.rootUrl("https://orders.example.com")
.build();
@@ -189,7 +194,7 @@ OkHttpClient intercepted = new OkHttpClient.Builder()
// httpClient.connectionPool().evictAll();
```
-If you supplied a shared `OkHttpClient`, call `shutdown()` on the last
`RestClient` to use it, or
+If you supplied a shared `OkHttpClient`, call `close()` on the last
`RestClient` to use it, or
manage the `OkHttpClient` lifecycle yourself.
---
diff --git a/pages/topics/13.15.04.RestClientJetty.md
b/pages/topics/13.15.04.RestClientJetty.md
index abfd105158..405ec1ec53 100644
--- a/pages/topics/13.15.04.RestClientJetty.md
+++ b/pages/topics/13.15.04.RestClientJetty.md
@@ -57,25 +57,27 @@ because they may need to start the underlying Jetty
`HttpClient`.
:::
```java
+import org.apache.juneau.marshall.json5.*;
import org.apache.juneau.rest.client.*;
import org.apache.juneau.rest.client.jetty.*;
RestClient client;
try {
- client = RestClient.create()
+ client = RestClient.builder()
.transport(JettyHttpTransport.create()) // starts a new HttpClient
internally
- .marshaller(Json5.DEFAULT)
+ .serializer(Json5Serializer.DEFAULT)
+ .parser(Json5Parser.DEFAULT)
.rootUrl("https://api.example.com")
.build();
} catch (Exception e) {
throw new RuntimeException("Failed to start Jetty transport", e);
}
-try (var req = client.get("/users/123")) {
- var user = req.run().as(User.class);
+try (var resp = client.get("/users/123").run()) {
+ var user = resp.body().as(User.class);
}
-client.shutdown();
+client.close();
```
`JettyHttpTransport.create()` is shorthand for
`JettyHttpTransport.builder().build()`. It
@@ -87,8 +89,9 @@ timeout.
Add the module to the classpath and omit the `.transport(...)` call:
```java
-RestClient client = RestClient.create()
- .marshaller(Json5.DEFAULT)
+RestClient client = RestClient.builder()
+ .serializer(Json5Serializer.DEFAULT)
+ .parser(Json5Parser.DEFAULT)
.rootUrl("https://api.example.com")
.build();
```
@@ -114,12 +117,13 @@ HttpClient jettyClient = new HttpClient();
RestClient client;
try {
- client = RestClient.create()
+ client = RestClient.builder()
.transport(JettyHttpTransport.builder()
.httpClient(jettyClient)
.responseTimeoutMs(15_000) // wait up to 15 s for response
headers
.build())
- .marshaller(Json5.DEFAULT)
+ .serializer(Json5Serializer.DEFAULT)
+ .parser(Json5Parser.DEFAULT)
.rootUrl("https://api.example.com")
.build();
} catch (Exception e) {
@@ -169,22 +173,22 @@ JettyHttpTransport transport =
JettyHttpTransport.builder()
## Lifecycle Management
-`JettyHttpTransport.close()` calls `HttpClient.stop()`. Map this to
`RestClient.shutdown()`:
+`JettyHttpTransport.close()` calls `HttpClient.stop()`. Map this to
`RestClient.close()`:
```java
-RestClient client = RestClient.create()
+RestClient client = RestClient.builder()
.transport(JettyHttpTransport.builder().build())
.build();
// ... application runs ...
// At shutdown — stops the Jetty HttpClient
-client.shutdown();
+client.close();
```
When embedding inside a `JettyMicroservice`, the transport's lifecycle aligns
naturally with the
server because both use the same Jetty runtime. If you pass your own
`HttpClient` to the adapter,
-stopping the client via `RestClient.shutdown()` also stops that shared
instance — factor this in
+stopping the client via `RestClient.close()` also stops that shared instance —
factor this in
if other components depend on it.
---
diff --git a/pages/topics/13.16.StreamingCursors.md
b/pages/topics/13.16.StreamingCursors.md
index 45df097a69..2117df98af 100644
--- a/pages/topics/13.16.StreamingCursors.md
+++ b/pages/topics/13.16.StreamingCursors.md
@@ -22,15 +22,14 @@ Juneau release.
## Getting an InputStream from a response
Obtain the raw response stream via
-<a
href="/site/apidocs/org/apache/juneau/rest/client/classic/ResponseContent.html#asInputStream()"
target="_blank">ResponseContent.asInputStream()</a>
+<a
href="/site/apidocs/org/apache/juneau/rest/client/ResponseBody.html#asStream()"
target="_blank">ResponseBody.asStream()</a>
and pass it directly to a `Marshaller` streaming method:
```java
-RestClient client = RestClient.create().build();
+RestClient client = RestClient.create();
-try (InputStream in = client.get("/api/records")
- .run()
- .getContent().asInputStream()) {
+try (var resp = client.get("/api/records").run();
+ InputStream in = resp.body().asStream()) {
// Stream is open; pass it to the cursor factory
Marshaller m = Json.DEFAULT;
@@ -44,7 +43,7 @@ try (InputStream in = client.get("/api/records")
```
The outer `try` keeps the HTTP connection open while you iterate; the inner
`try` closes the
-cursor (and the stream) when iteration is complete. **Do not** call
`ResponseContent.asString()`
+cursor (and the stream) when iteration is complete. **Do not** call
`ResponseBody.asString()`
or any other buffering method before opening the cursor — those consume the
stream first.
---
@@ -59,10 +58,10 @@ that yields one deserialized value per call. It works with
every format that im
```java
Marshaller m = Jsonl.DEFAULT; // JSONL: one JSON value per line
-try (InputStream in = client.get("/api/export")
+try (var resp = client.get("/api/export")
.header("Accept", "application/jsonl")
- .run()
- .getContent().asInputStream();
+ .run();
+ InputStream in = resp.body().asStream();
RecordReader r = m.fromRecords(in)) {
while (r.canRead()) {
@@ -85,9 +84,8 @@ full array:
```java
Marshaller m = Json.DEFAULT;
-try (InputStream in = client.get("/api/items")
- .run()
- .getContent().asInputStream();
+try (var resp = client.get("/api/items").run();
+ InputStream in = resp.body().asStream();
RecordReader r = m.fromArrayRecords(in)) {
while (r.canRead()) {
@@ -113,9 +111,8 @@ and navigate the document structure token-by-token:
```java
Marshaller m = Json.DEFAULT;
-try (InputStream in = client.get("/api/data")
- .run()
- .getContent().asInputStream();
+try (var resp = client.get("/api/data").run();
+ InputStream in = resp.body().asStream();
TokenReader r = m.fromTokens(in)) {
r.startObject();
@@ -140,10 +137,10 @@ try (InputStream in = client.get("/api/data")
`RecordReader` exposes JDK-friendly iteration surfaces:
```java
-try (InputStream in = client.get("/api/events")
+try (var resp = client.get("/api/events")
.header("Accept", "application/jsonl")
- .run()
- .getContent().asInputStream();
+ .run();
+ InputStream in = resp.body().asStream();
RecordReader r = Jsonl.DEFAULT.fromRecords(in)) {
// Enhanced-for loop via Iterable adapter
@@ -153,10 +150,10 @@ try (InputStream in = client.get("/api/events")
}
// Or as a Java Stream (cursor is still closed by the outer try)
-try (InputStream in = client.get("/api/events")
+try (var resp = client.get("/api/events")
.header("Accept", "application/jsonl")
- .run()
- .getContent().asInputStream();
+ .run();
+ InputStream in = resp.body().asStream();
RecordReader r = Jsonl.DEFAULT.fromRecords(in)) {
long count = r.stream(Event.class).filter(Event::isActive).count();
@@ -174,10 +171,10 @@ Check it before processing very large responses if memory
is a concern:
```java
Marshaller m = Yaml.DEFAULT; // PARTIAL-tier: buffered record adapter
-try (InputStream in = client.get("/api/data")
+try (var resp = client.get("/api/data")
.header("Accept", "application/yaml")
- .run()
- .getContent().asInputStream();
+ .run();
+ InputStream in = resp.body().asStream();
RecordReader r = m.fromRecords(in)) {
boolean isStreaming = r.isRecordStreaming(); // false for YAML
@@ -194,4 +191,4 @@ try (InputStream in = client.get("/api/data")
- <a href="/docs/topics/TokenStreaming">Token Streaming</a> — `TokenReader` /
`TokenWriter` contract
- <a href="/docs/topics/ArrayRecordStreaming">Array-Record Streaming</a> —
element-by-element array cursors
- <a href="/docs/topics/RestStreamingIntegration">REST Streaming
Integration</a> — server-side cursor parameters
-- <a href="/docs/topics/ResponseContent">Response Content</a> —
`ResponseContent.asInputStream()`
+- <a href="/site/apidocs/org/apache/juneau/rest/client/ResponseBody.html"
target="_blank">ResponseBody</a> — `ResponseBody.asStream()` (NG equivalent;
see <a href="/docs/topics/ResponseContent">Response Content</a> for the classic
client's `ResponseContent`)
diff --git a/pages/topics/13.17.ContentTypeNegotiation.md
b/pages/topics/13.17.ContentTypeNegotiation.md
index dcaa46cacb..0af0d4591c 100644
--- a/pages/topics/13.17.ContentTypeNegotiation.md
+++ b/pages/topics/13.17.ContentTypeNegotiation.md
@@ -23,11 +23,11 @@ With no explicit configuration, `RestClient` uses
`JsonSerializer` / `JsonParser
`Accept: application/json` on every request:
```java
-RestClient client = RestClient.create().build();
+RestClient client = RestClient.create();
MyBean bean = client.get("/api/item/1")
.run()
- .getContent().as(MyBean.class); // parsed with JsonParser
+ .body().as(MyBean.class); // parsed with JsonParser
```
---
@@ -48,7 +48,7 @@ Register multiple serializers and parsers at build time using
</tree>
```java
-RestClient client = RestClient.create()
+RestClient client = RestClient.builder()
.serializer(JsonSerializer.DEFAULT, CborSerializer.DEFAULT,
YamlSerializer.DEFAULT)
.parser(JsonParser.DEFAULT, CborParser.DEFAULT, YamlParser.DEFAULT)
.defaultSerializer(JsonSerializer.DEFAULT)
@@ -77,7 +77,8 @@ serializer to convert the POJO to bytes. Selection order:
Override the format for one request by setting the `Content-Type` header:
```java
-client.post("/api/items", myBean)
+client.post("/api/items")
+ .body(myBean)
.header("Content-Type", "application/cbor")
.run()
.assertStatus().asCode().is(201);
@@ -87,7 +88,7 @@ client.post("/api/items", myBean)
## How the client selects a parser for inbound responses
-When you call `ResponseContent.as(Class)`, the client reads the response
`Content-Type` header
+When you call `ResponseBody.as(Class)`, the client reads the response
`Content-Type` header
and calls `RestClient.getMatchingParser(contentType)`. Selection order:
1. The `ParserSet` is queried for a parser whose media type matches the
response `Content-Type`.
@@ -99,7 +100,7 @@ and calls `RestClient.getMatchingParser(contentType)`.
Selection order:
// Server responds with Content-Type: application/cbor
MyBean bean = client.get("/api/item/1")
.run()
- .getContent().as(MyBean.class); // → CborParser selected automatically
+ .body().as(MyBean.class); // → CborParser selected automatically
```
---
@@ -112,7 +113,7 @@ Force the server to respond in a specific format by setting
the `Accept` header
MyBean bean = client.get("/api/item/1")
.header("Accept", "application/yaml")
.run()
- .getContent().as(MyBean.class); // parsed with YamlParser
+ .body().as(MyBean.class); // parsed with YamlParser
```
The per-request header takes precedence over the client-wide default derived
from the
@@ -134,7 +135,7 @@ ParserSet parsers = ParserSet.create()
.add(JsonParser.DEFAULT, CborParser.DEFAULT)
.build();
-RestClient client = RestClient.create()
+RestClient client = RestClient.builder()
.serializers(serializers)
.parsers(parsers)
.build();
@@ -160,5 +161,5 @@ RestClient client = RestClient.create()
- <a href="/docs/topics/SerializerSetsParserSets">Serializer Sets and Parser
Sets</a> — the underlying registry API
- <a href="/docs/topics/PojoMarshalling">POJO Marshalling</a> — per-request
language shortcuts
-- <a href="/docs/topics/ResponseContent">Response Content</a> — parsing the
response body
+- <a href="/site/apidocs/org/apache/juneau/rest/client/ResponseBody.html"
target="_blank">ResponseBody</a> — parsing the response body (NG; see <a
href="/docs/topics/ResponseContent">Response Content</a> for the classic
client's `ResponseContent`)
- <a href="/docs/topics/RequestContent">Request Content</a> — setting the
request body
diff --git a/pages/topics/19.JuneauPetstore.md
b/pages/topics/19.JuneauPetstore.md
index ed3bf6a57f..388d71d903 100644
--- a/pages/topics/19.JuneauPetstore.md
+++ b/pages/topics/19.JuneauPetstore.md
@@ -30,6 +30,8 @@ The **core-hosted surface** is identical across both
deployments by construction
| FreeMarker view | `PetFreemarkerViewResource`
(`/pet-views/freemarker/pets/{id}/view`) | Typed-`View` return path through
`juneau-rest-server-view-freemarker`. |
| No-build React SPA | `PetstoreUiResource`
(`/petstore-ui/static/petstore-ui.html`) | Headless-JSON + decoupled-SPA
pattern; loads React + Babel and uses `fetch()` against `/petstore/pets`. |
| Bearer-token gate | `PetSecureResource` (`/petstore-secure/*`) | Fail-closed
`BearerTokenGuard` backed by a stub `TokenValidator`
(`StubBearerTokenValidator`, tokens `petstore-user`→`alice`,
`petstore-admin`→`admin`). Demonstrates the `@Auth Principal` injection
pattern. |
+| REST-server utility beans | `PetInfoResource` (`/petstore-info/*`) |
`BeanDescription`/`Hyperlink`/`SeeOtherRoot` utility-bean examples against the
`Pet` domain bean. |
+| HTML5 bean-builder DSL | `PetHtmlResource` (`/petstore-html/*`) | Hand-built
HTML5 `Div`/`Table` fragments rendered from live petstore data via
`HtmlBuilder`, bypassing the automatic HTML-doc view. |
The **deployment-specific surface** is intentionally non-parity and documented
as such:
@@ -67,6 +69,8 @@ After starting either deployment, hit a few of the following
URLs (replace the p
- `GET http://localhost:10000/pet-views/mustache/pets/1/view` —
Mustache-rendered pet detail page.
- `GET http://localhost:10000/pet-views/freemarker/pets/1/view` —
FreeMarker-rendered pet detail page.
- `GET http://localhost:10000/petstore-ui/static/petstore-ui.html` — React SPA.
+- `GET http://localhost:10000/petstore-info` — utility-bean demo links
(`BeanDescription`, `Hyperlink`, `SeeOtherRoot`).
+- `GET http://localhost:10000/petstore-html/table` — hand-built HTML5 table of
all seeded pets.
- `GET http://localhost:10000/petstore-secure/pets` — `401 Unauthorized` (no
bearer).
- `GET http://localhost:10000/petstore-secure/pets` with `Authorization:
Bearer petstore-user` — `200 OK` with pet list.
- `GET http://localhost:10000/petstore-secure/whoami` with `Authorization:
Bearer petstore-admin` — returns the principal name.
@@ -91,6 +95,8 @@ Start with these class-level Javadocs:
- `org.apache.juneau.petstore.rest.PetMustacheViewResource` /
`PetFreemarkerViewResource` — view-engine integration.
- `org.apache.juneau.petstore.rest.PetstoreUiResource` — static-file mixin
demo.
- `org.apache.juneau.petstore.rest.PetSecureResource` — bearer-token guard
demo.
+- `org.apache.juneau.petstore.rest.PetInfoResource` — REST-server
utility-beans demo (`BeanDescription`/`Hyperlink`/`SeeOtherRoot`).
+- `org.apache.juneau.petstore.rest.PetHtmlResource` — HTML5 bean-builder DSL
demo.
- `org.apache.juneau.petstore.jetty.App` /
`org.apache.juneau.petstore.jetty.RootResources` — Jetty deployment.
- `org.apache.juneau.petstore.springboot.App` /
`org.apache.juneau.petstore.springboot.RootResources` — Spring Boot deployment.
diff --git a/sidebars.ts b/sidebars.ts
index 480e2770f5..9ddb0db8ee 100644
--- a/sidebars.ts
+++ b/sidebars.ts
@@ -219,7 +219,7 @@ const sidebars: SidebarsConfig = {
{
type: 'doc',
id:
'topics/03.03.06.BeanIgnoreAnnotation',
- label: '3.3.6.
@MarshalledIgnore Annotation',
+ label: '3.3.6.
@BeanIgnore Annotation',
},
{
type: 'doc',