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 5f293673e1 Fix docs from TODO-297 audit: reference tables, part
annotations, OpenAPI quartet, childrenDefs, encoder/objecttools, developer-info
5f293673e1 is described below
commit 5f293673e1c9f8c68f7e7c9bcf1a4118743af5cc
Author: James Bognar <[email protected]>
AuthorDate: Sun Jul 26 13:50:14 2026 -0400
Fix docs from TODO-297 audit: reference tables, part annotations, OpenAPI
quartet, childrenDefs, encoder/objecttools, developer-info
Closes READY-302/304/305/306/308 from the TODO-297 Docusaurus docs audit:
- READY-302: refreshed the canonical @Rest/@RestOp reference tables
(10.00/10.02.00/10.03.00) and removed the fabricated serializer()/parser()
members from the 7-file classic @RemoteOp part-annotation cluster
(13.09.03-.09).
- READY-304: rewrote 10.10's children-vs-mixins thesis to reflect that
@Child/childrenDefs shipped in 10.0.0 (FINISHED-182), instead of the
stale "parked, not shipped" claim.
- READY-305: rewrote the 03.31.x OpenAPI-marshall quartet (methodology,
serializers, parsers) to fix stale imports and compile-breaking errors.
- READY-306: fixed the fabricated method names in 03.23/03.24 that were
copied verbatim from stale source Javadoc (paired with the source fix
in apache/juneau).
- READY-308: modernized developer-info for the JIRA->GitHub Issues
workflow, script-doc staleness, and personal-path cleanup.
Co-authored-by: Cursor <[email protected]>
---
.../02.02.NonCommittersContribute.md | 16 ++--
pages/developer-info/02.03.NewMemberGuidelines.md | 5 +-
pages/developer-info/02.04.NewReleaseGuidelines.md | 42 ++++++-----
pages/developer-info/04.01.Scripts.md | 27 ++++++-
pages/developer-info/04.02.01.ScriptTest.md | 36 +++++++++
pages/developer-info/04.02.02.ScriptPush.md | 9 ++-
.../04.02.07.ScriptApplyEclipsePrefs.md | 2 +-
.../04.02.08.ScriptCleanupWhitespace.md | 2 +-
.../04.02.09.ScriptCheckFluentSetterOverrides.md | 2 +-
pages/developer-info/04.03.03.ScriptBuildDocs.md | 4 +-
.../developer-info/04.03.04.ScriptCreateMvnSite.md | 5 +-
.../04.03.05.ScriptStartDocusaurus.md | 4 +-
.../04.03.06.ScriptCheckTopicLinks.md | 11 +--
pages/topics/03.23.MarshallEncoders.md | 7 +-
pages/topics/03.24.ObjectTools.md | 10 +--
pages/topics/03.31.01.OpenApiMethodology.md | 12 +--
pages/topics/03.31.02.OpenApiSerializers.md | 88 +++++++++++-----------
pages/topics/03.31.03.OpenApiParsers.md | 30 ++++----
pages/topics/10.00.JuneauRestServer.md | 16 +---
pages/topics/10.02.00.RestAnnotatedClasses.md | 2 +-
pages/topics/10.03.00.RestOpAnnotatedMethods.md | 2 +-
pages/topics/10.10.RestServerChildrenVsMixins.md | 43 +++++++----
pages/topics/13.09.03.Content.md | 4 +-
pages/topics/13.09.04.FormData.md | 3 +-
pages/topics/13.09.05.Query.md | 3 +-
pages/topics/13.09.06.Header.md | 3 +-
pages/topics/13.09.07.Path.md | 3 +-
pages/topics/13.09.08.Request.md | 2 +-
pages/topics/13.09.09.Response.md | 1 -
29 files changed, 228 insertions(+), 166 deletions(-)
diff --git a/pages/developer-info/02.02.NonCommittersContribute.md
b/pages/developer-info/02.02.NonCommittersContribute.md
index 6a391c6333..1b009d9da3 100644
--- a/pages/developer-info/02.02.NonCommittersContribute.md
+++ b/pages/developer-info/02.02.NonCommittersContribute.md
@@ -3,19 +3,21 @@ id: 02.02.NonCommittersContribute
title: How non-committers can contribute code
---
-This guide is for those who are new to Juneau and want to contribute code,
specifically those who do not have write access to our repositories:
-- [https://github.com/apache/juneau](https://github.com/apache/juneau)
--
[https://github.com/apache/juneau-website](https://github.com/apache/juneau-website)
+This guide is for those who are new to Juneau and want to contribute code,
specifically those who do not have write access to our repositories. All active
development happens in a single GitHub repository,
[https://github.com/apache/juneau](https://github.com/apache/juneau), split
across two branches:
+- **`master`** - the Java source code (core libraries, REST server/client,
examples, etc.)
+- **`docs`** - the Docusaurus documentation site (this site) under `pages/`
+
+The legacy
[https://github.com/apache/juneau-website](https://github.com/apache/juneau-website)
repository is no longer the live site and should not be used for new
contributions.
## Step-by-step guide
-1. **Create a fork** of the repository you want to contribute to -
[https://github.com/apache/juneau](https://github.com/apache/juneau) or
[https://github.com/apache/juneau-website](https://github.com/apache/juneau-website)
- the fork button is in the top right corner
+1. **Create a fork** of
[https://github.com/apache/juneau](https://github.com/apache/juneau) - the fork
button is in the top right corner

-2. **Clone your fork** of the repository locally
-3. **Make changes** to your local clone. If you haven't already, create a JIRA
issue.
-4. **Commit them locally**, using the commit format of `"JIRA-TICKET - What
you changed"` e.g. `"JUNEAU-123 - Made JUNEAU better."`
+2. **Clone your fork** of the repository locally, and check out the
**`master`** branch for code changes or the **`docs`** branch for documentation
changes
+3. **Make changes** to your local clone. If you haven't already, search
[GitHub Issues](https://github.com/apache/juneau/issues) for an existing issue
or open a new one describing the problem you're fixing or the feature you're
adding
+4. **Commit them locally**, using a clear, descriptive commit message that
summarizes the change; reference the GitHub issue number if one exists, e.g.
`"Fix NullPointerException in JsonSerializer (#123)"`
5. **Push these changes** to your fork
6. **Navigate back** to your fork or to our github repositories and you'll see
an option to create a new pull request.
7. **Click on the blue link "Pull request"** to bring up the create pull
request screen.
diff --git a/pages/developer-info/02.03.NewMemberGuidelines.md
b/pages/developer-info/02.03.NewMemberGuidelines.md
index 44800a124b..d6347a7538 100644
--- a/pages/developer-info/02.03.NewMemberGuidelines.md
+++ b/pages/developer-info/02.03.NewMemberGuidelines.md
@@ -26,14 +26,13 @@ If they accept, then do:
6. Request creation of the committer account if not already done by Secretary
7. Now wait until root says it is done
8. PMC Chair to enable svn and other access
-9. Add committer to the appropriate groups in JIRA and CWiki
+9. Add committer to the appropriate GitHub team/org groups
10. Notify the committer of completion
11. Announce the new committer
## Discussion
-Before approving membership, it's assumed that the person has actively
contributed through this process:
-[Contributing for
Non-committers](https://cwiki.apache.org/confluence/display/JUNEAU/Contributing+for+Non-committers)
+Before approving membership, it's assumed that the person has actively
contributed through this process: see **How non-committers can contribute
code** in this section.
Once it's been shown that the member submits good work, the team can invite
them to be a full member.
diff --git a/pages/developer-info/02.04.NewReleaseGuidelines.md
b/pages/developer-info/02.04.NewReleaseGuidelines.md
index 54bad3b806..6cee198da6 100644
--- a/pages/developer-info/02.04.NewReleaseGuidelines.md
+++ b/pages/developer-info/02.04.NewReleaseGuidelines.md
@@ -50,17 +50,21 @@ The release will be called 9.x.x-RCx. The next release will
be set to 7.x.y.
## 3 - Creating a release candidate
-### 3.1 - Create new release in JIRA
+### 3.1 - Author the release notes
-Log into **JIRA** and create the new version (e.g. **7.0.1**). Change the
**Release date** on the current version to today.
+Juneau tracks issues and releases through **GitHub Issues** on
[https://github.com/apache/juneau](https://github.com/apache/juneau) - there is
no JIRA project anymore.
-Generate the release notes for the current release as plain text. Click on the
current release and click the **Release Notes** button. Click the **Configure
Release Notes** button to select plain text. Copy the contents of this file to
the root **RELEASE-NOTES.txt** file and commit the change.
+Release notes are authored directly (not exported from a tracker) as a
Markdown file in the `juneau-docs` repository (the `docs` branch of
`apache/juneau`) at `pages/release-notes/<VERSION>.md` (e.g.
`pages/release-notes/10.0.0.md`). Use the previous version's file as a
structural guide: a top-level "major changes" overview followed by per-module
sections (new features, bug fixes, breaking changes, deprecations, etc.).
-### 3.2 - Update Release Notes section in overview.html
+<div class="info">
+
+**Note:** Do **NOT** add release notes to the root **RELEASE-NOTES.txt** file
in the `juneau` (Java) tree - that file is no longer the canonical location.
+
+</div>
-We maintain externally-consumable new-and-noteworthy information for all our
releases in our javadocs.
+### 3.2 - Javadoc overview page
-Using the release notes above as a guide, create release notes in the
**Release Notes** section of the **/docs/src/javadoc/overview.html** document.
Use the previous release as a guideline.
+The Javadoc overview page at **docs/src/javadoc/overview.html** (in the
`juneau` repo) currently contains only the project description and key-features
summary - it does not carry a per-release "Release Notes" section. The
authoritative, externally-consumable release notes are the
`pages/release-notes/<VERSION>.md` page from step 3.1 above; there's no
additional per-release edit required in `overview.html` unless the key-features
summary itself needs updating for the new release.
### 3.3 - Update LICENSE and NOTICE files
@@ -289,24 +293,24 @@ Wait to send the release announcement until you have
verified that:
3. If the component publishes maven artifacts, these artifacts have been
replicated to the central maven repo at **repo.maven.apache.org**.
(Clear your local repo of the release artifacts and either activate the
clirr report with the updated version info or update a local project with a
dependency to the new release version to get maven to try to download the
release artifacts. Or just access repo using a web browser.)
-## 7 - Updating Website
+## 7 - Updating the documentation site
-The website contents are located in GitHub:
https://github.com/apache/juneau-website
+The website is the Docusaurus site in the **`juneau-docs`** repository (the
`docs` branch of `apache/juneau`, typically checked out as a sibling folder of
`juneau`). The legacy `apache/juneau-website` repo and its `juneau-website.sh`
templating flow are **no longer used** to publish the site.
-Checkout the contents of this repo to the same git folder of the juneau
project (e.g. /juneau and /juneau-website should be in the same parent git
folder).
+Publishing is a **strict two-stage** process - stage first, verify, then
promote to production. See the **release-docs-stage.py** and
**release-docs.py** script pages in section 4.3 of this Developer Info guide
for full detail; summary below.
-Generate the Javadocs for the new version by doing the following:
+### 7.1 - Build and generate Javadocs
1. Make sure the version is set correctly in the root **pom.xml** (should
already be done at this point).
-2. Run the following command in the **/juneau** folder to generate the
Javadocs and add them to the website: **scripts/build-docs.py**
-3. Verify that a new folder is created at **docs/static/javadocs/x.x.x**
containing the newly-generated javadocs.
+2. From the **`juneau-docs`** repository root, run: **python3
scripts/build-docs.py**. This compiles the Java modules, generates the Maven
site/Javadocs, and builds the Docusaurus site.
+3. Verify that a new folder is created at
**juneau-docs/static/javadocs/x.x.x** containing the newly-generated javadocs,
and that `releases.json` was updated.
+
+### 7.2 - Deploy to staging
+
+From the **`juneau-docs`** repository root, run **python3
scripts/release-docs-stage.py**. This rebuilds the site for staging and
force-pushes it to the `asf-staging` branch, which serves
**https://juneau.staged.apache.org**.
-Update the downloads page and regenerate templates.
+Verify the new release notes and Javadocs render correctly on the staged site
before proceeding.
-1. Update the **juneau-website/templates/downloads.html** to reflect the
newest release.
- 1. Change **Current release** section.
- 2. Add new entry to **Older releases** section.
-2. Update the settings in **juneau-website.properties** to reflect new
versions.
-3. Run the **juneau-website.sh** script to regenerate the templated files.
+### 7.3 - Promote to production
-After completion, commit and push the changes to the master branch. The
website should be updated immediately.
+Once the staged site has been verified, run **python3
scripts/release-docs.py** from the **`juneau-docs`** repository root. This
promotes the current `asf-staging` branch to `asf-site`, which is the branch
served at **https://juneau.apache.org** - this is the live publish and cannot
be undone without a follow-up force-push, so confirm the staged content first.
diff --git a/pages/developer-info/04.01.Scripts.md
b/pages/developer-info/04.01.Scripts.md
index cb00400605..743ce32a8d 100644
--- a/pages/developer-info/04.01.Scripts.md
+++ b/pages/developer-info/04.01.Scripts.md
@@ -7,11 +7,11 @@ Apache Juneau includes a collection of Python scripts in the
`scripts/` director
## Available Scripts
-Scripts are organized into two categories based on which branch they're
located in:
+Scripts are organized into two categories based on which branch/repo checkout
they're located in. This index covers the most commonly-used developer scripts;
a handful of narrowly-scoped or CI-internal scripts are listed without
dedicated pages.
### 4.2. Code Scripts (master branch)
-These scripts are located in the `master` branch and are used for code
development, testing, and releases:
+These scripts are located in the `master` branch (the `juneau`
repository/checkout) and are used for code development, testing, and releases:
| Script | Description | Details |
|--------|-------------|---------|
@@ -28,19 +28,40 @@ These scripts are located in the `master` branch and are
used for code developme
| [revert-unstaged.py](/docs/developer-info/ScriptRevertUnstaged) | Revert
unstaged git changes | [Learn more
→](/docs/developer-info/ScriptRevertUnstaged) |
| [start-petstore-jetty.py](/docs/developer-info/ScriptStartPetstoreJetty) |
Start the petstore showcase under Jetty/Microservice | [Learn more
→](/docs/developer-info/ScriptStartPetstoreJetty) |
|
[start-petstore-springboot.py](/docs/developer-info/ScriptStartPetstoreSpringboot)
| Start the petstore showcase under Spring Boot | [Learn more
→](/docs/developer-info/ScriptStartPetstoreSpringboot) |
+| `check-bom-completeness.py` | Verifies the published `juneau-bom` lists all
reactor modules | — |
+| `check-container-tags.py` | Guardrail that verifies container-backed tests
are tagged correctly | — |
+| `ci-perf-guard.py` | CI wall-clock performance regression guard, per
module/bucket | — |
+| `coverage.py` | Generates and reports JaCoCo test coverage | — |
+| `microbench.py` | Runs JMH micro-benchmarks | — |
+| `normalize-generic-commas.py` | Normalizes comma spacing in generic type
arguments | — |
+| `push-timings.py` | Reports timing deltas from the `push.py`/`test.py`
timing-log history | — |
+| `slack-notify.py` | Sends build/release notifications to Slack | — |
+| `sonarqube.py` | Reports SonarQube/SonarCloud findings from the command line
| — |
+| `surefire-rollup.py` | Rolls up Surefire XML results into per-module/bucket
timing summaries | — |
+| `view-sonar-category.py` | Views SonarQube issue categories
non-interactively | — |
### 4.3. Doc Scripts (docs branch)
-These scripts are located in the `docs` branch and are used for documentation
building and deployment:
+These scripts are located in the `docs` branch (the `juneau-docs`
repository/checkout) and are used for documentation building, validation, and
deployment:
| Script | Description | Details |
|--------|-------------|---------|
+| `verify-docs.py` | **Docs integrity checker** - validates frontmatter,
slugs, sidebar structure, and internal links; the primary "does the site check
out?" gate | See
[check-topic-links.py](/docs/developer-info/ScriptCheckTopicLinks) for a
related, narrower link-only check |
| [release-docs-stage.py](/docs/developer-info/ScriptReleaseDocsStage) | Stage
documentation to asf-staging | [Learn more
→](/docs/developer-info/ScriptReleaseDocsStage) |
| [release-docs.py](/docs/developer-info/ScriptReleaseDocs) | Promote
documentation to production | [Learn more
→](/docs/developer-info/ScriptReleaseDocs) |
| [build-docs.py](/docs/developer-info/ScriptBuildDocs) | Build complete
documentation | [Learn more →](/docs/developer-info/ScriptBuildDocs) |
| [create-mvn-site.py](/docs/developer-info/ScriptCreateMvnSite) | Generate
Maven site for testing | [Learn more
→](/docs/developer-info/ScriptCreateMvnSite) |
| [start-docusaurus.py](/docs/developer-info/ScriptStartDocusaurus) | Start
Docusaurus dev server | [Learn more
→](/docs/developer-info/ScriptStartDocusaurus) |
| [check-topic-links.py](/docs/developer-info/ScriptCheckTopicLinks) |
Validate documentation links | [Learn more
→](/docs/developer-info/ScriptCheckTopicLinks) |
+| [generate-ai-artifacts.py /
check-ai-artifacts.py](/docs/developer-info/ScriptAiArtifacts) | Generate and
validate machine-consumable AI knowledge artifacts | [Learn more
→](/docs/developer-info/ScriptAiArtifacts) |
+| `apply-renames.py` | Mechanical bulk URL/text substitution pass across
`pages/` | — |
+| `normalize-headings.py` | Normalizes Markdown heading structure under
`pages/topics/` | — |
+
+<div class="info">
+
+**Note:** `verify-docs.py` is the primary docs-integrity gate - run `python3
scripts/verify-docs.py --strict --anchors` from the `juneau-docs` repository
root before publishing any documentation change. See the script's `--help`
output for the full list of checks and flags.
+
+</div>
## Common Features
diff --git a/pages/developer-info/04.02.01.ScriptTest.md
b/pages/developer-info/04.02.01.ScriptTest.md
index 4fcf590651..95300fcbbd 100644
--- a/pages/developer-info/04.02.01.ScriptTest.md
+++ b/pages/developer-info/04.02.01.ScriptTest.md
@@ -56,12 +56,48 @@ python3 scripts/test.py -v
Shows full Maven output instead of just the last 50 lines.
+### Exclude Container-Backed Tests
+
+```bash
+python3 scripts/test.py --no-container
+```
+
+Excludes tests tagged `@Tag("container")` (e.g. Springboot/Jetty/Tomcat
container tests), useful for a faster local inner loop when you only need core
coverage.
+
+### Record Per-Module Timing
+
+```bash
+python3 scripts/test.py --timing-log /path/to/timings.jsonl
+```
+
+Appends per-(module, bucket) timing records to the given JSONL file after the
run.
+
+### Enforce Performance Baseline
+
+```bash
+python3 scripts/test.py --enforce-perf
+```
+
+Compares the measured wall-clock time against `perf-baseline.txt` (project
root) and **hard-fails** if it exceeds the tolerance (default ±20%,
configurable via the `JUNEAU_CI_PERF_THRESHOLD` environment variable). Without
this flag, perf comparisons are printed but never fail the build. Modules with
no baseline entry are treated as new (warn, not fail).
+
+### One-Shot JFR Profiling
+
+```bash
+python3 scripts/test.py --profile juneau-marshall
+```
+
+Runs a one-shot JFR (Java Flight Recorder) profile for the given module's
tests, useful for investigating performance regressions.
+
## Command-Line Options
- `--build-only, -b` - Only build (skip tests)
- `--test-only, -t` - Only run tests (no build)
- `--full, -f` - Clean build + run tests (default)
- `--verbose, -v` - Show full Maven output
+- `--no-container` - Exclude `@Tag("container")` tests
+- `--timing-log <path>` - Append per-module/bucket timing JSONL records
+- `--enforce-perf` - Hard-fail if wall-clock exceeds the perf-baseline
tolerance
+- `--profile <module>` - Run a one-shot JFR profile for the given module's
tests
- `--help, -h` - Show help message
## Examples
diff --git a/pages/developer-info/04.02.02.ScriptPush.md
b/pages/developer-info/04.02.02.ScriptPush.md
index 954c75d09c..218aaee5fc 100644
--- a/pages/developer-info/04.02.02.ScriptPush.md
+++ b/pages/developer-info/04.02.02.ScriptPush.md
@@ -13,15 +13,22 @@ The script executes the following steps in order:
2. **Build and Install** - Runs `mvn clean package install` to build the
project
3. **Git Commit** - Stages all changes and commits with the provided message
4. **Git Push** - Pushes the commit to the remote repository
+5. **juneau-docs follow-up (conditional)** - If a sibling `juneau-docs`
checkout exists alongside `juneau` and has pending changes, the script
automatically runs a Docusaurus smoke check (`build-docs.py --skip-maven`)
there, and - if it passes - **stages, commits (using the same commit message),
and pushes the `juneau-docs` changes too**
If any step fails, the script stops immediately and reports the failure.
+<div class="info">
+
+**Note:** Step 5 is a real, easy-to-miss side effect: running `push.py` from
`juneau` can also commit and push an entirely different repository
(`juneau-docs`) if it has a dirty working tree. If you only want to push
`juneau` and handle docs separately, make sure `juneau-docs` has no pending
changes before running this script.
+
+</div>
+
## Usage
### Basic Usage
```bash
-cd /Users/james.bognar/git/juneau
+cd /path/to/juneau
python3 scripts/push.py "Your commit message here"
```
diff --git a/pages/developer-info/04.02.07.ScriptApplyEclipsePrefs.md
b/pages/developer-info/04.02.07.ScriptApplyEclipsePrefs.md
index 8509d1db08..180ce8e85c 100644
--- a/pages/developer-info/04.02.07.ScriptApplyEclipsePrefs.md
+++ b/pages/developer-info/04.02.07.ScriptApplyEclipsePrefs.md
@@ -24,7 +24,7 @@ The script copies Eclipse JDT (Java Development Tools)
preferences from the `ecl
### Apply preferences to all modules
```bash
-cd /Users/james.bognar/git/juneau
+cd /path/to/juneau
python3 scripts/apply-eclipse-prefs.py
```
diff --git a/pages/developer-info/04.02.08.ScriptCleanupWhitespace.md
b/pages/developer-info/04.02.08.ScriptCleanupWhitespace.md
index 353723bb16..816146b2d3 100644
--- a/pages/developer-info/04.02.08.ScriptCleanupWhitespace.md
+++ b/pages/developer-info/04.02.08.ScriptCleanupWhitespace.md
@@ -19,7 +19,7 @@ The script performs the following cleanup operations:
### Clean the entire Juneau codebase
```bash
-cd /Users/james.bognar/git/juneau
+cd /path/to/juneau
python3 scripts/cleanup-whitespace.py
```
diff --git a/pages/developer-info/04.02.09.ScriptCheckFluentSetterOverrides.md
b/pages/developer-info/04.02.09.ScriptCheckFluentSetterOverrides.md
index f741d64497..e756235a70 100644
--- a/pages/developer-info/04.02.09.ScriptCheckFluentSetterOverrides.md
+++ b/pages/developer-info/04.02.09.ScriptCheckFluentSetterOverrides.md
@@ -41,7 +41,7 @@ The script:
## Usage
```bash
-cd /Users/james.bognar/git/juneau
+cd /path/to/juneau
python3 scripts/check-fluent-setter-overrides.py
```
diff --git a/pages/developer-info/04.03.03.ScriptBuildDocs.md
b/pages/developer-info/04.03.03.ScriptBuildDocs.md
index 7ee9bf87cf..92d37a31d3 100644
--- a/pages/developer-info/04.03.03.ScriptBuildDocs.md
+++ b/pages/developer-info/04.03.03.ScriptBuildDocs.md
@@ -25,7 +25,7 @@ The script performs the following steps:
### Build all documentation
```bash
-cd /path/to/juneau
+cd /path/to/juneau-docs
python3 scripts/build-docs.py
```
@@ -75,7 +75,7 @@ After successful execution, the documentation will be
available in:
## Notes
- The script automatically skips tests (`-DskipTests`) to speed up the build
-- All commands are run from the project root directory
+- All commands are run from the `juneau-docs` repository root; the script
requires a sibling `../master/` checkout (the Java tree) to run the Maven steps
against, unless `--skip-maven` is used
- The script will exit immediately if any command fails (unless using
`--skip-*` options)
- The build directory (`juneau-docs/build/`) will be created if it doesn't
exist
- Existing site contents will be replaced when copying
diff --git a/pages/developer-info/04.03.04.ScriptCreateMvnSite.md
b/pages/developer-info/04.03.04.ScriptCreateMvnSite.md
index 3d7a56f89d..c608c72d0a 100644
--- a/pages/developer-info/04.03.04.ScriptCreateMvnSite.md
+++ b/pages/developer-info/04.03.04.ScriptCreateMvnSite.md
@@ -20,7 +20,7 @@ The script performs these operations:
### Generate Maven Site
```bash
-cd /Users/james.bognar/git/juneau
+cd /path/to/juneau-docs
python3 scripts/create-mvn-site.py
```
@@ -43,7 +43,8 @@ Use this script when:
## Notes
-- The script creates a log file (`create-mvn-site.log`) in the project root
+- The script requires a sibling `../master/` checkout (the Java tree)
alongside `juneau-docs` - the Maven site is generated there, then copied over
+- The script creates a log file (`create-mvn-site.log`) in the `master`
checkout's root
- The Maven site is copied to `juneau-docs/static/site/` where Docusaurus can
serve it
- This is primarily for local testing - production builds use `build-docs.py`
diff --git a/pages/developer-info/04.03.05.ScriptStartDocusaurus.md
b/pages/developer-info/04.03.05.ScriptStartDocusaurus.md
index 9f097cffe3..5f1d97d4a2 100644
--- a/pages/developer-info/04.03.05.ScriptStartDocusaurus.md
+++ b/pages/developer-info/04.03.05.ScriptStartDocusaurus.md
@@ -19,7 +19,7 @@ The script performs these operations before starting the
server:
### Start the Server
```bash
-cd /Users/james.bognar/git/juneau
+cd /path/to/juneau-docs
python3 scripts/start-docusaurus.py
```
@@ -44,7 +44,7 @@ Use this script when:
## Notes
-- The script automatically detects the `/juneau-docs` directory
+- The script resolves its working directory relative to its own location
(`scripts/../`), i.e. the `juneau-docs` repository root it lives in - it does
not need to be run from any particular directory itself
- Cache clearing is automatic - no flags needed
- The server supports hot-reloading (changes appear immediately in browser)
- Port 3000 must be available (script will kill existing processes)
diff --git a/pages/developer-info/04.03.06.ScriptCheckTopicLinks.md
b/pages/developer-info/04.03.06.ScriptCheckTopicLinks.md
index 43e847f767..6e2f0f82c7 100644
--- a/pages/developer-info/04.03.06.ScriptCheckTopicLinks.md
+++ b/pages/developer-info/04.03.06.ScriptCheckTopicLinks.md
@@ -9,11 +9,11 @@ slug: ScriptCheckTopicLinks
The script performs three main operations:
-1. **Extracts Topic Information** - Scans `/docs/pages/topics` for all
markdown files and extracts:
+1. **Extracts Topic Information** - Scans `pages/topics` (relative to the
`juneau-docs` repository root) for all markdown files and extracts:
- Slug names from the frontmatter
- Page titles from the frontmatter
-2. **Finds Topic Links** - Scans the entire Juneau source tree for links in
the format:
+2. **Finds Topic Links** - Scans the sibling `../master/` (Java tree) source
tree for links in the format:
```
https://juneau.apache.org/docs/topics/SLUG">TITLE</a>
```
@@ -27,13 +27,13 @@ The script performs three main operations:
### Check all topic links
```bash
-cd /Users/james.bognar/git/juneau
+cd /path/to/juneau-docs
python3 scripts/check-topic-links.py
```
The script will automatically:
-- Scan `/docs/pages/topics` for topic definitions
-- Scan the entire Juneau source tree for topic links
+- Scan `pages/topics` for topic definitions
+- Scan the sibling `../master/` source tree for topic links
- Report any issues found
## File Types Scanned
@@ -59,6 +59,7 @@ The script checks the following file types:
## Notes
+- The script requires a sibling `../master/` checkout (the Java tree)
alongside `juneau-docs`
- The script is typically run as part of `build-docs.py`
- It validates both slug names and title text
- Reports are printed to stdout with file locations and line numbers
diff --git a/pages/topics/03.23.MarshallEncoders.md
b/pages/topics/03.23.MarshallEncoders.md
index b58112acd4..ad6b8d113c 100644
--- a/pages/topics/03.23.MarshallEncoders.md
+++ b/pages/topics/03.23.MarshallEncoders.md
@@ -37,11 +37,8 @@ EncoderSet encoders = EncoderSet
.add(GzipEncoder.class)
.build();
-// Should return "gzip"
-String matchedCoding = encoders.findMatch("compress;q=1.0, gzip;q=0.8,
identity;q=0.5, *;q=0");
-
-// Get the encoder
-Encoder encoder = encoders.getEncoder(matchedCoding);
+// Get the encoder for "gzip"
+Encoder encoder = encoders.getEncoder("compress;q=1.0, gzip;q=0.8,
identity;q=0.5, *;q=0");
```
:::
diff --git a/pages/topics/03.24.ObjectTools.md
b/pages/topics/03.24.ObjectTools.md
index fea4a1a8b2..f7bbf03557 100644
--- a/pages/topics/03.24.ObjectTools.md
+++ b/pages/topics/03.24.ObjectTools.md
@@ -218,8 +218,8 @@ methods on `Objects` using arguments in serialized form.
```java
String string1 = "foobar";
String string2 = ObjectIntrospector
- .create(string)
- .invoke(String.class, "substring(int,int)", "[3,6]"); // "bar"
+ .create(string1)
+ .invokeMethod(String.class, "substring(int,int)", "[3,6]"); // "bar"
```
:::
@@ -270,12 +270,12 @@ public class A implements IA {
The getters will be called in order until the first non-null value is returned:
```java
-merge = ObjectMerger.merger(IA.class, new A("1"), new A("2"));
+merge = ObjectMerger.merge(IA.class, new A("1"), new A("2"));
assertEquals("1", merge.getX());
-merge = ObjectMerger.merger(IA.class, new A(null), new A("2"));
+merge = ObjectMerger.merge(IA.class, new A(null), new A("2"));
assertEquals("2", merge.getX());
-merge = ObjectMerger.merger(IA.class, new A(null), new A(null));
+merge = ObjectMerger.merge(IA.class, new A(null), new A(null));
assertEquals(null, merge.getX());
```
\ No newline at end of file
diff --git a/pages/topics/03.31.01.OpenApiMethodology.md
b/pages/topics/03.31.01.OpenApiMethodology.md
index e71125fefc..c35155843a 100644
--- a/pages/topics/03.31.01.OpenApiMethodology.md
+++ b/pages/topics/03.31.01.OpenApiMethodology.md
@@ -101,12 +101,10 @@ MyPojo myPojo = ...;
HttpPartSchema schema = HttpPartSchema.tByte().build();
// Convert POJO to BASE64-encoded string.
-HttpPartSerializer serializer = OpenApiSerializer.DEFAULT;
-String httpPart = serializer.write(schema, myPojo);
+String httpPart = OpenApi.of(schema, myPojo);
// Convert BASE64-encoded string back into a POJO.
-HttpPartParser parser = OpenApiParser.DEFAULT;
-myPojo = parser.read(schema, httpPart, MyPojo.class);
+myPojo = OpenApi.to(schema, httpPart, MyPojo.class);
```
In addition to defining format, the schema also allows for validations of the
serialized form.
@@ -120,18 +118,16 @@ MyPojo myPojo = ...;
HttpPartSchema schema = HttpPartSchema.tByte().minLength(100).build();
// Convert POJO to BASE64-encoded string.
-HttpPartSerializer serializer = OpenApiSerializer.DEFAULT;
String httpPart;
try {
- httpPart = serializer.write(schema, myPojo);
+ httpPart = OpenApi.of(schema, myPojo);
} catch (SchemaValidationException e) {
// Oops, output too small.
}
// Convert BASE64-encoded string back into a POJO.
-HttpPartParser parser = OpenApiParser.DEFAULT;
try {
- myPojo = parser.read(schema, httpPart, MyPojo.class);
+ myPojo = OpenApi.to(schema, httpPart, MyPojo.class);
} catch (SchemaValidationException e) {
// Oops, input too small.
}
diff --git a/pages/topics/03.31.02.OpenApiSerializers.md
b/pages/topics/03.31.02.OpenApiSerializers.md
index 069a4a04f7..e3ce4a50fb 100644
--- a/pages/topics/03.31.02.OpenApiSerializers.md
+++ b/pages/topics/03.31.02.OpenApiSerializers.md
@@ -40,11 +40,11 @@ public void post2dLongArray(
type="integer",
format="int64",
minimum="0",
- maximum="100"
+ maximum="100",
minLength=1,
maxLength=10
)
- )
+ ),
minLength=1,
maxLength=10
)
@@ -59,18 +59,18 @@ public void post2dLongArray(
schema=@Schema(
t="array",
cf="pipes",
- i=@Items(
+ items=@Items(
t="array",
cf="csv",
- i=@SubItems(
+ items=@SubItems(
t="integer",
f="int64",
min="0",
- max="100"
+ max="100",
minl=1,
maxl=10
)
- )
+ ),
minl=1,
maxl=10
)
@@ -108,7 +108,7 @@ HttpPartSchema schema = HttpPartSchema.create()
Various convenience methods exist for shortening this code.
```java
-import static org.apache.juneau.http.HttpPartSchema.*;
+import static org.apache.juneau.marshall.httppart.HttpPartSchema.*;
HttpPartSchema schema = tArrayPipes(
tArrayCsv(
@@ -309,11 +309,11 @@ public class MyBean {
public byte[] f2 = FOOB;
public byte[] f3 = FOOB;
public byte[] f4 = FOOB;
- public Calendar f5 = parseIsoCalendar("2012-12-21T12:34:56Z");
+ public Calendar f5 = new GregorianCalendar(2012, Calendar.DECEMBER, 21,
12, 34, 56);
public String f6 = "foo";
public int f7 = 1;
public Long f8 = 2l;
- public float f9 = 1.0;
+ public float f9 = 1.0f;
public Double f10 = 1.0;
public Boolean f11 = true;
public Object fExtra = "1";
@@ -323,20 +323,20 @@ public class MyBean {
We define the following schema:
```java
-import static org.apache.juneau.httppart.HttpPartSchema.*;
+import static org.apache.juneau.marshall.httppart.HttpPartSchema.*;
HttpPartSchema schema = tObject()
- .prop("f1", tString())
- .prop("f2", tByte())
- .prop("f3", tBinary())
- .prop("f4", tBinarySpaced())
- .prop("f5", tDateTime())
- .prop("f6", tUon())
- .prop("f7", tInteger())
- .prop("f8", tInt64())
- .prop("f9", tNumber())
- .prop("f10", tDouble())
- .prop("f11", tBoolean())
+ .p("f1", tString())
+ .p("f2", tByte())
+ .p("f3", tBinary())
+ .p("f4", tBinarySpaced())
+ .p("f5", tDateTime())
+ .p("f6", tUon())
+ .p("f7", tInteger())
+ .p("f8", tInt64())
+ .p("f9", tNumber())
+ .p("f10", tDouble())
+ .p("f11", tBoolean())
.ap(tInteger())
.build();
```
@@ -372,17 +372,17 @@ The following is an example of a bean with various array
property types:
public class MyBean {
private static byte[] FOOB = "foo".getBytes();
- public String[] f1 = {"a,b",null},
- public byte[][] f2 = new byte[][]{FOOB,null},
- public byte[][] f3 = new byte[][]{FOOB,null},
- public byte[][] f4 = new byte[][]{FOOB,null},
- public Calendar[] f5 = new
Calendar[]{parseIsoCalendar("2012-12-21T12:34:56Z"),null},
- public String[] f6 = {"a","b",null},
- public int[] f7 = new int[]{1,2,null},
- public Integer[] f8 = new Integer[]{3,4,null},
- public float[] f9 = new float[]{1f,2f,null},
- public Float[] f10 = new Float[]{3f,4f,null},
- public Boolean[] f11 = new Boolean[]{true,false,null},
+ public String[] f1 = {"a,b",null};
+ public byte[][] f2 = new byte[][]{FOOB,null};
+ public byte[][] f3 = new byte[][]{FOOB,null};
+ public byte[][] f4 = new byte[][]{FOOB,null};
+ public Calendar[] f5 = new Calendar[]{new GregorianCalendar(2012,
Calendar.DECEMBER, 21, 12, 34, 56),null};
+ public String[] f6 = {"a","b",null};
+ public Integer[] f7 = new Integer[]{1,2,null};
+ public Integer[] f8 = new Integer[]{3,4,null};
+ public Float[] f9 = new Float[]{1f,2f,null};
+ public Float[] f10 = new Float[]{3f,4f,null};
+ public Boolean[] f11 = new Boolean[]{true,false,null};
public Object[] fExtra = new Object[]{1,"2",null};
}
```
@@ -390,20 +390,20 @@ public class MyBean {
For this bean, we define the following schema:
```java
-import static org.apache.juneau.httppart.HttpPartSchema.*;
+import static org.apache.juneau.marshall.httppart.HttpPartSchema.*;
HttpPartSchema schema = tObject()
- .prop("f1", tArray(tString()))
- .prop("f2", tArray(tByte()))
- .prop("f3", tArray(tBinary()))
- .prop("f4", tArray(tBinarySpaced()))
- .prop("f5", tArray(tDateTime()))
- .prop("f6", tArray(tUon()))
- .prop("f7", tArray(tInteger()))
- .prop("f8", tArray(tInt64()))
- .prop("f9", tArray(tNumber()))
- .prop("f10", tArray(tDouble()))
- .prop("f11", tArray(tBoolean()))
+ .p("f1", tArray(tString()))
+ .p("f2", tArray(tByte()))
+ .p("f3", tArray(tBinary()))
+ .p("f4", tArray(tBinarySpaced()))
+ .p("f5", tArray(tDateTime()))
+ .p("f6", tArray(tUon()))
+ .p("f7", tArray(tInteger()))
+ .p("f8", tArray(tInt64()))
+ .p("f9", tArray(tNumber()))
+ .p("f10", tArray(tDouble()))
+ .p("f11", tArray(tBoolean()))
.ap(tArray(tInteger()))
.build();
```
diff --git a/pages/topics/03.31.03.OpenApiParsers.md
b/pages/topics/03.31.03.OpenApiParsers.md
index f53d11e514..8e69f234f8 100644
--- a/pages/topics/03.31.03.OpenApiParsers.md
+++ b/pages/topics/03.31.03.OpenApiParsers.md
@@ -24,7 +24,7 @@ numbers (e.g.
`"1,2,3|4,5,6|7,8,9"`):
```java
-import static org.apache.juneau.httppart.HttpPartSchema.*;
+import static org.apache.juneau.marshall.httppart.HttpPartSchema.*;
HttpPartSchema schema = tArrayPipes(
tArrayCsv(
@@ -37,7 +37,7 @@ The following code shows how the schema above can be used to
parse our input int
```java
// Our input being parsed.
-String input = "1,2,3|4,5,6|7,8,9"
+String input = "1,2,3|4,5,6|7,8,9";
// Convert string to a POJO.
try {
@@ -200,7 +200,7 @@ In the example above, our POJO class can be constructed
from our pipe-delimited
```java
// Our input being parsed.
-String input = "1,2,3|4,5,6|7,8,9"
+String input = "1,2,3|4,5,6|7,8,9";
// Convert string to a POJO.
try {
@@ -234,20 +234,20 @@ public class MyBean {
We define the following schema again:
```java
-import static org.apache.juneau.httppart.HttpPartSchema.*;
+import static org.apache.juneau.marshall.httppart.HttpPartSchema.*;
HttpPartSchema schema = tObject()
- .prop("f1", tString())
- .prop("f2", tByte())
- .prop("f3", tBinary())
- .prop("f4", tBinarySpaced())
- .prop("f5", tDateTime())
- .prop("f6", tUon())
- .prop("f7", tInteger())
- .prop("f8", tInt64())
- .prop("f9", tNumber())
- .prop("f10", tDouble())
- .prop("f11", tBoolean())
+ .p("f1", tString())
+ .p("f2", tByte())
+ .p("f3", tBinary())
+ .p("f4", tBinarySpaced())
+ .p("f5", tDateTime())
+ .p("f6", tUon())
+ .p("f7", tInteger())
+ .p("f8", tInt64())
+ .p("f9", tNumber())
+ .p("f10", tDouble())
+ .p("f11", tBoolean())
.ap(tInteger())
.build();
```
diff --git a/pages/topics/10.00.JuneauRestServer.md
b/pages/topics/10.00.JuneauRestServer.md
index 2f9eaa84ec..3a25336def 100644
--- a/pages/topics/10.00.JuneauRestServer.md
+++ b/pages/topics/10.00.JuneauRestServer.md
@@ -81,6 +81,8 @@ Many of the examples in this document are pulled directly
from the [juneau-petst
A REST resource is simply a Java class annotated with <a
href="/site/apidocs/org/apache/juneau/rest/server/Rest.html"
target="_blank">Rest</a>.
The most common case is a class that extends <a
href="/site/apidocs/org/apache/juneau/rest/server/servlet/BasicRestServlet.html"
target="_blank">BasicRestServlet</a>, which itself is simply an extension of
<a
href="https://jakarta.ee/specifications/servlet/6.0/apidocs/jakarta/servlet/http/HttpServlet.html"
target="_blank">HttpServlet</a> which allows it to be deployed as a servlet.
+For the complete, up-to-date list of `@Rest` members, see [@Rest-Annotated
Class](/docs/topics/RestAnnotatedClasses).
+
```java
// Sample REST resource that prints out a simple "Hello world!" message.
@Rest(
@@ -98,7 +100,6 @@ The most common case is a class that extends <a
href="/site/apidocs/org/apache/j
"The POJO serialized is a simple String.",
}
)
-@MarshalledConfig(sortProperties="true")
public class HelloWorldResource extends BasicRestServlet {
@RestGet(path="/*", summary="Responds with \"Hello world!\"")
@@ -274,8 +275,7 @@ public interface BasicUniversalConfig extends
DefaultConfig, DefaultHtmlConfig {
allowedMethodHeaders="$S{j.allowedMethodHeaders,$E{J_ALLOWED_METHOD_HEADERS,}}",
allowedMethodParams="$S{j.allowedMethodParams,$E{J_ALLOWED_METHOD_PARAMS,HEAD,OPTIONS}}",
clientVersionHeader="$S{j.clientVersionHeader,$E{J_CLIENT_VERSION_HEADER,Client-Version}}",
- debug="$S{j.debug,$E{J_DEBUG,}}",
- debugOn="$S{j.debugOn,$E{J_DEBUG_ON,}}",
+ debug=@Debug("$S{j.debug,$E{J_DEBUG,}}"),
defaultAccept="$S{j.defaultAccept,$E{J_DEFAULT_ACCEPT,}}",
defaultCharset="$S{j.defaultCharset,$E{J_DEFAULT_CHARSET,UTF-8}}",
defaultContentType="$S{j.defaultContentType,$E{J_DEFAULT_CONTENT_TYPE,}}",
@@ -300,17 +300,9 @@ public interface BasicUniversalConfig extends
DefaultConfig, DefaultHtmlConfig {
title="$S{j.title,$E{J_TITLE,}}",
// Injectable/overridable beans.
- beanStore=BeanStore.Void.class, // Defaults to BeanStore.
callLogger=CallLogger.Void.class, // Defaults to BasicCallLogger.
- debugEnablement=DebugEnablement.Void.class, // Defaults to
BasicDefaultEnablement.
- fileFinder=FileFinder.Void.class, // Defaults to BasicFileFinder.
staticFiles=StaticFiles.Void.class, // Defaults to BasicStaticFiles.
- swaggerProvider=SwaggerProvider.Void.class, // Defaults to
BasicSwaggerProvider.
-
- // Overridable context classes.
- contextClass=RestContext.class,
- restOpContextClass=RestOpContext.class,
- restOperationsClass=RestOperations.class
+ swaggerProvider=SwaggerProvider.Void.class // Defaults to
BasicSwaggerProvider.
)
@MarshalledConfig(
// When parsing generated beans, ignore unknown properties
diff --git a/pages/topics/10.02.00.RestAnnotatedClasses.md
b/pages/topics/10.02.00.RestAnnotatedClasses.md
index 16fc1a9262..054a96e323 100644
--- a/pages/topics/10.02.00.RestAnnotatedClasses.md
+++ b/pages/topics/10.02.00.RestAnnotatedClasses.md
@@ -11,7 +11,7 @@ The functionality of the class itself is covered in detail in
the topics later.
<tree>
<node-0><java-annotation><a
href="/site/apidocs/org/apache/juneau/rest/server/Rest.html"
target="_blank">Rest</a></java-annotation></node-0>
-<node-1><javac-method-annotation><a
href="/site/apidocs/org/apache/juneau/rest/server/Rest.html#allowedHeaderParams()"
target="_blank">allowedHeaderParams</a></javac-method-annotation>
<javac-method-annotation><a
href="/site/apidocs/org/apache/juneau/rest/server/Rest.html#allowedMethodHeaders()"
target="_blank">allowedMethodHeaders</a></javac-method-annotation>
<javac-method-annotation><a
href="/site/apidocs/org/apache/juneau/rest/server/Rest.html#allowedMethodParams()"
target="_blank">a [...]
+<node-1><javac-method-annotation><a
href="/site/apidocs/org/apache/juneau/rest/server/Rest.html#allowedHeaderParams()"
target="_blank">allowedHeaderParams</a></javac-method-annotation>
<javac-method-annotation><a
href="/site/apidocs/org/apache/juneau/rest/server/Rest.html#allowedMethodHeaders()"
target="_blank">allowedMethodHeaders</a></javac-method-annotation>
<javac-method-annotation><a
href="/site/apidocs/org/apache/juneau/rest/server/Rest.html#allowedMethodParams()"
target="_blank">a [...]
</tree>
The <a href="/site/apidocs/org/apache/juneau/rest/server/Rest.html"
target="_blank">@Rest</a> annotation in inheritable from parents and
diff --git a/pages/topics/10.03.00.RestOpAnnotatedMethods.md
b/pages/topics/10.03.00.RestOpAnnotatedMethods.md
index a49bdc12ca..aefb51073b 100644
--- a/pages/topics/10.03.00.RestOpAnnotatedMethods.md
+++ b/pages/topics/10.03.00.RestOpAnnotatedMethods.md
@@ -10,7 +10,7 @@ The annotation allows the framework to identify the available
REST methods throu
<tree>
<node-0><java-annotation><a
href="/site/apidocs/org/apache/juneau/rest/server/RestOp.html"
target="_blank">RestOp</a></java-annotation></node-0>
-<node-1><javac-method-annotation><a
href="/site/apidocs/org/apache/juneau/rest/server/RestOp.html#clientVersion()"
target="_blank">clientVersion</a></javac-method-annotation>
<javac-method-annotation><a
href="/site/apidocs/org/apache/juneau/rest/server/RestOp.html#consumes()"
target="_blank">consumes</a></javac-method-annotation>
<javac-method-annotation><a
href="/site/apidocs/org/apache/juneau/rest/server/RestOp.html#converters()"
target="_blank">converters</a></javac-method-annotation> [...]
+<node-1><javac-method-annotation><a
href="/site/apidocs/org/apache/juneau/rest/server/RestOp.html#allowedParserOptions()"
target="_blank">allowedParserOptions</a></javac-method-annotation>
<javac-method-annotation><a
href="/site/apidocs/org/apache/juneau/rest/server/RestOp.html#allowedSerializerOptions()"
target="_blank">allowedSerializerOptions</a></javac-method-annotation>
<javac-method-annotation><a
href="/site/apidocs/org/apache/juneau/rest/server/RestOp.html#asyncCompletionExecutor(
[...]
</tree>
:::tip Example
diff --git a/pages/topics/10.10.RestServerChildrenVsMixins.md
b/pages/topics/10.10.RestServerChildrenVsMixins.md
index dec9c548d0..b12d89e0f1 100644
--- a/pages/topics/10.10.RestServerChildrenVsMixins.md
+++ b/pages/topics/10.10.RestServerChildrenVsMixins.md
@@ -4,17 +4,20 @@ slug: RestServerChildrenVsMixins
---
Juneau offers two ways to compose one resource's operations into another:
-[`@Rest(children=...)`](/docs/topics/ChildResources) and
-[`@Rest(mixins=...)`](/docs/topics/RestServerComposition) (plus its host-side
override
+[`@Rest(children=...)`](/docs/topics/ChildResources) (plus its host-side
seeding form
+[`@Rest(childrenDefs=@Child(...))`](/docs/topics/ChildResources#host-side-seeding-with-child-1000))
+and [`@Rest(mixins=...)`](/docs/topics/RestServerComposition) (plus its
host-side override
form
[`@Rest(mixinDefs=@Mixin(...))`](/docs/topics/RestServerMixinSubContexts#host-side-overrides-with-mixin-1000)).
-They look superficially similar — both pull a second class's `@RestOp` methods
into a parent — but
-they are **opposite designs**, and picking the wrong one causes subtle routing
and configuration
-surprises.
+They look superficially similar — both pull a second class's `@RestOp` methods
into a parent, and
+both let a host reach in and adjust settings for the composed class — but the
underlying resolution
+models are **opposite**, and picking the wrong one causes subtle routing and
configuration surprises.
The one-line rule:
> **Mixins are *inline* — they share the host's URL namespace and inherit its
> configuration. Children
-> are *isolated* — they mount at their own URL prefix and resolve
configuration independently.**
+> are *isolated* — they mount at their own URL prefix and resolve
configuration independently. A host
+> can explicitly *seed* a curated set of settings onto a child (10.0.0), but
that's additive opt-in,
+> not inheritance.**
This page is the canonical "which one do I reach for" reference.
@@ -26,17 +29,20 @@ This page is the canonical "which one do I reach for"
reference.
`@Mixin(...)` when the *host* wants to override a setting (e.g. guard) for
that mixin's endpoints.
- **Reach for a child** when the second class is a *standalone* sub-resource
with its own URL subtree
and its own configuration lifecycle — often a separately-deployable REST
endpoint that just happens
- to be discovered through a parent.
+ to be discovered through a parent. If the host needs to impose a handful of
settings on that child
+ (an admin guard, a shared call logger) without editing the child class, use
+ `@Child(...)` — see [Host-side seeding with
`@Child`](/docs/topics/ChildResources#host-side-seeding-with-child-1000)
+ for the full seed-member table and semantics.
## Same vs. different matrix
-| Axis | Mixin (`@Rest(mixins=)` / `@Rest(mixinDefs=@Mixin)`) | Child
(`@Rest(children=)`) |
+| Axis | Mixin (`@Rest(mixins=)` / `@Rest(mixinDefs=@Mixin)`) | Child
(`@Rest(children=)` / `@Rest(childrenDefs=@Child)`) |
|---|---|---|
| **Path composition** | Op merges into the host's operation table and
resolves at its *own* `@RestOp(path)` under the host namespace — no
auto-inserted segment. (A host `@Mixin(path=...)` can re-mount the mixin's ops
under a chosen prefix.) | Child contributes a path **segment** from the child's
`@Rest(path)`; the request is re-dispatched to the child with a trimmed path
remainder. |
| **`RestContext`** | Own sub-context, **parent-linked** to the host
(`isMixinContext`). | Own context, **isolated** (no parent walk). |
-| **Config inheritance** (serializers, parsers, guards,
`roleGuard`/`rolesDeclared`, converters, encoders, responseProcessors,
restOpArgs; callLogger, partSerializer/partParser, debug; messages) |
**Inherited** from the host: list-shaped props = host chain then mixin
appended; replace-shaped props = mixin value wins else host inherited;
`messages` = mixin bundle chained under the host's. | **Isolated**: the child
resolves each property from its own `@Rest` only; nothing inherits from the
[...]
-| **`noInherit`** | Meaningful — cuts the host→mixin walk per property (mixin
class's `@Rest(noInherit=...)` and/or the host `@Mixin(noInherit=...)`,
unioned). | Not applicable — there is no inherited chain to cut. |
-| **Host-side override** | `@Rest(mixinDefs=@Mixin(type=X, guards=..., ...))`
lets the host override settings for the mixin's endpoints. | No equivalent
today (a future `@Child` is parked, not shipped). |
+| **Config inheritance** (serializers, parsers, guards,
`roleGuard`/`rolesDeclared`, converters, encoders, responseProcessors,
restOpArgs; callLogger, partSerializer/partParser, debug; messages) |
**Inherited** from the host: list-shaped props = host chain then mixin
appended; replace-shaped props = mixin value wins else host inherited;
`messages` = mixin bundle chained under the host's. | **Isolated by default**:
the child resolves each property from its own `@Rest` only; nothing inheri [...]
+| **`noInherit`** | Meaningful — cuts the host→mixin walk per property (mixin
class's `@Rest(noInherit=...)` and/or the host `@Mixin(noInherit=...)`,
unioned). | No `noInherit()` member on `@Child` itself (there's no inherited
chain to cut) — but a child's own `@Rest(noInherit="<property>")` cuts the
corresponding host-*seeded* value too, for every seedable property. |
+| **Host-side override / seed** | `@Rest(mixinDefs=@Mixin(type=X, guards=...,
...))` — the host **overrides** settings on the mixin's already-inherited
chain; the host's value wins outright over the mixin class's own declaration. |
`@Rest(childrenDefs=@Child(type=X, guards=..., ...))` (10.0.0) — the host
**seeds** a curated set of settings onto the child's otherwise-isolated
context. This is not an override: additive-security members (`guards`,
`converters`, `roleGuard`, `rolesDeclared`) [...]
| **Operation discovery / collision** | Single merged op table; **host wins**
over mixin on path+method collision; mixin-vs-mixin resolved by `mixins=`
declaration order. | Separate `RestChildren` registry matched by path prefix;
child ops never merge into the host table. |
| **Request routing / `getPathInfo`** | Mixin op sees the host request
**unchanged** (same servletPath/pathInfo). | Child sees a **rewritten**
servletPath/pathInfo (the matched segment is consumed). |
| **Matching order** | Ops (host + mixin) matched as one table. | **Children
are matched before** the host's own ops. |
@@ -58,10 +64,17 @@ The rationale behind the mixin sub-context model:
> is the right model for mixins; isolation is the right model for children."
Because the resolution models are opposite, the per-property mixin precedence
(the host `@Mixin`
-override → mixin class's `@Rest` → inherited host chain, gated by `noInherit`)
has **no child
-analog** — a child neither inherits a chain nor honors `noInherit`. A future
`@Rest(childrenDefs=@Child(...))`
-would *seed* settings onto an isolated child rather than *override* an
inherited chain; it is parked,
-not shipped.
+override → mixin class's `@Rest` → inherited host chain, gated by `noInherit`)
has **no exact child
+analog** — a child never inherits a chain from the host, so there's nothing
for a host to "override."
+What a host *can* do, as of 10.0.0, is **seed** settings directly onto an
isolated child via
+`@Rest(childrenDefs=@Child(...))` — a deliberately different mechanism from a
mixin override, not a
+lesser version of it. A `@Mixin` override wins outright over an
already-inherited value; a `@Child`
+seed can only add to or fill a gap in the child's own config, and the child's
own explicit
+declaration always has the final say. See [Host-side seeding with
+`@Child`](/docs/topics/ChildResources#host-side-seeding-with-child-1000) in
*Child Resources* for the
+full seed-member table, the additive-security/child-wins-scalar split, and the
`noInherit` interaction
+— that section is the canonical reference for the mechanism; this page only
summarizes it for the
+mixin-vs-child comparison above.
## See also
diff --git a/pages/topics/13.09.03.Content.md b/pages/topics/13.09.03.Content.md
index 8e9f87e257..8f2334f048 100644
--- a/pages/topics/13.09.03.Content.md
+++ b/pages/topics/13.09.03.Content.md
@@ -50,12 +50,11 @@ OpenAPI schema based serialization can be used by using the
<a href="/site/apido
@RemotePost("/comma-delimited-pipe-delimited-ints")
String addCommaDelimitedPipeDelimitedInts(
@Content(
- serializer=OpenApiSerializer.class,
schema=@Schema(
type="array",
collectionFormat="pipes",
items=@Items(
- type="array"
+ type="array",
items=@SubItems(
type="int32",
// Auto-validates on client side!
@@ -75,7 +74,6 @@ String addCommaDelimitedPipeDelimitedInts(
@RemotePost("/comma-delimited-pipe-delimited-ints")
String addCommaDelimitedPipeDelimitedInts(
@Content(
- serializer=OpenApiSerializer.class,
schema=@Schema(
"type:'array',collectionFormat:'pipes',items:[type:'array',items:[type:'int32',minimum:0,maximum:64]]"
)
diff --git a/pages/topics/13.09.04.FormData.md
b/pages/topics/13.09.04.FormData.md
index 99b1d3892c..03fdfafdab 100644
--- a/pages/topics/13.09.04.FormData.md
+++ b/pages/topics/13.09.04.FormData.md
@@ -9,7 +9,6 @@ The <a
href="/site/apidocs/org/apache/juneau/http/FormData.html" target="_blank"
<tree>
<node-0><java-annotation><a
href="/site/apidocs/org/apache/juneau/http/FormData.html"
target="_blank">@FormData</a></java-annotation></node-0>
<node-1><java-field><a
href="/site/apidocs/org/apache/juneau/http/FormData.html#name()"
target="_blank">name</a> - Form data entry name.</java-field></node-1>
-<node-1><java-field><a
href="/site/apidocs/org/apache/juneau/http/FormData.html#serializer()"
target="_blank">serializer</a> - Override the part
serializer.</java-field></node-1>
</tree>
:::tip Example
@@ -51,7 +50,7 @@ public interface MyProxy {
Form data arguments can be any of the following types:
- **Single-part arguments** (i.e. those with `name != "*"`):
- - Any serializable POJO - Converted to a string using the <a
href="/site/apidocs/org/apache/juneau/marshall/httppart/HttpPartSerializer.html"
target="_blank">HttpPartSerializer</a> registered with the <a
href="/site/apidocs/org/apache/juneau/rest/client/classic/RestClient.html"
target="_blank">RestClient</a> (<a
href="/site/apidocs/org/apache/juneau/marshall/oapi/OpenApiSerializer.html"
target="_blank">OpenApiSerializer</a> by default) or associated via the <a
href="/site/apidocs/org/a [...]
+ - Any serializable POJO - Converted to a string using the <a
href="/site/apidocs/org/apache/juneau/marshall/httppart/HttpPartSerializer.html"
target="_blank">HttpPartSerializer</a> registered with the <a
href="/site/apidocs/org/apache/juneau/rest/client/classic/RestClient.html"
target="_blank">RestClient</a> (<a
href="/site/apidocs/org/apache/juneau/marshall/oapi/OpenApiSerializer.html"
target="_blank">OpenApiSerializer</a> by default).
- **Multi-part arguments** (i.e. those with `name == "*"` or empty):
- <a
href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/io/Reader.html"
target="_blank">Reader</a> - Raw contents of `Reader` will be serialized to
remote resource.
diff --git a/pages/topics/13.09.05.Query.md b/pages/topics/13.09.05.Query.md
index 65bc1b86c2..65f5576c81 100644
--- a/pages/topics/13.09.05.Query.md
+++ b/pages/topics/13.09.05.Query.md
@@ -9,7 +9,6 @@ The <a href="/site/apidocs/org/apache/juneau/http/Query.html"
target="_blank">@Q
<tree>
<node-0><java-annotation><a
href="/site/apidocs/org/apache/juneau/http/Query.html"
target="_blank">@Query</a></java-annotation></node-0>
<node-1><java-field><a
href="/site/apidocs/org/apache/juneau/http/Query.html#name()"
target="_blank">name</a> - Query parameter name.</java-field></node-1>
-<node-1><java-field><a
href="/site/apidocs/org/apache/juneau/http/Query.html#serializer()"
target="_blank">serializer</a> - Override the part
serializer.</java-field></node-1>
</tree>
:::tip Example
@@ -54,7 +53,7 @@ public interface MyProxy {
Query arguments can be any of the following types:
- **Single-part arguments** (i.e. those with `name != "*"`):
- - Any serializable POJO - Converted to a string using the <a
href="/site/apidocs/org/apache/juneau/marshall/httppart/HttpPartSerializer.html"
target="_blank">HttpPartSerializer</a> registered with the <a
href="/site/apidocs/org/apache/juneau/rest/client/classic/RestClient.html"
target="_blank">RestClient</a> (<a
href="/site/apidocs/org/apache/juneau/marshall/oapi/OpenApiSerializer.html"
target="_blank">OpenApiSerializer</a> by default) or associated via the <a
href="/site/apidocs/org/a [...]
+ - Any serializable POJO - Converted to a string using the <a
href="/site/apidocs/org/apache/juneau/marshall/httppart/HttpPartSerializer.html"
target="_blank">HttpPartSerializer</a> registered with the <a
href="/site/apidocs/org/apache/juneau/rest/client/classic/RestClient.html"
target="_blank">RestClient</a> (<a
href="/site/apidocs/org/apache/juneau/marshall/oapi/OpenApiSerializer.html"
target="_blank">OpenApiSerializer</a> by default).
- **Multi-part arguments** (i.e. those with `name == "*"` or empty):
- <a
href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/io/Reader.html"
target="_blank">Reader</a> - Raw contents of `Reader` will be serialized
directly as query string.
diff --git a/pages/topics/13.09.06.Header.md b/pages/topics/13.09.06.Header.md
index e2052fb8a9..57ef92c3f8 100644
--- a/pages/topics/13.09.06.Header.md
+++ b/pages/topics/13.09.06.Header.md
@@ -9,7 +9,6 @@ The <a href="/site/apidocs/org/apache/juneau/http/Header.html"
target="_blank">@
<tree>
<node-0><java-annotation><a
href="/site/apidocs/org/apache/juneau/http/Header.html"
target="_blank">@Header</a></java-annotation></node-0>
<node-1><java-field><a
href="/site/apidocs/org/apache/juneau/http/Header.html#name()"
target="_blank">name</a> - Header name.</java-field></node-1>
-<node-1><java-field><a
href="/site/apidocs/org/apache/juneau/http/Header.html#serializer()"
target="_blank">serializer</a> - Override the part
serializer.</java-field></node-1>
</tree>
:::tip Example
@@ -44,7 +43,7 @@ public interface MyProxy {
Header arguments can be any of the following types:
- **Single-part arguments** (i.e. those with `name != "*"`):
- - Any serializable POJO - Converted to a string using the <a
href="/site/apidocs/org/apache/juneau/marshall/httppart/HttpPartSerializer.html"
target="_blank">HttpPartSerializer</a> registered with the `RestClient` (<a
href="/site/apidocs/org/apache/juneau/marshall/oapi/OpenApiSerializer.html"
target="_blank">OpenApiSerializer</a> by default) or associated via the <a
href="/site/apidocs/org/apache/juneau/http/Header.html#serializer()"
target="_blank">@Header(serializer)</a> annotation.
+ - Any serializable POJO - Converted to a string using the <a
href="/site/apidocs/org/apache/juneau/marshall/httppart/HttpPartSerializer.html"
target="_blank">HttpPartSerializer</a> registered with the `RestClient` (<a
href="/site/apidocs/org/apache/juneau/marshall/oapi/OpenApiSerializer.html"
target="_blank">OpenApiSerializer</a> by default).
- **Multi-part arguments** (i.e. those with `name == "*"` or empty):
- <a
href="/site/apidocs/org/apache/juneau/http/classic/header/HeaderList.html"
target="_blank">HeaderList</a> - Serialized as individual headers.
diff --git a/pages/topics/13.09.07.Path.md b/pages/topics/13.09.07.Path.md
index 18f7e6ce26..79e3f2fe21 100644
--- a/pages/topics/13.09.07.Path.md
+++ b/pages/topics/13.09.07.Path.md
@@ -9,7 +9,6 @@ The <a href="/site/apidocs/org/apache/juneau/http/Path.html"
target="_blank">@Pa
<tree>
<node-0><java-annotation><a
href="/site/apidocs/org/apache/juneau/http/Path.html"
target="_blank">@Path</a></java-annotation></node-0>
<node-1><java-field><a
href="/site/apidocs/org/apache/juneau/http/Path.html#name()"
target="_blank">name</a> - Path variable name.</java-field></node-1>
-<node-1><java-field><a
href="/site/apidocs/org/apache/juneau/http/Path.html#serializer()"
target="_blank">serializer</a> - Override the part
serializer.</java-field></node-1>
</tree>
:::tip Example
@@ -43,7 +42,7 @@ public interface MyProxy {
Path arguments can be any of the following types:
- **Single-part arguments** (i.e. those with name != "*"):
- - Any serializable POJO - Converted to a string using the <a
href="/site/apidocs/org/apache/juneau/marshall/httppart/HttpPartSerializer.html"
target="_blank">HttpPartSerializer</a> registered with the `RestClient` (<a
href="/site/apidocs/org/apache/juneau/marshall/oapi/OpenApiSerializer.html"
target="_blank">OpenApiSerializer</a> by default) or associated via the <a
href="/site/apidocs/org/apache/juneau/http/Path.html#serializer()"
target="_blank">@Path(serializer)</a> annotation.
+ - Any serializable POJO - Converted to a string using the <a
href="/site/apidocs/org/apache/juneau/marshall/httppart/HttpPartSerializer.html"
target="_blank">HttpPartSerializer</a> registered with the `RestClient` (<a
href="/site/apidocs/org/apache/juneau/marshall/oapi/OpenApiSerializer.html"
target="_blank">OpenApiSerializer</a> by default).
- **Multi-part arguments** (i.e. those with name == "*" or empty):
- <a href="/site/apidocs/org/apache/juneau/http/part/PartList.html"
target="_blank">PartList</a> - Serialized as individual path parameters.
diff --git a/pages/topics/13.09.08.Request.md b/pages/topics/13.09.08.Request.md
index 3b12730820..c72c8adfa3 100644
--- a/pages/topics/13.09.08.Request.md
+++ b/pages/topics/13.09.08.Request.md
@@ -8,7 +8,7 @@ The <a href="/site/apidocs/org/apache/juneau/http/Request.html"
target="_blank">
<tree>
<node-0><java-annotation><a
href="/site/apidocs/org/apache/juneau/http/Request.html"
target="_blank">Request</a></java-annotation></node-0>
-<node-1><java-method-annotation><a
href="/site/apidocs/org/apache/juneau/http/Request.html#serializer()"
target="_blank">serializer</a> - Override the part
serializer.</java-method-annotation></node-1>
+<node-1><java-method-annotation><a
href="/site/apidocs/org/apache/juneau/http/Request.html#description()"
target="_blank">description</a></java-method-annotation></node-1>
</tree>
:::tip Example
diff --git a/pages/topics/13.09.09.Response.md
b/pages/topics/13.09.09.Response.md
index 87c7565eb8..17c9a55497 100644
--- a/pages/topics/13.09.09.Response.md
+++ b/pages/topics/13.09.09.Response.md
@@ -8,7 +8,6 @@ returned by <a
href="/site/apidocs/org/apache/juneau/http/remote/RemoteOp.html"
<tree>
<node-0><java-annotation><a
href="/site/apidocs/org/apache/juneau/http/Response.html"
target="_blank">Response</a></java-annotation></node-0>
-<node-1><java-method-annotation><a
href="/site/apidocs/org/apache/juneau/http/Response.html#parser()"
target="_blank">parser</a> - Override the part
parser.</java-method-annotation></node-1>
</tree>
The <a href="/site/apidocs/org/apache/juneau/http/Response.html"
target="_blank">@Response</a> annotation can be used to define interfaces for
retrieving response parts using a bean-like proxy.