From 5504b89c27ff7c1e97a70fbe67fd83a1ecdc933b Mon Sep 17 00:00:00 2001 From: Bauke Scholtz Date: Tue, 2 May 2023 07:53:04 -0400 Subject: [PATCH 001/247] JETUT-20: Document diagramming tool --- README.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/README.md b/README.md index 535f22ab..490ecf2c 100644 --- a/README.md +++ b/README.md @@ -52,6 +52,19 @@ output. mvn generate-resources ``` +### Creating diagrams + +Diagrams are located in `src/main/asciidoc/images`. +Use [draw.io](https://draw.io) to create/adjust diagrams. +This tool is primarily chosen for being free to use and the most flexible. +For portability and maintainability, make sure that the diagram is saved/exported into following 3 formats: +- `*.drawio` +- `*.vsdx` +- `*.svg` + +The `*.drawio` format ensures being able to reopen exactly the intended diagram in the original tool. +The `*.vsdx` format ensures being able to import the diagram in another tool as this is the most supported format by various diagramming tools, just in case that draw.io stops to exist in some unpredictable future. +The `*.svg` format is ultimately used to embed the diagram in the tutorial document. ### Deploy the Site to Github Pages From 8d2ad8f151d63b55374adfe61c0fba15b337e838 Mon Sep 17 00:00:00 2001 From: "Kito D. Mann" Date: Fri, 12 May 2023 11:22:42 -0400 Subject: [PATCH 002/247] JETUT-21 Removed build artifacts, since this will be built by the playbook repo --- .github/workflows/build.yml | 36 - pom.xml | 137 - src/main/jbake/assets/img/icons/computer.svg | 5124 ------------------ tutorial.xml | 42 - 4 files changed, 5339 deletions(-) delete mode 100644 .github/workflows/build.yml delete mode 100644 pom.xml delete mode 100644 src/main/jbake/assets/img/icons/computer.svg delete mode 100644 tutorial.xml diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml deleted file mode 100644 index 8bc67d18..00000000 --- a/.github/workflows/build.yml +++ /dev/null @@ -1,36 +0,0 @@ -name: build - -on: - push: - branches: - - master - - release/* - pull_request: - branches: - - master - -jobs: - - build: - runs-on: ubuntu-latest - steps: - - - uses: actions/checkout@v1 - - - name: Set up JDK 1.8 - uses: actions/setup-java@v1 - with: - java-version: 1.8 - - - name: Build Docs - run: mvn clean package --file pom.xml #-Ppublish-site - - - name: Deploy 🚀 - uses: JamesIves/github-pages-deploy-action@3.7.1 - with: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - BRANCH: gh-pages # The branch the action should deploy to. - FOLDER: target/generated-docs # The folder the action should deploy. - CLEAN: true # Automatically remove deleted files from the deploy br - - diff --git a/pom.xml b/pom.xml deleted file mode 100644 index 849b211f..00000000 --- a/pom.xml +++ /dev/null @@ -1,137 +0,0 @@ - - - - - org.eclipse.ee4j - project - 1.0.5 - - 4.0.0 - jakarta.tutorial - tutorial - pom - 8.1 - Jakarta EE Tutorial - - - UTF-8 - true - 2.1.0 - - - scm:git:git@github.com:eclipse-ee4j/jakartaee-tutorial.git - scm:git:git@github.com:eclipse-ee4j/jakartaee-tutorial.git - https://github.com/eclipse-ee4j/jakartaee-tutorial - HEAD - - - - scm:git:git@github.com:eclipse-ee4j/jakartaee-tutorial.git - - - - package - - - org.asciidoctor - asciidoctor-maven-plugin - ${asciidoctor.maven.plugin.version} - - - asciidoc-to-html - generate-resources - - process-asciidoc - - - html5 - - book - ${status} - - font - left - font - true - - - - true - images - - - - - - index.adoc - coderay - - - - org.apache.maven.plugins - maven-release-plugin - - forked-path - false - ${release.arguments} - - - - org.apache.maven.scm - maven-scm-provider-gitexe - 1.9.4 - - - - - - - - - publish-site - - ${project.build.directory}/generated-docs - true - true - - - - - org.apache.maven.plugins - maven-scm-publish-plugin - 1.1 - - - deploy-site - deploy - - publish-scm - - - gh-pages - false - Update site - - - - - - - - - diff --git a/src/main/jbake/assets/img/icons/computer.svg b/src/main/jbake/assets/img/icons/computer.svg deleted file mode 100644 index cb81e3be..00000000 --- a/src/main/jbake/assets/img/icons/computer.svg +++ /dev/null @@ -1,5124 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/tutorial.xml b/tutorial.xml deleted file mode 100644 index 4c3b13e0..00000000 --- a/tutorial.xml +++ /dev/null @@ -1,42 +0,0 @@ - - - - - tutorial - - zip - - jakartaee-tutorial - - - target/generated-docs - - - - target/staging - doc - - _config.yml - _layouts/** - assets/** - *.md - - - - From 3aa32db41b2ad20063c57c5657dccfd9a4e3daa5 Mon Sep 17 00:00:00 2001 From: "Kito D. Mann" Date: Fri, 12 May 2023 11:26:27 -0400 Subject: [PATCH 003/247] JETUT-21 Added script to help with Antora conversion. --- AntoraConverter.java | 65 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) create mode 100644 AntoraConverter.java diff --git a/AntoraConverter.java b/AntoraConverter.java new file mode 100644 index 00000000..432d8045 --- /dev/null +++ b/AntoraConverter.java @@ -0,0 +1,65 @@ +///opt/homebrew/bin/jbang jbang "$0" "$@" ; exit $? +//DEPS com.github.lalyos:jfiglet:0.0.8 + +import java.io.File; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.List; + +class AntoraConverter { + + public static String replaceBetween(String str, String start, String end, String prefix, char fromChar, char toChar) { + StringBuilder result = new StringBuilder(); + int index = 0; + int startIndex, endIndex; + + while ((startIndex = str.indexOf(start, index)) != -1 && (endIndex = str.indexOf(end, startIndex + start.length())) != -1) { + result.append(str, index, startIndex + start.length()); + String substring = str.substring(startIndex + start.length(), endIndex); + String updatedSubstring = substring.replace(fromChar, toChar); + // don't add the prefix if nothing has changed + if (!substring.equals(updatedSubstring)) { + result.append(prefix); + result.append(updatedSubstring); + } else { + result.append(substring); + } + index = endIndex; + } + result.append(str, index, str.length()); + return result.toString(); + } + + public static void main(String... args) throws Exception { + List files = new ArrayList<>(); + String startPath = args.length == 0 ? "." : args[0]; + Files.walk(Paths.get(startPath)).filter(Files::isRegularFile) //.forEach(path -> System.out.println(path.getFileName())); + .filter(path -> path.toString().endsWith(".adoc")) + .forEach(path -> files.add(path.toFile())); + + for (File file : files) { + System.out.println("Evaluating file " + file.getAbsolutePath()); + String content = new String(Files.readAllBytes(file.toPath())); + int changeCount = 0; + + if (content.contains(("<<"))) { + System.out.println("=> Updating anchor links"); + String modifiedContent = replaceBetween(content, "<<", ">>", "_",'-', '_'); + Files.write(file.toPath(), modifiedContent.getBytes()); + changeCount++; + } + if (content.contains(("[["))) { + System.out.println("=> Updating anchor names"); + String modifiedContent = replaceBetween(content, "[[", "]]", "_", '-', '_'); + Files.write(file.toPath(), modifiedContent.getBytes()); + changeCount++; + } + if (changeCount == 0) { + System.out.println("=> (no changes necessary)"); + } else { + System.out.println("=> " + changeCount + " changes made"); + } + } + } +} From 1760f6b1a7ae0aeb48d7477c0a8bd0269ef06084 Mon Sep 17 00:00:00 2001 From: "Kito D. Mann" Date: Fri, 12 May 2023 11:59:43 -0400 Subject: [PATCH 004/247] JETUT-21 Added minimal Antora artifacts for empty site with a single ppage. --- src/main/antora/antora.yml | 10 ++++++++++ src/main/antora/modules/ROOT/pages/index.adoc | 5 +++++ src/main/antora/modules/ROOT/pages/nav.adoc | 1 + 3 files changed, 16 insertions(+) create mode 100644 src/main/antora/antora.yml create mode 100644 src/main/antora/modules/ROOT/pages/index.adoc create mode 100644 src/main/antora/modules/ROOT/pages/nav.adoc diff --git a/src/main/antora/antora.yml b/src/main/antora/antora.yml new file mode 100644 index 00000000..a6d643f6 --- /dev/null +++ b/src/main/antora/antora.yml @@ -0,0 +1,10 @@ +name: jakarta-ee-docs +title: Jakarta EE Documentation +version: 8 +asciidoc: + attributes: + source-language: asciidoc@ + table-caption: false +nav: + - modules/ROOT/nav.adoc + diff --git a/src/main/antora/modules/ROOT/pages/index.adoc b/src/main/antora/modules/ROOT/pages/index.adoc new file mode 100644 index 00000000..7aebdccd --- /dev/null +++ b/src/main/antora/modules/ROOT/pages/index.adoc @@ -0,0 +1,5 @@ += Overview + +Hey there! This is a version the Jakarta EE Tutorial built using https://antora.org/[Antora] (and still using Asciidoc). + +This is a work in progress. diff --git a/src/main/antora/modules/ROOT/pages/nav.adoc b/src/main/antora/modules/ROOT/pages/nav.adoc new file mode 100644 index 00000000..31f850ee --- /dev/null +++ b/src/main/antora/modules/ROOT/pages/nav.adoc @@ -0,0 +1 @@ +* xref:index.adoc[] From 403f8a5409edf386f1c6bae2d5ec857565544198 Mon Sep 17 00:00:00 2001 From: "Kito D. Mann" Date: Tue, 16 May 2023 21:14:25 -0400 Subject: [PATCH 005/247] JETUT-56 Added another sample page. --- src/main/antora/modules/ROOT/{pages => }/nav.adoc | 1 + src/main/antora/modules/ROOT/pages/page2.adoc | 3 +++ 2 files changed, 4 insertions(+) rename src/main/antora/modules/ROOT/{pages => }/nav.adoc (50%) create mode 100644 src/main/antora/modules/ROOT/pages/page2.adoc diff --git a/src/main/antora/modules/ROOT/pages/nav.adoc b/src/main/antora/modules/ROOT/nav.adoc similarity index 50% rename from src/main/antora/modules/ROOT/pages/nav.adoc rename to src/main/antora/modules/ROOT/nav.adoc index 31f850ee..73c45032 100644 --- a/src/main/antora/modules/ROOT/pages/nav.adoc +++ b/src/main/antora/modules/ROOT/nav.adoc @@ -1 +1,2 @@ * xref:index.adoc[] +* xref:page2.adoc[] diff --git a/src/main/antora/modules/ROOT/pages/page2.adoc b/src/main/antora/modules/ROOT/pages/page2.adoc new file mode 100644 index 00000000..b782b1e4 --- /dev/null +++ b/src/main/antora/modules/ROOT/pages/page2.adoc @@ -0,0 +1,3 @@ += Page 2 + +Lorem ipsum blah blah blah blah blah foo bar baz baz foo. From 0900387e4b73b5ac26618146ed7595b03616f642 Mon Sep 17 00:00:00 2001 From: "Kito D. Mann" Date: Tue, 16 May 2023 21:14:46 -0400 Subject: [PATCH 006/247] JETUT-56 Added initial version of Antora conversion instructions. --- CONVERTING_TO_ANTORA.adoc | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 CONVERTING_TO_ANTORA.adoc diff --git a/CONVERTING_TO_ANTORA.adoc b/CONVERTING_TO_ANTORA.adoc new file mode 100644 index 00000000..f1c64e04 --- /dev/null +++ b/CONVERTING_TO_ANTORA.adoc @@ -0,0 +1,13 @@ += Antora Migration Notes + +As part of the documentation upgrade process, we are migrating the existing content to Antora. This will allow us to go back to previous versions of the docs (currently 9.1 and 8.0) from within the docs site. + +Here’s the current process for migrating an individual module (i.e. security, bean validation, etc): + +1. Check out the release/8 branch and create a new branch from it for your work. +2. Select the module to migrate. We consider each Part of the current https://eclipse-ee4j.github.io/jakartaee-tutorial/[Jakata EE Tutorial] to be a module (for example, Introduction, Web Tier, Bean Validation, etc). +3. Create a new folder in the `src/main/antora/modules` folder with the name of the module you are migrating. For example, for the Security module, you would create a `security` folder. + * Inside of this folder, create a `pages` folder. +4. Move all the folders for the module you are migrating into the new `pages` folder. For example, for the Security module, you would move all of the `src/main/asciidoc/security-*` folders into the `src/main/antora/modules/security/pages`. (Copy the entire folders, not just the `.adoc` files). + +> NOTE: It's essential that you _move_ rather than copy the folders so that we keep the history intact. From 3d78f27f2c57cd360769a7c8307de110de4f43fb Mon Sep 17 00:00:00 2001 From: "Kito D. Mann" Date: Tue, 16 May 2023 21:15:13 -0400 Subject: [PATCH 007/247] JETUT-56 Moved security chapters. --- .../security/pages}/security-advanced/security-advanced.adoc | 0 .../security/pages}/security-advanced/security-advanced001.adoc | 0 .../security/pages}/security-advanced/security-advanced002.adoc | 0 .../security/pages}/security-advanced/security-advanced003.adoc | 0 .../security/pages}/security-advanced/security-advanced004.adoc | 0 .../security/pages}/security-advanced/security-advanced005.adoc | 0 .../security/pages}/security-advanced/security-advanced006.adoc | 0 .../security/pages}/security-advanced/security-advanced007.adoc | 0 .../security/pages}/security-advanced/security-advanced008.adoc | 0 .../modules/security/pages}/security-api/security-api.adoc | 0 .../modules/security/pages}/security-api/security-api001.adoc | 0 .../modules/security/pages}/security-api/security-api002.adoc | 0 .../modules/security/pages}/security-api/security-api003.adoc | 0 .../modules/security/pages}/security-api/security-api004.adoc | 0 .../modules/security/pages}/security-api/security-api005.adoc | 0 .../modules/security/pages}/security-intro/security-intro.adoc | 0 .../modules/security/pages}/security-intro/security-intro001.adoc | 0 .../modules/security/pages}/security-intro/security-intro002.adoc | 0 .../modules/security/pages}/security-intro/security-intro003.adoc | 0 .../security/pages}/security-intro/security-intro003a.adoc | 0 .../modules/security/pages}/security-intro/security-intro004.adoc | 0 .../modules/security/pages}/security-intro/security-intro005.adoc | 0 .../security/pages}/security-intro/security-intro005a.adoc | 0 .../modules/security/pages}/security-intro/security-intro006.adoc | 0 .../modules/security/pages}/security-intro/security-intro007.adoc | 0 .../security/pages}/security-jakartaee/security-jakartaee.adoc | 0 .../security/pages}/security-jakartaee/security-jakartaee001.adoc | 0 .../security/pages}/security-jakartaee/security-jakartaee002.adoc | 0 .../security/pages}/security-jakartaee/security-jakartaee003.adoc | 0 .../security/pages}/security-webtier/security-webtier.adoc | 0 .../security/pages}/security-webtier/security-webtier001.adoc | 0 .../security/pages}/security-webtier/security-webtier002.adoc | 0 .../security/pages}/security-webtier/security-webtier003.adoc | 0 .../security/pages}/security-webtier/security-webtier004.adoc | 0 34 files changed, 0 insertions(+), 0 deletions(-) rename src/main/{asciidoc => antora/modules/security/pages}/security-advanced/security-advanced.adoc (100%) rename src/main/{asciidoc => antora/modules/security/pages}/security-advanced/security-advanced001.adoc (100%) rename src/main/{asciidoc => antora/modules/security/pages}/security-advanced/security-advanced002.adoc (100%) rename src/main/{asciidoc => antora/modules/security/pages}/security-advanced/security-advanced003.adoc (100%) rename src/main/{asciidoc => antora/modules/security/pages}/security-advanced/security-advanced004.adoc (100%) rename src/main/{asciidoc => antora/modules/security/pages}/security-advanced/security-advanced005.adoc (100%) rename src/main/{asciidoc => antora/modules/security/pages}/security-advanced/security-advanced006.adoc (100%) rename src/main/{asciidoc => antora/modules/security/pages}/security-advanced/security-advanced007.adoc (100%) rename src/main/{asciidoc => antora/modules/security/pages}/security-advanced/security-advanced008.adoc (100%) rename src/main/{asciidoc => antora/modules/security/pages}/security-api/security-api.adoc (100%) rename src/main/{asciidoc => antora/modules/security/pages}/security-api/security-api001.adoc (100%) rename src/main/{asciidoc => antora/modules/security/pages}/security-api/security-api002.adoc (100%) rename src/main/{asciidoc => antora/modules/security/pages}/security-api/security-api003.adoc (100%) rename src/main/{asciidoc => antora/modules/security/pages}/security-api/security-api004.adoc (100%) rename src/main/{asciidoc => antora/modules/security/pages}/security-api/security-api005.adoc (100%) rename src/main/{asciidoc => antora/modules/security/pages}/security-intro/security-intro.adoc (100%) rename src/main/{asciidoc => antora/modules/security/pages}/security-intro/security-intro001.adoc (100%) rename src/main/{asciidoc => antora/modules/security/pages}/security-intro/security-intro002.adoc (100%) rename src/main/{asciidoc => antora/modules/security/pages}/security-intro/security-intro003.adoc (100%) rename src/main/{asciidoc => antora/modules/security/pages}/security-intro/security-intro003a.adoc (100%) rename src/main/{asciidoc => antora/modules/security/pages}/security-intro/security-intro004.adoc (100%) rename src/main/{asciidoc => antora/modules/security/pages}/security-intro/security-intro005.adoc (100%) rename src/main/{asciidoc => antora/modules/security/pages}/security-intro/security-intro005a.adoc (100%) rename src/main/{asciidoc => antora/modules/security/pages}/security-intro/security-intro006.adoc (100%) rename src/main/{asciidoc => antora/modules/security/pages}/security-intro/security-intro007.adoc (100%) rename src/main/{asciidoc => antora/modules/security/pages}/security-jakartaee/security-jakartaee.adoc (100%) rename src/main/{asciidoc => antora/modules/security/pages}/security-jakartaee/security-jakartaee001.adoc (100%) rename src/main/{asciidoc => antora/modules/security/pages}/security-jakartaee/security-jakartaee002.adoc (100%) rename src/main/{asciidoc => antora/modules/security/pages}/security-jakartaee/security-jakartaee003.adoc (100%) rename src/main/{asciidoc => antora/modules/security/pages}/security-webtier/security-webtier.adoc (100%) rename src/main/{asciidoc => antora/modules/security/pages}/security-webtier/security-webtier001.adoc (100%) rename src/main/{asciidoc => antora/modules/security/pages}/security-webtier/security-webtier002.adoc (100%) rename src/main/{asciidoc => antora/modules/security/pages}/security-webtier/security-webtier003.adoc (100%) rename src/main/{asciidoc => antora/modules/security/pages}/security-webtier/security-webtier004.adoc (100%) diff --git a/src/main/asciidoc/security-advanced/security-advanced.adoc b/src/main/antora/modules/security/pages/security-advanced/security-advanced.adoc similarity index 100% rename from src/main/asciidoc/security-advanced/security-advanced.adoc rename to src/main/antora/modules/security/pages/security-advanced/security-advanced.adoc diff --git a/src/main/asciidoc/security-advanced/security-advanced001.adoc b/src/main/antora/modules/security/pages/security-advanced/security-advanced001.adoc similarity index 100% rename from src/main/asciidoc/security-advanced/security-advanced001.adoc rename to src/main/antora/modules/security/pages/security-advanced/security-advanced001.adoc diff --git a/src/main/asciidoc/security-advanced/security-advanced002.adoc b/src/main/antora/modules/security/pages/security-advanced/security-advanced002.adoc similarity index 100% rename from src/main/asciidoc/security-advanced/security-advanced002.adoc rename to src/main/antora/modules/security/pages/security-advanced/security-advanced002.adoc diff --git a/src/main/asciidoc/security-advanced/security-advanced003.adoc b/src/main/antora/modules/security/pages/security-advanced/security-advanced003.adoc similarity index 100% rename from src/main/asciidoc/security-advanced/security-advanced003.adoc rename to src/main/antora/modules/security/pages/security-advanced/security-advanced003.adoc diff --git a/src/main/asciidoc/security-advanced/security-advanced004.adoc b/src/main/antora/modules/security/pages/security-advanced/security-advanced004.adoc similarity index 100% rename from src/main/asciidoc/security-advanced/security-advanced004.adoc rename to src/main/antora/modules/security/pages/security-advanced/security-advanced004.adoc diff --git a/src/main/asciidoc/security-advanced/security-advanced005.adoc b/src/main/antora/modules/security/pages/security-advanced/security-advanced005.adoc similarity index 100% rename from src/main/asciidoc/security-advanced/security-advanced005.adoc rename to src/main/antora/modules/security/pages/security-advanced/security-advanced005.adoc diff --git a/src/main/asciidoc/security-advanced/security-advanced006.adoc b/src/main/antora/modules/security/pages/security-advanced/security-advanced006.adoc similarity index 100% rename from src/main/asciidoc/security-advanced/security-advanced006.adoc rename to src/main/antora/modules/security/pages/security-advanced/security-advanced006.adoc diff --git a/src/main/asciidoc/security-advanced/security-advanced007.adoc b/src/main/antora/modules/security/pages/security-advanced/security-advanced007.adoc similarity index 100% rename from src/main/asciidoc/security-advanced/security-advanced007.adoc rename to src/main/antora/modules/security/pages/security-advanced/security-advanced007.adoc diff --git a/src/main/asciidoc/security-advanced/security-advanced008.adoc b/src/main/antora/modules/security/pages/security-advanced/security-advanced008.adoc similarity index 100% rename from src/main/asciidoc/security-advanced/security-advanced008.adoc rename to src/main/antora/modules/security/pages/security-advanced/security-advanced008.adoc diff --git a/src/main/asciidoc/security-api/security-api.adoc b/src/main/antora/modules/security/pages/security-api/security-api.adoc similarity index 100% rename from src/main/asciidoc/security-api/security-api.adoc rename to src/main/antora/modules/security/pages/security-api/security-api.adoc diff --git a/src/main/asciidoc/security-api/security-api001.adoc b/src/main/antora/modules/security/pages/security-api/security-api001.adoc similarity index 100% rename from src/main/asciidoc/security-api/security-api001.adoc rename to src/main/antora/modules/security/pages/security-api/security-api001.adoc diff --git a/src/main/asciidoc/security-api/security-api002.adoc b/src/main/antora/modules/security/pages/security-api/security-api002.adoc similarity index 100% rename from src/main/asciidoc/security-api/security-api002.adoc rename to src/main/antora/modules/security/pages/security-api/security-api002.adoc diff --git a/src/main/asciidoc/security-api/security-api003.adoc b/src/main/antora/modules/security/pages/security-api/security-api003.adoc similarity index 100% rename from src/main/asciidoc/security-api/security-api003.adoc rename to src/main/antora/modules/security/pages/security-api/security-api003.adoc diff --git a/src/main/asciidoc/security-api/security-api004.adoc b/src/main/antora/modules/security/pages/security-api/security-api004.adoc similarity index 100% rename from src/main/asciidoc/security-api/security-api004.adoc rename to src/main/antora/modules/security/pages/security-api/security-api004.adoc diff --git a/src/main/asciidoc/security-api/security-api005.adoc b/src/main/antora/modules/security/pages/security-api/security-api005.adoc similarity index 100% rename from src/main/asciidoc/security-api/security-api005.adoc rename to src/main/antora/modules/security/pages/security-api/security-api005.adoc diff --git a/src/main/asciidoc/security-intro/security-intro.adoc b/src/main/antora/modules/security/pages/security-intro/security-intro.adoc similarity index 100% rename from src/main/asciidoc/security-intro/security-intro.adoc rename to src/main/antora/modules/security/pages/security-intro/security-intro.adoc diff --git a/src/main/asciidoc/security-intro/security-intro001.adoc b/src/main/antora/modules/security/pages/security-intro/security-intro001.adoc similarity index 100% rename from src/main/asciidoc/security-intro/security-intro001.adoc rename to src/main/antora/modules/security/pages/security-intro/security-intro001.adoc diff --git a/src/main/asciidoc/security-intro/security-intro002.adoc b/src/main/antora/modules/security/pages/security-intro/security-intro002.adoc similarity index 100% rename from src/main/asciidoc/security-intro/security-intro002.adoc rename to src/main/antora/modules/security/pages/security-intro/security-intro002.adoc diff --git a/src/main/asciidoc/security-intro/security-intro003.adoc b/src/main/antora/modules/security/pages/security-intro/security-intro003.adoc similarity index 100% rename from src/main/asciidoc/security-intro/security-intro003.adoc rename to src/main/antora/modules/security/pages/security-intro/security-intro003.adoc diff --git a/src/main/asciidoc/security-intro/security-intro003a.adoc b/src/main/antora/modules/security/pages/security-intro/security-intro003a.adoc similarity index 100% rename from src/main/asciidoc/security-intro/security-intro003a.adoc rename to src/main/antora/modules/security/pages/security-intro/security-intro003a.adoc diff --git a/src/main/asciidoc/security-intro/security-intro004.adoc b/src/main/antora/modules/security/pages/security-intro/security-intro004.adoc similarity index 100% rename from src/main/asciidoc/security-intro/security-intro004.adoc rename to src/main/antora/modules/security/pages/security-intro/security-intro004.adoc diff --git a/src/main/asciidoc/security-intro/security-intro005.adoc b/src/main/antora/modules/security/pages/security-intro/security-intro005.adoc similarity index 100% rename from src/main/asciidoc/security-intro/security-intro005.adoc rename to src/main/antora/modules/security/pages/security-intro/security-intro005.adoc diff --git a/src/main/asciidoc/security-intro/security-intro005a.adoc b/src/main/antora/modules/security/pages/security-intro/security-intro005a.adoc similarity index 100% rename from src/main/asciidoc/security-intro/security-intro005a.adoc rename to src/main/antora/modules/security/pages/security-intro/security-intro005a.adoc diff --git a/src/main/asciidoc/security-intro/security-intro006.adoc b/src/main/antora/modules/security/pages/security-intro/security-intro006.adoc similarity index 100% rename from src/main/asciidoc/security-intro/security-intro006.adoc rename to src/main/antora/modules/security/pages/security-intro/security-intro006.adoc diff --git a/src/main/asciidoc/security-intro/security-intro007.adoc b/src/main/antora/modules/security/pages/security-intro/security-intro007.adoc similarity index 100% rename from src/main/asciidoc/security-intro/security-intro007.adoc rename to src/main/antora/modules/security/pages/security-intro/security-intro007.adoc diff --git a/src/main/asciidoc/security-jakartaee/security-jakartaee.adoc b/src/main/antora/modules/security/pages/security-jakartaee/security-jakartaee.adoc similarity index 100% rename from src/main/asciidoc/security-jakartaee/security-jakartaee.adoc rename to src/main/antora/modules/security/pages/security-jakartaee/security-jakartaee.adoc diff --git a/src/main/asciidoc/security-jakartaee/security-jakartaee001.adoc b/src/main/antora/modules/security/pages/security-jakartaee/security-jakartaee001.adoc similarity index 100% rename from src/main/asciidoc/security-jakartaee/security-jakartaee001.adoc rename to src/main/antora/modules/security/pages/security-jakartaee/security-jakartaee001.adoc diff --git a/src/main/asciidoc/security-jakartaee/security-jakartaee002.adoc b/src/main/antora/modules/security/pages/security-jakartaee/security-jakartaee002.adoc similarity index 100% rename from src/main/asciidoc/security-jakartaee/security-jakartaee002.adoc rename to src/main/antora/modules/security/pages/security-jakartaee/security-jakartaee002.adoc diff --git a/src/main/asciidoc/security-jakartaee/security-jakartaee003.adoc b/src/main/antora/modules/security/pages/security-jakartaee/security-jakartaee003.adoc similarity index 100% rename from src/main/asciidoc/security-jakartaee/security-jakartaee003.adoc rename to src/main/antora/modules/security/pages/security-jakartaee/security-jakartaee003.adoc diff --git a/src/main/asciidoc/security-webtier/security-webtier.adoc b/src/main/antora/modules/security/pages/security-webtier/security-webtier.adoc similarity index 100% rename from src/main/asciidoc/security-webtier/security-webtier.adoc rename to src/main/antora/modules/security/pages/security-webtier/security-webtier.adoc diff --git a/src/main/asciidoc/security-webtier/security-webtier001.adoc b/src/main/antora/modules/security/pages/security-webtier/security-webtier001.adoc similarity index 100% rename from src/main/asciidoc/security-webtier/security-webtier001.adoc rename to src/main/antora/modules/security/pages/security-webtier/security-webtier001.adoc diff --git a/src/main/asciidoc/security-webtier/security-webtier002.adoc b/src/main/antora/modules/security/pages/security-webtier/security-webtier002.adoc similarity index 100% rename from src/main/asciidoc/security-webtier/security-webtier002.adoc rename to src/main/antora/modules/security/pages/security-webtier/security-webtier002.adoc diff --git a/src/main/asciidoc/security-webtier/security-webtier003.adoc b/src/main/antora/modules/security/pages/security-webtier/security-webtier003.adoc similarity index 100% rename from src/main/asciidoc/security-webtier/security-webtier003.adoc rename to src/main/antora/modules/security/pages/security-webtier/security-webtier003.adoc diff --git a/src/main/asciidoc/security-webtier/security-webtier004.adoc b/src/main/antora/modules/security/pages/security-webtier/security-webtier004.adoc similarity index 100% rename from src/main/asciidoc/security-webtier/security-webtier004.adoc rename to src/main/antora/modules/security/pages/security-webtier/security-webtier004.adoc From 26fc5da0c11918ff181422c72f77e159e196e1a4 Mon Sep 17 00:00:00 2001 From: "Kito D. Mann" Date: Tue, 16 May 2023 21:39:58 -0400 Subject: [PATCH 008/247] JETUT-56 Ran migration script on security files; updated script and docs. --- AntoraConverter.java | 14 ++++++++-- CONVERTING_TO_ANTORA.adoc | 8 ++++++ .../security-advanced/security-advanced.adoc | 2 +- .../security-advanced001.adoc | 12 ++++---- .../security-advanced002.adoc | 10 +++---- .../security-advanced003.adoc | 4 +-- .../security-advanced004.adoc | 2 +- .../security-advanced005.adoc | 6 ++-- .../security-advanced006.adoc | 12 ++++---- .../security-advanced007.adoc | 6 ++-- .../security-advanced008.adoc | 2 +- .../pages/security-api/security-api.adoc | 2 +- .../pages/security-api/security-api001.adoc | 10 +++---- .../pages/security-api/security-api002.adoc | 2 +- .../pages/security-api/security-api003.adoc | 10 +++---- .../pages/security-api/security-api004.adoc | 20 ++++++------- .../pages/security-api/security-api005.adoc | 18 ++++++------ .../pages/security-intro/security-intro.adoc | 2 +- .../security-intro/security-intro001.adoc | 18 ++++++------ .../security-intro/security-intro002.adoc | 12 ++++---- .../security-intro/security-intro003.adoc | 8 +++--- .../security-intro/security-intro003a.adoc | 6 ++-- .../security-intro/security-intro004.adoc | 2 +- .../security-intro/security-intro005.adoc | 22 +++++++-------- .../security-intro/security-intro005a.adoc | 2 +- .../security-intro/security-intro006.adoc | 4 +-- .../security-intro/security-intro007.adoc | 2 +- .../security-jakartaee.adoc | 2 +- .../security-jakartaee001.adoc | 2 +- .../security-jakartaee002.adoc | 18 ++++++------ .../security-jakartaee003.adoc | 22 +++++++-------- .../security-webtier/security-webtier.adoc | 2 +- .../security-webtier/security-webtier001.adoc | 2 +- .../security-webtier/security-webtier002.adoc | 26 ++++++++--------- .../security-webtier/security-webtier003.adoc | 14 +++++----- .../security-webtier/security-webtier004.adoc | 28 +++++++++---------- 36 files changed, 176 insertions(+), 158 deletions(-) mode change 100644 => 100755 AntoraConverter.java diff --git a/AntoraConverter.java b/AntoraConverter.java old mode 100644 new mode 100755 index 432d8045..44a8cb6f --- a/AntoraConverter.java +++ b/AntoraConverter.java @@ -9,6 +9,8 @@ class AntoraConverter { + final static String START_PATH_PREFIX = "src/main/antora/modules/"; + public static String replaceBetween(String str, String start, String end, String prefix, char fromChar, char toChar) { StringBuilder result = new StringBuilder(); int index = 0; @@ -32,14 +34,22 @@ public static String replaceBetween(String str, String start, String end, String } public static void main(String... args) throws Exception { + System.out.println("\uD83E\uDD16 Antora Converter: Convert raw Asciidoc files to Antora-compatible format"); + System.out.println("Walks through all folders and subfolders from the specified startPath and converts all .adoc files"); List files = new ArrayList<>(); - String startPath = args.length == 0 ? "." : args[0]; + if (args.length == 0) { + System.out.println("Usage: AntoraConverter.java [startPath]"); + System.out.println(" Where [startPath] is relative to " + START_PATH_PREFIX); + System.exit(1); + } + String startPath = START_PATH_PREFIX + args[0]; + System.out.println("Start path: " + startPath); Files.walk(Paths.get(startPath)).filter(Files::isRegularFile) //.forEach(path -> System.out.println(path.getFileName())); .filter(path -> path.toString().endsWith(".adoc")) .forEach(path -> files.add(path.toFile())); for (File file : files) { - System.out.println("Evaluating file " + file.getAbsolutePath()); + System.out.println("\uD83D\uDD0E Evaluating file " + file.getAbsolutePath()); String content = new String(Files.readAllBytes(file.toPath())); int changeCount = 0; diff --git a/CONVERTING_TO_ANTORA.adoc b/CONVERTING_TO_ANTORA.adoc index f1c64e04..47a763f7 100644 --- a/CONVERTING_TO_ANTORA.adoc +++ b/CONVERTING_TO_ANTORA.adoc @@ -2,6 +2,12 @@ As part of the documentation upgrade process, we are migrating the existing content to Antora. This will allow us to go back to previous versions of the docs (currently 9.1 and 8.0) from within the docs site. +== Setup + +The conversion script is written in Java and requires https://jbang.io[JBang] to run. Install that first. + +== Migration Process + Here’s the current process for migrating an individual module (i.e. security, bean validation, etc): 1. Check out the release/8 branch and create a new branch from it for your work. @@ -9,5 +15,7 @@ Here’s the current process for migrating an individual module (i.e. security, 3. Create a new folder in the `src/main/antora/modules` folder with the name of the module you are migrating. For example, for the Security module, you would create a `security` folder. * Inside of this folder, create a `pages` folder. 4. Move all the folders for the module you are migrating into the new `pages` folder. For example, for the Security module, you would move all of the `src/main/asciidoc/security-*` folders into the `src/main/antora/modules/security/pages`. (Copy the entire folders, not just the `.adoc` files). +5. Run the migration script from the root project folder. For example, for the Security module, you would run `jbang AntoraConverter.java security`. (The first parameter is the folder relative to `src/main/antora/modules`). +6. > NOTE: It's essential that you _move_ rather than copy the folders so that we keep the history intact. diff --git a/src/main/antora/modules/security/pages/security-advanced/security-advanced.adoc b/src/main/antora/modules/security/pages/security-advanced/security-advanced.adoc index 57d859ff..9b6e0c56 100644 --- a/src/main/antora/modules/security/pages/security-advanced/security-advanced.adoc +++ b/src/main/antora/modules/security/pages/security-advanced/security-advanced.adoc @@ -1,6 +1,6 @@ = Jakarta EE Security: Advanced Topics -[[GJJWX]][[jakarta-ee-security-advanced-topics]] +[[GJJWX]][[_jakarta_ee_security_advanced_topics]] This chapter provides advanced information on securing Jakarta EE applications. diff --git a/src/main/antora/modules/security/pages/security-advanced/security-advanced001.adoc b/src/main/antora/modules/security/pages/security-advanced/security-advanced001.adoc index 475b05d8..f5eab4d6 100644 --- a/src/main/antora/modules/security/pages/security-advanced/security-advanced001.adoc +++ b/src/main/antora/modules/security/pages/security-advanced/security-advanced001.adoc @@ -1,4 +1,4 @@ -[[BNBYB]][[working-with-digital-certificates]] +[[BNBYB]][[_working_with_digital_certificates]] == Working with Digital Certificates @@ -66,7 +66,7 @@ For a better understanding of `keytool` and public-key cryptography, see link:#BABBGBBF[Further Information about Advanced Security Topics] for a link to the `keytool` documentation. -[[BNBYC]][[creating-a-server-certificate]] +[[BNBYC]][[_creating_a_server_certificate]] === Creating a Server Certificate @@ -99,7 +99,7 @@ contains more than one certificate. The next section provides specific information on using the `keytool` utility to perform these steps. -[[GJRGY]][[to-use-keytool-to-create-a-server-certificate]] +[[GJRGY]][[_to_use_keytool_to_create_a_server_certificate]] ==== To Use keytool to Create a Server Certificate @@ -194,7 +194,7 @@ Certificate was added to keystore [Storing cacerts.jks] ---- -[[GLIFW]][[adding-users-to-the-certificate-realm]] +[[GLIFW]][[_adding_users_to_the_certificate_realm]] === Adding Users to the Certificate Realm @@ -204,7 +204,7 @@ cryptographically verified client certificates. For step-by-step instructions for creating this type of certificate, see link:#BNBYB[Working with Digital Certificates]. -[[BNBYF]][[using-a-different-server-certificate-with-glassfish-server]] +[[BNBYF]][[_using_a_different_server_certificate_with_glassfish_server]] === Using a Different Server Certificate with GlassFish Server @@ -221,7 +221,7 @@ name of your server. For testing purposes, this can be `localhost`. change your keystore's password to the default password (`changeit`) or change the default password to your keystore's password. -[[sthref230]][[to-specify-a-different-server-certificate]] +[[sthref230]][[_to_specify_a_different_server_certificate]] ==== To Specify a Different Server Certificate diff --git a/src/main/antora/modules/security/pages/security-advanced/security-advanced002.adoc b/src/main/antora/modules/security/pages/security-advanced/security-advanced002.adoc index a88f56d6..0b29ecd3 100644 --- a/src/main/antora/modules/security/pages/security-advanced/security-advanced002.adoc +++ b/src/main/antora/modules/security/pages/security-advanced/security-advanced002.adoc @@ -1,11 +1,11 @@ -[[GLIEN]][[authentication-mechanisms]] +[[GLIEN]][[_authentication_mechanisms]] == Authentication Mechanisms This section discusses the client authentication and mutual authentication mechanisms. -[[GLIEQ]][[client-authentication]] +[[GLIEQ]][[_client_authentication]] === Client Authentication @@ -41,7 +41,7 @@ authentication mechanisms that can be provided with an application and deployed using CDI. See link:#overview-of-the-http-authentication-mechanism-interface[Overview of the HTTP Authentication Mechanism Interface]. -[[GLIEL]][[mutual-authentication]] +[[GLIEL]][[_mutual_authentication]] === Mutual Authentication @@ -93,7 +93,7 @@ image:jakartaeett_dt_049.png[ "Diagram of five steps in mutual authentication with user name and password"] -[[BNBYH]][[enabling-mutual-authentication-over-ssl]] +[[BNBYH]][[_enabling_mutual_authentication_over_ssl]] ==== Enabling Mutual Authentication over SSL @@ -126,7 +126,7 @@ all of the time, which can severely degrade performance. When client authentication is enabled in both of these ways, client authentication will be performed twice. -[[BNBYI]][[creating-a-client-certificate-for-mutual-authentication]] +[[BNBYI]][[_creating_a_client_certificate_for_mutual_authentication]] ==== Creating a Client Certificate for Mutual Authentication diff --git a/src/main/antora/modules/security/pages/security-advanced/security-advanced003.adoc b/src/main/antora/modules/security/pages/security-advanced/security-advanced003.adoc index 893790ae..b44dbe48 100644 --- a/src/main/antora/modules/security/pages/security-advanced/security-advanced003.adoc +++ b/src/main/antora/modules/security/pages/security-advanced/security-advanced003.adoc @@ -1,4 +1,4 @@ -[[BABEJJDE]][[using-the-jdbc-realm-for-user-authentication]] +[[BABEJJDE]][[_using_the_jdbc_realm_for_user_authentication]] == Using the JDBC Realm for User Authentication @@ -33,7 +33,7 @@ Two of the tutorial case studies, link:#GKAEE[Chapter link:#GLNPW[Chapter 62, "Duke's Forest Case Study Example,"] use a JDBC realm for user authentication. -[[sthref233]][[to-configure-a-jdbc-authentication-realm]] +[[sthref233]][[_to_configure_a_jdbc_authentication_realm]] === To Configure a JDBC Authentication Realm diff --git a/src/main/antora/modules/security/pages/security-advanced/security-advanced004.adoc b/src/main/antora/modules/security/pages/security-advanced/security-advanced004.adoc index 97b6de7c..d632801f 100644 --- a/src/main/antora/modules/security/pages/security-advanced/security-advanced004.adoc +++ b/src/main/antora/modules/security/pages/security-advanced/security-advanced004.adoc @@ -1,4 +1,4 @@ -[[BABGEJJJ]][[securing-http-resources]] +[[BABGEJJJ]][[_securing_http_resources]] == Securing HTTP Resources diff --git a/src/main/antora/modules/security/pages/security-advanced/security-advanced005.adoc b/src/main/antora/modules/security/pages/security-advanced/security-advanced005.adoc index e25d8d95..3f0e0874 100644 --- a/src/main/antora/modules/security/pages/security-advanced/security-advanced005.adoc +++ b/src/main/antora/modules/security/pages/security-advanced/security-advanced005.adoc @@ -1,4 +1,4 @@ -[[GLIGC]][[securing-application-clients]] +[[GLIGC]][[_securing_application_clients]] == Securing Application Clients @@ -35,7 +35,7 @@ descriptor. The application's callback handler must fully support `Callback` objects specified in the `javax.security.auth.callback` package. -[[GLIDW]][[using-login-modules]] +[[GLIDW]][[_using_login_modules]] === Using Login Modules @@ -74,7 +74,7 @@ refer to the documentation listed in link:#BABBGBBF[Further Information about Advanced Security Topics]. -[[GLIHQ]][[using-programmatic-login]] +[[GLIHQ]][[_using_programmatic_login]] === Using Programmatic Login diff --git a/src/main/antora/modules/security/pages/security-advanced/security-advanced006.adoc b/src/main/antora/modules/security/pages/security-advanced/security-advanced006.adoc index 68c87987..bb738084 100644 --- a/src/main/antora/modules/security/pages/security-advanced/security-advanced006.adoc +++ b/src/main/antora/modules/security/pages/security-advanced/security-advanced006.adoc @@ -1,11 +1,11 @@ -[[GLIFD]][[securing-enterprise-information-systems-applications]] +[[GLIFD]][[_securing_enterprise_information_systems_applications]] == Securing Enterprise Information Systems Applications In Enterprise Information Systems (EIS) applications, components request a connection to an EIS resource. -[[BABBJHIC]][[overview-of-securing-enterprise-information-systems-applications]] +[[BABBJHIC]][[_overview_of_securing_enterprise_information_systems_applications]] === Overview of Securing Enterprise Information Systems Applications @@ -23,7 +23,7 @@ sign-on by including code that performs the sign-on process to an EIS. You can also configure security for resource adapters. See link:#GLIGS[Configuring Resource Adapter Security]. -[[GLIHL]][[container-managed-sign-on]] +[[GLIHL]][[_container_managed_sign_on]] === Container-Managed Sign-On @@ -46,7 +46,7 @@ javax.resource.cci.Connection cx = cxf.getConnection(); ... ---- -[[GLIDP]][[component-managed-sign-on]] +[[GLIDP]][[_component_managed_sign_on]] === Component-Managed Sign-On @@ -77,7 +77,7 @@ javax.resource.cci.Connection cx = ... ---- -[[GLIGS]][[configuring-resource-adapter-security]] +[[GLIGS]][[_configuring_resource_adapter_security]] === Configuring Resource Adapter Security @@ -165,7 +165,7 @@ principal. The security map is usually used if one or more EIS back-end principals are used to execute operations (on the EIS) initiated by various principals or user groups in the application. -[[GLIGW]][[mapping-an-application-principal-to-eis-principals]] +[[GLIGW]][[_mapping_an_application_principal_to_eis_principals]] === Mapping an Application Principal to EIS Principals diff --git a/src/main/antora/modules/security/pages/security-advanced/security-advanced007.adoc b/src/main/antora/modules/security/pages/security-advanced/security-advanced007.adoc index eb99ff8f..fd56beab 100644 --- a/src/main/antora/modules/security/pages/security-advanced/security-advanced007.adoc +++ b/src/main/antora/modules/security/pages/security-advanced/security-advanced007.adoc @@ -1,4 +1,4 @@ -[[GKHRL]][[configuring-security-using-deployment-descriptors]] +[[GKHRL]][[_configuring_security_using_deployment_descriptors]] == Configuring Security Using Deployment Descriptors @@ -9,7 +9,7 @@ deployment descriptor to do so. This section describes how to use the deployment descriptor to specify basic authentication and to override default principal-to-role mapping. -[[BNCCM]][[specifying-security-for-basic-authentication-in-the-deployment-descriptor]] +[[BNCCM]][[_specifying_security_for_basic_authentication_in_the_deployment_descriptor]] === Specifying Security for Basic Authentication in the Deployment Descriptor @@ -57,7 +57,7 @@ been verified to be in the role `TutorialUser`. The user name and password data will be sent over a protected transport in order to keep it from being read in transit. -[[GKAFQ]][[specifying-non-default-principal-to-role-mapping-in-the-deployment-descriptor]] +[[GKAFQ]][[_specifying_non_default_principal_to_role_mapping_in_the_deployment_descriptor]] === Specifying Non-Default Principal-to-Role Mapping in the Deployment Descriptor diff --git a/src/main/antora/modules/security/pages/security-advanced/security-advanced008.adoc b/src/main/antora/modules/security/pages/security-advanced/security-advanced008.adoc index f297b6e8..266320b6 100644 --- a/src/main/antora/modules/security/pages/security-advanced/security-advanced008.adoc +++ b/src/main/antora/modules/security/pages/security-advanced/security-advanced008.adoc @@ -1,4 +1,4 @@ -[[BABBGBBF]][[further-information-about-advanced-security-topics]] +[[BABBGBBF]][[_further_information_about_advanced_security_topics]] == Further Information about Advanced Security Topics diff --git a/src/main/antora/modules/security/pages/security-api/security-api.adoc b/src/main/antora/modules/security/pages/security-api/security-api.adoc index ecd79fcf..cd917717 100644 --- a/src/main/antora/modules/security/pages/security-api/security-api.adoc +++ b/src/main/antora/modules/security/pages/security-api/security-api.adoc @@ -1,6 +1,6 @@ = Using Jakarta Security -[[using-the-jakarta-ee-security-api]] +[[_using_the_jakarta_ee_security_api]] This chapter describes the authentication and credential validation functionality provided by Jakarta Security. The API also diff --git a/src/main/antora/modules/security/pages/security-api/security-api001.adoc b/src/main/antora/modules/security/pages/security-api/security-api001.adoc index b767eb0b..15df8c37 100644 --- a/src/main/antora/modules/security/pages/security-api/security-api001.adoc +++ b/src/main/antora/modules/security/pages/security-api/security-api001.adoc @@ -1,4 +1,4 @@ -[[about-the-jakarta-ee-security-api]] +[[_about_the_jakarta_ee_security_api]] == About Jakarta Security Jakarta EE includes support for Jakarta Security, which defines portable, plug-in interfaces @@ -31,7 +31,7 @@ lists the main classes and interfaces in this package. -[[main-classes-and-interfaces-in-enterprise]] +[[_main_classes_and_interfaces_in_enterprise]] *Table 51-1 Main Classes and Interfaces in javax.security.enterprise* @@ -52,7 +52,7 @@ mechanism. authentication process. |======================================================================= -[[main-classes-and-interfaces-in-authentication]] +[[_main_classes_and_interfaces_in_authentication]] *Table 51-2 Main Classes and Interfaces in javax.security.enterprise.authentication.mechanism.http* @@ -84,7 +84,7 @@ authentication mechanisms or to modify the behavior of an authentication mechani -[[main-classes-and-interfaces-in-credential]] +[[_main_classes_and_interfaces_in_credential]] *Table 51-3 Main Classes and Interfaces in javax.security.enterprise.credential* [width="99%",cols="25%,75%"] @@ -113,7 +113,7 @@ for the explicit usage with the JSR 375 remember me function. used by standard caller name/password authentication. |======================================================================= -[[main-classes-and-interfaces-in-identitystore]] +[[_main_classes_and_interfaces_in_identitystore]] *Table 51-4 Main Classes and Interfaces in javax.security.enterprise.identitystore* [width="99%",cols="25%,75%"] diff --git a/src/main/antora/modules/security/pages/security-api/security-api002.adoc b/src/main/antora/modules/security/pages/security-api/security-api002.adoc index 69e1edb0..17493e36 100644 --- a/src/main/antora/modules/security/pages/security-api/security-api002.adoc +++ b/src/main/antora/modules/security/pages/security-api/security-api002.adoc @@ -1,4 +1,4 @@ -[[overview-of-the-http-authentication-mechanism-interface]] +[[_overview_of_the_http_authentication_mechanism_interface]] == Overview of the HTTP Authentication Mechanism Interface The `HttpAuthenticationMechanism` interface defines an SPI for writing diff --git a/src/main/antora/modules/security/pages/security-api/security-api003.adoc b/src/main/antora/modules/security/pages/security-api/security-api003.adoc index 6f796074..316c2948 100644 --- a/src/main/antora/modules/security/pages/security-api/security-api003.adoc +++ b/src/main/antora/modules/security/pages/security-api/security-api003.adoc @@ -1,11 +1,11 @@ -[[overview-of-the-identity-store-interfaces]] +[[_overview_of_the_identity_store_interfaces]] == Overview of the Identity Store Interfaces The Identity Store Interfaces are described in the following sections: * link:#the-identitystore-interface[The IdentityStore Interface] * link:#the-remembermeidentitystore-interface[The RememberMeIdentityStore Interface] -[[the-identitystore-interface]] +[[_the_identitystore_interface]] === The IdentityStore Interface The `IdentityStore` interface defines an SPI for interacting with identity stores, which are directories or databases containing user account information. @@ -73,7 +73,7 @@ An application may also supply its own `IdentityStoreHandler`, which can use any desired algorithm to select and invoke on IdentityStores, and return an aggregated (or non-aggregated) result. -[[identitystoreinterface-methods]] +[[_identitystoreinterface_methods]] ==== IdentityStore Interface Methods The IdentityStore interface itself has four methods: @@ -101,7 +101,7 @@ IdentityStores do check for this permission, if a SecurityManager is configured, and the built-in IdentityStoreHandler invokes the `getCallerGroups()` method in the context of a `PrivilegedAction` block. -[[the-passwordhash-interface]] +[[_the_passwordhash_interface]] ==== The PasswordHash Interface Unlike some types of identity stores, for example LDAP directories, @@ -166,7 +166,7 @@ the password value based on the timing of failed attempts. * A new random salt should be used each time a new password hash value is generated. -[[the-remembermeidentitystore-interface]] +[[_the_remembermeidentitystore_interface]] === The RememberMeIdentityStore Interface The `RememberMeIdentityStore` interface represents a special type of identity store. It is not directly related to the `IdentityStore` interface; that is, it does not diff --git a/src/main/antora/modules/security/pages/security-api/security-api004.adoc b/src/main/antora/modules/security/pages/security-api/security-api004.adoc index ca059600..ebea0223 100644 --- a/src/main/antora/modules/security/pages/security-api/security-api004.adoc +++ b/src/main/antora/modules/security/pages/security-api/security-api004.adoc @@ -1,4 +1,4 @@ -[[running-the-built-in-database-identity-store-example]] +[[_running_the_built_in_database_identity_store_example]] == Running the Built-In Database Identity Store Example The example described in this section demonstrates how to use the built-in database identity store for credential validation. @@ -8,7 +8,7 @@ Topics include: * link:#overview-of-the-built-in-database-identity-store-example[Overview of the Built-In Database Identity Store Example] * link:#running-the-built-in-db-id-store-example[Running the built-in-db-identity-store Example] -[[overview-of-the-built-in-database-identity-store-example]] +[[_overview_of_the_built_in_database_identity_store_example]] === Overview of the Built-In Database Identity Store Example Jakarta Security mandates that a Jakarta EE container MUST support a built-in `IdentityStore` backed by a database. To support this mandatory requirement, `DatabaseIdentityStore` @@ -57,7 +57,7 @@ Content-Type: text/html ---- -[[define-the-users-and-groups-in-the-identity-store]] +[[_define_the_users_and_groups_in_the_identity_store]] ==== Define the Users and Groups in the Identity Store The following table shows the users, passwords, and groups used in this example. @@ -124,7 +124,7 @@ public class DatabaseSetup { ---- -[[map-the-databaseidentitystore-to-the-default-data-source]] +[[_map_the_databaseidentitystore_to_the_default_data_source]] ==== Map the DatabaseIdentityStore to the Default Data source Use the `@DatabaseIdentityStoreDefinition` annotation to map the built-in `DatabaseIdentityStore` to the `DefaultDataSource` in @@ -156,7 +156,7 @@ public class ApplicationConfig { } ---- -[[specify-the-authentication-mechanism]] +[[_specify_the_authentication_mechanism]] ==== Specify the Authentication Mechanism In this application, credentials are validated using the BASIC authentication mechanism. @@ -176,7 +176,7 @@ the credential from the request. ) ---- -[[declare-roles-in-the-servlet-container]] +[[_declare_roles_in_the_servlet_container]] ==== Declare Roles in the Servlet Container When a request is made to the application, the roles the user is in are returned as part of the response. Note that the container needs to be made aware of the @@ -214,7 +214,7 @@ In GlassFish 5.1, group to role mapping is enabled by default. Therefore, you do not need to bundle web.xml with the application to provide mapping between roles and groups. -[[running-the-built-in-db-identity-store-example]] +[[_running_the_built_in_db_identity_store_example]] === Running the built-in-db-identity-store Example You can use either NetBeans IDE or Maven to build, package, deploy, and run the `built-in-db-identity-store` application @@ -225,7 +225,7 @@ as described in the following topics: * link:#to-run-the-built-in-db-identity-store-example[To Run the built-in-db-identity-store Example] -[[to-build-package-and-deploy-the-built-in-db-identity-store-example-using-netbeans-ide]] +[[_to_build_package_and_deploy_the_built_in_db_identity_store_example_using_netbeans_ide]] ==== To Build, Package, and Deploy the built-in-db-identity-store Example Using NetBeans IDE 1. If you have not already done so, start the default database. This is necessary because @@ -252,7 +252,7 @@ This command builds and deploys the example application to your GlassFish Server instance. -[[to-build-package-and-deploy-the-built-in-db-identity-store-example-using-using-maven]] +[[_to_build_package_and_deploy_the_built_in_db_identity_store_example_using_using_maven]] ==== To Build, Package, and Deploy the built-in-db-identity-store Example Using Maven 1. If you have not already done so, start the default database. This is necessary because @@ -280,7 +280,7 @@ This command builds and packages the application into a WAR file, `built-in-db-identity-store.war`, that is located in the `target` directory, then deploys the WAR file. -[[to-run-the-built-in-db-identity-store-example]] +[[_to_run_the_built_in_db_identity_store_example]] ==== To Run the built-in-db-identity-store Example In this example, use the credentials of user Joe to make a request and diff --git a/src/main/antora/modules/security/pages/security-api/security-api005.adoc b/src/main/antora/modules/security/pages/security-api/security-api005.adoc index 3a755a47..ea7a0bdc 100644 --- a/src/main/antora/modules/security/pages/security-api/security-api005.adoc +++ b/src/main/antora/modules/security/pages/security-api/security-api005.adoc @@ -1,4 +1,4 @@ -[[running-the-custom-identity-store-example]] +[[_running_the_custom_identity_store_example]] == Running the Custom Identity Store Example The example described in this section demonstrates how to bundle and use a custom identity store in your application for credential validation. @@ -8,7 +8,7 @@ Topics include: * link:#overview-of-the-custom-identity-store-example[Overview of the Custom Identity Store Example] * link:#running-the-custom-id-store-example[Running the custom-identity-store Example] -[[overview-of-the-custom-identity-store-example]] +[[_overview_of_the_custom_identity_store_example]] === Overview of the Custom Identity Store Example As an alternative to using a built-in identity store, an application can provide its own IdentityStore. When bundled with the application, @@ -54,7 +54,7 @@ Content-Language: Content-Type: text/html ---- -[[define-the-users-and-groups-in-the-identity-store-2]] +[[_define_the_users_and_groups_in_the_identity_store_2]] ==== Define the Users and Groups in the Identity Store @@ -77,7 +77,7 @@ if (usernamePasswordCredential.compareTo("Joe", "secret1")) { } ---- -[[specify-the-authentication-mechanism-2]] +[[_specify_the_authentication_mechanism_2]] ==== Specify the Authentication Mechanism @@ -102,7 +102,7 @@ public class ApplicationConfig { ---- -[[declare-roles-in-the-servlet-container-2]] +[[_declare_roles_in_the_servlet_container_2]] ==== Declare Roles in the Servlet Container @@ -141,7 +141,7 @@ In GlassFish 5.0, group to role mapping is enabled by default. Therefore, you do not need to bundle `web.xml` with the application to provide mapping between roles and groups. -[[running-the-custom-id-store-example]] +[[_running_the_custom_id_store_example]] === Running the custom-identity-store Example You can use either NetBeans IDE or Maven to build, package, deploy, and run the `custom-identity-store` application @@ -152,7 +152,7 @@ as described in the following topics: * link:#to-run-the-custom-identity-store-example[To Run the custom-identity-store Example] -[[to-build-package-and-deploy-the-custom-identity-store-example-using-netbeans-ide]] +[[_to_build_package_and_deploy_the_custom_identity_store_example_using_netbeans_ide]] ==== To Build, Package, and Deploy the custom-identity-store Example Using NetBeans IDE 1. If you have not already done so, start the GlassFish server. See @@ -172,7 +172,7 @@ select Build. This command builds and deploys the example application to your GlassFish Server instance. -[[to-build-package-and-deploy-the-custom-identity-store-example-using-using-maven]] +[[_to_build_package_and_deploy_the_custom_identity_store_example_using_using_maven]] ==== To Build, Package, and Deploy the custom-identity-store Example Using Maven @@ -195,7 +195,7 @@ This command builds and packages the application into a WAR file, `custom-identity-store.war`, that is located in the `target` directory, then deploys the WAR file. -[[to-run-the-custom-identity-store-example]] +[[_to_run_the_custom_identity_store_example]] ==== To Run the custom-identity-store Example In this example, use the credentials of user `Joe` to make a request and to validate the response according to the credentials defined in `TestIdentityStore`. diff --git a/src/main/antora/modules/security/pages/security-intro/security-intro.adoc b/src/main/antora/modules/security/pages/security-intro/security-intro.adoc index 73cdc6f3..c7e3f7a2 100644 --- a/src/main/antora/modules/security/pages/security-intro/security-intro.adoc +++ b/src/main/antora/modules/security/pages/security-intro/security-intro.adoc @@ -1,6 +1,6 @@ = Introduction to Security in the Jakarta EE Platform -[[BNBWJ]][[introduction-to-security-in-the-jakarta-ee-platform]] +[[BNBWJ]][[_introduction_to_security_in_the_jakarta_ee_platform]] This chapter introduces basic security concepts and security mechanisms. More information on these concepts and mechanisms can be found in the diff --git a/src/main/antora/modules/security/pages/security-intro/security-intro001.adoc b/src/main/antora/modules/security/pages/security-intro/security-intro001.adoc index 98c888f6..02572a3c 100644 --- a/src/main/antora/modules/security/pages/security-intro/security-intro001.adoc +++ b/src/main/antora/modules/security/pages/security-intro/security-intro001.adoc @@ -1,4 +1,4 @@ -[[BNBWK]][[overview-of-jakarta-ee-security]] +[[BNBWK]][[_overview_of_jakarta_ee_security]] == Overview of Jakarta Security @@ -61,7 +61,7 @@ components, such as enterprise beans and application clients. describes the authentication and credential validation funtionality provided by Jakarta Security, and provides examples. -[[BNBWL]][[a-simple-application-security-walkthrough]] +[[BNBWL]][[_a_simple_application_security_walkthrough]] === A Simple Application Security Walkthrough @@ -74,7 +74,7 @@ Specification, the web client relies on the web server to act as its authentication proxy by collecting user authentication data from the client and using it to establish an authenticated session. -[[BNBWM]][[step-1-initial-request]] +[[BNBWM]][[_step_1_initial_request]] ==== Step 1: Initial Request @@ -95,7 +95,7 @@ and invokes the appropriate authentication mechanism for this resource. For more information on these mechanisms, see link:#BNBWY[Security Mechanisms]. -[[BNBWO]][[step-2-initial-authentication]] +[[BNBWO]][[_step_2_initial_authentication]] ==== Step 2: Initial Authentication @@ -114,7 +114,7 @@ image:jakartaeett_dt_040.png[ "Diagram of initial authentication: server sends form to client, which sends authentication data to server for validation"] -[[BNBWQ]][[step-3-url-authorization]] +[[BNBWQ]][[_step_3_url_authorization]] ==== Step 3: URL Authorization @@ -138,7 +138,7 @@ the web server is able to map the user to a role. A "not authorized" outcome is reached if the web server is unable to map the user to any of the permitted roles. -[[BNBWS]][[step-4-fulfilling-the-original-request]] +[[BNBWS]][[_step_4_fulfilling_the_original_request]] ==== Step 4: Fulfilling the Original Request @@ -158,7 +158,7 @@ component of the application. See link:#BNCAS[Chapter 51, "Getting Started Securing Web Applications"] for more information on protecting web applications. -[[BNBWU]][[step-5-invoking-enterprise-bean-business-methods]] +[[BNBWU]][[_step_5_invoking_enterprise_bean_business_methods]] ==== Step 5: Invoking Enterprise Bean Business Methods @@ -195,7 +195,7 @@ enterprise bean method. The result of the bean's execution of the call is returned to the web page and ultimately to the user by the web server and the web client. -[[BNBWW]][[features-of-a-security-mechanism]] +[[BNBWW]][[_features_of_a_security_mechanism]] === Features of a Security Mechanism @@ -215,7 +215,7 @@ Ideally, properly implemented security mechanisms will also be * Transparent to system users * Interoperable across application and enterprise boundaries -[[BNBWX]][[characteristics-of-application-security]] +[[BNBWX]][[_characteristics_of_application_security]] === Characteristics of Application Security diff --git a/src/main/antora/modules/security/pages/security-intro/security-intro002.adoc b/src/main/antora/modules/security/pages/security-intro/security-intro002.adoc index 3447ae70..3aabf080 100644 --- a/src/main/antora/modules/security/pages/security-intro/security-intro002.adoc +++ b/src/main/antora/modules/security/pages/security-intro/security-intro002.adoc @@ -1,4 +1,4 @@ -[[BNBWY]][[security-mechanisms]] +[[BNBWY]][[_security_mechanisms]] == Security Mechanisms @@ -9,7 +9,7 @@ that can be used to secure Jakarta EE applications. Each of these mechanisms can be used individually or with others to provide protection layers based on the specific needs of your implementation. -[[BNBWZ]][[java-se-security-mechanisms]] +[[BNBWZ]][[_java_se_security_mechanisms]] === Java SE Security Mechanisms @@ -52,7 +52,7 @@ and obtaining, listing, and managing Kerberos tickets. For more information on Java SE security, visit `http://docs.oracle.com/javase/8/docs/technotes/guides/security/`. -[[BNBXA]][[jakarta-ee-security-mechanisms]] +[[BNBXA]][[_jakarta_ee_security_mechanisms]] === Jakarta EE Security Mechanisms @@ -64,7 +64,7 @@ authenticating users and authorizing access to application functions and associated data at many different layers. Jakarta EE security services are separate from the security mechanisms of the operating system. -[[BNBXB]][[application-layer-security]] +[[BNBXB]][[_application_layer_security]] ==== Application-Layer Security @@ -104,7 +104,7 @@ transferable between application types. For more information on providing security at the application layer, see link:#BNBXE[Securing Containers]. -[[BNBXC]][[transport-layer-security]] +[[BNBXC]][[_transport_layer_security]] ==== Transport-Layer Security @@ -156,7 +156,7 @@ For more information on transport-layer security, see link:#BNBXW[Establishing a Secure Connection Using SSL]. -[[BNBXD]][[message-layer-security]] +[[BNBXD]][[_message_layer_security]] ==== Message-Layer Security diff --git a/src/main/antora/modules/security/pages/security-intro/security-intro003.adoc b/src/main/antora/modules/security/pages/security-intro/security-intro003.adoc index cddd14d7..e6f90c99 100644 --- a/src/main/antora/modules/security/pages/security-intro/security-intro003.adoc +++ b/src/main/antora/modules/security/pages/security-intro/security-intro003.adoc @@ -1,4 +1,4 @@ -[[BNBXE]][[securing-containers]] +[[BNBXE]][[_securing_containers]] == Securing Containers @@ -6,7 +6,7 @@ In Jakarta EE, the component containers are responsible for providing application security. A container provides two types of security: declarative and programmatic. -[[BNBXG]][[using-annotations-to-specify-security-information]] +[[BNBXG]][[_using_annotations_to_specify_security_information]] === Using Annotations to Specify Security Information @@ -29,7 +29,7 @@ descriptors are described only where necessary. For more information on annotations, see link:#BNBYJ[Further Information about Security]. -[[BNBXF]][[using-deployment-descriptors-for-declarative-security]] +[[BNBXF]][[_using_deployment_descriptors_for_declarative_security]] === Using Deployment Descriptors for Declarative Security @@ -65,7 +65,7 @@ Chapter 14 of the Jakarta Enterprise Beans 3.2 Core Contracts and Requirements S which can be downloaded from `https://jakarta.ee/specifications/enterprise-beans/3.2/`. -[[BNBXH]][[using-programmatic-security]] +[[BNBXH]][[_using_programmatic_security]] === Using Programmatic Security diff --git a/src/main/antora/modules/security/pages/security-intro/security-intro003a.adoc b/src/main/antora/modules/security/pages/security-intro/security-intro003a.adoc index 660d8afc..14213f08 100644 --- a/src/main/antora/modules/security/pages/security-intro/security-intro003a.adoc +++ b/src/main/antora/modules/security/pages/security-intro/security-intro003a.adoc @@ -1,4 +1,4 @@ -[[using-pluggable-providers]] +[[_using_pluggable_providers]] == Using Pluggable Providers Jakarta EE includes two specifications that define SPI interfaces for pluggable security providers, JSR-196 and JSR-375. These specifications are @@ -8,7 +8,7 @@ described in more detail in the following sections: Authentication Service Provider Interface for Containers (JASPIC)] * link:#jsr-375-jakarta-ee-security-api[JSR-375 Jakarta EE Security API] -[[jsr-196-java-authentication-service-provider-interface-for-containers-jaspic]] +[[_jsr_196_java_authentication_service_provider_interface_for_containers_jaspic]] === JSR-196 Java Authentication Service Provider Interface for Containers (JASPIC) JSR-196 defines a model for securing messages sent between a client and server in @@ -56,7 +56,7 @@ is to register a corresponding `AuthConfigProvider` with the global `AuthConfigF An `AuthConfigProvider` makes a `ServerAuthModule` available to the container, via a series of intermediary objects, for runtime message processing. -[[jsr-375-jakarta-ee-security-api]] +[[_jsr_375_jakarta_ee_security_api]] === JSR-375 Jakarta EE Security API JSR-375 defines the following authentication-related plugin SPIs: diff --git a/src/main/antora/modules/security/pages/security-intro/security-intro004.adoc b/src/main/antora/modules/security/pages/security-intro/security-intro004.adoc index b9867284..f7934884 100644 --- a/src/main/antora/modules/security/pages/security-intro/security-intro004.adoc +++ b/src/main/antora/modules/security/pages/security-intro/security-intro004.adoc @@ -1,4 +1,4 @@ -[[BNBXI]][[securing-glassfish-server]] +[[BNBXI]][[_securing_glassfish_server]] == Securing GlassFish Server diff --git a/src/main/antora/modules/security/pages/security-intro/security-intro005.adoc b/src/main/antora/modules/security/pages/security-intro/security-intro005.adoc index 69c22a7c..06e88096 100644 --- a/src/main/antora/modules/security/pages/security-intro/security-intro005.adoc +++ b/src/main/antora/modules/security/pages/security-intro/security-intro005.adoc @@ -1,4 +1,4 @@ -[[BNBXJ]][[working-with-realms-users-groups-and-roles]] +[[BNBXJ]][[_working_with_realms_users_groups_and_roles]] == Working with Realms, Users, Groups, and Roles @@ -36,7 +36,7 @@ By default, group principal names are mapped to roles of the same name. |======================================================================= -[[BNBXK]][[what-are-realms-users-groups-and-roles]] +[[BNBXK]][[_what_are_realms_users_groups_and_roles]] === What Are Realms, Users, Groups, and Roles? @@ -71,7 +71,7 @@ definition of roles, and mapping of roles to users and groups"] The following sections provide more information on realms, users, groups, and roles. -[[BNBXM]][[what-is-a-realm]] +[[BNBXM]][[_what_is_a_realm]] ==== What Is a Realm? @@ -109,7 +109,7 @@ Administration Console to manage users in this realm in the same way you manage users in the `file` realm. For more information, see link:#BNBXR[Managing Users and Groups in GlassFish Server]. -[[BNBXN]][[what-is-a-user]] +[[BNBXN]][[_what_is_a_user]] ==== What Is a User? @@ -127,7 +127,7 @@ operating system. The Jakarta EE server authentication service is not connected to the security mechanism of the operating system. The two security services manage users that belong to different realms. -[[BNBXO]][[what-is-a-group]] +[[BNBXO]][[_what_is_a_group]] ==== What Is a Group? @@ -145,7 +145,7 @@ A group in GlassFish Server has a different scope from a role. A group is designated for the entire GlassFish Server, whereas a role is associated only with a specific application in GlassFish Server. -[[BNBXP]][[what-is-a-role]] +[[BNBXP]][[_what_is_a_role]] ==== What Is a Role? @@ -154,7 +154,7 @@ of resources in an application. A role can be compared to a key that can open a lock. Many people might have a copy of the key. The lock doesn't care who you are, only that you have the right key. -[[BNBXQ]][[some-other-terminology]] +[[BNBXQ]][[_some_other_terminology]] ==== Some Other Terminology @@ -177,14 +177,14 @@ attributes used to authenticate a principal for Jakarta EE services. A principal acquires a credential upon authentication or from another principal that allows its credential to be used. -[[BNBXR]][[managing-users-and-groups-in-glassfish-server]] +[[BNBXR]][[_managing_users_and_groups_in_glassfish_server]] === Managing Users and Groups in GlassFish Server Follow these steps for managing users before you run the tutorial examples. -[[BNBXS]][[to-add-users-to-glassfish-server]] +[[BNBXS]][[_to_add_users_to_glassfish_server]] ==== To Add Users to GlassFish Server @@ -235,7 +235,7 @@ in this tutorial. 10. Click OK to add this user to the realm, or click Cancel to quit without saving. -[[BNBXU]][[setting-up-security-roles]] +[[BNBXU]][[_setting_up_security_roles]] === Setting Up Security Roles @@ -316,7 +316,7 @@ has declared what roles are authorized to access protected parts of an application, the next step is to map the security role to the name of a user, or principal. -[[BNBXV]][[mapping-roles-to-users-and-groups]] +[[BNBXV]][[_mapping_roles_to_users_and_groups]] === Mapping Roles to Users and Groups diff --git a/src/main/antora/modules/security/pages/security-intro/security-intro005a.adoc b/src/main/antora/modules/security/pages/security-intro/security-intro005a.adoc index abdf8aee..1764dcf5 100644 --- a/src/main/antora/modules/security/pages/security-intro/security-intro005a.adoc +++ b/src/main/antora/modules/security/pages/security-intro/security-intro005a.adoc @@ -1,4 +1,4 @@ -[[working-with-identity-stores]] +[[_working_with_identity_stores]] == Working with Identity Stores An identity store is a database or directory (store) that contains identity information about a collection of users that includes an application's callers. An identity store diff --git a/src/main/antora/modules/security/pages/security-intro/security-intro006.adoc b/src/main/antora/modules/security/pages/security-intro/security-intro006.adoc index 5dbc4f0c..ffc142a6 100644 --- a/src/main/antora/modules/security/pages/security-intro/security-intro006.adoc +++ b/src/main/antora/modules/security/pages/security-intro/security-intro006.adoc @@ -1,4 +1,4 @@ -[[BNBXW]][[establishing-a-secure-connection-using-ssl]] +[[BNBXW]][[_establishing_a_secure_connection_using_ssl]] == Establishing a Secure Connection Using SSL @@ -60,7 +60,7 @@ domain names do not match, these browsers will display a warning to the client. In general, only address-based virtual hosts are commonly used with SSL in a production environment. -[[BNBXX]][[verifying-and-configuring-ssl-support]] +[[BNBXX]][[_verifying_and_configuring_ssl_support]] === Verifying and Configuring SSL Support diff --git a/src/main/antora/modules/security/pages/security-intro/security-intro007.adoc b/src/main/antora/modules/security/pages/security-intro/security-intro007.adoc index 6efebce8..cbcdf6b9 100644 --- a/src/main/antora/modules/security/pages/security-intro/security-intro007.adoc +++ b/src/main/antora/modules/security/pages/security-intro/security-intro007.adoc @@ -1,4 +1,4 @@ -[[BNBYJ]][[further-information-about-security]] +[[BNBYJ]][[_further_information_about_security]] == Further Information about Security diff --git a/src/main/antora/modules/security/pages/security-jakartaee/security-jakartaee.adoc b/src/main/antora/modules/security/pages/security-jakartaee/security-jakartaee.adoc index e7af83f6..a0c39ce3 100644 --- a/src/main/antora/modules/security/pages/security-jakartaee/security-jakartaee.adoc +++ b/src/main/antora/modules/security/pages/security-jakartaee/security-jakartaee.adoc @@ -1,6 +1,6 @@ = Getting Started Securing Enterprise Applications -[[BNBYK]][[getting-started-securing-enterprise-applications]] +[[BNBYK]][[_getting_started_securing_enterprise_applications]] This chapter describes how to administer security for enterprise applications. diff --git a/src/main/antora/modules/security/pages/security-jakartaee/security-jakartaee001.adoc b/src/main/antora/modules/security/pages/security-jakartaee/security-jakartaee001.adoc index 66a40452..0d0810e8 100644 --- a/src/main/antora/modules/security/pages/security-jakartaee/security-jakartaee001.adoc +++ b/src/main/antora/modules/security/pages/security-jakartaee/security-jakartaee001.adoc @@ -1,4 +1,4 @@ -[[CACGIFHJ]][[basic-security-tasks-for-enterprise-applications]] +[[CACGIFHJ]][[_basic_security_tasks_for_enterprise_applications]] == Basic Security Tasks for Enterprise Applications diff --git a/src/main/antora/modules/security/pages/security-jakartaee/security-jakartaee002.adoc b/src/main/antora/modules/security/pages/security-jakartaee/security-jakartaee002.adoc index cd89b1ea..ac17a59f 100644 --- a/src/main/antora/modules/security/pages/security-jakartaee/security-jakartaee002.adoc +++ b/src/main/antora/modules/security/pages/security-jakartaee/security-jakartaee002.adoc @@ -1,4 +1,4 @@ -[[BNBYL]][[securing-enterprise-beans]] +[[BNBYL]][[_securing_enterprise_beans]] == Securing Enterprise Beans @@ -110,7 +110,7 @@ specification. This document can be downloaded from "Security Management," discusses security management for enterprise beans. -[[GJGDI]][[securing-an-enterprise-bean-using-declarative-security]] +[[GJGDI]][[_securing_an_enterprise_bean_using_declarative_security]] === Securing an Enterprise Bean Using Declarative Security @@ -155,7 +155,7 @@ The following sections show how an application developer uses declarative security to either secure an application or to create a security view to pass along to the deployer. -[[GJGCQ]][[specifying-authorized-users-by-declaring-security-roles]] +[[GJGCQ]][[_specifying_authorized_users_by_declaring_security_roles]] ==== Specifying Authorized Users by Declaring Security Roles @@ -343,7 +343,7 @@ To clarify, the annotations are not inherited by the subclass itself. Instead, the annotations apply to methods of the superclass that are inherited by the subclass. -[[BNBYU]][[specifying-an-authentication-mechanism-and-secure-connection]] +[[BNBYU]][[_specifying_an_authentication_mechanism_and_secure_connection]] ==== Specifying an Authentication Mechanism and Secure Connection @@ -354,7 +354,7 @@ To use a different type of authentication or to require a secure connection using SSL, specify this information in an application deployment descriptor. -[[GJGCS]][[securing-an-enterprise-bean-programmatically]] +[[GJGCS]][[_securing_an_enterprise_bean_programmatically]] === Securing an Enterprise Bean Programmatically @@ -488,7 +488,7 @@ during a particular time of day. An example application that uses the link:#BNCAA[The converter-secure Example: Securing an Enterprise Bean with Programmatic Security]. -[[BNBYR]][[propagating-a-security-identity-run-as]] +[[BNBYR]][[_propagating_a_security_identity_run_as]] === Propagating a Security Identity (Run-As) @@ -534,7 +534,7 @@ interfaces, the message listener methods of a message-driven bean, the timeout method of an enterprise bean, and all internal methods of the bean that might be called in turn. -[[BNBZB]][[configuring-a-components-propagated-security-identity]] +[[BNBZB]][[_configuring_a_components_propagated_security_identity]] ==== Configuring a Component's Propagated Security Identity @@ -560,7 +560,7 @@ You will have to map the run-as role name to a given principal defined in GlassFish Server if the given roles are associated with more than one user principal. -[[BNBZC]][[trust-between-containers]] +[[BNBZC]][[_trust_between_containers]] ==== Trust between Containers @@ -581,7 +581,7 @@ By default, GlassFish Server is configured to trust identities that are propagated from different containers. Therefore, you do not need to take any special steps to set up a trust relationship. -[[BNBZG]][[deploying-secure-enterprise-beans]] +[[BNBZG]][[_deploying_secure_enterprise_beans]] === Deploying Secure Enterprise Beans diff --git a/src/main/antora/modules/security/pages/security-jakartaee/security-jakartaee003.adoc b/src/main/antora/modules/security/pages/security-jakartaee/security-jakartaee003.adoc index ef382894..107dccf4 100644 --- a/src/main/antora/modules/security/pages/security-jakartaee/security-jakartaee003.adoc +++ b/src/main/antora/modules/security/pages/security-jakartaee/security-jakartaee003.adoc @@ -1,11 +1,11 @@ -[[GKBSZ]][[examples-securing-enterprise-beans]] +[[GKBSZ]][[_examples_securing_enterprise_beans]] == Examples: Securing Enterprise Beans The following examples show how to secure enterprise beans using declarative and programmatic security. -[[BNBZK]][[the-cart-secure-example-securing-an-enterprise-bean-with-declarative-security]] +[[BNBZK]][[_the_cart_secure_example_securing_an_enterprise_bean_with_declarative_security]] === The cart-secure Example: Securing an Enterprise Bean with Declarative Security @@ -49,7 +49,7 @@ the client application by following the steps in link:#BNBZN[To Run the cart-secure Example Using NetBeans IDE] or link:#BNBZO[To Run the cart-secure Example Using Maven]. -[[BNBZL]][[annotating-the-bean]] +[[BNBZL]][[_annotating_the_bean]] ==== Annotating the Bean @@ -154,7 +154,7 @@ authentication will be required for a user to access these methods. If no authentication method is specified in the deployment descriptor, the type of authentication will be user name/password authentication. -[[BNBZN]][[to-run-the-cart-secure-example-using-netbeans-ide]] +[[BNBZN]][[_to_run_the_cart_secure_example_using_netbeans_ide]] ==== To Run the cart-secure Example Using NetBeans IDE @@ -199,7 +199,7 @@ Java Result: 1 If the user name and password are not authenticated, the dialog box reappears until you enter correct values. -[[BNBZO]][[to-run-the-cart-secure-example-using-maven]] +[[BNBZO]][[_to_run_the_cart_secure_example_using_maven]] ==== To Run the cart-secure Example Using Maven @@ -241,7 +241,7 @@ Java Result: 1 If the user name and password are not authenticated, the dialog box reappears until you enter correct values. -[[BNCAA]][[the-converter-secure-example-securing-an-enterprise-bean-with-programmatic-security]] +[[BNCAA]][[_the_converter_secure_example_securing_an_enterprise_bean_with_programmatic_security]] === The converter-secure Example: Securing an Enterprise Bean with Programmatic Security @@ -283,7 +283,7 @@ link:#GJRMH[Specifying Security for Basic Authentication Using Annotations]. 5. Build, package, deploy, and run the application. -[[BNCAB]][[modifying-converterbean]] +[[BNCAB]][[_modifying_converterbean]] ==== Modifying ConverterBean @@ -343,7 +343,7 @@ public class ConverterBean{ } ---- -[[GKBSI]][[modifying-converterservlet]] +[[GKBSI]][[_modifying_converterservlet]] ==== Modifying ConverterServlet @@ -358,7 +358,7 @@ client, `ConverterServlet`: rolesAllowed = {"TutorialUser"})) ---- -[[BNCAD]][[to-run-the-converter-secure-example-using-netbeans-ide]] +[[BNCAD]][[_to_run_the_converter_secure_example_using_netbeans_ide]] ==== To Run the converter-secure Example Using NetBeans IDE @@ -378,7 +378,7 @@ tut-install/examples/security This command builds and deploys the example application to your GlassFish Server instance. -[[BNCAE]][[to-run-the-converter-secure-example-using-maven]] +[[BNCAE]][[_to_run_the_converter_secure_example_using_maven]] ==== To Run the converter-secure Example Using Maven @@ -401,7 +401,7 @@ This command builds and packages the application into a WAR file, `converter-secure.war`, that is located in the `target` directory, and deploys the WAR file. -[[GJTDP]][[to-run-the-converter-secure-example]] +[[GJTDP]][[_to_run_the_converter_secure_example]] ==== To Run the converter-secure Example diff --git a/src/main/antora/modules/security/pages/security-webtier/security-webtier.adoc b/src/main/antora/modules/security/pages/security-webtier/security-webtier.adoc index 5e1073d4..0ce13feb 100644 --- a/src/main/antora/modules/security/pages/security-webtier/security-webtier.adoc +++ b/src/main/antora/modules/security/pages/security-webtier/security-webtier.adoc @@ -1,6 +1,6 @@ = Getting Started Securing Web Applications -[[BNCAS]][[getting-started-securing-web-applications]] +[[BNCAS]][[_getting_started_securing_web_applications]] This chapter describes in greater detail the ways to implement security for Jakarta EE web applications discussed in a general way in diff --git a/src/main/antora/modules/security/pages/security-webtier/security-webtier001.adoc b/src/main/antora/modules/security/pages/security-webtier/security-webtier001.adoc index fac0bd22..f5e46690 100644 --- a/src/main/antora/modules/security/pages/security-webtier/security-webtier001.adoc +++ b/src/main/antora/modules/security/pages/security-webtier/security-webtier001.adoc @@ -1,4 +1,4 @@ -[[BNCAT]][[overview-of-web-application-security]] +[[BNCAT]][[_overview_of_web_application_security]] == Overview of Web Application Security diff --git a/src/main/antora/modules/security/pages/security-webtier/security-webtier002.adoc b/src/main/antora/modules/security/pages/security-webtier/security-webtier002.adoc index 3b96372a..ac8fe116 100644 --- a/src/main/antora/modules/security/pages/security-webtier/security-webtier002.adoc +++ b/src/main/antora/modules/security/pages/security-webtier/security-webtier002.adoc @@ -1,4 +1,4 @@ -[[GKBAA]][[securing-web-applications]] +[[GKBAA]][[_securing_web_applications]] == Securing Web Applications @@ -6,7 +6,7 @@ Web applications are created by application developers who give, sell, or otherwise transfer the application to an application deployer for installation into a runtime environment. -[[CHDBIBHI]][[overview-of-securing-web-applications]] +[[CHDBIBHI]][[_overview_of_securing_web_applications]] === Overview of Securing Web Applications @@ -24,7 +24,7 @@ explains how to secure web applications using annotations wherever possible. It explains how to use deployment descriptors where annotations cannot be used. -[[BNCBK]][[specifying-security-constraints]] +[[BNCBK]][[_specifying_security_constraints]] === Specifying Security Constraints @@ -60,7 +60,7 @@ protected when transported between a client and a server. User data constraints are discussed in link:#BNCBM[Specifying a Secure Connection]. -[[GJJCD]][[specifying-a-web-resource-collection]] +[[GJJCD]][[_specifying_a_web_resource_collection]] ==== Specifying a Web Resource Collection @@ -101,7 +101,7 @@ are protected) ** If the collection contains one or more `http-method-omission` elements, none of which names the HTTP method -[[GJJCG]][[specifying-an-authorization-constraint]] +[[GJJCG]][[_specifying_an_authorization_constraint]] ==== Specifying an Authorization Constraint @@ -130,7 +130,7 @@ For a servlet, the `@HttpConstraint` and `@HttpMethodConstraint` annotations accept a `rolesAllowed` element that specifies the authorized roles. -[[BNCBM]][[specifying-a-secure-connection]] +[[BNCBM]][[_specifying_a_secure_connection]] ==== Specifying a Secure Connection @@ -204,7 +204,7 @@ easily implemented by using a filter. |======================================================================= -[[BNCBL]][[specifying-security-constraints-for-resources]] +[[BNCBL]][[_specifying_security_constraints_for_resources]] ==== Specifying Security Constraints for Resources @@ -249,7 +249,7 @@ following: ---- -[[GKBSA]][[specifying-authentication-mechanisms]] +[[GKBSA]][[_specifying_authentication_mechanisms]] === Specifying Authentication Mechanisms @@ -316,7 +316,7 @@ conjunction with basic or form-based authentication, some of these concerns can be alleviated. To specify a secure transport mechanism, use the elements described in link:#BNCBM[Specifying a Secure Connection]. -[[BNCBO]][[http-basic-authentication]] +[[BNCBO]][[_http_basic_authentication]] ==== HTTP Basic Authentication @@ -347,7 +347,7 @@ image:jakartaeett_dt_045.png[ "Diagram of four steps in HTTP basic authentication between client and server"] -[[BNCBQ]][[form-based-authentication]] +[[BNCBQ]][[_form_based_authentication]] ==== Form-Based Authentication @@ -401,7 +401,7 @@ HTML page: ---- -[[BNCBW]][[digest-authentication]] +[[BNCBW]][[_digest_authentication]] ==== Digest Authentication @@ -414,7 +414,7 @@ wire, digest authentication requires that clear-text password equivalents be available to the authenticating container so that it can validate received authenticators by calculating the expected digest. -[[BNCBN]][[specifying-an-authentication-mechanism-in-the-deployment-descriptor]] +[[BNCBN]][[_specifying_an_authentication_mechanism_in_the_deployment_descriptor]] === Specifying an Authentication Mechanism in the Deployment Descriptor @@ -482,7 +482,7 @@ deployment descriptor: ---- -[[BNCAV]][[declaring-security-roles]] +[[BNCAV]][[_declaring_security_roles]] === Declaring Security Roles diff --git a/src/main/antora/modules/security/pages/security-webtier/security-webtier003.adoc b/src/main/antora/modules/security/pages/security-webtier/security-webtier003.adoc index 23745c5c..27c3b2fd 100644 --- a/src/main/antora/modules/security/pages/security-webtier/security-webtier003.adoc +++ b/src/main/antora/modules/security/pages/security-webtier/security-webtier003.adoc @@ -1,4 +1,4 @@ -[[GJIIE]][[using-programmatic-security-with-web-applications]] +[[GJIIE]][[_using_programmatic_security_with_web_applications]] == Using Programmatic Security with Web Applications @@ -6,14 +6,14 @@ Programmatic security is used by security-aware applications when declarative security alone is not sufficient to express the security model of the application. -[[GIRCJ]][[authenticating-users-programmatically]] +[[GIRCJ]][[_authenticating_users_programmatically]] === Authenticating Users Programmatically You can use the `SecurityContext` and `HttpServletRequest` interfaces to authenticate users for a web application programmatically. -[[security-context]] +[[_security_context]] == SecurityContext The `SecurityContext` interface, as specified in the Jakarta EE Security API specification, defines the following method to programmatically trigger the @@ -131,7 +131,7 @@ public class TestServlet extends HttpServlet { } ---- -[[BNCBA]][[checking-caller-identity-programmatically]] +[[BNCBA]][[_checking_caller_identity_programmatically]] === Checking Caller Identity Programmatically @@ -195,7 +195,7 @@ Your application can make business-logic decisions based on the information obtained using these APIs. -[[testing-access-to-a-resource-programmatically]] +[[_testing_access_to_a_resource_programmatically]] === Testing Access to a Resource Programmatically The `SecurityContext` interface, as specified in the Jakarta Security API @@ -232,7 +232,7 @@ securityContext.hasAccessToWebResource("/protectedServlet", GET) The above `hasAccessToWebResource()` call returns true if, and only if, the caller is in role "foo". -[[GJJLQ]][[example-code-for-programmatic-security]] +[[GJJLQ]][[_example_code_for_programmatic_security]] === Example Code for Programmatic Security @@ -313,7 +313,7 @@ public class LoginServlet extends HttpServlet { } ---- -[[BNCBB]][[declaring-and-linking-role-references]] +[[BNCBB]][[_declaring_and_linking_role_references]] === Declaring and Linking Role References diff --git a/src/main/antora/modules/security/pages/security-webtier/security-webtier004.adoc b/src/main/antora/modules/security/pages/security-webtier/security-webtier004.adoc index e6934bae..cdd59ed3 100644 --- a/src/main/antora/modules/security/pages/security-webtier/security-webtier004.adoc +++ b/src/main/antora/modules/security/pages/security-webtier/security-webtier004.adoc @@ -1,11 +1,11 @@ -[[BNCBX]][[examples-securing-web-applications]] +[[BNCBX]][[_examples_securing_web_applications]] == Examples: Securing Web Applications Some basic setup is required before any of the example applications will run correctly. -[[CHDEBCHG]][[overview-of-examples-of-securing-web-applications]] +[[CHDEBCHG]][[_overview_of_examples_of_securing_web_applications]] === Overview of Examples of Securing Web Applications @@ -21,7 +21,7 @@ Enterprise Bean with Declarative Security] Securing an Enterprise Bean with Programmatic Security] * Jakarta EE 8 Eclipse GlassFish samples: `https://github.com/eclipse-ee4j/glassfish-samples` -[[GJJLK]][[to-set-up-your-system-for-running-the-security-examples]] +[[GJJLK]][[_to_set_up_your_system_for_running_the_security_examples]] === To Set Up Your System for Running the Security Examples @@ -67,7 +67,7 @@ the console. |======================================================================= -[[BNCCK]][[the-hello2-basicauth-example-basic-authentication-with-a-servlet]] +[[BNCCK]][[_the_hello2_basicauth_example_basic_authentication_with_a_servlet]] === The hello2-basicauth Example: Basic Authentication with a Servlet @@ -102,7 +102,7 @@ the hello2-basicauth Example Using Maven]. 5. Run the web application by following the steps described in link:#GJQZF[To Run the hello2-basicauth Example]. -[[GJRMH]][[specifying-security-for-basic-authentication-using-annotations]] +[[GJRMH]][[_specifying_security_for_basic_authentication_using_annotations]] ==== Specifying Security for Basic Authentication Using Annotations @@ -157,7 +157,7 @@ security settings in the deployment descriptor. Use the deployment descriptor to specify settings for nondefault authentication mechanisms, for which you cannot use the `@ServletSecurity` annotation. -[[GJQYS]][[to-build-package-and-deploy-the-hello2-basicauth-example-using-netbeans-ide]] +[[GJQYS]][[_to_build_package_and_deploy_the_hello2_basicauth_example_using_netbeans_ide]] ==== To Build, Package, and Deploy the hello2-basicauth Example Using NetBeans IDE @@ -178,7 +178,7 @@ select Build. This command builds and deploys the example application to your GlassFish Server instance. -[[GJQZH]][[to-build-package-and-deploy-the-hello2-basicauth-example-using-maven]] +[[GJQZH]][[_to_build_package_and_deploy_the_hello2_basicauth_example_using_maven]] ==== To Build, Package, and Deploy the hello2-basicauth Example Using Maven @@ -201,7 +201,7 @@ This command builds and packages the application into a WAR file, `hello2-basicauth.war`, that is located in the `target` directory, then deploys the WAR file. -[[GJQZF]][[to-run-the-hello2-basicauth-example]] +[[GJQZF]][[_to_run_the_hello2_basicauth_example]] ==== To Run the hello2-basicauth Example @@ -245,7 +245,7 @@ application now. + The application responds by saying "Hello" to the name you entered. -[[BNCBY]][[the-hello1-formauth-example-form-based-authentication-with-a-javaserver-faces-application]] +[[BNCBY]][[_the_hello1_formauth_example_form_based_authentication_with_a_javaserver_faces_application]] === The hello1-formauth Example: Form-Based Authentication with a Jakarta Server Faces Application @@ -274,7 +274,7 @@ Error Page]. This application can be found in the `_tut-install_/examples/security/hello1-formauth/` directory. -[[BNCCA]][[creating-the-login-form-and-the-error-page]] +[[BNCCA]][[_creating_the_login_form_and_the_error_page]] ==== Creating the Login Form and the Error Page @@ -361,7 +361,7 @@ again. Here is the code for this page: ---- -[[BNCCB]][[specifying-security-for-the-form-based-authentication-example]] +[[BNCCB]][[_specifying_security_for_the_form_based_authentication_example]] ==== Specifying Security for the Form-Based Authentication Example @@ -404,7 +404,7 @@ deployment descriptor for this example, which can be found in ---- -[[GJRBA]][[to-build-package-and-deploy-the-hello1-formauth-example-using-netbeans-ide]] +[[GJRBA]][[_to_build_package_and_deploy_the_hello1_formauth_example_using_netbeans_ide]] ==== To Build, Package, and Deploy the hello1-formauth Example Using NetBeans IDE @@ -425,7 +425,7 @@ select Run. This command builds and deploys the example application to your GlassFish Server instance, then opens it in a browser. -[[GJRAZ]][[to-build-package-and-deploy-the-hello1-formauth-example-using-maven-and-the-asadmin-command]] +[[GJRAZ]][[_to_build_package_and_deploy_the_hello1_formauth_example_using_maven_and_the_asadmin_command]] ==== To Build, Package, and Deploy the hello1-formauth Example Using Maven and the asadmin Command @@ -449,7 +449,7 @@ This command builds and packages the application into a WAR file, `hello1-formauth.war`, that is located in the `target` directory, then deploys the WAR file to GlassFish Server. -[[GJRAL]][[to-run-the-hello1-formauth-example]] +[[GJRAL]][[_to_run_the_hello1_formauth_example]] ==== To Run the hello1-formauth Example From 62cd3c25f01dde828c9bfdb617a08e9c2b7907ac Mon Sep 17 00:00:00 2001 From: "Kito D. Mann" Date: Tue, 16 May 2023 22:24:02 -0400 Subject: [PATCH 009/247] JETUT-56 Added security to the navigation and updated docs. --- CONVERTING_TO_ANTORA.adoc | 32 ++++++++++++++++++++++- src/main/antora/antora.yml | 1 + src/main/antora/modules/security/nav.adoc | 8 ++++++ 3 files changed, 40 insertions(+), 1 deletion(-) create mode 100644 src/main/antora/modules/security/nav.adoc diff --git a/CONVERTING_TO_ANTORA.adoc b/CONVERTING_TO_ANTORA.adoc index 47a763f7..d7d12360 100644 --- a/CONVERTING_TO_ANTORA.adoc +++ b/CONVERTING_TO_ANTORA.adoc @@ -16,6 +16,36 @@ Here’s the current process for migrating an individual module (i.e. security, * Inside of this folder, create a `pages` folder. 4. Move all the folders for the module you are migrating into the new `pages` folder. For example, for the Security module, you would move all of the `src/main/asciidoc/security-*` folders into the `src/main/antora/modules/security/pages`. (Copy the entire folders, not just the `.adoc` files). 5. Run the migration script from the root project folder. For example, for the Security module, you would run `jbang AntoraConverter.java security`. (The first parameter is the folder relative to `src/main/antora/modules`). -6. +6. Create a new file called `nav.adoc` in the root of the module folder. For example, for the Security module, you would create a `security/nav.adoc`. +7. Copy all the include statements from the corresponding "part" file in the `src/main/asciidoc/` folder. For example, for the Security module, you would copy the include statements of `src/main/asciidoc/partsecurity.adoc` into the `security/nav.adoc` file. Here are the include statements for the Security module: + +```asciidoc +include::security-intro/security-intro.adoc[] + +include::security-webtier/security-webtier.adoc[] + +include::security-jakartaee/security-jakartaee.adoc[] + +include::security-api/security-api.adoc[] + +include::security-advanced/security-advanced.adoc[] +``` + +After copying these into `nav.adoc`, replace "include::" with "* xref:" and add a header with the module name: + +```asciidoc +.Security +* xref:security-intro/security-intro.adoc[] + +* xref:security-webtier/security-webtier.adoc[] + +* xref:security-jakartaee/security-jakartaee.adoc[] + +* xref:security-api/security-api.adoc[] + +* xref:security-advanced/security-advanced.adoc[] +``` + + > NOTE: It's essential that you _move_ rather than copy the folders so that we keep the history intact. diff --git a/src/main/antora/antora.yml b/src/main/antora/antora.yml index a6d643f6..e0e91d26 100644 --- a/src/main/antora/antora.yml +++ b/src/main/antora/antora.yml @@ -7,4 +7,5 @@ asciidoc: table-caption: false nav: - modules/ROOT/nav.adoc + - modules/security/nav.adoc diff --git a/src/main/antora/modules/security/nav.adoc b/src/main/antora/modules/security/nav.adoc new file mode 100644 index 00000000..746f93a7 --- /dev/null +++ b/src/main/antora/modules/security/nav.adoc @@ -0,0 +1,8 @@ +.Security +* xref:security-intro/security-intro.adoc[] +* xref:security-webtier/security-webtier.adoc[] +* xref:security-jakartaee/security-jakartaee.adoc[] +* xref:security-api/security-api.adoc[] +* xref:security-advanced/security-advanced.adoc[] + + From e417487709ba281a18549a893f8a298bff70add0 Mon Sep 17 00:00:00 2001 From: "Kito D. Mann" Date: Tue, 16 May 2023 22:50:34 -0400 Subject: [PATCH 010/247] JETUT-56 Moved images --- .../images}/images/eclipse_foundation_logo_tiny.png | Bin .../modules/images}/images/jakartaeett_dt_001.png | Bin .../modules/images}/images/jakartaeett_dt_002.png | Bin .../modules/images}/images/jakartaeett_dt_003.png | Bin .../modules/images}/images/jakartaeett_dt_004.png | Bin .../modules/images}/images/jakartaeett_dt_005.png | Bin .../modules/images}/images/jakartaeett_dt_006.png | Bin .../modules/images}/images/jakartaeett_dt_007.png | Bin .../modules/images}/images/jakartaeett_dt_008.png | Bin .../modules/images}/images/jakartaeett_dt_009.png | Bin .../modules/images}/images/jakartaeett_dt_010.png | Bin .../modules/images}/images/jakartaeett_dt_011.png | Bin .../modules/images}/images/jakartaeett_dt_012.png | Bin .../modules/images}/images/jakartaeett_dt_013.png | Bin .../modules/images}/images/jakartaeett_dt_014.png | Bin .../modules/images}/images/jakartaeett_dt_015.png | Bin .../modules/images}/images/jakartaeett_dt_016.png | Bin .../modules/images}/images/jakartaeett_dt_017.png | Bin .../modules/images}/images/jakartaeett_dt_018.png | Bin .../modules/images}/images/jakartaeett_dt_019.png | Bin .../modules/images}/images/jakartaeett_dt_020.png | Bin .../modules/images}/images/jakartaeett_dt_021.png | Bin .../modules/images}/images/jakartaeett_dt_022.png | Bin .../modules/images}/images/jakartaeett_dt_023.png | Bin .../modules/images}/images/jakartaeett_dt_024.png | Bin .../modules/images}/images/jakartaeett_dt_025.png | Bin .../modules/images}/images/jakartaeett_dt_026.png | Bin .../modules/images}/images/jakartaeett_dt_027.png | Bin .../modules/images}/images/jakartaeett_dt_028.png | Bin .../modules/images}/images/jakartaeett_dt_029.png | Bin .../modules/images}/images/jakartaeett_dt_030.png | Bin .../modules/images}/images/jakartaeett_dt_031.png | Bin .../modules/images}/images/jakartaeett_dt_032.png | Bin .../modules/images}/images/jakartaeett_dt_033.png | Bin .../modules/images}/images/jakartaeett_dt_034.png | Bin .../modules/images}/images/jakartaeett_dt_035.png | Bin .../modules/images}/images/jakartaeett_dt_036.png | Bin .../modules/images}/images/jakartaeett_dt_037.png | Bin .../modules/images}/images/jakartaeett_dt_038.png | Bin .../modules/images}/images/jakartaeett_dt_039.png | Bin .../modules/images}/images/jakartaeett_dt_040.png | Bin .../modules/images}/images/jakartaeett_dt_041.png | Bin .../modules/images}/images/jakartaeett_dt_042.png | Bin .../modules/images}/images/jakartaeett_dt_043.png | Bin .../modules/images}/images/jakartaeett_dt_044.png | Bin .../modules/images}/images/jakartaeett_dt_045.png | Bin .../modules/images}/images/jakartaeett_dt_046.png | Bin .../modules/images}/images/jakartaeett_dt_047.png | Bin .../modules/images}/images/jakartaeett_dt_048.png | Bin .../modules/images}/images/jakartaeett_dt_049.png | Bin .../modules/images}/images/jakartaeett_dt_050.png | Bin .../modules/images}/images/jakartaeett_dt_051.png | Bin .../modules/images}/images/jakartaeett_dt_052.png | Bin .../modules/images}/images/jakartaeett_dt_053.png | Bin .../modules/images}/images/jakartaeett_dt_054.png | Bin .../modules/images}/images/jakartaeett_dt_055.png | Bin .../modules/images}/images/jakartaeett_dt_056.png | Bin .../modules/images}/images/jakartaeett_dt_057.png | Bin .../modules/images}/images/jakartaeett_dt_058.png | Bin .../modules/images}/images/jakartaeett_dt_059.png | Bin .../modules/images}/images/jakartaeett_dt_060.png | Bin .../modules/images}/images/jakartaeett_dt_061.png | Bin .../modules/images}/images/jakartaeett_dt_062.png | Bin .../modules/images}/images/jakartaeett_dt_063.png | Bin .../modules/images}/images/jakartaeett_dt_064.png | Bin .../images}/images/jakartaeett_dt_065_frmcmpnt.png | Bin .../images}/images/jakartaeett_dt_066_slctmny.png | Bin .../images}/images/jakartaeett_dt_067_slctn.png | Bin .../images}/images/jakartaeett_dt_068_txtcmpnts.png | Bin 69 files changed, 0 insertions(+), 0 deletions(-) rename src/main/{asciidoc => antora/modules/images}/images/eclipse_foundation_logo_tiny.png (100%) rename src/main/{asciidoc => antora/modules/images}/images/jakartaeett_dt_001.png (100%) rename src/main/{asciidoc => antora/modules/images}/images/jakartaeett_dt_002.png (100%) rename src/main/{asciidoc => antora/modules/images}/images/jakartaeett_dt_003.png (100%) rename src/main/{asciidoc => antora/modules/images}/images/jakartaeett_dt_004.png (100%) rename src/main/{asciidoc => antora/modules/images}/images/jakartaeett_dt_005.png (100%) rename src/main/{asciidoc => antora/modules/images}/images/jakartaeett_dt_006.png (100%) rename src/main/{asciidoc => antora/modules/images}/images/jakartaeett_dt_007.png (100%) rename src/main/{asciidoc => antora/modules/images}/images/jakartaeett_dt_008.png (100%) rename src/main/{asciidoc => antora/modules/images}/images/jakartaeett_dt_009.png (100%) rename src/main/{asciidoc => antora/modules/images}/images/jakartaeett_dt_010.png (100%) rename src/main/{asciidoc => antora/modules/images}/images/jakartaeett_dt_011.png (100%) rename src/main/{asciidoc => antora/modules/images}/images/jakartaeett_dt_012.png (100%) rename src/main/{asciidoc => antora/modules/images}/images/jakartaeett_dt_013.png (100%) rename src/main/{asciidoc => antora/modules/images}/images/jakartaeett_dt_014.png (100%) rename src/main/{asciidoc => antora/modules/images}/images/jakartaeett_dt_015.png (100%) rename src/main/{asciidoc => antora/modules/images}/images/jakartaeett_dt_016.png (100%) rename src/main/{asciidoc => antora/modules/images}/images/jakartaeett_dt_017.png (100%) rename src/main/{asciidoc => antora/modules/images}/images/jakartaeett_dt_018.png (100%) rename src/main/{asciidoc => antora/modules/images}/images/jakartaeett_dt_019.png (100%) rename src/main/{asciidoc => antora/modules/images}/images/jakartaeett_dt_020.png (100%) rename src/main/{asciidoc => antora/modules/images}/images/jakartaeett_dt_021.png (100%) rename src/main/{asciidoc => antora/modules/images}/images/jakartaeett_dt_022.png (100%) rename src/main/{asciidoc => antora/modules/images}/images/jakartaeett_dt_023.png (100%) rename src/main/{asciidoc => antora/modules/images}/images/jakartaeett_dt_024.png (100%) rename src/main/{asciidoc => antora/modules/images}/images/jakartaeett_dt_025.png (100%) rename src/main/{asciidoc => antora/modules/images}/images/jakartaeett_dt_026.png (100%) rename src/main/{asciidoc => antora/modules/images}/images/jakartaeett_dt_027.png (100%) rename src/main/{asciidoc => antora/modules/images}/images/jakartaeett_dt_028.png (100%) rename src/main/{asciidoc => antora/modules/images}/images/jakartaeett_dt_029.png (100%) rename src/main/{asciidoc => antora/modules/images}/images/jakartaeett_dt_030.png (100%) rename src/main/{asciidoc => antora/modules/images}/images/jakartaeett_dt_031.png (100%) rename src/main/{asciidoc => antora/modules/images}/images/jakartaeett_dt_032.png (100%) rename src/main/{asciidoc => antora/modules/images}/images/jakartaeett_dt_033.png (100%) rename src/main/{asciidoc => antora/modules/images}/images/jakartaeett_dt_034.png (100%) rename src/main/{asciidoc => antora/modules/images}/images/jakartaeett_dt_035.png (100%) rename src/main/{asciidoc => antora/modules/images}/images/jakartaeett_dt_036.png (100%) rename src/main/{asciidoc => antora/modules/images}/images/jakartaeett_dt_037.png (100%) rename src/main/{asciidoc => antora/modules/images}/images/jakartaeett_dt_038.png (100%) rename src/main/{asciidoc => antora/modules/images}/images/jakartaeett_dt_039.png (100%) rename src/main/{asciidoc => antora/modules/images}/images/jakartaeett_dt_040.png (100%) rename src/main/{asciidoc => antora/modules/images}/images/jakartaeett_dt_041.png (100%) rename src/main/{asciidoc => antora/modules/images}/images/jakartaeett_dt_042.png (100%) rename src/main/{asciidoc => antora/modules/images}/images/jakartaeett_dt_043.png (100%) rename src/main/{asciidoc => antora/modules/images}/images/jakartaeett_dt_044.png (100%) rename src/main/{asciidoc => antora/modules/images}/images/jakartaeett_dt_045.png (100%) rename src/main/{asciidoc => antora/modules/images}/images/jakartaeett_dt_046.png (100%) rename src/main/{asciidoc => antora/modules/images}/images/jakartaeett_dt_047.png (100%) rename src/main/{asciidoc => antora/modules/images}/images/jakartaeett_dt_048.png (100%) rename src/main/{asciidoc => antora/modules/images}/images/jakartaeett_dt_049.png (100%) rename src/main/{asciidoc => antora/modules/images}/images/jakartaeett_dt_050.png (100%) rename src/main/{asciidoc => antora/modules/images}/images/jakartaeett_dt_051.png (100%) rename src/main/{asciidoc => antora/modules/images}/images/jakartaeett_dt_052.png (100%) rename src/main/{asciidoc => antora/modules/images}/images/jakartaeett_dt_053.png (100%) rename src/main/{asciidoc => antora/modules/images}/images/jakartaeett_dt_054.png (100%) rename src/main/{asciidoc => antora/modules/images}/images/jakartaeett_dt_055.png (100%) rename src/main/{asciidoc => antora/modules/images}/images/jakartaeett_dt_056.png (100%) rename src/main/{asciidoc => antora/modules/images}/images/jakartaeett_dt_057.png (100%) rename src/main/{asciidoc => antora/modules/images}/images/jakartaeett_dt_058.png (100%) rename src/main/{asciidoc => antora/modules/images}/images/jakartaeett_dt_059.png (100%) rename src/main/{asciidoc => antora/modules/images}/images/jakartaeett_dt_060.png (100%) rename src/main/{asciidoc => antora/modules/images}/images/jakartaeett_dt_061.png (100%) rename src/main/{asciidoc => antora/modules/images}/images/jakartaeett_dt_062.png (100%) rename src/main/{asciidoc => antora/modules/images}/images/jakartaeett_dt_063.png (100%) rename src/main/{asciidoc => antora/modules/images}/images/jakartaeett_dt_064.png (100%) rename src/main/{asciidoc => antora/modules/images}/images/jakartaeett_dt_065_frmcmpnt.png (100%) rename src/main/{asciidoc => antora/modules/images}/images/jakartaeett_dt_066_slctmny.png (100%) rename src/main/{asciidoc => antora/modules/images}/images/jakartaeett_dt_067_slctn.png (100%) rename src/main/{asciidoc => antora/modules/images}/images/jakartaeett_dt_068_txtcmpnts.png (100%) diff --git a/src/main/asciidoc/images/eclipse_foundation_logo_tiny.png b/src/main/antora/modules/images/images/eclipse_foundation_logo_tiny.png similarity index 100% rename from src/main/asciidoc/images/eclipse_foundation_logo_tiny.png rename to src/main/antora/modules/images/images/eclipse_foundation_logo_tiny.png diff --git a/src/main/asciidoc/images/jakartaeett_dt_001.png b/src/main/antora/modules/images/images/jakartaeett_dt_001.png similarity index 100% rename from src/main/asciidoc/images/jakartaeett_dt_001.png rename to src/main/antora/modules/images/images/jakartaeett_dt_001.png diff --git a/src/main/asciidoc/images/jakartaeett_dt_002.png b/src/main/antora/modules/images/images/jakartaeett_dt_002.png similarity index 100% rename from src/main/asciidoc/images/jakartaeett_dt_002.png rename to src/main/antora/modules/images/images/jakartaeett_dt_002.png diff --git a/src/main/asciidoc/images/jakartaeett_dt_003.png b/src/main/antora/modules/images/images/jakartaeett_dt_003.png similarity index 100% rename from src/main/asciidoc/images/jakartaeett_dt_003.png rename to src/main/antora/modules/images/images/jakartaeett_dt_003.png diff --git a/src/main/asciidoc/images/jakartaeett_dt_004.png b/src/main/antora/modules/images/images/jakartaeett_dt_004.png similarity index 100% rename from src/main/asciidoc/images/jakartaeett_dt_004.png rename to src/main/antora/modules/images/images/jakartaeett_dt_004.png diff --git a/src/main/asciidoc/images/jakartaeett_dt_005.png b/src/main/antora/modules/images/images/jakartaeett_dt_005.png similarity index 100% rename from src/main/asciidoc/images/jakartaeett_dt_005.png rename to src/main/antora/modules/images/images/jakartaeett_dt_005.png diff --git a/src/main/asciidoc/images/jakartaeett_dt_006.png b/src/main/antora/modules/images/images/jakartaeett_dt_006.png similarity index 100% rename from src/main/asciidoc/images/jakartaeett_dt_006.png rename to src/main/antora/modules/images/images/jakartaeett_dt_006.png diff --git a/src/main/asciidoc/images/jakartaeett_dt_007.png b/src/main/antora/modules/images/images/jakartaeett_dt_007.png similarity index 100% rename from src/main/asciidoc/images/jakartaeett_dt_007.png rename to src/main/antora/modules/images/images/jakartaeett_dt_007.png diff --git a/src/main/asciidoc/images/jakartaeett_dt_008.png b/src/main/antora/modules/images/images/jakartaeett_dt_008.png similarity index 100% rename from src/main/asciidoc/images/jakartaeett_dt_008.png rename to src/main/antora/modules/images/images/jakartaeett_dt_008.png diff --git a/src/main/asciidoc/images/jakartaeett_dt_009.png b/src/main/antora/modules/images/images/jakartaeett_dt_009.png similarity index 100% rename from src/main/asciidoc/images/jakartaeett_dt_009.png rename to src/main/antora/modules/images/images/jakartaeett_dt_009.png diff --git a/src/main/asciidoc/images/jakartaeett_dt_010.png b/src/main/antora/modules/images/images/jakartaeett_dt_010.png similarity index 100% rename from src/main/asciidoc/images/jakartaeett_dt_010.png rename to src/main/antora/modules/images/images/jakartaeett_dt_010.png diff --git a/src/main/asciidoc/images/jakartaeett_dt_011.png b/src/main/antora/modules/images/images/jakartaeett_dt_011.png similarity index 100% rename from src/main/asciidoc/images/jakartaeett_dt_011.png rename to src/main/antora/modules/images/images/jakartaeett_dt_011.png diff --git a/src/main/asciidoc/images/jakartaeett_dt_012.png b/src/main/antora/modules/images/images/jakartaeett_dt_012.png similarity index 100% rename from src/main/asciidoc/images/jakartaeett_dt_012.png rename to src/main/antora/modules/images/images/jakartaeett_dt_012.png diff --git a/src/main/asciidoc/images/jakartaeett_dt_013.png b/src/main/antora/modules/images/images/jakartaeett_dt_013.png similarity index 100% rename from src/main/asciidoc/images/jakartaeett_dt_013.png rename to src/main/antora/modules/images/images/jakartaeett_dt_013.png diff --git a/src/main/asciidoc/images/jakartaeett_dt_014.png b/src/main/antora/modules/images/images/jakartaeett_dt_014.png similarity index 100% rename from src/main/asciidoc/images/jakartaeett_dt_014.png rename to src/main/antora/modules/images/images/jakartaeett_dt_014.png diff --git a/src/main/asciidoc/images/jakartaeett_dt_015.png b/src/main/antora/modules/images/images/jakartaeett_dt_015.png similarity index 100% rename from src/main/asciidoc/images/jakartaeett_dt_015.png rename to src/main/antora/modules/images/images/jakartaeett_dt_015.png diff --git a/src/main/asciidoc/images/jakartaeett_dt_016.png b/src/main/antora/modules/images/images/jakartaeett_dt_016.png similarity index 100% rename from src/main/asciidoc/images/jakartaeett_dt_016.png rename to src/main/antora/modules/images/images/jakartaeett_dt_016.png diff --git a/src/main/asciidoc/images/jakartaeett_dt_017.png b/src/main/antora/modules/images/images/jakartaeett_dt_017.png similarity index 100% rename from src/main/asciidoc/images/jakartaeett_dt_017.png rename to src/main/antora/modules/images/images/jakartaeett_dt_017.png diff --git a/src/main/asciidoc/images/jakartaeett_dt_018.png b/src/main/antora/modules/images/images/jakartaeett_dt_018.png similarity index 100% rename from src/main/asciidoc/images/jakartaeett_dt_018.png rename to src/main/antora/modules/images/images/jakartaeett_dt_018.png diff --git a/src/main/asciidoc/images/jakartaeett_dt_019.png b/src/main/antora/modules/images/images/jakartaeett_dt_019.png similarity index 100% rename from src/main/asciidoc/images/jakartaeett_dt_019.png rename to src/main/antora/modules/images/images/jakartaeett_dt_019.png diff --git a/src/main/asciidoc/images/jakartaeett_dt_020.png b/src/main/antora/modules/images/images/jakartaeett_dt_020.png similarity index 100% rename from src/main/asciidoc/images/jakartaeett_dt_020.png rename to src/main/antora/modules/images/images/jakartaeett_dt_020.png diff --git a/src/main/asciidoc/images/jakartaeett_dt_021.png b/src/main/antora/modules/images/images/jakartaeett_dt_021.png similarity index 100% rename from src/main/asciidoc/images/jakartaeett_dt_021.png rename to src/main/antora/modules/images/images/jakartaeett_dt_021.png diff --git a/src/main/asciidoc/images/jakartaeett_dt_022.png b/src/main/antora/modules/images/images/jakartaeett_dt_022.png similarity index 100% rename from src/main/asciidoc/images/jakartaeett_dt_022.png rename to src/main/antora/modules/images/images/jakartaeett_dt_022.png diff --git a/src/main/asciidoc/images/jakartaeett_dt_023.png b/src/main/antora/modules/images/images/jakartaeett_dt_023.png similarity index 100% rename from src/main/asciidoc/images/jakartaeett_dt_023.png rename to src/main/antora/modules/images/images/jakartaeett_dt_023.png diff --git a/src/main/asciidoc/images/jakartaeett_dt_024.png b/src/main/antora/modules/images/images/jakartaeett_dt_024.png similarity index 100% rename from src/main/asciidoc/images/jakartaeett_dt_024.png rename to src/main/antora/modules/images/images/jakartaeett_dt_024.png diff --git a/src/main/asciidoc/images/jakartaeett_dt_025.png b/src/main/antora/modules/images/images/jakartaeett_dt_025.png similarity index 100% rename from src/main/asciidoc/images/jakartaeett_dt_025.png rename to src/main/antora/modules/images/images/jakartaeett_dt_025.png diff --git a/src/main/asciidoc/images/jakartaeett_dt_026.png b/src/main/antora/modules/images/images/jakartaeett_dt_026.png similarity index 100% rename from src/main/asciidoc/images/jakartaeett_dt_026.png rename to src/main/antora/modules/images/images/jakartaeett_dt_026.png diff --git a/src/main/asciidoc/images/jakartaeett_dt_027.png b/src/main/antora/modules/images/images/jakartaeett_dt_027.png similarity index 100% rename from src/main/asciidoc/images/jakartaeett_dt_027.png rename to src/main/antora/modules/images/images/jakartaeett_dt_027.png diff --git a/src/main/asciidoc/images/jakartaeett_dt_028.png b/src/main/antora/modules/images/images/jakartaeett_dt_028.png similarity index 100% rename from src/main/asciidoc/images/jakartaeett_dt_028.png rename to src/main/antora/modules/images/images/jakartaeett_dt_028.png diff --git a/src/main/asciidoc/images/jakartaeett_dt_029.png b/src/main/antora/modules/images/images/jakartaeett_dt_029.png similarity index 100% rename from src/main/asciidoc/images/jakartaeett_dt_029.png rename to src/main/antora/modules/images/images/jakartaeett_dt_029.png diff --git a/src/main/asciidoc/images/jakartaeett_dt_030.png b/src/main/antora/modules/images/images/jakartaeett_dt_030.png similarity index 100% rename from src/main/asciidoc/images/jakartaeett_dt_030.png rename to src/main/antora/modules/images/images/jakartaeett_dt_030.png diff --git a/src/main/asciidoc/images/jakartaeett_dt_031.png b/src/main/antora/modules/images/images/jakartaeett_dt_031.png similarity index 100% rename from src/main/asciidoc/images/jakartaeett_dt_031.png rename to src/main/antora/modules/images/images/jakartaeett_dt_031.png diff --git a/src/main/asciidoc/images/jakartaeett_dt_032.png b/src/main/antora/modules/images/images/jakartaeett_dt_032.png similarity index 100% rename from src/main/asciidoc/images/jakartaeett_dt_032.png rename to src/main/antora/modules/images/images/jakartaeett_dt_032.png diff --git a/src/main/asciidoc/images/jakartaeett_dt_033.png b/src/main/antora/modules/images/images/jakartaeett_dt_033.png similarity index 100% rename from src/main/asciidoc/images/jakartaeett_dt_033.png rename to src/main/antora/modules/images/images/jakartaeett_dt_033.png diff --git a/src/main/asciidoc/images/jakartaeett_dt_034.png b/src/main/antora/modules/images/images/jakartaeett_dt_034.png similarity index 100% rename from src/main/asciidoc/images/jakartaeett_dt_034.png rename to src/main/antora/modules/images/images/jakartaeett_dt_034.png diff --git a/src/main/asciidoc/images/jakartaeett_dt_035.png b/src/main/antora/modules/images/images/jakartaeett_dt_035.png similarity index 100% rename from src/main/asciidoc/images/jakartaeett_dt_035.png rename to src/main/antora/modules/images/images/jakartaeett_dt_035.png diff --git a/src/main/asciidoc/images/jakartaeett_dt_036.png b/src/main/antora/modules/images/images/jakartaeett_dt_036.png similarity index 100% rename from src/main/asciidoc/images/jakartaeett_dt_036.png rename to src/main/antora/modules/images/images/jakartaeett_dt_036.png diff --git a/src/main/asciidoc/images/jakartaeett_dt_037.png b/src/main/antora/modules/images/images/jakartaeett_dt_037.png similarity index 100% rename from src/main/asciidoc/images/jakartaeett_dt_037.png rename to src/main/antora/modules/images/images/jakartaeett_dt_037.png diff --git a/src/main/asciidoc/images/jakartaeett_dt_038.png b/src/main/antora/modules/images/images/jakartaeett_dt_038.png similarity index 100% rename from src/main/asciidoc/images/jakartaeett_dt_038.png rename to src/main/antora/modules/images/images/jakartaeett_dt_038.png diff --git a/src/main/asciidoc/images/jakartaeett_dt_039.png b/src/main/antora/modules/images/images/jakartaeett_dt_039.png similarity index 100% rename from src/main/asciidoc/images/jakartaeett_dt_039.png rename to src/main/antora/modules/images/images/jakartaeett_dt_039.png diff --git a/src/main/asciidoc/images/jakartaeett_dt_040.png b/src/main/antora/modules/images/images/jakartaeett_dt_040.png similarity index 100% rename from src/main/asciidoc/images/jakartaeett_dt_040.png rename to src/main/antora/modules/images/images/jakartaeett_dt_040.png diff --git a/src/main/asciidoc/images/jakartaeett_dt_041.png b/src/main/antora/modules/images/images/jakartaeett_dt_041.png similarity index 100% rename from src/main/asciidoc/images/jakartaeett_dt_041.png rename to src/main/antora/modules/images/images/jakartaeett_dt_041.png diff --git a/src/main/asciidoc/images/jakartaeett_dt_042.png b/src/main/antora/modules/images/images/jakartaeett_dt_042.png similarity index 100% rename from src/main/asciidoc/images/jakartaeett_dt_042.png rename to src/main/antora/modules/images/images/jakartaeett_dt_042.png diff --git a/src/main/asciidoc/images/jakartaeett_dt_043.png b/src/main/antora/modules/images/images/jakartaeett_dt_043.png similarity index 100% rename from src/main/asciidoc/images/jakartaeett_dt_043.png rename to src/main/antora/modules/images/images/jakartaeett_dt_043.png diff --git a/src/main/asciidoc/images/jakartaeett_dt_044.png b/src/main/antora/modules/images/images/jakartaeett_dt_044.png similarity index 100% rename from src/main/asciidoc/images/jakartaeett_dt_044.png rename to src/main/antora/modules/images/images/jakartaeett_dt_044.png diff --git a/src/main/asciidoc/images/jakartaeett_dt_045.png b/src/main/antora/modules/images/images/jakartaeett_dt_045.png similarity index 100% rename from src/main/asciidoc/images/jakartaeett_dt_045.png rename to src/main/antora/modules/images/images/jakartaeett_dt_045.png diff --git a/src/main/asciidoc/images/jakartaeett_dt_046.png b/src/main/antora/modules/images/images/jakartaeett_dt_046.png similarity index 100% rename from src/main/asciidoc/images/jakartaeett_dt_046.png rename to src/main/antora/modules/images/images/jakartaeett_dt_046.png diff --git a/src/main/asciidoc/images/jakartaeett_dt_047.png b/src/main/antora/modules/images/images/jakartaeett_dt_047.png similarity index 100% rename from src/main/asciidoc/images/jakartaeett_dt_047.png rename to src/main/antora/modules/images/images/jakartaeett_dt_047.png diff --git a/src/main/asciidoc/images/jakartaeett_dt_048.png b/src/main/antora/modules/images/images/jakartaeett_dt_048.png similarity index 100% rename from src/main/asciidoc/images/jakartaeett_dt_048.png rename to src/main/antora/modules/images/images/jakartaeett_dt_048.png diff --git a/src/main/asciidoc/images/jakartaeett_dt_049.png b/src/main/antora/modules/images/images/jakartaeett_dt_049.png similarity index 100% rename from src/main/asciidoc/images/jakartaeett_dt_049.png rename to src/main/antora/modules/images/images/jakartaeett_dt_049.png diff --git a/src/main/asciidoc/images/jakartaeett_dt_050.png b/src/main/antora/modules/images/images/jakartaeett_dt_050.png similarity index 100% rename from src/main/asciidoc/images/jakartaeett_dt_050.png rename to src/main/antora/modules/images/images/jakartaeett_dt_050.png diff --git a/src/main/asciidoc/images/jakartaeett_dt_051.png b/src/main/antora/modules/images/images/jakartaeett_dt_051.png similarity index 100% rename from src/main/asciidoc/images/jakartaeett_dt_051.png rename to src/main/antora/modules/images/images/jakartaeett_dt_051.png diff --git a/src/main/asciidoc/images/jakartaeett_dt_052.png b/src/main/antora/modules/images/images/jakartaeett_dt_052.png similarity index 100% rename from src/main/asciidoc/images/jakartaeett_dt_052.png rename to src/main/antora/modules/images/images/jakartaeett_dt_052.png diff --git a/src/main/asciidoc/images/jakartaeett_dt_053.png b/src/main/antora/modules/images/images/jakartaeett_dt_053.png similarity index 100% rename from src/main/asciidoc/images/jakartaeett_dt_053.png rename to src/main/antora/modules/images/images/jakartaeett_dt_053.png diff --git a/src/main/asciidoc/images/jakartaeett_dt_054.png b/src/main/antora/modules/images/images/jakartaeett_dt_054.png similarity index 100% rename from src/main/asciidoc/images/jakartaeett_dt_054.png rename to src/main/antora/modules/images/images/jakartaeett_dt_054.png diff --git a/src/main/asciidoc/images/jakartaeett_dt_055.png b/src/main/antora/modules/images/images/jakartaeett_dt_055.png similarity index 100% rename from src/main/asciidoc/images/jakartaeett_dt_055.png rename to src/main/antora/modules/images/images/jakartaeett_dt_055.png diff --git a/src/main/asciidoc/images/jakartaeett_dt_056.png b/src/main/antora/modules/images/images/jakartaeett_dt_056.png similarity index 100% rename from src/main/asciidoc/images/jakartaeett_dt_056.png rename to src/main/antora/modules/images/images/jakartaeett_dt_056.png diff --git a/src/main/asciidoc/images/jakartaeett_dt_057.png b/src/main/antora/modules/images/images/jakartaeett_dt_057.png similarity index 100% rename from src/main/asciidoc/images/jakartaeett_dt_057.png rename to src/main/antora/modules/images/images/jakartaeett_dt_057.png diff --git a/src/main/asciidoc/images/jakartaeett_dt_058.png b/src/main/antora/modules/images/images/jakartaeett_dt_058.png similarity index 100% rename from src/main/asciidoc/images/jakartaeett_dt_058.png rename to src/main/antora/modules/images/images/jakartaeett_dt_058.png diff --git a/src/main/asciidoc/images/jakartaeett_dt_059.png b/src/main/antora/modules/images/images/jakartaeett_dt_059.png similarity index 100% rename from src/main/asciidoc/images/jakartaeett_dt_059.png rename to src/main/antora/modules/images/images/jakartaeett_dt_059.png diff --git a/src/main/asciidoc/images/jakartaeett_dt_060.png b/src/main/antora/modules/images/images/jakartaeett_dt_060.png similarity index 100% rename from src/main/asciidoc/images/jakartaeett_dt_060.png rename to src/main/antora/modules/images/images/jakartaeett_dt_060.png diff --git a/src/main/asciidoc/images/jakartaeett_dt_061.png b/src/main/antora/modules/images/images/jakartaeett_dt_061.png similarity index 100% rename from src/main/asciidoc/images/jakartaeett_dt_061.png rename to src/main/antora/modules/images/images/jakartaeett_dt_061.png diff --git a/src/main/asciidoc/images/jakartaeett_dt_062.png b/src/main/antora/modules/images/images/jakartaeett_dt_062.png similarity index 100% rename from src/main/asciidoc/images/jakartaeett_dt_062.png rename to src/main/antora/modules/images/images/jakartaeett_dt_062.png diff --git a/src/main/asciidoc/images/jakartaeett_dt_063.png b/src/main/antora/modules/images/images/jakartaeett_dt_063.png similarity index 100% rename from src/main/asciidoc/images/jakartaeett_dt_063.png rename to src/main/antora/modules/images/images/jakartaeett_dt_063.png diff --git a/src/main/asciidoc/images/jakartaeett_dt_064.png b/src/main/antora/modules/images/images/jakartaeett_dt_064.png similarity index 100% rename from src/main/asciidoc/images/jakartaeett_dt_064.png rename to src/main/antora/modules/images/images/jakartaeett_dt_064.png diff --git a/src/main/asciidoc/images/jakartaeett_dt_065_frmcmpnt.png b/src/main/antora/modules/images/images/jakartaeett_dt_065_frmcmpnt.png similarity index 100% rename from src/main/asciidoc/images/jakartaeett_dt_065_frmcmpnt.png rename to src/main/antora/modules/images/images/jakartaeett_dt_065_frmcmpnt.png diff --git a/src/main/asciidoc/images/jakartaeett_dt_066_slctmny.png b/src/main/antora/modules/images/images/jakartaeett_dt_066_slctmny.png similarity index 100% rename from src/main/asciidoc/images/jakartaeett_dt_066_slctmny.png rename to src/main/antora/modules/images/images/jakartaeett_dt_066_slctmny.png diff --git a/src/main/asciidoc/images/jakartaeett_dt_067_slctn.png b/src/main/antora/modules/images/images/jakartaeett_dt_067_slctn.png similarity index 100% rename from src/main/asciidoc/images/jakartaeett_dt_067_slctn.png rename to src/main/antora/modules/images/images/jakartaeett_dt_067_slctn.png diff --git a/src/main/asciidoc/images/jakartaeett_dt_068_txtcmpnts.png b/src/main/antora/modules/images/images/jakartaeett_dt_068_txtcmpnts.png similarity index 100% rename from src/main/asciidoc/images/jakartaeett_dt_068_txtcmpnts.png rename to src/main/antora/modules/images/images/jakartaeett_dt_068_txtcmpnts.png From 0ac7b598c6a82a5c4a05eb6ec0e9adc80a929c26 Mon Sep 17 00:00:00 2001 From: "Kito D. Mann" Date: Tue, 16 May 2023 23:03:37 -0400 Subject: [PATCH 011/247] JETUT-56 Fixed image references --- AntoraConverter.java | 12 ++++++++++++ CONVERTING_TO_ANTORA.adoc | 9 ++++++++- .../security-advanced/security-advanced002.adoc | 4 ++-- .../pages/security-intro/security-intro001.adoc | 10 +++++----- .../pages/security-intro/security-intro005.adoc | 2 +- .../security-jakartaee/security-jakartaee002.adoc | 2 +- .../pages/security-webtier/security-webtier002.adoc | 4 ++-- 7 files changed, 31 insertions(+), 12 deletions(-) diff --git a/AntoraConverter.java b/AntoraConverter.java index 44a8cb6f..39919b73 100755 --- a/AntoraConverter.java +++ b/AntoraConverter.java @@ -65,6 +65,18 @@ public static void main(String... args) throws Exception { Files.write(file.toPath(), modifiedContent.getBytes()); changeCount++; } + if (content.contains("image:")) { + System.out.println("=> Updating block image references"); + String modifiedContent = content.replace("image::", "image::images:"); + Files.write(file.toPath(), modifiedContent.getBytes()); + changeCount++; + } + if (content.contains("image:")) { + System.out.println("=> Updating inline image references"); + String modifiedContent = content.replace("image:", "image:images:"); + Files.write(file.toPath(), modifiedContent.getBytes()); + changeCount++; + } if (changeCount == 0) { System.out.println("=> (no changes necessary)"); } else { diff --git a/CONVERTING_TO_ANTORA.adoc b/CONVERTING_TO_ANTORA.adoc index d7d12360..ede36247 100644 --- a/CONVERTING_TO_ANTORA.adoc +++ b/CONVERTING_TO_ANTORA.adoc @@ -15,6 +15,9 @@ Here’s the current process for migrating an individual module (i.e. security, 3. Create a new folder in the `src/main/antora/modules` folder with the name of the module you are migrating. For example, for the Security module, you would create a `security` folder. * Inside of this folder, create a `pages` folder. 4. Move all the folders for the module you are migrating into the new `pages` folder. For example, for the Security module, you would move all of the `src/main/asciidoc/security-*` folders into the `src/main/antora/modules/security/pages`. (Copy the entire folders, not just the `.adoc` files). + +> NOTE: It's essential that you _move_ rather than copy the folders so that we keep the history intact. + 5. Run the migration script from the root project folder. For example, for the Security module, you would run `jbang AntoraConverter.java security`. (The first parameter is the folder relative to `src/main/antora/modules`). 6. Create a new file called `nav.adoc` in the root of the module folder. For example, for the Security module, you would create a `security/nav.adoc`. 7. Copy all the include statements from the corresponding "part" file in the `src/main/asciidoc/` folder. For example, for the Security module, you would copy the include statements of `src/main/asciidoc/partsecurity.adoc` into the `security/nav.adoc` file. Here are the include statements for the Security module: @@ -46,6 +49,10 @@ After copying these into `nav.adoc`, replace "include::" with "* xref:" and add * xref:security-advanced/security-advanced.adoc[] ``` +8. Add this module to the `src/main/antora/antora.yml`. For example, for the Security module, you would add this line to the end of `src/main/antora/antora.yml` file: + +```yaml + - modules/security/nav.adoc +``` -> NOTE: It's essential that you _move_ rather than copy the folders so that we keep the history intact. diff --git a/src/main/antora/modules/security/pages/security-advanced/security-advanced002.adoc b/src/main/antora/modules/security/pages/security-advanced/security-advanced002.adoc index 0b29ecd3..747f8d44 100644 --- a/src/main/antora/modules/security/pages/security-advanced/security-advanced002.adoc +++ b/src/main/antora/modules/security/pages/security-advanced/security-advanced002.adoc @@ -68,7 +68,7 @@ mutual authentication. [[GLIFJ]] .*Figure 53-1 Certificate-Based Mutual Authentication* -image:jakartaeett_dt_048.png[ +image:images:jakartaeett_dt_048.png[ "Diagram of six steps in mutual authentication with certificates"] In user name/password-based mutual authentication, the following actions @@ -89,7 +89,7 @@ name/password-based mutual authentication. [[GLIGQ]] .*Figure 53-2 User Name/Password-Based Mutual Authentication* -image:jakartaeett_dt_049.png[ +image:images:jakartaeett_dt_049.png[ "Diagram of five steps in mutual authentication with user name and password"] diff --git a/src/main/antora/modules/security/pages/security-intro/security-intro001.adoc b/src/main/antora/modules/security/pages/security-intro/security-intro001.adoc index 02572a3c..51953e72 100644 --- a/src/main/antora/modules/security/pages/security-intro/security-intro001.adoc +++ b/src/main/antora/modules/security/pages/security-intro/security-intro001.adoc @@ -84,7 +84,7 @@ application URL. This action is shown in link:#BNBWN[Figure 50-1]. [[BNBWN]] .*Figure 50-1 Initial Request* -image:jakartaeett_dt_039.png[ +image:images:jakartaeett_dt_039.png[ "Diagram of initial request from web client to web server for access to a protected resource"] @@ -110,7 +110,7 @@ server sets a credential for the user. [[BNBWP]] .*Figure 50-2 Initial Authentication* -image:jakartaeett_dt_040.png[ +image:images:jakartaeett_dt_040.png[ "Diagram of initial authentication: server sends form to client, which sends authentication data to server for validation"] @@ -130,7 +130,7 @@ link:#BNBWR[Figure 50-3] shows this process. [[BNBWR]] .*Figure 50-3 URL Authorization* -image:jakartaeett_dt_041.png[ +image:images:jakartaeett_dt_041.png[ "Diagram of URL authorization"] The web server's evaluation stops with an "is authorized" outcome when @@ -148,7 +148,7 @@ original URL request, as shown in link:#BNBWT[Figure 50-4]. [[BNBWT]] .*Figure 50-4 Fulfilling the Original Request* -image:jakartaeett_dt_042.png[ +image:images:jakartaeett_dt_042.png[ "Diagram of request fulfillment, showing server returning result to client"] @@ -171,7 +171,7 @@ one in the web server and one in the enterprise bean container. [[BNBWV]] .*Figure 50-5 Invoking an Enterprise Bean Business Method* -image:jakartaeett_dt_043.png[ +image:images:jakartaeett_dt_043.png[ "Diagram of authorization process between web component and enterprise bean"] diff --git a/src/main/antora/modules/security/pages/security-intro/security-intro005.adoc b/src/main/antora/modules/security/pages/security-intro/security-intro005.adoc index 06e88096..0838d99f 100644 --- a/src/main/antora/modules/security/pages/security-intro/security-intro005.adoc +++ b/src/main/antora/modules/security/pages/security-intro/security-intro005.adoc @@ -64,7 +64,7 @@ Roles]. [[BNBXL]] .*Figure 50-6 Mapping Roles to Users and Groups* -image:jakartaeett_dt_044.png[ +image:images:jakartaeett_dt_044.png[ "Diagram of role mapping, showing creation of users and groups, definition of roles, and mapping of roles to users and groups"] diff --git a/src/main/antora/modules/security/pages/security-jakartaee/security-jakartaee002.adoc b/src/main/antora/modules/security/pages/security-jakartaee/security-jakartaee002.adoc index ac17a59f..07033453 100644 --- a/src/main/antora/modules/security/pages/security-jakartaee/security-jakartaee002.adoc +++ b/src/main/antora/modules/security/pages/security-jakartaee/security-jakartaee002.adoc @@ -500,7 +500,7 @@ illustrates this concept. [[BNBZA]] .*Figure 52-1 Security Identity Propagation* -image:jakartaeett_dt_047.png[ +image:images:jakartaeett_dt_047.png[ "Diagram of security identity propagation from client to intermediate container to target container"] diff --git a/src/main/antora/modules/security/pages/security-webtier/security-webtier002.adoc b/src/main/antora/modules/security/pages/security-webtier/security-webtier002.adoc index ac8fe116..9f4a9435 100644 --- a/src/main/antora/modules/security/pages/security-webtier/security-webtier002.adoc +++ b/src/main/antora/modules/security/pages/security-webtier/security-webtier002.adoc @@ -343,7 +343,7 @@ authentication. [[BNCBP]] .*Figure 51-1 HTTP Basic Authentication* -image:jakartaeett_dt_045.png[ +image:images:jakartaeett_dt_045.png[ "Diagram of four steps in HTTP basic authentication between client and server"] @@ -375,7 +375,7 @@ authentication. [[GEXFA]] .*Figure 51-2 Form-Based Authentication* -image:jakartaeett_dt_046.png[ +image:images:jakartaeett_dt_046.png[ "Diagram of four steps in form-based authentication between client and server"] From c59f92a89a3bb8da4ced3d6d88f3b8ae592eec79 Mon Sep 17 00:00:00 2001 From: "Kito D. Mann" Date: Wed, 17 May 2023 08:08:23 -0400 Subject: [PATCH 012/247] JETUT-56 Minor correction to script for images --- AntoraConverter.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AntoraConverter.java b/AntoraConverter.java index 39919b73..6d0db043 100755 --- a/AntoraConverter.java +++ b/AntoraConverter.java @@ -65,7 +65,7 @@ public static void main(String... args) throws Exception { Files.write(file.toPath(), modifiedContent.getBytes()); changeCount++; } - if (content.contains("image:")) { + if (content.contains("image::")) { System.out.println("=> Updating block image references"); String modifiedContent = content.replace("image::", "image::images:"); Files.write(file.toPath(), modifiedContent.getBytes()); From 4267149faa09092b4804aae037aea9c3f156e2f8 Mon Sep 17 00:00:00 2001 From: "Kito D. Mann" Date: Wed, 17 May 2023 11:22:08 -0400 Subject: [PATCH 013/247] JETUT-56 Renamed "images" module to "common"; fixed images and captions --- AntoraConverter.java | 20 +++++++++--------- src/main/antora/antora.yml | 1 + .../images/eclipse_foundation_logo_tiny.png | Bin .../images/jakartaeett_dt_001.png | Bin .../images/jakartaeett_dt_002.png | Bin .../images/jakartaeett_dt_003.png | Bin .../images/jakartaeett_dt_004.png | Bin .../images/jakartaeett_dt_005.png | Bin .../images/jakartaeett_dt_006.png | Bin .../images/jakartaeett_dt_007.png | Bin .../images/jakartaeett_dt_008.png | Bin .../images/jakartaeett_dt_009.png | Bin .../images/jakartaeett_dt_010.png | Bin .../images/jakartaeett_dt_011.png | Bin .../images/jakartaeett_dt_012.png | Bin .../images/jakartaeett_dt_013.png | Bin .../images/jakartaeett_dt_014.png | Bin .../images/jakartaeett_dt_015.png | Bin .../images/jakartaeett_dt_016.png | Bin .../images/jakartaeett_dt_017.png | Bin .../images/jakartaeett_dt_018.png | Bin .../images/jakartaeett_dt_019.png | Bin .../images/jakartaeett_dt_020.png | Bin .../images/jakartaeett_dt_021.png | Bin .../images/jakartaeett_dt_022.png | Bin .../images/jakartaeett_dt_023.png | Bin .../images/jakartaeett_dt_024.png | Bin .../images/jakartaeett_dt_025.png | Bin .../images/jakartaeett_dt_026.png | Bin .../images/jakartaeett_dt_027.png | Bin .../images/jakartaeett_dt_028.png | Bin .../images/jakartaeett_dt_029.png | Bin .../images/jakartaeett_dt_030.png | Bin .../images/jakartaeett_dt_031.png | Bin .../images/jakartaeett_dt_032.png | Bin .../images/jakartaeett_dt_033.png | Bin .../images/jakartaeett_dt_034.png | Bin .../images/jakartaeett_dt_035.png | Bin .../images/jakartaeett_dt_036.png | Bin .../images/jakartaeett_dt_037.png | Bin .../images/jakartaeett_dt_038.png | Bin .../images/jakartaeett_dt_039.png | Bin .../images/jakartaeett_dt_040.png | Bin .../images/jakartaeett_dt_041.png | Bin .../images/jakartaeett_dt_042.png | Bin .../images/jakartaeett_dt_043.png | Bin .../images/jakartaeett_dt_044.png | Bin .../images/jakartaeett_dt_045.png | Bin .../images/jakartaeett_dt_046.png | Bin .../images/jakartaeett_dt_047.png | Bin .../images/jakartaeett_dt_048.png | Bin .../images/jakartaeett_dt_049.png | Bin .../images/jakartaeett_dt_050.png | Bin .../images/jakartaeett_dt_051.png | Bin .../images/jakartaeett_dt_052.png | Bin .../images/jakartaeett_dt_053.png | Bin .../images/jakartaeett_dt_054.png | Bin .../images/jakartaeett_dt_055.png | Bin .../images/jakartaeett_dt_056.png | Bin .../images/jakartaeett_dt_057.png | Bin .../images/jakartaeett_dt_058.png | Bin .../images/jakartaeett_dt_059.png | Bin .../images/jakartaeett_dt_060.png | Bin .../images/jakartaeett_dt_061.png | Bin .../images/jakartaeett_dt_062.png | Bin .../images/jakartaeett_dt_063.png | Bin .../images/jakartaeett_dt_064.png | Bin .../images/jakartaeett_dt_065_frmcmpnt.png | Bin .../images/jakartaeett_dt_066_slctmny.png | Bin .../images/jakartaeett_dt_067_slctn.png | Bin .../images/jakartaeett_dt_068_txtcmpnts.png | Bin .../security-advanced002.adoc | 7 ++---- .../security-intro/security-intro001.adoc | 19 +++++------------ .../security-intro/security-intro005.adoc | 4 +--- .../security-jakartaee002.adoc | 4 +--- .../security-webtier/security-webtier002.adoc | 8 ++----- 76 files changed, 22 insertions(+), 41 deletions(-) rename src/main/antora/modules/{images => common}/images/eclipse_foundation_logo_tiny.png (100%) rename src/main/antora/modules/{images => common}/images/jakartaeett_dt_001.png (100%) rename src/main/antora/modules/{images => common}/images/jakartaeett_dt_002.png (100%) rename src/main/antora/modules/{images => common}/images/jakartaeett_dt_003.png (100%) rename src/main/antora/modules/{images => common}/images/jakartaeett_dt_004.png (100%) rename src/main/antora/modules/{images => common}/images/jakartaeett_dt_005.png (100%) rename src/main/antora/modules/{images => common}/images/jakartaeett_dt_006.png (100%) rename src/main/antora/modules/{images => common}/images/jakartaeett_dt_007.png (100%) rename src/main/antora/modules/{images => common}/images/jakartaeett_dt_008.png (100%) rename src/main/antora/modules/{images => common}/images/jakartaeett_dt_009.png (100%) rename src/main/antora/modules/{images => common}/images/jakartaeett_dt_010.png (100%) rename src/main/antora/modules/{images => common}/images/jakartaeett_dt_011.png (100%) rename src/main/antora/modules/{images => common}/images/jakartaeett_dt_012.png (100%) rename src/main/antora/modules/{images => common}/images/jakartaeett_dt_013.png (100%) rename src/main/antora/modules/{images => common}/images/jakartaeett_dt_014.png (100%) rename src/main/antora/modules/{images => common}/images/jakartaeett_dt_015.png (100%) rename src/main/antora/modules/{images => common}/images/jakartaeett_dt_016.png (100%) rename src/main/antora/modules/{images => common}/images/jakartaeett_dt_017.png (100%) rename src/main/antora/modules/{images => common}/images/jakartaeett_dt_018.png (100%) rename src/main/antora/modules/{images => common}/images/jakartaeett_dt_019.png (100%) rename src/main/antora/modules/{images => common}/images/jakartaeett_dt_020.png (100%) rename src/main/antora/modules/{images => common}/images/jakartaeett_dt_021.png (100%) rename src/main/antora/modules/{images => common}/images/jakartaeett_dt_022.png (100%) rename src/main/antora/modules/{images => common}/images/jakartaeett_dt_023.png (100%) rename src/main/antora/modules/{images => common}/images/jakartaeett_dt_024.png (100%) rename src/main/antora/modules/{images => common}/images/jakartaeett_dt_025.png (100%) rename src/main/antora/modules/{images => common}/images/jakartaeett_dt_026.png (100%) rename src/main/antora/modules/{images => common}/images/jakartaeett_dt_027.png (100%) rename src/main/antora/modules/{images => common}/images/jakartaeett_dt_028.png (100%) rename src/main/antora/modules/{images => common}/images/jakartaeett_dt_029.png (100%) rename src/main/antora/modules/{images => common}/images/jakartaeett_dt_030.png (100%) rename src/main/antora/modules/{images => common}/images/jakartaeett_dt_031.png (100%) rename src/main/antora/modules/{images => common}/images/jakartaeett_dt_032.png (100%) rename src/main/antora/modules/{images => common}/images/jakartaeett_dt_033.png (100%) rename src/main/antora/modules/{images => common}/images/jakartaeett_dt_034.png (100%) rename src/main/antora/modules/{images => common}/images/jakartaeett_dt_035.png (100%) rename src/main/antora/modules/{images => common}/images/jakartaeett_dt_036.png (100%) rename src/main/antora/modules/{images => common}/images/jakartaeett_dt_037.png (100%) rename src/main/antora/modules/{images => common}/images/jakartaeett_dt_038.png (100%) rename src/main/antora/modules/{images => common}/images/jakartaeett_dt_039.png (100%) rename src/main/antora/modules/{images => common}/images/jakartaeett_dt_040.png (100%) rename src/main/antora/modules/{images => common}/images/jakartaeett_dt_041.png (100%) rename src/main/antora/modules/{images => common}/images/jakartaeett_dt_042.png (100%) rename src/main/antora/modules/{images => common}/images/jakartaeett_dt_043.png (100%) rename src/main/antora/modules/{images => common}/images/jakartaeett_dt_044.png (100%) rename src/main/antora/modules/{images => common}/images/jakartaeett_dt_045.png (100%) rename src/main/antora/modules/{images => common}/images/jakartaeett_dt_046.png (100%) rename src/main/antora/modules/{images => common}/images/jakartaeett_dt_047.png (100%) rename src/main/antora/modules/{images => common}/images/jakartaeett_dt_048.png (100%) rename src/main/antora/modules/{images => common}/images/jakartaeett_dt_049.png (100%) rename src/main/antora/modules/{images => common}/images/jakartaeett_dt_050.png (100%) rename src/main/antora/modules/{images => common}/images/jakartaeett_dt_051.png (100%) rename src/main/antora/modules/{images => common}/images/jakartaeett_dt_052.png (100%) rename src/main/antora/modules/{images => common}/images/jakartaeett_dt_053.png (100%) rename src/main/antora/modules/{images => common}/images/jakartaeett_dt_054.png (100%) rename src/main/antora/modules/{images => common}/images/jakartaeett_dt_055.png (100%) rename src/main/antora/modules/{images => common}/images/jakartaeett_dt_056.png (100%) rename src/main/antora/modules/{images => common}/images/jakartaeett_dt_057.png (100%) rename src/main/antora/modules/{images => common}/images/jakartaeett_dt_058.png (100%) rename src/main/antora/modules/{images => common}/images/jakartaeett_dt_059.png (100%) rename src/main/antora/modules/{images => common}/images/jakartaeett_dt_060.png (100%) rename src/main/antora/modules/{images => common}/images/jakartaeett_dt_061.png (100%) rename src/main/antora/modules/{images => common}/images/jakartaeett_dt_062.png (100%) rename src/main/antora/modules/{images => common}/images/jakartaeett_dt_063.png (100%) rename src/main/antora/modules/{images => common}/images/jakartaeett_dt_064.png (100%) rename src/main/antora/modules/{images => common}/images/jakartaeett_dt_065_frmcmpnt.png (100%) rename src/main/antora/modules/{images => common}/images/jakartaeett_dt_066_slctmny.png (100%) rename src/main/antora/modules/{images => common}/images/jakartaeett_dt_067_slctn.png (100%) rename src/main/antora/modules/{images => common}/images/jakartaeett_dt_068_txtcmpnts.png (100%) diff --git a/AntoraConverter.java b/AntoraConverter.java index 6d0db043..33e1838d 100755 --- a/AntoraConverter.java +++ b/AntoraConverter.java @@ -11,7 +11,7 @@ class AntoraConverter { final static String START_PATH_PREFIX = "src/main/antora/modules/"; - public static String replaceBetween(String str, String start, String end, String prefix, char fromChar, char toChar) { + public static String replaceBetween(String str, String start, String end, String prefix, String fromString, String toString) { StringBuilder result = new StringBuilder(); int index = 0; int startIndex, endIndex; @@ -19,7 +19,7 @@ public static String replaceBetween(String str, String start, String end, String while ((startIndex = str.indexOf(start, index)) != -1 && (endIndex = str.indexOf(end, startIndex + start.length())) != -1) { result.append(str, index, startIndex + start.length()); String substring = str.substring(startIndex + start.length(), endIndex); - String updatedSubstring = substring.replace(fromChar, toChar); + String updatedSubstring = substring.replace(fromString, toString); // don't add the prefix if nothing has changed if (!substring.equals(updatedSubstring)) { result.append(prefix); @@ -55,25 +55,25 @@ public static void main(String... args) throws Exception { if (content.contains(("<<"))) { System.out.println("=> Updating anchor links"); - String modifiedContent = replaceBetween(content, "<<", ">>", "_",'-', '_'); + String modifiedContent = replaceBetween(content, "<<", ">>", "_","-", "_"); Files.write(file.toPath(), modifiedContent.getBytes()); changeCount++; } if (content.contains(("[["))) { System.out.println("=> Updating anchor names"); - String modifiedContent = replaceBetween(content, "[[", "]]", "_", '-', '_'); + String modifiedContent = replaceBetween(content, "[[", "]]", "_", "-", "_"); Files.write(file.toPath(), modifiedContent.getBytes()); changeCount++; } - if (content.contains("image::")) { - System.out.println("=> Updating block image references"); - String modifiedContent = content.replace("image::", "image::images:"); + if (content.contains("image:")) { + System.out.println("=> Converting inline image references to block image references and adding module prefix"); + String modifiedContent = content.replace("image:", "image::common:"); Files.write(file.toPath(), modifiedContent.getBytes()); changeCount++; } - if (content.contains("image:")) { - System.out.println("=> Updating inline image references"); - String modifiedContent = content.replace("image:", "image:images:"); + if (content.contains((".png["))) { + System.out.println("=> Removing newlines from image captions"); + String modifiedContent = replaceBetween(content, ".png[", "]", "", System.getProperty("line.separator"), " "); Files.write(file.toPath(), modifiedContent.getBytes()); changeCount++; } diff --git a/src/main/antora/antora.yml b/src/main/antora/antora.yml index e0e91d26..46eace97 100644 --- a/src/main/antora/antora.yml +++ b/src/main/antora/antora.yml @@ -5,6 +5,7 @@ asciidoc: attributes: source-language: asciidoc@ table-caption: false + figure-caption: false nav: - modules/ROOT/nav.adoc - modules/security/nav.adoc diff --git a/src/main/antora/modules/images/images/eclipse_foundation_logo_tiny.png b/src/main/antora/modules/common/images/eclipse_foundation_logo_tiny.png similarity index 100% rename from src/main/antora/modules/images/images/eclipse_foundation_logo_tiny.png rename to src/main/antora/modules/common/images/eclipse_foundation_logo_tiny.png diff --git a/src/main/antora/modules/images/images/jakartaeett_dt_001.png b/src/main/antora/modules/common/images/jakartaeett_dt_001.png similarity index 100% rename from src/main/antora/modules/images/images/jakartaeett_dt_001.png rename to src/main/antora/modules/common/images/jakartaeett_dt_001.png diff --git a/src/main/antora/modules/images/images/jakartaeett_dt_002.png b/src/main/antora/modules/common/images/jakartaeett_dt_002.png similarity index 100% rename from src/main/antora/modules/images/images/jakartaeett_dt_002.png rename to src/main/antora/modules/common/images/jakartaeett_dt_002.png diff --git a/src/main/antora/modules/images/images/jakartaeett_dt_003.png b/src/main/antora/modules/common/images/jakartaeett_dt_003.png similarity index 100% rename from src/main/antora/modules/images/images/jakartaeett_dt_003.png rename to src/main/antora/modules/common/images/jakartaeett_dt_003.png diff --git a/src/main/antora/modules/images/images/jakartaeett_dt_004.png b/src/main/antora/modules/common/images/jakartaeett_dt_004.png similarity index 100% rename from src/main/antora/modules/images/images/jakartaeett_dt_004.png rename to src/main/antora/modules/common/images/jakartaeett_dt_004.png diff --git a/src/main/antora/modules/images/images/jakartaeett_dt_005.png b/src/main/antora/modules/common/images/jakartaeett_dt_005.png similarity index 100% rename from src/main/antora/modules/images/images/jakartaeett_dt_005.png rename to src/main/antora/modules/common/images/jakartaeett_dt_005.png diff --git a/src/main/antora/modules/images/images/jakartaeett_dt_006.png b/src/main/antora/modules/common/images/jakartaeett_dt_006.png similarity index 100% rename from src/main/antora/modules/images/images/jakartaeett_dt_006.png rename to src/main/antora/modules/common/images/jakartaeett_dt_006.png diff --git a/src/main/antora/modules/images/images/jakartaeett_dt_007.png b/src/main/antora/modules/common/images/jakartaeett_dt_007.png similarity index 100% rename from src/main/antora/modules/images/images/jakartaeett_dt_007.png rename to src/main/antora/modules/common/images/jakartaeett_dt_007.png diff --git a/src/main/antora/modules/images/images/jakartaeett_dt_008.png b/src/main/antora/modules/common/images/jakartaeett_dt_008.png similarity index 100% rename from src/main/antora/modules/images/images/jakartaeett_dt_008.png rename to src/main/antora/modules/common/images/jakartaeett_dt_008.png diff --git a/src/main/antora/modules/images/images/jakartaeett_dt_009.png b/src/main/antora/modules/common/images/jakartaeett_dt_009.png similarity index 100% rename from src/main/antora/modules/images/images/jakartaeett_dt_009.png rename to src/main/antora/modules/common/images/jakartaeett_dt_009.png diff --git a/src/main/antora/modules/images/images/jakartaeett_dt_010.png b/src/main/antora/modules/common/images/jakartaeett_dt_010.png similarity index 100% rename from src/main/antora/modules/images/images/jakartaeett_dt_010.png rename to src/main/antora/modules/common/images/jakartaeett_dt_010.png diff --git a/src/main/antora/modules/images/images/jakartaeett_dt_011.png b/src/main/antora/modules/common/images/jakartaeett_dt_011.png similarity index 100% rename from src/main/antora/modules/images/images/jakartaeett_dt_011.png rename to src/main/antora/modules/common/images/jakartaeett_dt_011.png diff --git a/src/main/antora/modules/images/images/jakartaeett_dt_012.png b/src/main/antora/modules/common/images/jakartaeett_dt_012.png similarity index 100% rename from src/main/antora/modules/images/images/jakartaeett_dt_012.png rename to src/main/antora/modules/common/images/jakartaeett_dt_012.png diff --git a/src/main/antora/modules/images/images/jakartaeett_dt_013.png b/src/main/antora/modules/common/images/jakartaeett_dt_013.png similarity index 100% rename from src/main/antora/modules/images/images/jakartaeett_dt_013.png rename to src/main/antora/modules/common/images/jakartaeett_dt_013.png diff --git a/src/main/antora/modules/images/images/jakartaeett_dt_014.png b/src/main/antora/modules/common/images/jakartaeett_dt_014.png similarity index 100% rename from src/main/antora/modules/images/images/jakartaeett_dt_014.png rename to src/main/antora/modules/common/images/jakartaeett_dt_014.png diff --git a/src/main/antora/modules/images/images/jakartaeett_dt_015.png b/src/main/antora/modules/common/images/jakartaeett_dt_015.png similarity index 100% rename from src/main/antora/modules/images/images/jakartaeett_dt_015.png rename to src/main/antora/modules/common/images/jakartaeett_dt_015.png diff --git a/src/main/antora/modules/images/images/jakartaeett_dt_016.png b/src/main/antora/modules/common/images/jakartaeett_dt_016.png similarity index 100% rename from src/main/antora/modules/images/images/jakartaeett_dt_016.png rename to src/main/antora/modules/common/images/jakartaeett_dt_016.png diff --git a/src/main/antora/modules/images/images/jakartaeett_dt_017.png b/src/main/antora/modules/common/images/jakartaeett_dt_017.png similarity index 100% rename from src/main/antora/modules/images/images/jakartaeett_dt_017.png rename to src/main/antora/modules/common/images/jakartaeett_dt_017.png diff --git a/src/main/antora/modules/images/images/jakartaeett_dt_018.png b/src/main/antora/modules/common/images/jakartaeett_dt_018.png similarity index 100% rename from src/main/antora/modules/images/images/jakartaeett_dt_018.png rename to src/main/antora/modules/common/images/jakartaeett_dt_018.png diff --git a/src/main/antora/modules/images/images/jakartaeett_dt_019.png b/src/main/antora/modules/common/images/jakartaeett_dt_019.png similarity index 100% rename from src/main/antora/modules/images/images/jakartaeett_dt_019.png rename to src/main/antora/modules/common/images/jakartaeett_dt_019.png diff --git a/src/main/antora/modules/images/images/jakartaeett_dt_020.png b/src/main/antora/modules/common/images/jakartaeett_dt_020.png similarity index 100% rename from src/main/antora/modules/images/images/jakartaeett_dt_020.png rename to src/main/antora/modules/common/images/jakartaeett_dt_020.png diff --git a/src/main/antora/modules/images/images/jakartaeett_dt_021.png b/src/main/antora/modules/common/images/jakartaeett_dt_021.png similarity index 100% rename from src/main/antora/modules/images/images/jakartaeett_dt_021.png rename to src/main/antora/modules/common/images/jakartaeett_dt_021.png diff --git a/src/main/antora/modules/images/images/jakartaeett_dt_022.png b/src/main/antora/modules/common/images/jakartaeett_dt_022.png similarity index 100% rename from src/main/antora/modules/images/images/jakartaeett_dt_022.png rename to src/main/antora/modules/common/images/jakartaeett_dt_022.png diff --git a/src/main/antora/modules/images/images/jakartaeett_dt_023.png b/src/main/antora/modules/common/images/jakartaeett_dt_023.png similarity index 100% rename from src/main/antora/modules/images/images/jakartaeett_dt_023.png rename to src/main/antora/modules/common/images/jakartaeett_dt_023.png diff --git a/src/main/antora/modules/images/images/jakartaeett_dt_024.png b/src/main/antora/modules/common/images/jakartaeett_dt_024.png similarity index 100% rename from src/main/antora/modules/images/images/jakartaeett_dt_024.png rename to src/main/antora/modules/common/images/jakartaeett_dt_024.png diff --git a/src/main/antora/modules/images/images/jakartaeett_dt_025.png b/src/main/antora/modules/common/images/jakartaeett_dt_025.png similarity index 100% rename from src/main/antora/modules/images/images/jakartaeett_dt_025.png rename to src/main/antora/modules/common/images/jakartaeett_dt_025.png diff --git a/src/main/antora/modules/images/images/jakartaeett_dt_026.png b/src/main/antora/modules/common/images/jakartaeett_dt_026.png similarity index 100% rename from src/main/antora/modules/images/images/jakartaeett_dt_026.png rename to src/main/antora/modules/common/images/jakartaeett_dt_026.png diff --git a/src/main/antora/modules/images/images/jakartaeett_dt_027.png b/src/main/antora/modules/common/images/jakartaeett_dt_027.png similarity index 100% rename from src/main/antora/modules/images/images/jakartaeett_dt_027.png rename to src/main/antora/modules/common/images/jakartaeett_dt_027.png diff --git a/src/main/antora/modules/images/images/jakartaeett_dt_028.png b/src/main/antora/modules/common/images/jakartaeett_dt_028.png similarity index 100% rename from src/main/antora/modules/images/images/jakartaeett_dt_028.png rename to src/main/antora/modules/common/images/jakartaeett_dt_028.png diff --git a/src/main/antora/modules/images/images/jakartaeett_dt_029.png b/src/main/antora/modules/common/images/jakartaeett_dt_029.png similarity index 100% rename from src/main/antora/modules/images/images/jakartaeett_dt_029.png rename to src/main/antora/modules/common/images/jakartaeett_dt_029.png diff --git a/src/main/antora/modules/images/images/jakartaeett_dt_030.png b/src/main/antora/modules/common/images/jakartaeett_dt_030.png similarity index 100% rename from src/main/antora/modules/images/images/jakartaeett_dt_030.png rename to src/main/antora/modules/common/images/jakartaeett_dt_030.png diff --git a/src/main/antora/modules/images/images/jakartaeett_dt_031.png b/src/main/antora/modules/common/images/jakartaeett_dt_031.png similarity index 100% rename from src/main/antora/modules/images/images/jakartaeett_dt_031.png rename to src/main/antora/modules/common/images/jakartaeett_dt_031.png diff --git a/src/main/antora/modules/images/images/jakartaeett_dt_032.png b/src/main/antora/modules/common/images/jakartaeett_dt_032.png similarity index 100% rename from src/main/antora/modules/images/images/jakartaeett_dt_032.png rename to src/main/antora/modules/common/images/jakartaeett_dt_032.png diff --git a/src/main/antora/modules/images/images/jakartaeett_dt_033.png b/src/main/antora/modules/common/images/jakartaeett_dt_033.png similarity index 100% rename from src/main/antora/modules/images/images/jakartaeett_dt_033.png rename to src/main/antora/modules/common/images/jakartaeett_dt_033.png diff --git a/src/main/antora/modules/images/images/jakartaeett_dt_034.png b/src/main/antora/modules/common/images/jakartaeett_dt_034.png similarity index 100% rename from src/main/antora/modules/images/images/jakartaeett_dt_034.png rename to src/main/antora/modules/common/images/jakartaeett_dt_034.png diff --git a/src/main/antora/modules/images/images/jakartaeett_dt_035.png b/src/main/antora/modules/common/images/jakartaeett_dt_035.png similarity index 100% rename from src/main/antora/modules/images/images/jakartaeett_dt_035.png rename to src/main/antora/modules/common/images/jakartaeett_dt_035.png diff --git a/src/main/antora/modules/images/images/jakartaeett_dt_036.png b/src/main/antora/modules/common/images/jakartaeett_dt_036.png similarity index 100% rename from src/main/antora/modules/images/images/jakartaeett_dt_036.png rename to src/main/antora/modules/common/images/jakartaeett_dt_036.png diff --git a/src/main/antora/modules/images/images/jakartaeett_dt_037.png b/src/main/antora/modules/common/images/jakartaeett_dt_037.png similarity index 100% rename from src/main/antora/modules/images/images/jakartaeett_dt_037.png rename to src/main/antora/modules/common/images/jakartaeett_dt_037.png diff --git a/src/main/antora/modules/images/images/jakartaeett_dt_038.png b/src/main/antora/modules/common/images/jakartaeett_dt_038.png similarity index 100% rename from src/main/antora/modules/images/images/jakartaeett_dt_038.png rename to src/main/antora/modules/common/images/jakartaeett_dt_038.png diff --git a/src/main/antora/modules/images/images/jakartaeett_dt_039.png b/src/main/antora/modules/common/images/jakartaeett_dt_039.png similarity index 100% rename from src/main/antora/modules/images/images/jakartaeett_dt_039.png rename to src/main/antora/modules/common/images/jakartaeett_dt_039.png diff --git a/src/main/antora/modules/images/images/jakartaeett_dt_040.png b/src/main/antora/modules/common/images/jakartaeett_dt_040.png similarity index 100% rename from src/main/antora/modules/images/images/jakartaeett_dt_040.png rename to src/main/antora/modules/common/images/jakartaeett_dt_040.png diff --git a/src/main/antora/modules/images/images/jakartaeett_dt_041.png b/src/main/antora/modules/common/images/jakartaeett_dt_041.png similarity index 100% rename from src/main/antora/modules/images/images/jakartaeett_dt_041.png rename to src/main/antora/modules/common/images/jakartaeett_dt_041.png diff --git a/src/main/antora/modules/images/images/jakartaeett_dt_042.png b/src/main/antora/modules/common/images/jakartaeett_dt_042.png similarity index 100% rename from src/main/antora/modules/images/images/jakartaeett_dt_042.png rename to src/main/antora/modules/common/images/jakartaeett_dt_042.png diff --git a/src/main/antora/modules/images/images/jakartaeett_dt_043.png b/src/main/antora/modules/common/images/jakartaeett_dt_043.png similarity index 100% rename from src/main/antora/modules/images/images/jakartaeett_dt_043.png rename to src/main/antora/modules/common/images/jakartaeett_dt_043.png diff --git a/src/main/antora/modules/images/images/jakartaeett_dt_044.png b/src/main/antora/modules/common/images/jakartaeett_dt_044.png similarity index 100% rename from src/main/antora/modules/images/images/jakartaeett_dt_044.png rename to src/main/antora/modules/common/images/jakartaeett_dt_044.png diff --git a/src/main/antora/modules/images/images/jakartaeett_dt_045.png b/src/main/antora/modules/common/images/jakartaeett_dt_045.png similarity index 100% rename from src/main/antora/modules/images/images/jakartaeett_dt_045.png rename to src/main/antora/modules/common/images/jakartaeett_dt_045.png diff --git a/src/main/antora/modules/images/images/jakartaeett_dt_046.png b/src/main/antora/modules/common/images/jakartaeett_dt_046.png similarity index 100% rename from src/main/antora/modules/images/images/jakartaeett_dt_046.png rename to src/main/antora/modules/common/images/jakartaeett_dt_046.png diff --git a/src/main/antora/modules/images/images/jakartaeett_dt_047.png b/src/main/antora/modules/common/images/jakartaeett_dt_047.png similarity index 100% rename from src/main/antora/modules/images/images/jakartaeett_dt_047.png rename to src/main/antora/modules/common/images/jakartaeett_dt_047.png diff --git a/src/main/antora/modules/images/images/jakartaeett_dt_048.png b/src/main/antora/modules/common/images/jakartaeett_dt_048.png similarity index 100% rename from src/main/antora/modules/images/images/jakartaeett_dt_048.png rename to src/main/antora/modules/common/images/jakartaeett_dt_048.png diff --git a/src/main/antora/modules/images/images/jakartaeett_dt_049.png b/src/main/antora/modules/common/images/jakartaeett_dt_049.png similarity index 100% rename from src/main/antora/modules/images/images/jakartaeett_dt_049.png rename to src/main/antora/modules/common/images/jakartaeett_dt_049.png diff --git a/src/main/antora/modules/images/images/jakartaeett_dt_050.png b/src/main/antora/modules/common/images/jakartaeett_dt_050.png similarity index 100% rename from src/main/antora/modules/images/images/jakartaeett_dt_050.png rename to src/main/antora/modules/common/images/jakartaeett_dt_050.png diff --git a/src/main/antora/modules/images/images/jakartaeett_dt_051.png b/src/main/antora/modules/common/images/jakartaeett_dt_051.png similarity index 100% rename from src/main/antora/modules/images/images/jakartaeett_dt_051.png rename to src/main/antora/modules/common/images/jakartaeett_dt_051.png diff --git a/src/main/antora/modules/images/images/jakartaeett_dt_052.png b/src/main/antora/modules/common/images/jakartaeett_dt_052.png similarity index 100% rename from src/main/antora/modules/images/images/jakartaeett_dt_052.png rename to src/main/antora/modules/common/images/jakartaeett_dt_052.png diff --git a/src/main/antora/modules/images/images/jakartaeett_dt_053.png b/src/main/antora/modules/common/images/jakartaeett_dt_053.png similarity index 100% rename from src/main/antora/modules/images/images/jakartaeett_dt_053.png rename to src/main/antora/modules/common/images/jakartaeett_dt_053.png diff --git a/src/main/antora/modules/images/images/jakartaeett_dt_054.png b/src/main/antora/modules/common/images/jakartaeett_dt_054.png similarity index 100% rename from src/main/antora/modules/images/images/jakartaeett_dt_054.png rename to src/main/antora/modules/common/images/jakartaeett_dt_054.png diff --git a/src/main/antora/modules/images/images/jakartaeett_dt_055.png b/src/main/antora/modules/common/images/jakartaeett_dt_055.png similarity index 100% rename from src/main/antora/modules/images/images/jakartaeett_dt_055.png rename to src/main/antora/modules/common/images/jakartaeett_dt_055.png diff --git a/src/main/antora/modules/images/images/jakartaeett_dt_056.png b/src/main/antora/modules/common/images/jakartaeett_dt_056.png similarity index 100% rename from src/main/antora/modules/images/images/jakartaeett_dt_056.png rename to src/main/antora/modules/common/images/jakartaeett_dt_056.png diff --git a/src/main/antora/modules/images/images/jakartaeett_dt_057.png b/src/main/antora/modules/common/images/jakartaeett_dt_057.png similarity index 100% rename from src/main/antora/modules/images/images/jakartaeett_dt_057.png rename to src/main/antora/modules/common/images/jakartaeett_dt_057.png diff --git a/src/main/antora/modules/images/images/jakartaeett_dt_058.png b/src/main/antora/modules/common/images/jakartaeett_dt_058.png similarity index 100% rename from src/main/antora/modules/images/images/jakartaeett_dt_058.png rename to src/main/antora/modules/common/images/jakartaeett_dt_058.png diff --git a/src/main/antora/modules/images/images/jakartaeett_dt_059.png b/src/main/antora/modules/common/images/jakartaeett_dt_059.png similarity index 100% rename from src/main/antora/modules/images/images/jakartaeett_dt_059.png rename to src/main/antora/modules/common/images/jakartaeett_dt_059.png diff --git a/src/main/antora/modules/images/images/jakartaeett_dt_060.png b/src/main/antora/modules/common/images/jakartaeett_dt_060.png similarity index 100% rename from src/main/antora/modules/images/images/jakartaeett_dt_060.png rename to src/main/antora/modules/common/images/jakartaeett_dt_060.png diff --git a/src/main/antora/modules/images/images/jakartaeett_dt_061.png b/src/main/antora/modules/common/images/jakartaeett_dt_061.png similarity index 100% rename from src/main/antora/modules/images/images/jakartaeett_dt_061.png rename to src/main/antora/modules/common/images/jakartaeett_dt_061.png diff --git a/src/main/antora/modules/images/images/jakartaeett_dt_062.png b/src/main/antora/modules/common/images/jakartaeett_dt_062.png similarity index 100% rename from src/main/antora/modules/images/images/jakartaeett_dt_062.png rename to src/main/antora/modules/common/images/jakartaeett_dt_062.png diff --git a/src/main/antora/modules/images/images/jakartaeett_dt_063.png b/src/main/antora/modules/common/images/jakartaeett_dt_063.png similarity index 100% rename from src/main/antora/modules/images/images/jakartaeett_dt_063.png rename to src/main/antora/modules/common/images/jakartaeett_dt_063.png diff --git a/src/main/antora/modules/images/images/jakartaeett_dt_064.png b/src/main/antora/modules/common/images/jakartaeett_dt_064.png similarity index 100% rename from src/main/antora/modules/images/images/jakartaeett_dt_064.png rename to src/main/antora/modules/common/images/jakartaeett_dt_064.png diff --git a/src/main/antora/modules/images/images/jakartaeett_dt_065_frmcmpnt.png b/src/main/antora/modules/common/images/jakartaeett_dt_065_frmcmpnt.png similarity index 100% rename from src/main/antora/modules/images/images/jakartaeett_dt_065_frmcmpnt.png rename to src/main/antora/modules/common/images/jakartaeett_dt_065_frmcmpnt.png diff --git a/src/main/antora/modules/images/images/jakartaeett_dt_066_slctmny.png b/src/main/antora/modules/common/images/jakartaeett_dt_066_slctmny.png similarity index 100% rename from src/main/antora/modules/images/images/jakartaeett_dt_066_slctmny.png rename to src/main/antora/modules/common/images/jakartaeett_dt_066_slctmny.png diff --git a/src/main/antora/modules/images/images/jakartaeett_dt_067_slctn.png b/src/main/antora/modules/common/images/jakartaeett_dt_067_slctn.png similarity index 100% rename from src/main/antora/modules/images/images/jakartaeett_dt_067_slctn.png rename to src/main/antora/modules/common/images/jakartaeett_dt_067_slctn.png diff --git a/src/main/antora/modules/images/images/jakartaeett_dt_068_txtcmpnts.png b/src/main/antora/modules/common/images/jakartaeett_dt_068_txtcmpnts.png similarity index 100% rename from src/main/antora/modules/images/images/jakartaeett_dt_068_txtcmpnts.png rename to src/main/antora/modules/common/images/jakartaeett_dt_068_txtcmpnts.png diff --git a/src/main/antora/modules/security/pages/security-advanced/security-advanced002.adoc b/src/main/antora/modules/security/pages/security-advanced/security-advanced002.adoc index 747f8d44..89df5ca6 100644 --- a/src/main/antora/modules/security/pages/security-advanced/security-advanced002.adoc +++ b/src/main/antora/modules/security/pages/security-advanced/security-advanced002.adoc @@ -68,8 +68,7 @@ mutual authentication. [[GLIFJ]] .*Figure 53-1 Certificate-Based Mutual Authentication* -image:images:jakartaeett_dt_048.png[ -"Diagram of six steps in mutual authentication with certificates"] +image::common:jakartaeett_dt_048.png["Diagram of six steps in mutual authentication with certificates"] In user name/password-based mutual authentication, the following actions occur. @@ -89,9 +88,7 @@ name/password-based mutual authentication. [[GLIGQ]] .*Figure 53-2 User Name/Password-Based Mutual Authentication* -image:images:jakartaeett_dt_049.png[ -"Diagram of five steps in mutual authentication with user name and -password"] +image::common:jakartaeett_dt_049.png["Diagram of five steps in mutual authentication with user name andpassword"] [[BNBYH]][[_enabling_mutual_authentication_over_ssl]] diff --git a/src/main/antora/modules/security/pages/security-intro/security-intro001.adoc b/src/main/antora/modules/security/pages/security-intro/security-intro001.adoc index 51953e72..3d1a0741 100644 --- a/src/main/antora/modules/security/pages/security-intro/security-intro001.adoc +++ b/src/main/antora/modules/security/pages/security-intro/security-intro001.adoc @@ -84,9 +84,7 @@ application URL. This action is shown in link:#BNBWN[Figure 50-1]. [[BNBWN]] .*Figure 50-1 Initial Request* -image:images:jakartaeett_dt_039.png[ -"Diagram of initial request from web client to web server for access to a -protected resource"] +image::common:jakartaeett_dt_039.png["Diagram of initial request from web client to web server for access to aprotected resource"] Since the client has not yet authenticated itself to the application environment, the server responsible for delivering the web portion of @@ -110,9 +108,7 @@ server sets a credential for the user. [[BNBWP]] .*Figure 50-2 Initial Authentication* -image:images:jakartaeett_dt_040.png[ -"Diagram of initial authentication: server sends form to client, which -sends authentication data to server for validation"] +image::common:jakartaeett_dt_040.png["Diagram of initial authentication: server sends form to client, whichsends authentication data to server for validation"] [[BNBWQ]][[_step_3_url_authorization]] @@ -130,8 +126,7 @@ link:#BNBWR[Figure 50-3] shows this process. [[BNBWR]] .*Figure 50-3 URL Authorization* -image:images:jakartaeett_dt_041.png[ -"Diagram of URL authorization"] +image::common:jakartaeett_dt_041.png["Diagram of URL authorization"] The web server's evaluation stops with an "is authorized" outcome when the web server is able to map the user to a role. A "not authorized" @@ -148,9 +143,7 @@ original URL request, as shown in link:#BNBWT[Figure 50-4]. [[BNBWT]] .*Figure 50-4 Fulfilling the Original Request* -image:images:jakartaeett_dt_042.png[ -"Diagram of request fulfillment, showing server returning result to -client"] +image::common:jakartaeett_dt_042.png["Diagram of request fulfillment, showing server returning result to client"] In our example, the response URL of a web page is returned, enabling the user to post form data that needs to be handled by the business-logic @@ -171,9 +164,7 @@ one in the web server and one in the enterprise bean container. [[BNBWV]] .*Figure 50-5 Invoking an Enterprise Bean Business Method* -image:images:jakartaeett_dt_043.png[ -"Diagram of authorization process between web component and enterprise -bean"] +image::common:jakartaeett_dt_043.png["Diagram of authorization process between web component and enterprise bean"] The enterprise container is responsible for enforcing access control on the enterprise bean method. The container consults the security policy diff --git a/src/main/antora/modules/security/pages/security-intro/security-intro005.adoc b/src/main/antora/modules/security/pages/security-intro/security-intro005.adoc index 0838d99f..d765f794 100644 --- a/src/main/antora/modules/security/pages/security-intro/security-intro005.adoc +++ b/src/main/antora/modules/security/pages/security-intro/security-intro005.adoc @@ -64,9 +64,7 @@ Roles]. [[BNBXL]] .*Figure 50-6 Mapping Roles to Users and Groups* -image:images:jakartaeett_dt_044.png[ -"Diagram of role mapping, showing creation of users and groups, -definition of roles, and mapping of roles to users and groups"] +image::common:jakartaeett_dt_044.png["Diagram of role mapping, showing creation of users and groups, definition of roles, and mapping of roles to users and groups"] The following sections provide more information on realms, users, groups, and roles. diff --git a/src/main/antora/modules/security/pages/security-jakartaee/security-jakartaee002.adoc b/src/main/antora/modules/security/pages/security-jakartaee/security-jakartaee002.adoc index 07033453..1c62d1a2 100644 --- a/src/main/antora/modules/security/pages/security-jakartaee/security-jakartaee002.adoc +++ b/src/main/antora/modules/security/pages/security-jakartaee/security-jakartaee002.adoc @@ -500,9 +500,7 @@ illustrates this concept. [[BNBZA]] .*Figure 52-1 Security Identity Propagation* -image:images:jakartaeett_dt_047.png[ -"Diagram of security identity propagation from client to intermediate -container to target container"] +image::common:jakartaeett_dt_047.png["Diagram of security identity propagation from client to intermediatecontainer to target container"] In this illustration, an application client is making a call to an enterprise bean method in one enterprise bean container. This enterprise bean diff --git a/src/main/antora/modules/security/pages/security-webtier/security-webtier002.adoc b/src/main/antora/modules/security/pages/security-webtier/security-webtier002.adoc index 9f4a9435..b424e622 100644 --- a/src/main/antora/modules/security/pages/security-webtier/security-webtier002.adoc +++ b/src/main/antora/modules/security/pages/security-webtier/security-webtier002.adoc @@ -343,9 +343,7 @@ authentication. [[BNCBP]] .*Figure 51-1 HTTP Basic Authentication* -image:images:jakartaeett_dt_045.png[ -"Diagram of four steps in HTTP basic authentication between client and -server"] +image::common:jakartaeett_dt_045.png["Diagram of four steps in HTTP basic authentication between client andserver"] [[BNCBQ]][[_form_based_authentication]] @@ -375,9 +373,7 @@ authentication. [[GEXFA]] .*Figure 51-2 Form-Based Authentication* -image:images:jakartaeett_dt_046.png[ -"Diagram of four steps in form-based authentication between client and -server"] +image::common:jakartaeett_dt_046.png["Diagram of four steps in form-based authentication between client andserver"] The section link:#BNCBY[The hello1-formauth Example: Form-Based Authentication with a Jakarta Server Faces Application] From 2c39f33935a6b198686cabd20ca1d3ec19a0fa1f Mon Sep 17 00:00:00 2001 From: "Kito D. Mann" Date: Wed, 17 May 2023 13:38:03 -0400 Subject: [PATCH 014/247] JETUT-56 Moved conversion artifact; updated script to handle updating links to other pages. --- AntoraConverter.java | 87 --------- atora-conversion/AntoraConverter.java | 177 ++++++++++++++++++ .../CONVERTING_TO_ANTORA.adoc | 16 +- 3 files changed, 192 insertions(+), 88 deletions(-) delete mode 100755 AntoraConverter.java create mode 100755 atora-conversion/AntoraConverter.java rename CONVERTING_TO_ANTORA.adoc => atora-conversion/CONVERTING_TO_ANTORA.adoc (76%) diff --git a/AntoraConverter.java b/AntoraConverter.java deleted file mode 100755 index 33e1838d..00000000 --- a/AntoraConverter.java +++ /dev/null @@ -1,87 +0,0 @@ -///opt/homebrew/bin/jbang jbang "$0" "$@" ; exit $? -//DEPS com.github.lalyos:jfiglet:0.0.8 - -import java.io.File; -import java.nio.file.Files; -import java.nio.file.Paths; -import java.util.ArrayList; -import java.util.List; - -class AntoraConverter { - - final static String START_PATH_PREFIX = "src/main/antora/modules/"; - - public static String replaceBetween(String str, String start, String end, String prefix, String fromString, String toString) { - StringBuilder result = new StringBuilder(); - int index = 0; - int startIndex, endIndex; - - while ((startIndex = str.indexOf(start, index)) != -1 && (endIndex = str.indexOf(end, startIndex + start.length())) != -1) { - result.append(str, index, startIndex + start.length()); - String substring = str.substring(startIndex + start.length(), endIndex); - String updatedSubstring = substring.replace(fromString, toString); - // don't add the prefix if nothing has changed - if (!substring.equals(updatedSubstring)) { - result.append(prefix); - result.append(updatedSubstring); - } else { - result.append(substring); - } - index = endIndex; - } - result.append(str, index, str.length()); - return result.toString(); - } - - public static void main(String... args) throws Exception { - System.out.println("\uD83E\uDD16 Antora Converter: Convert raw Asciidoc files to Antora-compatible format"); - System.out.println("Walks through all folders and subfolders from the specified startPath and converts all .adoc files"); - List files = new ArrayList<>(); - if (args.length == 0) { - System.out.println("Usage: AntoraConverter.java [startPath]"); - System.out.println(" Where [startPath] is relative to " + START_PATH_PREFIX); - System.exit(1); - } - String startPath = START_PATH_PREFIX + args[0]; - System.out.println("Start path: " + startPath); - Files.walk(Paths.get(startPath)).filter(Files::isRegularFile) //.forEach(path -> System.out.println(path.getFileName())); - .filter(path -> path.toString().endsWith(".adoc")) - .forEach(path -> files.add(path.toFile())); - - for (File file : files) { - System.out.println("\uD83D\uDD0E Evaluating file " + file.getAbsolutePath()); - String content = new String(Files.readAllBytes(file.toPath())); - int changeCount = 0; - - if (content.contains(("<<"))) { - System.out.println("=> Updating anchor links"); - String modifiedContent = replaceBetween(content, "<<", ">>", "_","-", "_"); - Files.write(file.toPath(), modifiedContent.getBytes()); - changeCount++; - } - if (content.contains(("[["))) { - System.out.println("=> Updating anchor names"); - String modifiedContent = replaceBetween(content, "[[", "]]", "_", "-", "_"); - Files.write(file.toPath(), modifiedContent.getBytes()); - changeCount++; - } - if (content.contains("image:")) { - System.out.println("=> Converting inline image references to block image references and adding module prefix"); - String modifiedContent = content.replace("image:", "image::common:"); - Files.write(file.toPath(), modifiedContent.getBytes()); - changeCount++; - } - if (content.contains((".png["))) { - System.out.println("=> Removing newlines from image captions"); - String modifiedContent = replaceBetween(content, ".png[", "]", "", System.getProperty("line.separator"), " "); - Files.write(file.toPath(), modifiedContent.getBytes()); - changeCount++; - } - if (changeCount == 0) { - System.out.println("=> (no changes necessary)"); - } else { - System.out.println("=> " + changeCount + " changes made"); - } - } - } -} diff --git a/atora-conversion/AntoraConverter.java b/atora-conversion/AntoraConverter.java new file mode 100755 index 00000000..6d76e447 --- /dev/null +++ b/atora-conversion/AntoraConverter.java @@ -0,0 +1,177 @@ +///opt/homebrew/bin/jbang jbang "$0" "$@" ; exit $? +//DEPS com.github.lalyos:jfiglet:0.0.8 + +import java.io.File; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; +import java.util.function.BiFunction; +import java.util.function.Consumer; + +class AntoraConverter { + + record PageLocation(String path, String page) { + public String toString() { + return path + "/" + page; + } + } + static Map anchorMap = new HashMap<>(); + + final static String START_PATH_PREFIX = "src/main/antora/modules/"; + + public static String replaceBetween(String str, String start, String end, String prefix, String fromString, String toString, + BiFunction contentUpdater) { + StringBuilder result = new StringBuilder(); + int index = 0; + int startIndex, endIndex; + + while ((startIndex = str.indexOf(start, index)) != -1 && (endIndex = str.indexOf(end, startIndex + start.length())) != -1) { + result.append(str, index, startIndex + start.length()); + String substring = str.substring(startIndex + start.length(), endIndex); + String updatedSubstring = substring.replace(fromString, toString); + + // don't add the prefix if nothing has changed + if (!substring.equals(updatedSubstring)) { + // special case for anchors + if (updatedSubstring.startsWith("#")) { + updatedSubstring = updatedSubstring.replaceFirst("#", "#" + prefix); + } else { + updatedSubstring = prefix + updatedSubstring; + } + } + if (contentUpdater != null) { + updatedSubstring = contentUpdater.apply(substring, updatedSubstring); + } + result.append(updatedSubstring); + index = endIndex; + } + result.append(str, index, str.length()); + return result.toString(); + } + + public static void processInbetween(String str, String start, String end, Consumer updatedContentConsumer) { + int index = 0; + int startIndex, endIndex; + + while ((startIndex = str.indexOf(start, index)) != -1 && (endIndex = str.indexOf(end, startIndex + start.length())) != -1) { + String substring = str.substring(startIndex + start.length(), endIndex); + updatedContentConsumer.accept(substring); + index = endIndex; + } + } + + public static void main(String... args) throws Exception { + var dryRun = true; + System.out.println("\uD83E\uDD16 Antora Converter: Convert raw Asciidoc files to Antora-compatible format"); + System.out.println("Walks through all folders and subfolders from the specified startPath and converts all .adoc files"); + if (dryRun) { + System.out.println("=> dryRun is enabled; no files will be modified"); + } + var files = new ArrayList(); + if (args.length == 0) { + System.out.println("Usage: AntoraConverter.java [startPath]"); + System.out.println(" Where [startPath] is relative to " + START_PATH_PREFIX); + System.exit(1); + } + String startPath = START_PATH_PREFIX + args[0]; + System.out.println("Start path: " + startPath); + Files.walk(Paths.get(startPath)).filter(Files::isRegularFile) + .filter(path -> path.toString().endsWith(".adoc")) + .forEach(path -> files.add(path.toFile())); + + System.out.println("\uD83E\uDD16 Pre-scanning files for anchors, links, etc."); + + for (File file : files) { + System.out.println("\uD83D\uDD0E Pre-scanning file " + file.getAbsolutePath()); + String content = new String(Files.readAllBytes(file.toPath())); + System.out.println("=> Processing anchor names"); + processInbetween(content, "[[", "]]", (anchor) -> { + final var pageLocation = new PageLocation(file.getParentFile().getName(), file.getName()); + anchorMap.put("#" + anchor, pageLocation); + System.out.printf(" => Stored anchor \"%s\" for %s%n", anchor, pageLocation); + }); + } + + System.out.println("\uD83E\uDD16 Updating files"); + for (File file : files) { + System.out.println("\uD83D\uDD0E Evaluating file " + file.getAbsolutePath()); + String content = new String(Files.readAllBytes(file.toPath())); + int changeCount = 0; + + if (content.contains(("<<"))) { + System.out.println("=> Updating anchor links"); + String modifiedContent = replaceBetween(content, "<<", ">>", "_", "-", "_", null); + System.out.println(" => Updating anchor link"); + if (!dryRun) { + Files.write(file.toPath(), modifiedContent.getBytes()); + } + changeCount++; + } + if (content.contains(("[["))) { + System.out.println("=> Updating anchor names"); + String modifiedContent = replaceBetween(content, "[[", "]]", "_", "-", "_", null); + if (!dryRun) { + Files.write(file.toPath(), modifiedContent.getBytes()); + } + changeCount++; + } + if (content.contains(("link:#"))) { + System.out.println("=> Updating anchor links"); + String modifiedContent = replaceBetween(content, "link:", "[", "_", "-", "_", (originalLink, newLink) -> { + var pageLocation = anchorMap.get(originalLink); + if (pageLocation == null) { + pageLocation = anchorMap.get(newLink); + } + if (pageLocation == null) { + System.out.printf(" => WARNING: No page location found for anchor %s or %s; the file with the anchor may not have been within the startPath%n", + originalLink, newLink); + return newLink; + } + // If it's a link to the current page, no need to reference another page. + if (pageLocation.page.equalsIgnoreCase(file.getName())) { + return newLink; + } + final var updatedLink = pageLocation + "#" + newLink; + System.out.printf(" => Updating anchor link from %s to %s%n", originalLink, updatedLink); + return updatedLink; + }); + if (!dryRun) { + Files.write(file.toPath(), modifiedContent.getBytes()); + } + changeCount++; + } + if (content.contains("link:")) { + System.out.println("=> Converting links to use xrefs"); + String modifiedContent = content.replace("link:", "xref:"); + if (!dryRun) { + Files.write(file.toPath(), modifiedContent.getBytes()); + } + changeCount++; + } + if (content.contains("image:")) { + System.out.println("=> Converting inline image references to block image references and adding module prefix"); + String modifiedContent = content.replace("image:", "image::common:"); + if (!dryRun) { + Files.write(file.toPath(), modifiedContent.getBytes()); + } + changeCount++; + } + if (content.contains((".png["))) { + System.out.println("=> Removing newlines from image captions"); + String modifiedContent = replaceBetween(content, ".png[", "]", "", System.getProperty("line.separator"), " ", null); + if (!dryRun) { + Files.write(file.toPath(), modifiedContent.getBytes()); + } + changeCount++; + } + if (changeCount == 0) { + System.out.println("=> (no changes necessary)"); + } else { + System.out.println("=> " + changeCount + " changes made"); + } + } + } +} diff --git a/CONVERTING_TO_ANTORA.adoc b/atora-conversion/CONVERTING_TO_ANTORA.adoc similarity index 76% rename from CONVERTING_TO_ANTORA.adoc rename to atora-conversion/CONVERTING_TO_ANTORA.adoc index ede36247..2d13b740 100644 --- a/CONVERTING_TO_ANTORA.adoc +++ b/atora-conversion/CONVERTING_TO_ANTORA.adoc @@ -16,7 +16,7 @@ Here’s the current process for migrating an individual module (i.e. security, * Inside of this folder, create a `pages` folder. 4. Move all the folders for the module you are migrating into the new `pages` folder. For example, for the Security module, you would move all of the `src/main/asciidoc/security-*` folders into the `src/main/antora/modules/security/pages`. (Copy the entire folders, not just the `.adoc` files). -> NOTE: It's essential that you _move_ rather than copy the folders so that we keep the history intact. + > NOTE: It's essential that you _move_ rather than copy the folders so that we keep the history intact. 5. Run the migration script from the root project folder. For example, for the Security module, you would run `jbang AntoraConverter.java security`. (The first parameter is the folder relative to `src/main/antora/modules`). 6. Create a new file called `nav.adoc` in the root of the module folder. For example, for the Security module, you would create a `security/nav.adoc`. @@ -55,4 +55,18 @@ After copying these into `nav.adoc`, replace "include::" with "* xref:" and add - modules/security/nav.adoc ``` +9. Check the links. For any links that refer to anchors in other files (usually within the same folder) you will need to fix them manually. For example, in the Security module, this link: +```asciidoc +* link:#BNBYK[Chapter 52, "Getting Started Securing +Enterprise Applications"] +``` + +should be changed to this: + +```asciidoc +* xref:security-jakartaee/security-jakartaee.adoc#BNBYK[Chapter 52, "Getting Started Securing +Enterprise Applications"] +``` + +This is necessary because the entire module isn't a single file. Note the use of the `xref` here instead of `link`. We're referring to another folder within the `security` module's `pages` folder. (See the https://docs.antora.org/antora/latest/page/xref/[the Antora docs] for more info about xrefs.) From 68f6c9bbd9ffe7eeff36a28d18cc6da42273b6bb Mon Sep 17 00:00:00 2001 From: Arjan Tijms Date: Wed, 17 May 2023 21:34:38 +0200 Subject: [PATCH 015/247] Initial refresh of security chapter Two examples have been added. Signed-off-by: Arjan Tijms --- .../asciidoc/images/authentication_mvc.svg | 3 + src/main/asciidoc/partsecurity.adoc | 2 + .../asciidoc/security-refresh/security.adoc | 410 ++++++++++++++++++ 3 files changed, 415 insertions(+) create mode 100644 src/main/asciidoc/images/authentication_mvc.svg create mode 100644 src/main/asciidoc/security-refresh/security.adoc diff --git a/src/main/asciidoc/images/authentication_mvc.svg b/src/main/asciidoc/images/authentication_mvc.svg new file mode 100644 index 00000000..321dec8f --- /dev/null +++ b/src/main/asciidoc/images/authentication_mvc.svg @@ -0,0 +1,3 @@ + + +
Authentication Mechanism
(Controller)
Authentication Mecha...
Login Form/Dialog
(View)
Login Form/Dialog...
Identity Store
(Model)
Identity Store...
HTTP
Cookies
Headers
URLs
HTTP...
Credentials
Caller name
Groups
Credentials...
Viewer does not support full SVG 1.1
\ No newline at end of file diff --git a/src/main/asciidoc/partsecurity.adoc b/src/main/asciidoc/partsecurity.adoc index 3176c8ef..54193232 100644 --- a/src/main/asciidoc/partsecurity.adoc +++ b/src/main/asciidoc/partsecurity.adoc @@ -4,6 +4,8 @@ Part X explores security concepts and examples. :leveloffset: +1 +include::security-refresh/security.adoc[] + include::security-intro/security-intro.adoc[] include::security-webtier/security-webtier.adoc[] diff --git a/src/main/asciidoc/security-refresh/security.adoc b/src/main/asciidoc/security-refresh/security.adoc new file mode 100644 index 00000000..4ece00b5 --- /dev/null +++ b/src/main/asciidoc/security-refresh/security.adoc @@ -0,0 +1,410 @@ += Jakarta Security + +Jakarta Security is the overarching security API in Jakarta EE. + +Due to historical and political reasons, a number of security features are distributed among several other APIs in Jakarta EE. Sometimes they overlap, sometimes such features are only accessible from these other APIs. In this chapter we will focus primarily on explaining Jakarta Security, and will mention when other APIs are needed to accomplish a certain task. + +== Overview + +Before we look at some practical examples, let's quickly go through some basics. + +Some of the guiding principles in Jakarta Security are: + +1. It should work directly out of the box, without requiring any kind of vendor specific configuration or activation. +2. It leverages Jakarta CDI as much as possible. Most artefacts are CDI beans and many features are done via CDI interceptors. +3. The difference between framework provided artefacts and custom (user provided) artefacts is minimal or non-existent. +4. It fully integrates with security features from other Jakarta EE APIs and proprietary (vendor specific) artefacts. + +Jakarta Security makes an important distinction between several distinct artefacts that play an important role in the security process: + +1. The Authentication Mechanism +2. The Identity Store +3. The Permission Store + +The first two of these are used in the authentication process: + +An _authentication mechanism_ is somewhat like a controller in the well-known MVC pattern; it’s the entity that interacts with the caller (typically a human) via some kind of view to collect credentials and with the model (business logic) to validate these credentials. An authentication mechanism knows about the environment that this caller uses to communicate with the server. An authentication mechanism for HTTP knows about URLs to redirect or forward to, or about response headers to send to the client. It also knows about the data coming back, such as cookies, request headers, and post data. Examples of authentication mechanisms are FORM authentication and BASIC authentication. + +An _identity store_ on its turn is more like the model in the MVC pattern. This entity strictly performs a business / data operation where credentials go in, and an identity comes out. The identity contains logic to validate said credentials, and embeds or contacts a database. This "database" contains user names, along with their credentials and (typically) roles. An identity store therefore knows nothing about the environment that this caller uses to communicate with the server; e.g. it doesn't know about HTTP or headers etc. +Example of identity stores are services that contact SQL/JDBC databases, LDAP servers, files on the file-system, etc. + + +image::authentication_mvc.svg["Diagram illustrating the role of the authentication mechanism and identity store in an MVC like structure"] + +The third one is used for the authorization process: + +A _permission store_ is another kind of model that stores permissions, typically either globally, or per role (role based permissions). This entity then performs a business / data operation where a query and an identity go in, and a yes/no answer goes out. For instance, a query such as "can access /foo/bar" along with the identity for user "John" with roles "bar" and "kaz". +Examples of permissions stores are the Jakarta Authorization usage of the Policy class, or the internal data structure where a Servlet Container such as Tomcat or Jetty stores the security constraints an application defined. + + +== Provided authentication mechanisms and identity stores + +Jakarta Security provides a number of build-in authentication mechanisms and identity stores. We'll enumerate them here first, and will look at them in more detail below. + +Authentication mechanisms: + +1. The Basic Authentication Mechanism +2. The Form Authentication Mechanism +3. The Custom Form Authentication Mechanism +4. The Open ID Connect (OIDC) Authentication Mechanism + +Identity stores: + +1. The Database Identity Store +2. The LDAP Identity Store + +== Custom authentication mechanisms and identity stores + +When the provided authentication mechanisms and identity stores are not sufficient, we can easily define our own. The provided ones and our own ones use the exact same interfaces, and the system doesn't distinguish between calling our own one or one that was provided by the system. + +== Authentication mechanisms and identity stores from other APIs + +The Servlet specification defines the exact same Form and Basic authentication mechanisms. Authenticating with them will have the exact same result as authenticating with a Jakarta Security authentication mechanism. E.g. role checks will work exactly the same independent on which API was used to authenticate. + +A Servlet authentication mechanism however will not necessarily consult a Jakarta Security identity store. This is server dependent. The identity store that is called is server dependent as well. Calling this server dependent identity store is possible from Jakarta Security, but as an advanced feature. + +Likewise, programmatic role checks can be done from various APIs, including Jakarta Security, Jakarta REST and Jakarta Servlet. These all return the same outcome, independent from whether authentication took place with a Jakarta Security Authentication Mechanism or a Servlet Authentication Mechanism. + + +== Securing an endpoint with Basic Authentication + +In the following example we'll be securing a REST endpoint using Basic Authentication. + +You'll learn the following things; + +1. How to define security constraints +2. How to set a provided authentication mechanisms +3. How to define (and implicitly set) a custom identity store +4. How to use the Jakarta Security SecurityContext + +=== Write the application + +Let's start with defining a simple REST resource class for a `/rest/resource` endpoint: + +[source,java] +---- +@Path("/resource") +@RequestScoped +public class Resource { + + @Inject + private SecurityContext securityContext; + + @GET + @Produces(TEXT_PLAIN) + public String getCallerAndRole() { + return + securityContext.getCallerPrincipal().getName() + " : " + + securityContext.isCallerInRole("user"); + } + +} +---- + +This resource uses the injected Jakarta EE SecurityContext to obtain access to the current authenticated caller, which is represented by a `Principal` instance. For simplicity sake the code here does not check whether the caller principal is `null`. If the resource is also available to non-authenticated callers, this is something we have to do. The `getCallerPrincipal()` call would return `null` then. + +Also note that there is a Jakarta REST specific type that is also named `SecurityContext` and has similar methods as the ones we used here. From the point of view of Jakarta EE that is a deprecated type and replaced by the Jakarta Security version. + +==== Declare the security constraints + +Next we'll define the security constraints in `web.xml`, which are used to tell the security system that access to a given URL or URL pattern is protected, and hence authentication is required: + +[source,xml] +---- + + + + + + protected + /rest/* + + + user + + + + +---- + +This XML essentially says that to access any URL that starts with "/rest" requires the caller to have the role "user". Roles are opaque strings; merely identifiers. It's fully up to the application how broad or fine-grained they are. + +Note that in Jakarta EE, internally these XML constraints are transformed into `Permission` instances and made available via a specific type of the Permission Store that we explained above. Knowledge about this transformation is only needed for very advanced use cases. + +The observant reader may wonder if XML is really the only option here, given the strong feelings that exist in parts of the community around XML. The answer is yes and no. Jakarta EE does define the `@RolesAllowed` annotation that could be used to replace the XML shown above, but only the legacy Enterprise Beans has specified a behaviour for this when put on an Enterprise Bean. Jakarta REST has done no such thing, although the JWT API in MicroProfile has defined this for REST resources. In Jakarta EE however this remains a vendor specific extension. + +There are also a number of annotations and APIs in Jakarta EE to set these kinds of constraints for individual Servlets, but those won't help us much either here. + +==== Declare the authentication mechanism + +[source,java] +---- +@ApplicationScoped +@BasicAuthenticationMechanismDefinition(realmName = "basicAuth") +@DeclareRoles({ "user", "caller" }) +@ApplicationPath("/rest") +public class ApplicationConfig extends Application { + +} +---- + +To declare the usage of a specific authentication mechanism, Jakarta EE provides `[XYZ]MechanismDefinition` annotations. Such an annotation is picked up by the security system, and in response to it a CDI bean that implements the `HttpAuthenticationMechanism` is enabled for it. + +The annotation can be put on any bean, but in a REST application it fits particularly well on the `Application` subclass that also declares the path for REST resources. + +==== Define the identity store + +Finally, let's define a very simple identity store that the security system can use to validate provided credentials for a Basic authentication: + +[source,java] +---- +@ApplicationScoped +public class TestIdentityStore implements IdentityStore { + + public CredentialValidationResult validate(UsernamePasswordCredential usernamePasswordCredential) { + if (usernamePasswordCredential.compareTo("john", "secret1")) { + return new CredentialValidationResult("john", Set.of("user", "caller")); + } + + return INVALID_RESULT; + } + +} +---- + +This identity store only "contains" the single identity (user) "john", with password "secret1" and roles "user" and "caller". Defining this kind of identity store is often the simplest way to get started. Note that Jakarta Security does not define a simple identity store out of the box, because there are questions whether that would promote security best practices. + +Also note that the identity store is installed and used by the security system just by the virtue of being there; it picks up all enabled CDI beans that implement `IdentityStore`. Such beans can be enabled by the security system itself (following some configuration annotation), or can be programmatically added using the appropriate CDI APIs. Where the bean comes from doesn't matter for Jakarta Security, only the fact that it's there. + + +==== Test the application + +It's now time to test our application. A ready to test version is available from the Jakarta EE Examples project at https://github.com/eclipse-ee4j/jakartaee-examples. + +Download or clone this repo, then cd into the `focused` folder and execute: + +``` +mvn clean install -pl :restBasicAuthCustomStore +``` + +This will run a test associated with the project, printing something like the following: + +``` +john : true +[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 6.414 s - in jakartaee.examples.focused.security.restbasicauthcustomstore.RestBasicAuthCustomStoreIT +``` + +Let's take a quick look at the actual test: + +[source,java] +---- +@RunWith(Arquillian.class) +@RunAsClient +public class RestBasicAuthCustomStoreIT extends ITBase { + + /** + * Stores the base URL. + */ + @ArquillianResource + private URL baseUrl; + + /** + * Test the call to a protected REST service + * + * @throws Exception when a serious error occurs. + */ + @RunAsClient + @Test + public void testRestCall() throws Exception { + DefaultCredentialsProvider credentialsProvider = new DefaultCredentialsProvider(); + credentialsProvider.addCredentials("john", "secret1"); + + webClient.setCredentialsProvider(credentialsProvider); + + TextPage page = webClient.getPage(baseUrl + "/rest/resource"); + String content = page.getContent(); + + System.out.println(content); + } +} +---- + +Using Arquillian, the test starts the default server (GlassFish 7), and deploys the actual output of the build process (a .war file) to it. The test runs in the integration test phase (and not the unit test phase) to make sure this output is indeed available. The test then does a request to the remote GlassFish server using a provided html unit web client. Note that anything that can do an HTTP request could have been used here as well. + +The `DefaultCredentialsProvider` used here makes sure that the headers for Basic authentication are added to the request. The Basic authentication mechanism that we defined for our applications reads those headers, extracts the username and password from them, and consults our identity store with them. + +Alternatively, we can manually deploy the war file found in `security/restBasicAuthCustomStore/target/restBasicAuthCustomStore.war` to a server of our choice (e.g. GlassFish 7), and request the URL via a browser or a commandline util such as `curl`. + +== Securing an endpoint with Basic Authentication and a Database identity store + +In the following example we'll be securing a REST endpoint using Basic Authentication and the database identity store that is provided by Jakarta Security. + +You'll learn the following things; + +1. How to define security constraints +2. How to set a provided authentication mechanisms +3. How to set a provided identity store that uses a database +4. How to populate and configure that identity store +5. How to use the Jakarta Security SecurityContext + +=== Write the application + +We'll use the same resource and same security constraints as we used for the <> example. + +==== Declare the authentication mechanism and identity store + +[source,java] +---- +@ApplicationScoped +@BasicAuthenticationMechanismDefinition( + realmName = "basicAuth" +) +@DatabaseIdentityStoreDefinition( + callerQuery = "select password from basic_auth_user where username = ?", + groupsQuery = "select name from basic_auth_group where username = ?", + hashAlgorithmParameters = { + "Pbkdf2PasswordHash.Iterations=3072", + "Pbkdf2PasswordHash.Algorithm=PBKDF2WithHmacSHA512", + "Pbkdf2PasswordHash.SaltSizeBytes=64" + } +) +@DeclareRoles("user") +@ApplicationPath("/rest") +public class ApplicationConfig extends Application { + +---- + +To declare the usage of a specific authentication mechanism, Jakarta EE provides `[XYZ]MechanismDefinition` annotations. Such an annotation is picked up by the security system, and in response to it a CDI bean that implements the `HttpAuthenticationMechanism` is enabled for it. + +Likewise, to declare the usage of a specific identity store, Jakarta EE provides `[XYZ]StoreDefinition` annotations. + +The annotations can be put on any bean, but in a REST application it fits particularly well on the `Application` subclass that also declares the path for REST resources. + +In the case of the `DatabaseIdentityStoreDefinition` we need to provide it with at least two queries: + +1. The SQL query that returns a password for the username part of credentials entered by a caller. The returned password is compared with the password part of those credentials. If they match (of more typically, their hashes match) the credential is considered valid. +2. The query that returns a number of roles given that same username part of the credentials + +Although not required, it's a good practice to provide some parameters for the hash algorithm. Passwords should obviously never be stored in plain-text in a database. + +Note that the provided `DatabaseIdentityStoreDefinition` is suited for to be paired with any authentication mechanism that validates username/password credentials. + + +==== Populating the identity store + +In order to use the identity store we need to put some data in a database. The following code shows one way how to do that: + + +[source,java] +---- +@ApplicationScoped +@BasicAuthenticationMechanismDefinition( + realmName = "basicAuth" +) +@DatabaseIdentityStoreDefinition( + callerQuery = "select password from basic_auth_user where username = ?", + groupsQuery = "select name from basic_auth_group where username = ?", + hashAlgorithmParameters = { + "Pbkdf2PasswordHash.Iterations=3072", + "Pbkdf2PasswordHash.Algorithm=PBKDF2WithHmacSHA512", + "Pbkdf2PasswordHash.SaltSizeBytes=64" + } +) +@DeclareRoles("user") +@ApplicationPath("/rest") +public class ApplicationConfig extends Application { + + /** + * Id of the one and only user we populate in out DB. + */ + private static final BigInteger USER_ID = ONE; + + /** + * Id of the one and only group we populate in out DB. + */ + private static final BigInteger GROUP_ID = ONE; + + @PersistenceContext + private EntityManager entityManager; + + @Inject + private Pbkdf2PasswordHash passwordHash; + + @Transactional + public void onStart(@Observes @Initialized(ApplicationScoped.class) Object applicationContext) { + passwordHash.initialize(Map.of( + "Pbkdf2PasswordHash.Iterations", "3072", + "Pbkdf2PasswordHash.Algorithm", "PBKDF2WithHmacSHA512", + "Pbkdf2PasswordHash.SaltSizeBytes", "64")); + + if (entityManager.find(User.class, USER_ID) == null) { + var user = new User(); + user.id = USER_ID; + user.username = "john"; + user.password = passwordHash.generate("secret1".toCharArray()); + entityManager.persist(user); + } + + if (entityManager.find(Group.class, GROUP_ID) == null) { + var group = new Group(); + group.id = GROUP_ID; + group.name = "user"; + group.username = "john"; + entityManager.persist(group); + } + } + +} + +@Entity +@Table(name = "basic_auth_user") +class User { + @Id + BigInteger id; + + @Column(name = "password") + String password; + + @Column(name = "username", unique = true) + String username; +} + +@Entity +@Table(name = "basic_auth_group") +class Group { + @Column(name = "id") + @Id + BigInteger id; + + @Column(name = "name") + String name; + + @Column(name = "username") + String username; +} +---- + +The code above uses Jakarta Persistence, which generates SQL from java types. Jakarta Persistence is discussed in detail in its own chapter. For here it's important to note that the code takes advantage of the default datasource in Jakarta EE, so we don't have to explicitly install and configure an external database such as Postgres or MySQL. Without specifying a datasource, the `@DatabaseIdentityStoreDefinition` annotation defaults to using the default datasource, but if needed we can specify a different one using the `dataSourceLookup` attribute. + +==== Test the application + +It's now time to test our application. A ready to test version is available from the Jakarta EE Examples project at https://github.com/eclipse-ee4j/jakartaee-examples. + +Download or clone this repo, then cd into the `focused` folder and execute: + +``` +mvn clean install -pl :restBasicAuthDBStore +``` + +This will run a test associated with the project, printing something like the following: + +``` +john : true +[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 8.307 s - in jakartaee.examples.focused.security.restbasicauthdbstore.RestBasicAuthDBStoreIT +``` + +The test itself is basically the same as that for the <> example. + From 0bd141541ab0be2f1e2b4a3fb37e76dea15aafeb Mon Sep 17 00:00:00 2001 From: Bauke Scholtz Date: Fri, 19 May 2023 06:44:14 -0400 Subject: [PATCH 016/247] JETUT-53: specify diagram font and colors --- README.md | 26 ++++++++++++++++++ README/images/drawio-font-1-select-font.png | Bin 0 -> 96278 bytes README/images/drawio-font-2-select-custom.png | Bin 0 -> 87699 bytes .../drawio-font-3-set-google-open-sans.png | Bin 0 -> 99463 bytes .../drawio-font-4-using-google-open-sans.png | Bin 0 -> 101720 bytes 5 files changed, 26 insertions(+) create mode 100644 README/images/drawio-font-1-select-font.png create mode 100644 README/images/drawio-font-2-select-custom.png create mode 100644 README/images/drawio-font-3-set-google-open-sans.png create mode 100644 README/images/drawio-font-4-using-google-open-sans.png diff --git a/README.md b/README.md index 490ecf2c..a1ccf605 100644 --- a/README.md +++ b/README.md @@ -66,6 +66,32 @@ The `*.drawio` format ensures being able to reopen exactly the intended diagram The `*.vsdx` format ensures being able to import the diagram in another tool as this is the most supported format by various diagramming tools, just in case that draw.io stops to exist in some unpredictable future. The `*.svg` format is ultimately used to embed the diagram in the tutorial document. +#### Diagram requirements + +- Font must be 'Open Sans' conform the [Jakarta EE Brand Usage Handbook](https://jakarta.ee/legal/trademark_guidelines/jakarta-ee-branding-guidelines.pdf). + You can use Google Fonts for this. + In case you're using draw.io: + - Wherever you see a 'Font' dropdown, unfold it. + ![Select font](README/images/drawio-font-1-select-font.png) + - If there's no 'Open Sans' option, pick 'Custom'. + ![Select custom](README/images/drawio-font-2-select-custom.png) + - Choose the 'Google Fonts' option and set the font name to 'Open Sans' and apply. + ![Set Google Open Sans](README/images/drawio-font-3-set-google-open-sans.png) + - Type text and verify that the font is Open Sans + ![Using Google Open Sans](README/images/drawio-font-4-using-google-open-sans.png) + +- Color must be one of those defined in [Jakarta EE Brand Usage Handbook](https://jakarta.ee/legal/trademark_guidelines/jakarta-ee-branding-guidelines.pdf), along with black and white. + - Primary colors: + - Blue: `#1B208B` + - Orange: `#F98200` + - Black: `#3D3D3D` + - White: `#FFFFFF` + - Secondary colors: + - Yellow: `#FDB940` + - Grey: `#58595B` + - Dark blue: `#131660` + + ### Deploy the Site to Github Pages If you want to manually push a build to the gh-pages branch, use: diff --git a/README/images/drawio-font-1-select-font.png b/README/images/drawio-font-1-select-font.png new file mode 100644 index 0000000000000000000000000000000000000000..0ce3911388ad7a3d92f31274f7cc4c1fe7363ef3 GIT binary patch literal 96278 zcmYIw1ymK?_cnrnfPl2LNGaVN64Kq>-QC?tOG|@vcXxL;m+o%3K{_9(=8P=V9 z?umVNJYVN^^%G@CVLDMAaSwf`<6* zdgqeM>jVMu1wvGiPr+sB804yf(af%Nsmt{Yls$)R=G0YmcPaS3i?14@QMHJmRqrm ze}EMH95QOgoe&>i%T3;Y&S-;D@eT=kUG+0p3M@1;e(tO(`8Ra&Z1iHYO>t2{if`7+S|KI$Oi|cPfKtb?|<0;TkChiIHTa*X=zj4dx1r_=8)e3*B zp=J}v70xK$Gkm+<&{F()H012}zaAiVwBn1H%?e404!2U8t3c-X=njT_vd>twFS(h~ z`fp2Hx%QPWqbG6DdTbb)M9=1tQ_4&9t1kXkyml4{^=@D<1n9~(7DlSEub?DjbBnS@ zWAFSN$JNuCmNt*;4$qoaP0&e7DsWGc(m`pi2^KkXUakDp>ZC%xL=zuGm+kb*N!r(^9**zyiyktk?6~SdxLKc)&tkzL((1;#HKjjmOg)@NC* zBHn3<%bLIobvY(o4XiQ{^eLUf8$21kX zQ-Il@!A;C;ct}A=xI~WRZwi&DsUOlr#7Q2U-!HxXjLd5TBi(_`mO;RqC8ueg1(`Fi zlmQj!j274CEwF(d(8c&6_iU}A=#TD@tXASLg+he_g~aZ%;9%J0?Dp-`W{!9cLYwpVIwY#Azkjbz4(TKKk$KN@ZYacc?bRAAL2HijWMF@Wr!Te`t zREr&)95VmC$(+G}fB+>*n>o3Chjd5Me726H+`c$OD*&&c?=@l~Qao9kh@+@A7ltIRE~Rd4^WNXVMNlQeG?{dTkFNb5j> zzQ7o@H6Yph#}!6>7u#a7P=)pd?pqNaSFtSKjM4_nV)J|7z&KT4iavfX~f z%C=Xo-i+gu;l0@36B-*D_MEVnC$)9A=1uGP5|6`dCa5rDzv8J(&cMj1TKA;ybi4rf zLq_Hcqw!NpBtB=2c?lobIscH+Q5Lr<1Ku&88f2Li1i3R-nowedLn zaGmv9xkMUAV4J5~mI4L%q<$@#dk@iAWcu;`69#j<73j2c!^UQVALq=wBJQmH^_>sv zYLYRip4NpnPgn%3R(Ys3*jjKj zrE6vapdPkY24k1)chyx@E|-Jk5J@c0y~U7wnS4;-?O5p@oGlL6F~Fc8zS%|@U&vaP zTkkutL2!PXHCc)xyQ}{^Lhk*p!(|({<>i7cv2Fx17(ZBm&np2ZHyC6{yVmB(x$3ed z=>=-f03;1KmEvPw8=qKmX-K-u3)v^|UdDn&Zu@TSE+snr%NegdJ7DhuFU;YbR_$qk z?79iP@pi8drdw)t2=d2Mb?-y^FV4?(92(!CQQ(oex^W7AL`-6O! z8V=3IW%IQ*eEZ#(U~O;ExX-)iWHwt!+IEH%e^}(H=6QjUKVVe%+v8H1BuE*G`1qof zquTQ4#~a;|ec6$;N5U62hmepE8ZI8Y_wCQOob{^@tV_-&{r!aAVopvh1Ox=R383le zSTyhSFRZl4wQ3Pc#l3o!di9Ckk?kz*WsDY(7He(Y?4@)a)p>hnslCAP)R8LW>_gW&OqL8Dw7zzZ>so+y_S*`SLQ|Bqq<;q(78dk># zODxzmEQe+ab62}nJ#4bR%javY3FomzwFdLTm$DXRa%Sa}ix4S>>25dI9b|G(P(XV1u{9EuJnd%bnh=@`7=7GQ6-oM<(iKIORQV5?LXln zyn#%l(cF9_)MIzJr$a$`)p>n^s#G>!NEa^YIS6# ze){J9#a1e}dt~j=%Wx9C^kj)DV8ZC|tcdl8s78g4~!ojQWv10~;Ir{@$h801N8r`P~AhXCsDOp+c4S>$^Aq<>l4JsGt}q zmYXe`13{yC@fjsoZm^*;=V11T@7j%9C?_Ud9C~=gZkYOWgpl!v;t+GoGchn2tWv79 z0s^HGjc?ej9~`LaHIkmSjptJ;zl%;b{YGET;Ar1^H>+2fJ&nPo%tA|x9Ng_ImA?f@ z+G6bm(3x)>Rpuf6WfN`bsOhsW1^7oy=H5& zF~{0LOHET5h*L}7-?AGjiq)N)p>@@Rj)P6}@IO{S-d&!N7AtQ=3E2Cr)qamJ|5oTw zJ2iaympui^t>w(~+o&~fk^j%*Rk{P~aGHL7B`1u`0sPjNJ0ta)6O+N;^v z&>4@XQ`_S=gChB}I?QS}Y}jnxkJf3bbv9VhZj~w{F)LNkVA@l#|bB8qb(UFtmtvBM#!<))( z3E~dA2>jIR1h4jU1oqd;X-m~%8BNw99`2616V>Yyn#)FwwnmbxuU*!?Afcd4-PKdz zN5=;TNoyoOh~@tN`_~{c_b;9Ku6T`^BV_~*^aS90AtDJl`>fla$BN5GzW#MIhlG5( zxVUIEN(O?$hY#m_XU;2~0T=qNUWe!jw694(kc;P1p&(_$`xZ}8qh=ZEDjY?yHB%@r zk%9R$M=0V0B4U=U%tS5n3v-<^8ihQoqoX!1lgSSqoiA2aI5c_rSWh9FyFn=_xXx>{ zaOD)?yNX}&oX^}8*F7w6HGt^JSAVK`bcEh7Z(?hYN1Q>u)~D)cGVovULJ3YQfak(prw^&V4$gV0`27{kWy1e z?Bz-9HhzyC92(l4$m(vn-~8zG+OSt-=zUKVd0s)6K?tW*_69O>5Jjqv9 zT8XI5FvOz<7kYeWWM{i_`l6ZII%Q%)ZY1Hrqr9?H^Q}I>iud{A#7F_phsPE@&>Mzz zaebZXs|^JJDRxB{9jh21J&EUdc0(i~c}sPHBr|)-SYWsvTKg*B*T+XFerbIk`PENs zqoeG)FKG=T<>x!Liao>43e1m9*)ry`ZucD0Lc!l*o4>9aXB(Qgvj^;q}e|X?%bOWncqgXB`%0K^9D8x z+05cvEteaC^(PD1)yx9ZFjPq*cs5|vhQL_9fuD#x3_;=#Q%v*eVSrlc?nv@9mB#fL zB5s#eo@c4~8f-j5%BANQphEzR7>uQ)4XbnTdhbKDEe+=ks7Z=lGR!Vm{<0fSk_ZdB zc(jhq`5F+WP?8(_2VYf5sPtbX++6<-2mwZogAg>y2cX*raH-FcH$@!oW8i-RVr@2$ z)GC&t$PEf8=%;uhQ2GWR#8Mt}_8AQQ=GhxuX@vk_7>CBeY*srH{plvDiQ!E5=LT$p zxEH&_K%(zkFK-P9IcCiwfCjAM`&2Kv>jiy@e%(Z@H~*j%fCRx=@>w#O)29E10l=c- zy_^iXQ=qL(qc#bCqV;~FHsSv!l-)9Mu(9DQMhY?yEErdyz#vFZSA5mWJP*s-Pwd@n zm%_~0{r0pd+xFrAw)kt7e5vf##>V$r;vU3~>F(-FkVW~Ep3FD+rYiK;4q6_`|KBz{ zYr4A|h-+SQjQlGa^wmp4;)OG7+iqme5IwOt+7%I z-}SIi!Uck0ux7d~>A#W9*c@1{k)zcr= z;(v2#Z{vKB6(s2St}$l8qR*02p;EeF>2&PG8Sf5J@zy}lGxJBGLbk&9$%5I2MpIjR z`{wVrE&C5rg$kKU<}!tf1@RQ@q(y^f^}4lcm8zu+C(zSzLl0|G-?HQz0=hRkOh(9o z>`8c%Q}AuH&Av9sE~|Ro`sE5Ws_nhK92ts>>vO^U>8ys%bov7uwhGnK2KR;>nQs*; zR4P=Mmsb(M-GU`06?OKnT;YTX6X^?pA1|-2WD93*Zc~3xd@mX`VEUbs=s&9Dt~>qi z8y=FY&cB(L#s9YXhCZ`9>(^~XPEMZk^aOZ})(O*ERzbx-qhtzV(CJ#~8ZAkYvu5#E z#V`vNEEX)dLOB<9I`YLAcX#BhtXRz;Sz7gJQiorM&{DB6CC4Rd-kNZ!Z({rQ>c?jb zD#HeTvZx9Z$K$qg=z3nGGUC$EtY4?X=FNivVQp>waD5<|-^_u6iYgXMRu5sbJEHnK zHuioaSVhk}gp`w0eXQH8O06`N*PEbKD@v&tU|O;!XUc`wzn>x1{3TlS-l04h+azqOw$ zRVUw={#j#XbBF^tDC+4k8o+(W`sYKD3cQz{{HKfhyuV3yfcRnvx5_6wb|26 zx&uRYFk{Gxo+2p|6JnNoB66r({gH|52Sw|JvzsR;5rYP0tb1`>3_CDPmTu_NdEDCi z%g$_g2F8Y>Ki^DjGjC(#G%~o^J$`v6G1=T6V;?-dK7p+ppP0k@JS^%` z?ssip-CZshZKS*#d^C->{iT6TY`}InUU=uj?f$BqdxHQIJlGEc<*4o4?=B}%l-_kb z$Hc3xn$>RZ>~w;!3dbpPLMo)(*vCaV#dTf1N$tKPE>T34UPI}&ZPAt}bJUyo5#ey`7_a%wZ z1`=3{-UKm}>hq$Q+iiFY#iu!ib*_ZpU6pa@ZafRqJJjhwGQP6XLQz^gedv<8=g;+g zZ2#|?xaxERlR29&`O8MF2nZ8)Jif#1KhuA#S>B#ThOo9eT1qLa7n6KjZRPdZTB6tU zgOWL}t1EO))SM$yFcdPfGmVx6tjNm)6BQ@44j|Wb0({5GHyA- zDHAe5h`4U@skGWwFMjh{?!DkwBzz8=WlKwq2OKO~t)A)Wob%+uS=P&oen5Vog?L_) zhL5@pLrYxV7Q#O>V>*BGX3VXtDxlbJGwR#1d@OibHFu2D#yakb`@ zEEN+~xr9JkK6s8od<0^TwR@5tOKn>rwHo|gzgY2tfJDf%Sv6mwRtmuVV-{R7!<%JP z;Yg1W@Lf@Sv8Ea!jp+duwGE~tc`HGQ5@qw27s+(AY7TWepw{6TbY)*=M%6n29ZvN{ zTUQZ-zuKezLQh|*1Z6BGg~ZOzE-0C{dxwkWsb__~@!JgIHfr8Cf@GeGh%EE!N^ zD$r^qrL$VmDY5FJ(G~+lun=4Y!5-fGqw@B*DaKHRd$Ihpu!IA^^b_&V_dIKObOJl1%2B6dX+v?%$gF)rD~d+XB-$DM{4UOqwDN8 z6A(Z;y4c7Vl*Xw)^fBOMxxRe1L-jA2U;e03@nsW78j?TJG}zmp2(8uHpTcT1;@lKh zgzcQuo8UFArvY(<(18+~d&$~xffM(h%!^Psl5l6d+kNpx7hN+2y;ObmiP9zbVmnw} zgiWL3cvn^T9z8_=P2C^fBCe(|d1Vqg8oaSiBzGehDD^Csz-It=!^LK(KCkuGL0> zUVXwrvtBJx-6_j0spDvWHH#m@=HLX)7LM$U zrLv3Xb8^N%>;b^QuuR$E)!6X)vG<_oc%`#Vdz1aTpRdk(dB`*O{emwPYz3tetoM^` zG{|=CYC<5<`oPU#;z!%F5&7Fg%SrWyy$lrP(zSMPUOlJN^$9}Q(5SWHT}kaYm$YAT z`d4|hN!*XKr~no9XJB%>8&8sFL|&R(wU9xR65!S;<^#s!i(S`WL=x-m_?esM=Vm)x z4bMvo%jz`0Hle2~;Ie8ne$tA1d+4C3te%o%Mi?iJfkbgLMOiJL%$gpR=%q49{f8a@ z?z=U?z-Eo8__8jei|(n#ZGWVWWdbigr_+ySZyH(L@gG0fqQbrX3^UAJTkei}D4m+zC9GPO@{uwH{C5|8<~5 zkjxX2XpH~GX+dnNi~Q;#KwUJMH4yu;`rH)f$DHXEhH9Hhihbykk_>B3UX=deO81lf zlT+12{`garYvY#gYC5B@z)D}i!St_D+KN~IjgeJD$SQVEH5x4-B+nqfAmUz*FiKA! z|N4>~7dHar{Hd=59M{^UyRSF%+AWW#j~Wuvw0F!Jj<1@MKn(}TdZ0d`%H5jOB48<= z{9!1t-J&SP!o=)btTuMNsa@Q!Q4``~@#_s+%QK&MA8c@d^XV7n=?kNk+S`g!{zRDJ zQ(jIx2w=!v&+`pABs`IA04!~7MI~O%$m=gWZxKKcxLdF>8n^WHQ}XBnL_kAx^VOW6 zYmF7?&sp1RR@ctA(Lc3ED%D2#5T>T47&P*(S@QYQdbM*WS4C=B_MKhe_w^K?*~l9d zDce@63RfK8IGe?Sy0yf|?YUh%yP;5?n9a`e?%=U(3Hd_C!~sypF8@(>sy zx;LBtA@q}mj3+M@y!;EKZ)0v9J>SZS<=xZYdk{*flj^O5z4l5+E z!%qJ}>%neanq}aTF+T5zFO;1$kUfVy?C801TRM+#`-t^Y1keBcRYK`-9kxc+rmMu=BPOD#$yTq|tNwR&avewS6Z#9?9m-?y4BqgaFlr@KjhSr$jYeXoQ zQ4*KAPU|jw)N-k!v`l&UkpNeUDP=CMz2sqn#hd2kH->K&m}IwW-Ryx}re3^kQY5(% z_Ka1mNmH*>KPi^d1vDzmdLH>oJ^KFL>OBM&g7;5G(^`{Soyg}nS~(t_uDmpd@RvAb z9#!F$i%Z^2xk&Av?Ja-g^|>M_$=Y`g8V|6f{byn19k9{;^*~rJ*t@*E0t|*d-0c$X z;qEM~y`7MfM^#lXSyq~dPf!r+_IPplmo!i5N_D0*tXgUZ#fB%cy+ueR{_i{BBzyMlWTFU;^8;@&gxgGojaD4jX+)poTtKxtuH`A=cisvvGB^E#u?_~>Waer>>8Pm=RC-V$6J?K+fbDg%dLGP8;Iff z)uky=8t_I0e@k7`M3?0TE)TkoGLT9dv1XbwHPkFSjU<>GGsq^)%9G^on-<|luoq(Y z+qRPEycj46v4^l?h3PDn*?pG`nl#?2`JlIbzJsI`a~Nf|efWwFYAN~&WP}B4N*o9R_aHbh(5!5q%yVIrNyZOIV3*9|2qp{Hj5)taQ}n3 zv$GVaw0Ho!aX5mTSJQDYB%FUt{iOJoFz(QBZX8@ZF@E*y=;&~JepjL}8zC*0p;V6= zjWPbqH6?@-p!+hAVx3Cq=4+rVp(IjyJX++gMuU-TmS%oMrllw}YwX5#r{;aPuhl?`0g3(n9I=4`$rzherYByPmT^6IQFEEv*(rk+}6i=)Kki_lDa(~^vNdk?w*i6m0?0QSX#VSMPQt#81MV#+<0QEI6 zK2H91^U&8tPEKxMbd)$-JP~#J^&)BvkJ}ABcCaUuS6Zi5t?}`+SyQX-_}Ie3)00v& z?^mGIyu)HyH542MaypP!JHw1GSzWXc_@e1d_lQ^ACj`#_Oyz9v9hrPAoQG zPxMzqOoPX8DtnC>QvIGUdUeowegHMN6wjY<%i>Yf>+Wo3I%|wNUEQYZoxmHj)jvsZ ziL0+)HJq`wEz1MqiSS|0+2{5~BkbYotU4g9R%s637f>}>W@)UVuhiS&XiH<}jo7+5 zAfyv-j?1WeI^f!8slhAg^HS=vgu-5%?8%B_lHjSIr2ip4cR(f4dv}*+S7+;iX0Df^ z(^-86^jDS118LPuZi!~TMdJsidz6cPx-hb{vsZ0>U=)gQ^9v9E2%sj3V5E~Y>daYNz{9^412)l6>2M+z zN?5#Bs`FRgobytNQXGY28c)84TvHP!mpQQw=E)uGnfE}=fviLd!OvzVZ(|^}OVhMm zuD2F8Fo+uVzZ+5S08r}9LpM-$*R5500m~KcjmNVm$sB_1<6mV$wL8L*Azi>RizRru z(DIn3`B7K$l}tw2-(#lN4E&H&SKA}7x3r9uS;lBG4aaCFMG{BLOr`0+o5RSbr%J9t zQ0J8}Nu5P)$tW2PI|kLp=1(|yp+`x0r)(@S4IRX5W<8gDJIll0e?0!7^WqP^NUA;>Lu0!+JA`N%(H*}qGNMybhVO0lU5z%UQ`v0&D!0huK6E0iss->D zZV!?Z_6wKqMXkL8H4MFK<#J}*$?SSK_>Tq~UC`SG#??kA9BOQfW4oygc2nZ*-PFqPlGKCN5MNnx|2u2<3E^XAv63_L44BdRZy5GHTrD zhf%UBwe()OMaikF`=Y@MC5hqj{01sI6QtQ;S14rPzkeqoBQOBG67%Yz`Ydv$*d9A8 zs{#cxOA3bU!4k2@1X>LP{+@#x=29N_=NkjqDLt%e?SI7?+5WB|&a<{ho=4=k7Q|g3 zF*|F!jM%BqMZEho&2(GTKJv}`-EGckshlZY1u>JWN3?1qyLVwWlI3s+8RYrDy3|F z*J;7Bbz0V~SE)mXuJP#V?mqpzdJ52T5q%NXwsl@)q@?zzE2>`iM0Gmb>ToGETSvvh zrAo0G)?K5crCRZt{P_i|!O?>O8*cBVgQ3vj*&+T-dwTvO56^?0`uiiO;!$`cSm1!$ zn5^Z`6Ced*vRH^-S<(0*Yuz-1nV-=8t*BeFI2T|}tExUOSk$SxYXu11zR+6SW_@-HX|0FYCmgG3o!1b3#D%)H*l~oP%bnt z-7y~+!|YgK00hE!c6J^yVl=9T3!D7~GU~Ughnfmgf71)r6^u_}xv24Cp+cp6IgZ_u zTTb%Fja3VoA}q!DDYN0CQXjA~)LErM5+{Hn0wCN~&NB2-a5kPRH<^Q{Qr;264TR9r%noU#r`*`&0Tat!tq>j zY_9utfiY9vjSXe$yPJ7V2r(*U*{P}jtD3MDiYGEGT+AW?M0?saaN+}w7LyA&b<|+gJI7+&X{om-_j`AtRF$6Z_`~MOWD2aD3z8Ne7a36as=V%JR0Mw@aXvU~{2TpR{RJY~LX!AUSP< zb-yQ7TRbJD$M5lJa*ZdxVF-rN{Hr*O<5zUks>w&Aw2%b>he_+=-xu1pUuhL5Km^50&b}xuiC3vN$E+p6+|J%<3 zs01plk>9;xX;ANT@i<{RDmJ>`onKuMQ+pL6H2WGboD8ML)oO>CfR0})VjNKK}++03eqt4t7!}p zFhy8&F0$V7@$w!!FE6iqFnF>;w_C2>cIT2AlLH^ln*TCrsgzWlhQzw#-3^_KmOoEi z1?Q2ltmCLVDzmd)I!|zBpPP5&Nkgj`$Iy3(@*2%^a<~pMCbbdblTA;BV$eR z&NL`6xY}tHr|rcp_^R@o`FsfxpfyUJogK3|OG*ki&GRqd*_-0hBk)r1PG7Z0*Ov#O z6+RJpZ%AAhl!YoZ?mil_vbg2X5o?m9JCRxBu`oQHYDeBc& zkKa72el;7G-LtVkVo{Mj=t^TtT! zwFC~k9cwQB5iCy8hFn}v*gIko^H#K4AZ~%46yW1Go21&bx~6>?2Ypv)^+ywc=t=x17h{ zS{Vvx@SHrngwc;8B!n%t{4N-XUtj!PF<|xapoo;w3t^H_(%?O{sLBjtng=5Y5Y1f%JgPe z52*ItT-i0JPq}VKR3IsvKo$MT*CQBr0ts#z#;9jwDiZwN{ov!~yM6V~_hh_G@$N9x zTOesvZ1!qy6*N^Yb8OLcZq;*;P#=1rggGk0SK_2tt+Wh!emLv$;BAuMvA*7MZAmnj zhCE?ZEV}%k{kzFgTV2V6-U+~;Vnig5hL6WiAiG3qQWE6<+*owG1Q7>}QW(l)V?Mh+ zKPQUAcziit#0bE6eBFK&vb`H9wRk>!uisZsrF6>@p4vQtEl3`Sym=~GS>x@9JNa`M zo6vad8HH-0CB5O*fmlxNzsh>Sp09nsGN;Kz$N1ust6>9|+x43fZ%pNWG@f4`ik>t# zr}0BwtjG0DB|ng%=BC)5z^r>R`rGUIY+@`ydLz+EsBdH3h0`^dfsF3pD!D2u!SEg_ zX+*zQoq4uxzqMHX13rf*)E7blr=JO|dLpbk77M=Tm;eeiz?6zweqtt{J;8q5-04uI zRw52^AYS6+L@Q$X?e?(LPg-Hl%I_#7l}=TcTE-3Pf+V{8Ad0n3h4s%=Zq|ShK!L&p z#I>}XC4Rp7MRB447DQ{XVH z=1YQN$=OZccMJQQ+{u2otq`S1{;_@#n_6>dLb#L%(-e$Dk3;hgu?$;BehZUP|CB+` zi^sPUe%}Gw5ZqjO-ZpkclE&ck!nYKtkk18!;ke4t;geM(qs#m|!@LFWcbRH4M~8}g6qhW<6UIZ2`^X8d!;Qz;gkH`lRc5Can_^G!?+R*X;rj}4$<7CA zN^S18BvNK#Cw|c7c?>?O9?>gpgR&@&8UWf7@bLiQe?tHL=Bq=I009jzE69#DVVkzx z9J=0Q6*7%EsOOnH(|njxPJ#=LoDT~{Es!RI!@;Zrz7L)NKMm(&0(|7RhhVzq#V-obowqx{eI{?$@z9L%(~B6%h+8lPr?MA%^4B6Pdj=7;L(uK{ktX3%w~XB^Tup|1T;x3<1?n zil>ibzoOka#IxGZblsSkepeimDv@F#c+8<$xLDHLHga?k94dj4st^UZTqz<(^LO|Ap>lQkXF>)6>HC_r7Xt%=P0Ybp!Q;~}@wF0W z^L`UD)D|j(SJJQ-52=F=h!*49?6INPbxG{4r+UWaB3;&#e5bCzQ9;;MU~ZVBcl_8_ zyAE|o>7#yLC_Oh3BrT0dAIU?WyFa93ge2uVRjse>P3rd~xu*Zs))!?n=vbgj70oCi zEz(>($@jgxA(3d0MI68BYN#j2_jAzUmOjQNW}>ZI$)RO*oqZm0b^f9mOGtKk=KEQ? zw~CpAfH(`Iz#3nZ@KAI;=w{@YHRNyG#(P&NtS!;1AybE0#S0H0iiFQU z)+(U0G+%z|RA%NjyK?}9VN$!!_sO+VJ=Z1_E+{yQ$%wW)C$fqW#_mMSQK-ph%;6$u zeZEqGHM$VYdgrZ5B4ozPP@)>j@<->ZN{^bkffZKeD*GF~Y{|^&BRC6Gsrhr3dk%!f z^a8}?$?>$&OCV%&Nr~$$k2#zy{YG3nIG;_>UVC^KcHgx=oVuf~^13SZaev~-|HI)z z#Q8GRj^IE4SAa}|=fh3A#de3bKrKgTC~GFebovpcI!iW~L!K&-h_hcd4UvtfxwvcC zjGv%w_Xj^jp68kV>YY}vvrZ4KogGNwqhM5PEDAm7{x}Nb`X&zNjn4{bn1ssT3KK!c zK?aV>+6AxIF4(Gsvr)NzBM2>I?5tK&=b#?c&W1aPI!vgL+gl!c3BTb${z`HfJySa3 zaVq|i+RtSB0AcPb^@%-bzZGVQn>UgGmF-`8YUSasMe{M0Kn`n1POB`Ro3`7hlvR8G zeMS0e*kJ;l1e~=#PX!*tsHMOJ=nB4WM%y~o7&z24%&f;miqfo0UU&d={_*e6Wt%># zha^+!0AggC|E7GwKK2|i)h$htjS5Wq)}A-3fOw}6wCCUkoz;4TZIKws4n^*>bMD4e z`nWk~iBUXG(GfEt;vxV;3<~RF|AZEBYvyt`| z_t}3;^#MRWU?guiLrokfyKAQ|?v1 z=XzL(iB)dw6HqKI?9_4fws2HWy1i87pZ_|@mb19^Ygc3-lYK@`JB$t<_CO-{0R*oQ zan?rRV77$h2s1X-eN5c|Vt=Qk!0NzMC~qAuPo&^cvUnmv{4ANm31-W1<>2L9 z2H<74U5nvu&{IFuOY&^LGDR*=@EE+Ojyr3k+aERc7dJCkhMZ5EyKt#>$5bsZ zbDsm%NHM+&;%`(e(HR=V*smkQrSs3AWgHLczKl`rz3!cjWUEFKO0O7}FThlVQ-zM{ z%@Q$^U-1zZ;%SAl&Q!ln~?0GG)1%di_BmFZp zFBvqtl=+cV(p(>ip1nu-VN$Y4<^RC`=I&0RqRyB-a1{SE&kufOHCPC4fj!wO*k?FR zP(6TIM;+nAECd*OS}w|fVKY`kj{&d7WT*E?z%%q3+9tYYyd(VVGKAN-_pc(_>SQo9 zRLh6iAIDh6$)*=yxtN1r^NN#s%1~mhDytlifHJ-X$>3j-nh5f0mX>oGcgquEyr2mH?+r^Yy+(&I;a@WG$oZNWhi&taRoX7KX1tptFgT>13K z7;iCdl7M;BCW@y$-5+c7TsQaf9VePfa1|Mi6np{7Od0g)Lg{MhqJFtv1W<|f4r;&K z1vfzN9k-gxkP_I9E7P8_#V-?;N2}9+^)@^*Gf|&XbKB%SM}j*pIg~ufL( z{F<3>^mn)G=Tb7fHJ+Q00oR~(LI37S8G0J=zL;d(ki!N{RFIp#xIF#r_lUs`mP7T; zg$$#<&4(m=%8I&Qoy7hhz@))DkC!TSq$%uV(7vPG$+xuHeJr#V-SQL%%ga%fmgqjX z(;RzMFIWiVw&WtEy4%F3;m6xbpX5ASKZ9AJuBI%0Y?Lxda=U^F@Tnm#?UOGU!|^~q zF{SWEQFsO9x=t{~k%w^R#nBURI;(dCyG8Hkx{oUHw6yankGF;W_b>PmRwL9!{<6g1 z@0XI)sw%*Wn{BTLxl-L(Xn*4HP7{tIQr~Z~LasiA>CRHwjIa!8VXVLmLmwUqktK-) z|JuJm4X~yXl6s*{m?7haGxyp$HMCoy&{N>vu|bd>m-ISehQMsU{G|}|iPbl!P$_(O z_)d5E7-Ok} zn{`E&^<n}CawfUf;6UW=6d@HR!O!+TOXNi>$>sx}g&2Z9BhpGDfam3c$2qd@! zIo%797y}w>_ScPs7phEQU!D;wt`^}^lW?QXeq)(#d-*YzQ-3M%*HC+{4kz5OL%TQU zV}JDKJ{*8F+19}1pRojE!cMbj=*_;`l{K#HU8s5xWb{^Z`h zxzI`UuWu4AlEDf!|Natn+0?WYx|kwh`eP1!3p82+NX*G@1YP*ao4UV^Y72$ zE*AdS81T{6#M)8+Lf*|;l8Cr5wuA4#o z<0q0IEZkrL9*MYfy-3b^V7i#}P>YDR>{9zP%(`?$;8eh^PK2=(x%Y#YLJ9uGh!kdc zONJBmGn@rlX9%l4f*N)dZJuxkzF;pqWx~D}6m;(YoduAU{E%ET4Hl23cS9dlkNnCp zkKvfobBMt^={2NgwCe7sSgbG3<2?9j*e|9P&V2fBrdRVQS?3?I>k-}SeFd34UrV=Y z5^Rw*F@+v{CggLwbST)cp`^ChWdE-p5Uluhpu8ddi9d5WlamTvN<|nBE_89gnedC; zKZm*XSDP()#+WQt?9dX(!S* zc?Z~QccoLZdBLvX3#wFj^JxYl>+MDkyGK8Oxb|FES|s1+%%>I1-nDIbhhc-7(TMm0 z4Z~=TZlo)8)vQlVwOyXnowCmYdP)Ay8=2DDoW`S&cq?B@MuT6zA8<)FX%WxWc~a@LpuL(P3OTgHA%v)z%xSqZ$h;kcYLJT-)v z+S^)vgi6da2vdd>?duGtn_|oe4VzB7@T5`q9ydN(l}K0nBkCbfOJJ_JI)|~(9shak zPsn(M{s=?0qd82NG$)2+-it=5=c1 zCjO{yU`j&Sz7q8HXu1i}ED2u!8mw8kL(MThbpZM6m-Y=CQfQU=Uwx*x`%Zr5;T!eR z98{nF@uzXiZ83oSqd*srz{}I!M=?!@@#2Jo(ZSbvD{Z-gSj!Fg>Y|p*8AQ3YI5=p@ zj27s{CETu_ASafQk9*s{b-CJUF#ZIitv+#uJ|ff`Ns@SF_|Eu;rc$k(`9Gr4*Pclv zQI;)xX$?Neb7McMunDAleBRoPKc;xm=X3kYsV{|kIRejO0UBs7e+rY4ve6O#7(_!` z?RMnELX|FMVE!&x zSFC4y1Z?}G9mB7$)xiPxo=?2)&IDM7jj!HMj>wF3-J9V)AN{HtAR04O{Qd|_$}!as z&D7LHwpU5z)-BXa0nUM%4R?;+HI=9h;4<#&QknvNCVXF>%c?&g)O6_y%eH=4qvr+`%b8pzjHf4EHLfHS;F@lg57W z^f-a__P5(kTdJpEA7#bD)yb7(r{|U80YOz&woIX|gg+=_oy9T>=6IT)!_a6X?jxqx z+0DC$&&M>E!~!j2LdIfREam1`*NY614Z@Ix%QZ%7BCT~#X#ewc&6K?Q_=8TC{n|`? zZn>W=NN=g0$MlztZR4eP+lPX=vn-Fb9PLv$9PiHI(3pF-M{fHXr1x}QxfuKm>BZ>5 zNRNl#FIg_Kd@_G6-f9}mU!Q!FAEVGFAb_R`-k1+YZvFk_tjN%zFF2g3taTu;mY&yo z@SLXeoXZ`Byi~bZe3w4RE1mi5OFH;C`G(KWns#2#$YNY%$$guw#`F;ZxY+`skNxJ{ zBkv3_Bwsz3L}-~=an;b^p^h!ewA_nH2Lw%0oGdpSDL;rzn#}UfhN^)FLia8_7wR0n zgOP@w&nTe1Sl}?(A`HUPYBYWVLN9iZP-xW;zI>Kk&ow385FOT2v4%CPe;^m!ecL2# zkF5(B-n8jwabN>~IoAATikF-=eH2q1YcyZLSrn@TGChc()MWN0i7l2k2d*shKBv0S z`)L(nI`AR+I`Sc{zobGYvbFi3?ev(ND-2Y(TsWl7HHtr&xxsGyP?Tva`Xo28dzM-n zyU_^?(^EyZqKeY&+x#oSk>vA2G+!h2&l@lCzToGv&DFq?X7BF6`M$(1D@5@VW%J$N zJE*Q$T!T}T%w7)`A6F%mY1wKMa5-s}zDH;BYDBoQ&R8~4vrK;ST-SZjU-WmM79XXI zEauObN-Zm29Ff|Pds`SN9LM#7hA2^qDxf{t))*UI2xg7J(tJ0Xx6*8^^`Dqmz4-dF zyQ1BQ)E#Q#UUW%M7tNX8w^#aV@`jj#k(j{1aaO>C5uQ>Z@ywVmrR4Y6V(SnAhezQ) ziC7vA$177O3!mb9L0oKp=gp${A9v!FkV&Phl+)Yu!wuzYl7qLmRDT)+NZ>x(O3;=! zL*Cqqjek6n>JI%r&AVyCT51yvBa|mMSZxiBtl?DF%Ke^U&l!ij5zq`}f1vp5$T-?= zEkqYBd|?QIxzUFMdiZ_u(`Y5mf1M2d)3OF-8PdMc*wcY#88XRT^Bb^ zQ-pvUAAEol$@9?duN42*11k{q2{RTfy5g-VNgW>WR=I*uch9c^GiXTnu3D&pV; zj=NvvR-k7+7SyJi`BBR!7AO+Fi99L-Ux z!~|saN=rRCO``Yr?01i*`S@*Cj$birv<5OE;Wa*{#T$@e2x#s-4u^-+lmc zlai0o8V{RE&Spk)l4mr5$1%z#_$yIk*6xCLz} zmec4JywkK-H^bVq1AjT%$u&#Hkd5D|)A3C1#Cq~}ltpg>p4OWZ2YzXM?r+8%HjL&{ zUFU^o$mUxWh$!jwr_U$6jAD#Zj)097f0^H8sU-T<#J3xkLHZ}J7}h2mw|3X_#VRaS z1`67_R*?G&(o}P3goH8!J<1v&w;Q?|z3~!9-KKLm>V!O}e1qk-F`ikP`VU4gGYfnz z)=;%6NfjfK+Al0M-YwDR;!fW;({I9AdPhNgzRVJaZf%HrGVi^Hq&{2;N1o1q!>X`E zOTB-#`r26Su(>VoVK7*IQZH6W_@~f&)~UbAUNfH4D5OMFtYG^T= znzx+hgRXs8<_!3a7kx%F?EXkr*VZL3BEwP4$XP&m3&sDr6?j{Skpwp-X6XHfxYGDg z=y)rRuhRhG)a!h=PBy$2FGh~)Zd7Ce;MiDi&705>Tj`p)@_It#`DyC3b9wtm15Y$X zF)y(yLwxXpctubUInbPgQZQ#|_!f=w0MI2{?SdUw{~3wI8hw)eJ%*#fcZ+%@c!lca zz=q|+4m|iU;i|GA5^6|Niq*&B_U#qoIjz?Fl`w6-rj}rDY3--RF5yn_@pNfS73uxE z^P|G_m??gh4UyQ=kD7v&$sY<0jEJ&pL9_n#+2+D08vqb-!e^o`al<7QTP{v}z0&BD zl@i6grI|-X9DyVT#(`}`OW}e#rC(PzH!TTrPG|;0LP&rHm`&g?!)30Y$e?`uq4Oo1 z#%&pX1AwReOvTf_OeFh2Gb8AkWo)xaLf0zBcri>gtY=d&eoKUA-Jqyf>A)$lf=F?* zuju|`JQb@$?qFvef^Qv>sD_AI0M38i-`ElzP1GGi#aA#UQh#OYg7I>8mpb-jHUT7Wf(j{FQmv4nPLXUoV`=Re*H-XU{MRiwV?ggSPaKq34YvQEgyDK~fp6j&nl^{++ZGabNp@AX& zDmau<&a(tVI`?ON>U}XAov=@uo0^1X?@ZuqDu#>X<=_k@1v9YP!0DhvOo-_$%?&w5 z*Fq#E1Z#W@@Fj!)EN zuy{dprNIILQ4Z2JxS8E{3bQ`*XP=t~&9$z;`zb(!ryg2;&F;vM_-znk$4U==yAi2l zX!*W^=$>O!aPzQ|XBrBE^OVtZVAZc=1LP&HAxu+jBTjirG%&wW$%77$(!o7g1)6}! z`FyQ;KJaz7-h{x^jLA7dxY>mAVCQQ<15kRf4K&OLJq0uypK|!e;sq+8iLCZZJiIxg ztWqH!*c`iWKA?XmK=_6d3NfG zf$`>sB?1^+Dcp?;=2M{|G-mQDs+f=HwXBA8r-;qaV8e7~Om$`qKiT0LPOne2ch5p2 zhlJf2o8fQg9hC#pd;+c>9EhC!13lw9uDFu!hEU)&Uy+0!sYV_y`j_|Rw90P&tS1LA z{yK(eVg(_CJ*f*{dtaX7ZrGUDT_5E(|M2#kHB^C_u6r{tMor2C4?ir53U^jbme^;X zpVB1Yvm66i(s4ff-Z1oK#t}gTxikD!-{|W>usz+Tor#ynmuoDWEU)PmtdT0r5&vL( z2yFffft|zlq5J{V%on7=F(O^_OKtZQi*`q);VCiJ@}}$#Kf}nANBm2`E5kt|Hq_g^ zgtZ13Uv0o+CEhfWp8G=V_^7ebz#<;=T375m@`AOl>CJJVvgY-?tr7C~y$(jNFX4^do2U=fh^4?691|J))>`&ZwZ(f@0RIiZ~8U zJ@@q)gxuUxj$iyslJ4fq*!4b+LAURcj?YKsiOvkY2;UD&stIRnOuU6puTcHZ8nNvAuDgWw z`JQ^8)h3{LZqbu@P@n`$Pw%YP)o9*r;MZ_3y~JvQTbtK>yG7uX`nFg$Mgs_)*1eC- z@TY!q9lW;*t)76Rd*!SvJCMYS^1oUl?3ecm11UUv_7DE4m(>g7x3k)@ z><4_lB#|KUsG!~1^1y;hsg}SuDR|z#M#hjn#1{FTI|PO?MVGc(%Kblqqbi4 zoX*jiUtjMaDH^~B7d=Ib1$ct(N7cPwE~F5eg9=h#9{W|YLJVK`lOOCF8f-_39lMzHcb2l z!Yq6kPB(oL&bJ?Hov-Fwv+LQjp{OP&cAb%NJQDX+@{cvVmUyjHf5m4q>>`WOK)qfTk5~ zpgDS8O^47bybCbRsmG9)6}~nHG)kN>>3QC?SOTtHpH&f>VaLIo`J%!d22wqlu^pIIonQb$139F)P|A)5vdGCA&_V zcO|uvUVF01XTvtRJkzXuAF$X}z%g&+r&o#hm(=(1!?B~(kpRj;7L&WLA2-`PGd~cz zSfkUs6^KF!;`SycS0KcY5rcnCM_#(^BfgF$NiPvHB~CXMjx3={2ANlx>@%h`eeP~N z#Zvp@rSVh834W!xnR`UR!_evSJ4@(46D4BO>WE%e9(26aPl+{r1Z%9`a9Q9Q(twKC zc;b}tt@;r_Mh|Yr-xoU;<6&A0%f#|gw1|D8(Q9lxbkltXsON8swz*3mey!;@)_S58 zBi|T{<=r5!Hhw(WvTI8dT;oWB{0*M=J|V1rskP6*`s8^W@fDqJyNucx zhy4TfpmHUu?4-TN4?4#z(Ul&!G(W#nFrrWMzF#bh%(%fnZA5eb9L2)1pI7Uh%DqhR zbDI5(uYD#i;>JOzd&f?oPWRKp!aJ}mx>JBkQo|zzMYZs;UK-_IPdF`Y*ybsDoMO!r z)O*EpI%{5NxWLkKkr*sk{+((}jiaJ9rgC7Spr(VN^f?t3u1e%!1R&&)CT!Xn(TaZN zdTYzs+sn7B-Ak>-FjMxtA&qd<$&GYTG}^hYT9bJw_ff&jpq7;#I@lw9RS+l0T9X;% zjbO^T^(w)0=KN@K!T)$Qf}5$M9vvTSeHFh!*8E=doh0T)=CtS>a7FK&?g0<1qb7T` zc*mkG^U5jRW&J~OIqHJGpIWPVL&cx%w(*5i>Kh&#_bU~b*1d24_GX{d$Id+ZemeE5 z4bCz(?%SvR#PY-qU!^#3{~Soc2GQ6TyzY9SVZUt6RmyCwJ{#qyr*?x?onL1TxYK&P zHaS9*JU$WKBN*v3V^(%$TU{Tz9HV&50Z@7Y);qGb-OdcI%T=-7nq7vFEEj->VPuMQ z1LO>4P$cQ)j%u=}f0Xs$xw#l6%L}M$ORl7PVVXXV-PHJ}uKJGUt2M+cQeO~e8;x|E zW5-mf6Vt!1cVgL4$dflj@H%T@@edlV_T8nPbPi6ie3C>r`^Hrp+n99S@ca%LYvDt5 z-*o0g1u6;?cVsw3^u=fU0&MHmok*~jx4p4Yf9{6b7IQ}q9)$; zI9Ayh1B_t1yLK}SxZRPa147X?>)+D`g7c9F?CucqgT*sD;0G?!l-KKX z_O|ZE8$1so1Ma(r=g$BK#DntL{emUYES~QghgM)J2CHqUccOwy)^+(Dxb~W@sLw#y zoGMU%IE>Uf{qwqHuP-<>N@XtWQS)(1&VbK|I;AKyVWf5fLOB`}9qV zT%UGM<^6IR!ERR5arCkJi@_s!t^=?YoO0RyddHrGwX)eNnBo)z`)K|v=Im$0pUo`) z@$EqK%i(@LSNLr6a~;Cx+s%WgWCZ*TMF_!XxIB{i`bD#?tB7)+hm}khd`~CT03H)2 zR7Tl>t=}<`nzz5!uPL&ivjBCb6K~HYHQVi}(!U4msn`=ZjQ6}WLo0gjCy7-yJ|qCk zMfN*%^dcT#<$>qaJ35w?pC+6lKhe(Mf3FH2Ja^fC-PY$#<G4aeun> zNI9owD=%6C#vQ>I?Ds*=c4B|!P}*G?%FDiH?li-}Xyk0>cgsidzl8$RbZc)c)ivw1 z-n6*%GrJx=g6=KW`z_W*RGeLFCQ{`5z^wUc2uWZ)vuwtlGn_-x{&@gB;|@K81k)*Siteag* zd+x99aMLEZa)g8ytBnKA=IUh#{|hbJ(Ms5E{F_VjH|^r9^S`p`NP;YU=O~mr|5HUk zA2<4Q$2p+lB%DXIr%1`4G$JOnLfqlEj-%|qkw^4&);soF<&{AfDEkS?RWd?ba?IJGoh%Pe0BGbT!;NnZ9`~;J&z&{ zjlzw5eqmAG**bh#nS#O=QUL>2sfzs$MEGz}c_o7R43kb4kH1#F|9^2$Ehs7QG&H$a z=u&bVCT2o<*{_`^L!j0iOC5Lv$3mtSQT3{{I${N0jwJv0SWotx^Ai)hhrOw&_-6Y& zY`N%Z12-S@8aQ$xAisZpw0QfN8j(zIsVG7I>y0#^gzsd>sTDwJ7rpB1(td5#F=*_~ z?kM$rhumLcc0(>jL6q_QcM*sMwF=GEP4E69oM;I+!;ICjW6v<()3bTvl|6bOsJcR| z&L%bP!>>ddds^x`337>bNdifN;X`VduQ^e%lOhkb9?IxCdU^(IJ8&@|f?W~FDUGY! zSEz~f+KNB`BDd<%#dT#xh)SsRoJ9%Koo}c58)5R!m**fLnuv$ZX%Jz<=dy!Bvq@0! zm9D6$=qm*Ui{}{j^RK_XxP+3S0F|5qij;H>4OUfc?%g{DKAi6Al(F>9+riUQ=<%XO ztJ(F@eS|$bzbtry7BLDDn4*cY=w?wi-iXBFl2lPU>RQ$0_4{udw?Mou;1!Rt^G+!N zCKCimZ2Gk{??CqIP=Bo(wBSTVS$V6fraDBS9ZA)FZ#*x3`I*m2cE2{f)HN! zA8bk``NzR>Bnt2=~fWWLgd9c1<#FQ!O{>Ham$FrqcF(Na!swUbXwnPToy+3i4dL8M0 zejs{)UBrWlG$+{ra~I^pNx@GUBcq+;t>g1^`lwUPr?#a;`9Yn@&8Wi<-Rg652P8&D zo%Pmjd|$lse50j0obYf4LOxcO?qiXnQu|gN6s(X@1ABR;uM8&vG^Jo7J4 zg7JuYG<4@X9y4YCoFTejK$EhWtri5FFA~=43H@$24;(yY}M` zRAuBFq17*rEsHk$6IgTozzWW+CYaq3t)A^3Etz?NJ!h~ z(@!Vry}Sxvwn%`}dg&XGZwd(s2{PvSa$G^kXN6Q&g~JEH+nkfq@u6Vk2x%kDrNhT`GdWGaA)R}+(5^uN= z+8nuw#{Bin%iW;Ne`rH<@Y^Yzo`>rfWC&}+d2rNkxVOc!rvB#wW`MXL+ga_m{T?r- zH*@%UPk+V@tv*61*QZ}o07(3Yd^<%>?g8V58JmMS1M|5 z*7QFdUx2I-6JSr6%@x+OTD5H)T(cEU>Nv1B0P@T{AI^q@+AeJyYzRk3dV#fmK%{=Y zHqbEOUmgJyE4C`m&h^$zBf~+(my?qM(%-&yA8&S@2nMOMx-TGP&Pz#4FE?7L7g)Cm z3>5|C4=S%V_6xCj(O^__*w{auM~qmDQ8NUCL+9r2?DPPsx4v(vNqzpawjp@7-Sfp! zG7NJ8nX7%=PJ@wR&xDEFjff_bA(Pi1JrH`SIo)r9RlKh~H&JvibWu;{fc>Amq<;SG zKJH|~nBF7VuliqI54$uQ_ycf;YnaI~vGL_D7BW&FYh3siXv4-DWDwrXScvCf$i6UD zN|DVX702kAiI(8JxwUj^F6z3tm!GzlP8$!#W@dV;{rNGm+L0+{=d$~-_Di!KwcX`Z zt;u$Mg(|8@m)C8<6JTjc-R641N9%pD@;f2h!QrNe7?;gH8}CoG*i|LHy;_d-?*%km zQ11?BY7n<5yv0I1)-PKk!fc_Zul1!B12uyfxZxG@MCcJXm1>VDEAaFYN=`sNJY>0Y ziT(X?1T6=qx<+an^!%)HuQ~n6Ye!0Ktb)1SQ6o&|d@~-IJICnM^8#Lt{?+xT$HSz0 zhfM7xWj(>xme-izV^1LU8BLg(g?E42;p1uGM*+H$jKP}?XBsGMe-2?ZUQf60_SlC5 zXWGNpNYtLxl;T)3`EReQwvMY&J*l^LX7qm0U714etTk=vdS3VQx3+?hDP21A=W1=Z zt5q>4!^-7$i`Gv-Xu@OV)LYN%CFfI0e{~k`_3bV1X=_mCnKc|7oZO>la&mH=+hlgV z=XcRrt5D9AK~0w>T6+2_^)x(VwN-dXIUJ?cUqi30jaH0LFNKDE>2n`!jW>E{O2sRL zT}u)T#dB&FM^-!;tJe#;&OADbidtYKOA z|6!nmG#HtL^Z{chT7ZTQq{c!+;lBW+UY~!3YVg8AfaQCyVJ_@Q_;b<2c;md{6zS)-*?T(e-jXbMya5rOu`Codx1PXeX(pae*zz( z9@6)&2NFKwV^ew;&yn`<=QoK;@S@%peC=-^RJFOsgeysdg>W)HGkRzu`jvM(=Dk(> z;z`ci5wfRoXY@Vbza@e|Z9(`|03=j8#|!A~1?cy{hN zH%eKb<}tu3@Z!{0EE2nye^JVwc%3a^Lg3PXunkHk57N~%)K|-1Szr6tr%U~$B?bYq zi%X@X6-T5<$RXk28QX)+UF;iHxA!Ee7{rDr#hKIW5pjc9tFai2Q7rf-vn@(b*rhbn zyd-MI4?6Wr2KIMP3A0bPNw(|58d%HiINQR4st>S?5Z>eu5l;0JN*SHZN1=nagH&tht2-U6-{+|p)Uz;X~S{Fyz$rgPrPo>*=BT{@pzIu<2J=81R~VfOGZlqxvU0HFO`#%6R_I8PscUJT()Xl zr?o*}G=Dma%@eM%;2qrBiVzU5-bG&|b&vB`jV;<}9?D}b%d4Oz&f(!-l zz8yALuz6e@C+$z2^G(bPR@$(9KMBamz-ef^`@qS+qN^XuP4Qy_*PMO6^DJG*jc}PP zaSGCT1b_Ct3UJsTQ4gTTh&#OrYP{p6-)@!Hq_g_hhxVQTtmX?&L4p}UuBX~#uk`7b zHD4VTFw!5`Fvs))K6(%%S;06TNM0sspMOj;LD^~zUoe2DozHq#9Iroa@Y=a900+;U z?4lcBxo;FEU(J9kUd6O4yRP+96$&B&UyT_|D%tN!=Q8KtFWWH>lQ49uNYQ>KZQ>@EBJl@2`9TY%xE9#ckM z-50(NVp@1|!A+mA65uMks%ZeRo*xL)IbJ<{a967t*SzIczv0|*TsTY&3(_(>`TDUu z>Cv^Lc)-V;%za`XEb|%AOcY)Ef}Woy03bP_%-&^8I8Y``?@mM(G*_#s-yFC*&lqEs z-AV|lSP(s9ifSg>94v5qFw*P(Rt(^ZIx^E!c7bdgMEbiB+j&_)r@;7uWLU!EuC`fC zf2A7ION$6_@u5Im_M!o91OoE?!~$vA&`Y$UMrP3lYA_0|11ssM7;6Amm6bueLk7Y) z;q&3;r7&;rioUOiu4jH{){n2;Sr_)2CZKKLqMLB)z==7pNl%a740CO}8S${~)7y*?)wwwZF>X_DQNRp;y-*V8M!sHJ}%JE`jNwrbG@!c$Oxp;FUn2NgouJ`(V4+3q(B(d0 z)W3hpxOXW#b=H&58E?!)Io0x|Ky;BkY}^)_L>))Bq9J2f%5WNvxKL9cE_T3uXN1|j>b`$LQkSI6Im zxSDdp4+I^!&mxC>I15IjT;or>KfVVxBmL{`0S^MYEo3eky)Dpcd~x+$K?zJ$^kVzB z+|cp7N>I>*v}-M7L`4)fvycF+gCyvc=Sp=;CoZ+D<)5k+4u-} zDUUR*5lxQ2A_JSeBa3LL^xih8fItgy?gs@e6%xu5hEBX(Y+Jk?8?D&1*G?JjU?|C- zTNgfY_7?;9_1)Tcd3eeG_bxvVSk|INCCW`8kfo?dsyKd^<-J#)l1y=zLQt~ z^4Tg>5(3xmvUN_Mrz~`MFHF%M+nT@=&l5kXd?F!$N0JkER#1wAz;6!;@olq{%g0;6 zQm zX<~_j%FA2K!?kxfG{yogo&JMF=-&?((bvz^ZOeD}D!5T7NKESK3B)4$p}qKO*_gW+ z7$YB{nWOyQ2IfLW_p^U47(%y!XUd_c%yv{t8W01UQ<$0A5@AS{pSR;qx)my!;McCM zsqtEu`$q=)tJ*ja*z@G&gAM$Etj8%Tg{dUJ$ZJ5NY|)`2ADC)oZ{YA7@V3lTR$NPf zdVUe|>+&KcNfVLyk7BaJ1Djb?L`8Y4P#2w7Nc8i}I`Pf>@e37D!)cy929ZWhOxD|Q z<>TvKgw{G<@3S_IlKZc4a!PEUoRpU;Q;GyE?rKw1nk9ba%H)AGHN80Htngyb0!lG0 zcX^HTd9#zqDK#+&RX{Yxze+kRu5}pfxfH@96zl2?E(sH}cuB~>;ox%H@$sWqzz_C= zZ~pDs3{7CU|13rmE3J9+JSvQn@Z zPGyLHSQ8SWV_+!8`{0M9q<8}}cAbMoMS$Yd^f#GeZ@&30XC7cR(BCp^i_Ok=(VT?r zw5Vn^s3Toi!H&EO=q$O!_%Dfdj_6TPMdgR}o;$fvMbqCDP)_8sm_yYjaI+R6 z({eOIt?rE$es1DfCEIRw2GRRl%fMONY&fhl!upe(ci1c_qe@- z0O~!j4=AY7N*Y^w8MFJXS0Y09FhFq0)*&yleSR(Q(gnrKxG>tEPQgiB`M>qA1?Qj{wo1qF4gwESxr z8Hk7;-~THU0y|N*7Ci$nYWG7%FYFo1b{t#1xVJ0yq*C%*QZ&juI!f}l%8_#B`>a)2 z0A>FP=%7-hBtpUqfU2~Go&_99%3Nv-4EO$Dct22fH7=to0>Xs8>ummgHDdO)jYB7G z9Gb#{$ZH8ilFxai6y+kW%~c)wxY7>2>uJgULXik!D48KhxFc_e;;!@fEzBCnr zO|*KGvY9YNEn@s;H1A~AWOdD#Bt`yD_xh)O{RC=#<>UKGu3yQf!y%;#9;gNgJ)?$2 zTR}J(lzs$Od0}7?=^S-hE24?Ne75l_C2MxK<(h8~Uu}iFa4vPSo5Cj-KBB8e(LdO} z7A`L+^i=C}seo<~TMZ$}tiKprZ)5RG{ToEH$Uj?aO#|Yyrt#q}t(sfbkdrM@LX#f< za;~EUTEpPRLT$kM`C>=7QM>D5Vu8(7FQIpZ!7JS-;cdY8a@%Ay)IggS#Ty-KQ`SwJ z3*G^RkS8x9eR8a13=>8Ag;!xL>@Fd(ph(sPrqhpS2{~re+x)dG0e_USXDTzqe6@b5 zkrCNBt{>Y;VtlEudQ9M}sMTy*gY#yfSIY$fiWUr2X4xJ*NSPz=}5y957Y}3n&YFtsZTRidLFyCb@p@NyYm94(NSe(X>MUl zXk8tP4ntaw6dNEsKX>-{>fY*SNlJ>!KR$O^@Cb1Ifpm0j3%|ye6P7M&osoFDqH^ts zgtY~y8fVd_7{YVuJ@!lqNr!O6{tOr3H-eF5g*^nWIq7M)0uc4z?L*k9a z$17;AIstsOzVt;DjUwc-ByhQooH-q>iNekX-FuS#KgzR>B*{F+ka;cJ`>nO@@|)gem9q-2hs{`-Rh5q;@`u#sdlWjy9hAaK)%@>Y^U{Eu10#o z(ng<|bV0UzJ(x-Cf!47+INC3gK#6YnVSO{@5J%ou$UTCEMgDGc+pCZK^YtOYw!E8` zDN;hv9s>L7p<%ZO@oQlM=Z{m^XhOmMgU_cg4+f+pNkH@)mVx3aY#2gMc8ci4hl$!t z@YNOwSuwqS{n;TOzAs6?Gkh+a6{BV`o#U7*6A#x*A7|yVc@HgB{Di+~VaeynNs?Bv z%!TkbDh|hk@cN~5Z(GSfKjPVf?r9>TK@91Am2vwE8|PNECstwe(Th-XDs+? z%1v51drTAzneQ0N1K?M<@Me_>FHh4M*H4ZY*NgDS5F1s{LF@rUn??)ozG;pM3ni(Q zjRKX@yR|uXgc=T%^X8N+9NuN)-~JoyUa0q+vF<}@hRxy?7f6yVx0RA*Q0wcUAZ_dY zP4ZZ^xMcn)W5O81&?q2k%!#jsyHX1z#dCFgz0HWOOV;He8^qLy8^Qv{9)_`RtIh zq9W>to=xFjTg%W>Ue_-RZU}%g-SFc-giSWjX~Hf zL~v-=1YW+#hhT_{R{AK9%`@|HmhNVFW4kU`{oFzxaTol4-M+r`%?WK^^G#-Gs@P^P zg417yilEW>NN0?>Zky7l!VQP#hUcy0_&l271ut607)u0=e9M#2`WT5k_+0i|_P^!R zEv)cPb#z4H;Hh}~(_@h5Wr8(E8SEArad}2ZMquFK6D~=nNpTRMWGE6;{>}pq9Tjv% zD*I8*D|p7vM8V5-+^rm0;mVMSC{Q%)1||9VU|g(1BfJ#R3>mY_ZI6_`4u0y+bn|J- zRgTR^1RT(%-dEG00~;bp*kYHttmF1I3ooa|>9lm@iQt7b`|s+D3la(giCk-W!_8J; zy79<$ePEr;J}o`Xre|I~AK-gjYm|g_59j=+we8^0OyqY%8kcUgrk}+oO0qwCU!wEm zOS8c77Je=2#H5r5z`$P{9s2Y6>iv#RD=O z+TQNdWpU*ETZg4ktwDn(Nvc};FOLfXvdd?@t0@Tu#iCo{OPzBX3_VQSJp9f< z;rs}sZ862O3~J{E!CVRXf}#MbWSt(<;Ha-|7U?@QrDIX;a&+ zr%0YN){oQcGyh%EpzOSuL3b&Tg0m;?9mYD5#=yCN#5s_)+#-{df(lQHe6fS+Z6l4j zE6~)SBQFW@f^vo-`v!^KHe3ImCXnUV;(r&0&^>B95RNN6$s8$rCYPEM7;xr1;{;cF zWpDT4nRo1tR{PN%hQ3hw>`yOfXJ&juqa=4S1=iGOrP=w8z9QG>;eJBAQXyCC^Q<*P z`+c>E9ttDzQg^&d@HJpk;5E#6+!Qt=0h&tz=1J5^*kb$*s~0h=y~on<^HMX#p2~gN z)PQt-^;s#qF+pG1HD32v)^9pAPe6I#r1!|_mB?c+Omi&VLC_~~?Xpa@0+f*lIjuXi zMFJspSW2Ffw+oD2!6U7WQMwpr8XM5cz>?(Vv-s8O=+NKm3;F*pYK5Px3E4r{zu>IW z*ItyktQ)lQ#0!nYmw; zxH;>d5|k5q%^_Nj%O1!RV%O^8a4tr${%Ng|5TH4q+;0fmz_B6`zBx{*t*nu-78nw| z*{j=}X)-V=&h2`Ht`!&^FV#{hDpk+Y0Wl zU5i~(=rR;yb7Dw|5Dr1Q2AV;{XJtjnl@wSlR^J^>3sZFe#bk*TFz1Ys9$J99)`0LJ zw@39$SZd`EFnQTuZhB_AH4jex?3dInrJwvdo~cVFVre1hO##63J-B`dEWTPIE?c2h z4TkQF2CIuc*ivYpYCfHi1&5yg9f#>0yNNJe$(<$l@w)k0=X$OM^g;tt@JcExBY_Z2 zplJdFg-q%<35h?dj44`Gwsn)rWh(z(g8tobu&3Rycj!&Nz~fwr7bC|$q+0kQ=!&rv zjjCGXNhd`doK58kdq1wb^$!lRST8ZXy}tvGPl2PNAJ9cDd4Dv;>GS;&2(qM4`WGaq zpWS{Sul`AbrK0Qg=iC~pH6hPiUn{FYzr;=;9`_`V^7BoSi4YMW5fm%K^kq(9p-RHc zt2K-z1WMOHe8-MJQi=0Z+KXs<&w9NTqhR_^Dzov`^)=|4xlxiw5h;D|&Jkc{ziUzq zkE+$P)*x7$F1ci3^I4K!2m5$G|6pl~=3t5Ww&qhW(Li2**QWo68l3HWe-y5`lDHoW z5`c4aJI87erZUYTQLtFq+dC>2;^s>!Ofcn~p4?FZ^fLZM%ysO{GhO zu!9qdz_gGdd-NuUHH-*p36A=bD*=n5vDbEWXr|e9=Hwzx=D4!Y*Myy@az$#)czcVk zkj|boW|IK!_ptYsA&b{;$(ND}O$orudbY$t%H_?>0dX%`A8gE-$fK=;^9-omiEmDV zw&Vodel?CVtg5iXh|s}DLl$tX0p%6NBtR>X|GG9R_kc|F%R-f_{sPH#NPTqpf+I@v z@wK1{tM0uX`N>flMp*@KsT`-fUVbpI-n{2OUTiiPrKNJY;UaYoWZHfYh_VjP3 z!+Jtq`z;VrQBfdk^*@qLzGkr8T+l<-pRphoxcX@OCkrTX4my+d7cL-Q?aR7T6YljiBdBEinkhThvwgox{F&P$iuK*XRV) zq_1;AAGJm0AQ%RZqrz@Z2zhwPw--ZRVaM3QW4WmPz|$;J&UI%rUI*l4~;nzd)so4|GY+S zDn=xmhD|?O^?18TEk|6YZd#f;J~yfP^!xc57%Cr1(yooLU2dJMrq)#t<#HdZJmjHW z#MF$StEw?;!Js5DDwhmUm$|$Khe5m$Y2K1^KIM&V!EkzJBM$PIaKn|H-9G~EesjWQ zl^^Z|yh9U4Mx0srVJXy9RH4ALlMvt-ce`w!gNlw0bX?m4dOu#YHm_>dn<2Vwcu)eZ zc~aoe{<-gb?w@j5-^a@sQ|eU&qvJS(cT1X-Q(F^MA_TJn=CFN8r+jL|s(xo-qf{2V zFJiqJM{(|&AyQoC!W#Fg#J{|J7o|8=!!SZFGtDZFl?&2dypetZ5#l`oMws#Tp{tm{ za+UATyX%m#eeaHum^LUk$~k#iO+6ak*-@s42k4s&1vF5^Bc#Gq)!G749-&9F!eq1gtheNdsVRLyvFzfLMK@ZfsjYE&Ui-tf63Iz)F zC`m9^O-MGaxA??|F{*cr;<>W_m?Yl0z!8sBr{Fzp4B3u+1MF(F@udB9N>S1Q<>`ov z?x1A3HUro%5by}2L809)|2X*I$H~%)(zk&5z91yG{4E4Gsyeg^{-CbCH@ezKkRtjd z2=~bCQ3S3_ZydUY5qj>)4QHr7|}EL&?ApO(Gne`S|ql{%VP(_DMK}Mk$wh@3h)vBfrU! zc5}RTy>qGR6AWb2>(3wl9<}JTV3YbEo$2d{dXC=Y-I#TIqpT5qr&&eATJ$tkLYNLL zPz8$a8~xfyq16sN>Yb@KmoNJp!TD(+6eN3GiBlfB*FC#a6sE0UT2!{fZ5~3^e^=Bv&SNe=>Pm%V3bs=9?cy)r;eMIQBRYmjhi|1 zWc{;S0yerxhAFeStGd!KTgyjyntId!T~ts1NdgvjnFD+?$GhG)~J0Ytk2NylaU695}FaL3o9HPHtokiK}kD5&_1O zxnU(KU`-(7QHVkNLB4z!?FkSP?fHT6xZh-i)!d{8=%87kIaiJQvEKZkR`V(bX+ulX zNJaBUkKGUED{$}jCp&YP?(lKQMCgmq7h>A>oEYesy|GNE1J+Ge*u$(#?#-HXRgpa9 z!i)y?Lk+LPuct@%#B3zZC(1tM^7mx|^NV;VrwZ2vT(9M<5;hO^$0?s%=a1^O9b++Z zJOPrd6UI6Kti+n#b9Diu*-j;y*%(%itTjt4`-eY4!8R3YeB*ZNAi}=g0R5zpJY{0k zpK_?c54TuS_3rv1oG@kAgUDbGXW;fe(bdlBC{)_7Hz7_>BM9NA= zLraxbmRmQ~Mx>@<=fKbDI?(gQ?0aFrX|$Jr+2MxC zJpoA(S8MQA%tm$GuWNie^M$1J|NinFelny0k(w-`nhQJd=b^QAYL{S)eG7r1&7LnX z-)gzD1Ks=wgK`a5&RQu42b&nvd8LjLDb4c7I7PTrIa45yGbwZd@K%AJV;nHh$`Ps3 zvK|_0|8Ko|xJW#$|G zmlJDUx<(sxzR4xR6!}xsq`*%HjlC8mWFA1fSx6R919KWRZmC?XcdJK3QgX|&tV6_8 z`KYp-N}V>efrMwFKnw+V1$4>tC|rS7i$+yikZrC#8yyDCyG_`0 zf_H@SsK=dCWeJvX(TfY2#^+i8kFmD^YP0LwMhmo1ij`7aiw^H2Q-Jw8&I|PT|?vQiS=Xt;PJ7@m+=VT@`B*Wa*?C4`=C3(Z>MkXaGYK3_-CuB`m3p>n&!3n_eXuP?%E(excM?6uW;Opbl# z{^PatkH6a`WeDCyK!`?xGi_ZA?I*^ZM1!)G&5%#)vijwwgvO@4Xy_d?Q}zGP|G#~K zi&S1dJvvGyLQ$CadVFr?^Wl6gP8>KK3&Ts7d~zDE>_to&HO>3xG)0E#JxlF>cRd{6 zPweoj?AGV$WAT9@%`>qPOL!VYN;n~Gs`A#SY^LlC?$07f%EW*MRP%vtw?igR^}M0? zWK5|%HqLOa;t7-2YjsCXT6)9oUNL!Q^>mRX`>o61e`X=0gcWmn$M+)y{nIA{wNLL9 zu;Qi~!8h0Mh>LK7eUfd!eV7+K0%TY>*w@|}XJpuZaZeN(YJ!4>PhV?km4O7+U0lBW z`B}qS&BF41qVSgiY0dasYsUV_G~d|7U{R(J%ZR}3X(B(?c-Cfo3x?V`DtdsLC-F`E zLE-vTh>`uar?`RH;8=JBGQYnvTX@#D!(cYN_4OG)rkT87ZQ%Y!c zusHlxw7NRu4B1z?tg7fPV-#3Sh<)+$utg;|=F68=bMFUmai8NqiHgd&>+Uv`Q^cNl zLD7Bw%dP`?>|3g!p&Pn2Cm?<856^0fm_y5r9X2*zY{4j*sKwh=v#{b!moIK+R4bBw zf@R5H2;mDz0yj)~_9W`PUh-(xTwlLIOiTv&#ScjhAD}e~kH-*U2Q1rUyi$I$6Mx4# zbuagc^i0O6QjF?d*>B{+qR^!l5KEx!Q{9cvx?xUG3cnom9O7sGVIB4{7ta^L#>;8Y zo}ITokmaWffyB7D+ecM1Z97=P>M*8RvpFq-agTNlvXwSyRa;=y%tQ&Oc5i?k7=2zx1A@R_kr0(BwUAf54BF=1!PvX^K#` z0MBsU>zHl8xB5q)n#e3I#WUVK|9VK5zf3j5*Ts$P_HG!CdG=;9aFCv+^V(ZeO-)%V zxVVCId`C-TYItn+`G#Nnu!y%v(V{K zi7lT3uIc&-@-!1uc|jq%&lTO|Y;~Cj*GqguHT3|`J7nKDF9K4q4OtEe80Ot<{|n=B z+d;1-g&q#UhJf5ED6sP=s>$~9E|LCctRdU$wsK=M->SDoBB0qOAuS1U;WTmrgNR^) zn_ZrsA@8L5*4^b9;?yf~QV)~u#~V`jzGrs&a>pu*MeFP9?m}sbGZ!IjE$=+E`0MNI zQ#@xanoDd_6wM=ap|-V!|1mDIXIcbtQz4m6WHoky)mDZJ4Z{Wk>+5LYE3=nA{o&Z& z!jjVCFR|0~*xZ|^MX}B%e)Lg zpy=Bx%gVkI>bpldnWbc|vQkqEa}iBU7#0>hdouLn$FPBj55gDaiR{gcbw(T9)%a{j znwS&T(Mt#DFtNE{8@5OzqA?WZA0r=zWFlH495K$KHvO%#2CGo>u%+QPeesJ zhgV>$nxeGn)ToeD&l_&aBBFPHCh$xihs)=L&&jOHUf=kr)x!j`Aaru!@-jyJ9RI`v z0j4iEx{s*a%wD%AWZ6eNVLsn0ZCKj-E>U;qVZrpdRjbv;w56{%s zRjm&OhIiL^P&Ne*m@O|gG?irx#SCM5vDZIN$02V55~OI*cnfiwesy#?ucIiq_ja;W zzqAdA$eL;DBqa@gQK^1goJ2EM;WDIQz60VHg-fA^#Zyjck!JR7I&A&=!AE3JZzR0U<}RA4w-ja!&gMBIc0!e`>5___t1$_nyR6~b7%Q!YB>^7W zH`A?Jt%mZ+9L0uhX<N%u2xF}+4dCI zb(mStdS#y>!I;ooU-P<$-p#4HBZK(hGg#J~ugtsWnrgZYwrRkI z`|A`-w0{U&{#@&w9AT81-Bl^(qTt8jRi^l`gbAbZoH32391#(ANDJ@{ ze}?hwAy&xRbmS`|Ms05am7AIw&6T4RHjyR6V9rz-JtsP@YwyHao+#vUokEwVDZTy0 z?CZv!i;#iW51iuRCNR@aB)%A#)yqAb7NDtfZsD3 zVaE?V0o@pd5&0r6SC7oiUWA5CMk)U*g`iET6H!n|?=V#`54p?#!XD_0i^MWEG%mJ!r)A_8`qZEf8Vk}>$ zi2}9TH3m^2AD9txuOa5!p-cB>!D;efal$|hA%^bo-3FU~8bLYrF03;XUgnt9+UZOk zLn$^k>Y?Q;g}Oh9Q7>P0nj^C)Nq@Xu;E}(eb)4NM-Y1o=z#A-xlZMDbAg>bFt(kb* znU~IB3q74+eYti$_LOyH%8;QI-JdbyQVqFoKG#K@KYkPje@O2;Y_U=LxqIZ!x0!O+ zi3mV3TJ7}|2bQkWV`e>GMNfUvKHtWU?1_eiL^u);DNk*(fwz!r=hxZKey(15o0WO5 zog;FANciwq0HT*v0qhv*AwcSlVtiLj2eJ5_p52Hw+$uzA5q5gZ@4*FdrCc5V5KnZY68gfWk$sTktz#~*i$ zO|1pq8zULeHDk_wK)?S9oB5)Wov{jx)Z_fDu+O!rmwe2YMrb^24rx5;ZFpEeBjfYw zz8)5KV~N7p32^ZfY8=eQ?@wN?zM`A?bs08Sci$hD;sMonw{|3Z0=*3y&@X|>Id0uq z-+GeD5AJ?P^q;L?GI9}*D1gs)cH0uu(vaX8z4$_aa!EV!mHo~vXP`F<32GytRI(qY z`kNOrkK=vO0>s`30xKE0??W~+xX4P#!tch4zj?`#Mr>JX0mc>CoXPOTuZD`~AfLOx z>C&5L+SbexQbtzJ{RJ?}2HetaMkA6l2#+3AU)BF?uXeh|y1k&_*>^}Me7$N${FO)B zBR&yAyK`kC{^)lfp0(%Y-7RZi`zA+Ci41TN;#j+z++bAJ=R7^sP;P4UGj&UqnAE+g zl~F2sWR$#X+;PF6>~p}`a_d6P6mM(Z5sPPk(`sSr(de8^*1Ghpfs=j=1|gt(v_|?&dGf^9SS;90_>S9tfy$=|nACgwQlvT6 z!pZseGe#P4eUt8a5;=vyK&k`n4Q#bqS}(hfL9@#CNPr_@=GBwn8#kEV3)nE zvqwN8IIAQ5FG8cwJFcO-@cfz0qmhw}!zo||0@#W7_pJ9^Y-;XGy&_#YZz?CyWOvV% z-(fr!clyRtg7Z{e!%ees+FL|NQu0)*`kB=Tby2m|9BhEN<)BLGZB|Yj0BiM9MsSWC3#K9CbJ4P4kl8G%4ByPiJunlS43qDB%U&CA97^)xg{=`*Oh*`ODOKoY ztzZNkcHwxJ(rV;=fJA?4VeDlt0JoqAgTUzDI|Gze4B0D=!V*`Z#sX9Jux5`zgabv| zw&P&SH}L|>COx)&9#1)Zq1DFIGwbzOwcg7vrEVdoeTR7!S0*_G$SPATG>a=XK3-K% zkKj6XVgU7u@y#2{ij<_J+1J+lhFeQDFr~tHN|zPS<##D5DMkM#@k(bd`XCnmAn4m{P`XBQVrP+mK5HDFD+Kx3fGP+D*dwn27~zU={t$Q-JK{-WzIq9(4xY zz`q$0bO3MBczO3uI29(u8Iwrr^JlgrGxop8dSaJqQpJH%IE6wzz?cBv=fg#RyN)Ua0nc6 zFUl&5e4xSRbfb%NvR`1-gidqSJ%({5cC>Koxj#^JTY_v9BSQ(sg9>?ZzjtBB(Ka=u z%fCZ=?fl01hj^}{(%D(bwYS&B3!VBGJ43waEeMg_#f6qO3!;oNk5O68)gEIk z@*lBDKk!LOxASerGqtK#1&xf1oL8tvQN(k59H|p$><$cTNW=mBChO$tPE%4+vryfz zSPSLmyc#51JVZdEaB-g(&$I6exr*kJo&tA2ACNtncmRTUA3y1Hf~D?o zbk8rSjgb-+#cug_QVYg#+1#&5Oq?W0vyq$~d{+`&MGv*80K@de*M)y-Z>Q~Wy{4r^T8=@&1`KB|_3F38mt z6uu}91CTV&-nlZ)W|`r1j#BS^^TD#q1%FoC44*sw=}xW`A>8a)Ds?KAkjd?`2uy27 z?2EYVKZxuDB&EHLfm%*YgHBH`Zbtv}r@_fh`I|T57j6P%85EFRYwO&!A9nz@i$ft_ z=3c7ED)I6!4ks~dP;2beSe~6@6h;<2wAuM1xLy6zOA??3!8at7vM`eGpj&tA_kjVd z?f4JCsl_>f2=jL~7z;Npl>Bc+!bVg7_#$p7faT4PcZmBkD~&G(8GSO=T3XYboMpgy zNR~GRLl!C$Kw$>hJrY?Cp4|k*=(4hWMn+}PF&Pz{r#dFIHFbPJA;1~j!1sG}j&Hv~ z3Vt|N`^k|0HWs#gjEfr;zG80>652&UO#JMZZ`*yZZppA|%{fi_jNQU4_e+A8WTVZ6 zfuN6j&e3U6?ZBbwPtv3=r!}h#yKNYQTSf9%fgO+sp0&2YnB3 zyyX))pSTgu6Kk85Tj#~TM<{E&8B02`hf0h0E zy4)G)CToCX-?)HDDU#CRhdeRzfxLO|Qnq(kIQ0Q=cN{;uxzi=kBteVci1#bN2A7KX zJZfnWC@6fxp@7FU&jbsZw&ua?{H5fKSrYX0(VI7g>{iWaAW;B^q#0GPmaqDY=mNT9 zel#&r?xqAtOcs-f{ZV7{h3;z-Ow|0mJcEnL-*&-==;-L6kdU2NUp(pEof*E;ubC9vgDefaLtr>&O{g(C|yfEDL`IwJiuHr7SE ztl?(A(PJwk@IjPuOH8`vQ#Ugadv zor@qxYruRU4(YI&(frY2DURrHMVz3G$7%ppm#2}eg2EUZ*Tbx8H{z>VwJNf-xA_pa zCrEvRgX3cSKlVN!64@Oa>)jfY#Srd-=j9V2v!la27>)pbd z9&L8rzYI?mq;68=xLOoQ`|>|8l{uKNV0W~Ub7)HyI1zF zN^O|1Vj-H_TSIF1Z@DDnh5oD&C|V5-nPMVfZuK5nzE}OF{HEtRidROgIJe7zO=qJ1 z?&aUxv~-$sF9IMo+O^UAU!IqjQ(WT^y>oVc+ivi@Gst?&_t_XA87uzhPb0aki2!R~ zYiN*E4VaS1R4)0}nZIM}xNr_&tK9p*kYbPgC^y~5v$pACa8SO+X0GQwj&K*7&k=?J zBD-bVW6wy<>hh#Io+CZk;{+$hBA=<7h%5C(Iv|ZhF$uz`=2m9H6>4Ex+uwgTdv;8Y zuPDguY&%=$OAZ4CYH1IY;nFz!u`Tp0+ec1<-*r0PPwA@yr=%plB@c@EH)I9WY>-(U zq?iE8_>P_E)4#Rs+-pxs&;lbF&qK0#TU~22huWrX*F3>;06N>Aprxg?2bhpfz?Pq`sC*=yTAG=eSvEwKRPC^oBpyAQzhzeqCEedgCLv|^+TK&4 zQf~hUAXf;x{=fXnS;Doac&WM4Q`I3fc27X%+<|vPHP4x)YdSX$tUaCAuKRN2sot#$ zpS{8+6xP(AJtPRbk&Fg!nkY`|q2|XV-hg?zdeF&46X9y28$UU!f0iVAwOM`JgbO85 za4VUsj40OF%zWtiB|kcPy@N+B3F)LV3lDnc=E)WqvN@tIz780;AIY{2`TeWl>#=kJZ)_+H zcB}a^Q1zc0|C9<}%Tt^rp+O-}Q^;QkR8~3>@v)~SOly*J!$&@T z981Dvr~PZb3)hEC&j`u!ggRkv0l?#IJBNjW!Y0%zN_!;5=T(O3ePT#jLtd|L)hSKc z*6y4O(P0rw><8N#<+_bW-nqZfh!hkSwihd$)@~5_hOP^9^cC3lUKz2FBSCvcnY&PGEUB3g`LvN6Q5E2By> zt2kjj?v@W`Fc0^y1J~8T#RZ(@^z+#wJwEq>A+t_)%s=Q%l*O?WvTv08MY0sR0P>m)!yVWXYU_N}_DrKJ^>=;0%T|dG!;H zXk=4s?b?7a!9RznI_{$ptKU@ogDmo6sy)&4ORl2#yetpvjbw)USHHb-;CouOBPyq* zq3JudLt}98-pEsc!wgr@O~Yt~`js&zLpWUNQ=Y&%s4@v*y(n2vIFIhnci*KmO6~i{ zPOHTTk1lrN(hpll1=K%C-rHAo2+Bq}FGiqYOrnI}uMP1f{sdhW=~MgyBq zSII|f@lEnmy6iQ>!$VP;weLw|CsMl0?U_Hrw`!UFv-p8hf{w#^kk9dj?sMz>y~<#L zFWL{z%$YfNEO=_Cd(YKv#>%sK5oP1G8aYG{blcI+#hP)Ta(04Cinn0sTOlWIe(3|T zg&$d8J5bRTimH5<++_wL7H(6zi7s+5YRpI7$0*pp?UzV6)A~DamY&5O4;`BpX{XEl z>4(=@wwPX3cq1oz$P47N*@9m&#e2(T*Iw;Bp03{KnmkZ=b#NLZdw5{5U~Z*Fp4yeQ zYZhOMI&gVChQE6ly7BWM*NE-v$9iF0Ogej56uQ{pF{g}hFqc%$pl|JoO(eQ^(IG#GuQS>s> zs5&G{-kM*1R=4?JbR0yKx7c+It$o3m`S~;hs#EY@tk0`Wuj)QK}i-6 z9Ay89nU&S{?CQ|v)JFIB$jA=TCpER|`tbioQfg;sdvp8@CvalowarZ~@5@70bXL96 z_}g1=z}|n7X8Ic*3)4Eg4hW~B850p*9&$gHM8l2ZcuS!(g^wq_wK7LrfqHIwGWkKi ztro;|6DlT8GD8_b{*=fAx~6RbVx z;IK!g`FQ;Z)YnhZ7Kh(BO-Lm1`Ob^`nurM7ziQcEcDlkh`k4#{f}+;96Bj$qbr<_k zEly=siTc%>0Ds-c-5)8^KQz}A*ym)+ME7|#a=~qPk?}_-Y`999peVko)^o2=3Vz*L2#=r7DRQFlsCR)O% zs?s5nRfc(0D9c#txAuT=ABa7N|LKHM78Tf!ok7rd>M zv`J-Utv`@-Ko*+9o?665xDl7lyr@HYMXjT3`4OdR_F#jPJ%trD#T}cW#vaFH6M^VIoBA<^NMZ+rW*f_=ZKwfrVxNvBa@HxX>0Y~PW2ojxWOEvMzoD@Vxja6>FVey5 ztWq7duz5-!*nH&Rwj4w`NE{RB)CNXl32mGA{A+B6O-KUI<>6G+&F|ULa=E^iLb{5I za~uz_TeRxG#lq_QNQ9#wd(F+EA}e^U38A1qSG!`-x1CoAv-sHJ#Wumxb4trOO7;>| zA7|rL$e|FERMGrt(rucb3_Fj}xD=h%gp=KpmvqWoPWF4Sg}Q2eE#}E^rmzJ{%%P1o zG#(bKVw{vPVfs@8ZMNDbUBtEE$Fms?IKb^cVsL>c~ za~8sfRj{@O9h2Zy)biz=BAJb*h(JU1*|OO9AvCQU{O6nv)C z`bjEHBxSJ9|6-yZm8`dKCD!_Oi+u7)+cKv;!#U2`em9o!Em6$GRr*o8hL{eA%Gs;q zug#I1*Pk4xN)1gme{X3*Rl>csF8l7n#Fvs3y9tM$Y@i9gXT^?@|VL9j> zsqLJ7z>okI5RSHo=>)C<4<2@^@FwS6=Xz$&Z|p`~Uw?r&t=dq+E7$OJp0u~$sV%Yq zCPzWo3{|`ITxUi+iziW5CzOvub!Xjh&MJ>TD z6@PuYqPT=-K6Ya+7ZGNSRoxy%VNFn}h`y3am@L&+N01yflig3`O%>YbPnES)#B{uy zNZ$Vq7izyjinVLXY<3771F&d{5nmVQUPQrD__%e`gEBRbN~n2kr{8@>Agy7N=AZ(> z4F8{Ez%q3B`PrsBzIWNWBoFB=eg8fem$<>-?qIRGSPi2CnAqL_A=ueM-^*BavnFfZ2*3249v^?Jm}vi|cQgEBUK9n;-%K=Do-Y>omOJ2q zAXf4(c+rn8@O5s_?DBB=0X|U37ivUBM!u8Upt{S6p~y6tQ+M5;?oTLZaGv?9u}2)4(KuN-xA$MNVnlvv zrKj+n4>&&c7q5tl-M!DPkEm|SUJ()l@FnT%-5qZhphelM24p5$~bD_*G|>=!xcbDBwZow z0TDzQ5Bve@1vguxiQHg+?`nZ{5BTCLp^Ubqr%)-=U`puKQ@UE(<8_G_a5@+Wsr*I9Kr`PD4Hx@KA)+w>8YOVC`Y;kJp?%LzMd~TdgmM{aG`(qf~G!KDi zS~Urok67*}Iv_uCA}FSJm+9TvYI^(mf5tsKHuFa)V!5;w|M6##$SwEts@ZBiJInNN z?370ULbF%4G?NAhVaLXSG2J+uS<63t)cAJHN8(0!-njJNWy5fW3#Tp*kN)8ki^s8qy{=)i#;U3Vg$y)j zfjk@h$y*6)p3DmFtA-4S2^?GkRK~xtc_nLWF5Y>BBFW^Jt9q7u*X+0eP<46h;<$*g zu2;BzE;FU?#zh@HEiJp}=@vHmgvP%E!`Jn|F@CO{>1$-IfEs#LTGS~>j)2*ru=AQH-+m9s|&Q{+?QM7KvF>8&|y1SY${R5;$8GqCW$Tk?Z^!P=D zk+!gF=W;mek7Y|zM7fZ&j%3+3;y;%;^&O%ft}nNT*ups>=~ztn;fo_()bx;|- zZ(lxf+5LxlDUKIXgZ&FodwFbEzui7@1`sQq(k9Zrj4aF-2$HCUVxt??JebR^q~s|1lc!2FHGYP zq!>+lc7Va(+}w;wi*k5J?jSh%724GyRVHHet;O}0QzWL2-0E{tCPP(VIIP^^7W|p4`(H7(94eEeKx&q`3A^QK0?M|*9?7#-@5Z_Rad@KtR8;uQ{LH0O-xgw5CvWq4 zH#DjL4KV&w<&em_7+J6OiCJN3WUt^n%Hz)R2fAL?UVF0>Jr>8aaa;F%q^723Q!rGS*j#OI)~)_wTr)eT;V&1RS%q#S-7IEm+5pr`;N>{D^)n4} zOjqjw$;PQz-x9uLql54^hwSXMqD;3{232vz?_1! zJab7<5CkLjfAK6um-Qi?h&%S3RkNerK=5+MJ=#or_(k1j>%rz(_RecA$As%jQBFk8 zk^5`&Bi(pMs2|qLU4U&VL+^F0c6;A0n3ym>Swk;hmZI=LDOCs{mu*y4sJKA%vWjnYO0lx)1M|x zce)er-qk+l)0a^Zwt0CiOkn31dg9}F*ap|{MbXgdL19`+@R(X1Of)RJERn1C5aT!a zSZ2n*bC;PYe891>z=?ivbKx|U^8IIRz0LnWCS&6D+lP%9bZVd$i{B+7jYmwJ-!}6d z@T*Z#QNU+aH7$p(8>{NlgB3Y8!C$?V6K&{axuHgwoY%a~BTWV)cS4myiHQgh{_14w zpA##CZT|?ai*1ubbLBGkXHdi{EMYSYt!;}pO-n;x5?l1E5}{*f0d!_7y}yoawtf#F z$62_a$qu&oeB7GruV&V@Cnx2_2fX0l)yy*IXx0PDs^iZWy4W$_%yBrnXwQ<#5N$gM5UI|viHxmGg~TwD#es4Xv?v8*O3)&}Og zwuLv}F$ccIC>%g)#G|2)^6l*9S|1eph;zlmO&I*XhjTJM2xI#Cyt#?gg>EW6k-&2{ zt?k!{M^|?J#6EQ(i2zP8N3iyOLidW5{%TTww~hn+t)ozxgBtwarAN2xJ5AcAFT?%@ zF`|BrzVV2_tH18@v*VXcv}5~PtbeIG^j03%-G-M_$JaCm9Pn@p5*--<32mqFYB$A- za6KGxJjef#&s9Oq87_;A}#BSY637n5CFF*si2h2;~B{^sv@W2v6{>PAI zKMQ_|9c6M7fEO#m5#PIbncyNgaCqKtuu?zebYnvp392K9+@A^EWD?5wtoWFns^DEr z52HtNoT*bJdhWDq$fWnAZ02%ow)Oqlt-WAx9HCK7pB_2&8G1iWK;^NW+9YxY@uyw0 z81$&j1_hI~;{XR)jHmv;>4lt^Fp~ZifqD^J*NofaBVQI~pLNh5DV;tgHrXu81(^GK z?04Gvw;^JrB1_HD)~u~po0w%9AMxeCIDmukz!0UJtmO)npJmm{#4)#$Y~|xZ!69~i zG!1LUi|(tY1Q*Rwm1y2T}lxOEylPMuqPvwhrAkj5}fOk?qGG_ zQGiANejXLF{lYcw3DH|B-%EAZ151l9icU0zJQAGyNn^x6AJL|?UjThqANO2rE2N7l67G0_2o5yXwK+(5{T`*Lv| z;=qUA78J*S(bRU$$)4&Ue|vQ|f6{3^&$MYjYV&PCJ*m; zeV@ed7=%2Jp&cFKC9U_KB3Em8U$Jr0{*C#ZD|?+fJTy2R-qA*ZesgRK;tdtYCXB$l zz6%oWp?7s(&3sbxw>ouZUA%F-zXD$zTdZj23|)%U_XiGRXsLcMWe-@!vY3#pVnB8B zGR4S@tYfE6ecY6!yR7`PR9~t6S8%AD<+;SH1Z(T-)4d!9TO*${m!|UrE?Gy2fxE!s6ku!un!*Q49wOHlG5Mt9RrC3+1%5!;ooXC zb|7xNjJM8MFB!;)z2F1miC7cH)BVgMOu*MZ@)yg6teCG}M73^#Jyz|GFmLeS71N*oyp_Pw4X8)4d99nK!Yo= zUeEQrf{_`^Rl4Z9+Z0c}y5prke-96Ev1SROD`_CmSQTRlBkM6k_`4B+B_=}wG6m&E zBawqe97&6Rol|dAvkN1W>wDMLMaY7k{mvOF|7POAD+BhUxLS|>-`9Qx(~-CE*yVJmak_PNbwJP@{+>2b)+%)C3^hHfy`tM=ff z!-vKbyT|2PmF6d(2wn9CdYCr1cMX_v3Oy@$Cb}G!yTN&pR)2ej!LSMuVjMS|kuh2% zPH7X+b3fEe^Immwo#ghJG`Osfcl=Qvu0c^B&p>FyU^5#lPoCxLConiXP=6n)Fo@_j zW@b4JKwgGq3!R6+PFfh^4bw2`)6&{UH`7c(-0%414$^wMV9d4xG8S^a1bAbQds2FW z*X<6s<{IBCS$o7WF+f*FZWkAvmzMxi?;_l{Qg}x1Vf7&Vw0RMG?3qZ!Y`<{T((JA%(R=ROm9-S5AX-PE5Rt0_bB%QjqULcWszL zO|TCugQhF_$q8J`Xg}GmNl(&P*5U-s9Y-mVJ|TbbP_8yn@8B<56D?8ZpZi~X+Ep-=Y z(2`%njHBqYNlr!0PSGx>o{!oMl>d8575^-_Z$#|kpUgK%CRar%SH}F-fdBtcWFFsP zEUuU-W5!4x%Bk5xjWZQPt7`sN1+%0%=WXT3KD~Fw8+*$!zfZFm@sK+fGmZvqX-1Iz zB`_31+l`E7DsyRHzQcMioTl4V!7M+PRZ;N6=k7&>kn^_5=Z8g+@TAs|c4JhHDtdvWzCM{J5LO_13knUT1wI%2`9ZUo{x4_fR3>LC#E{4`$kvDmHD{{u zU+=>2Z4Gi0!D*?+)xX5m-+{Wh2$NS#^$23@o4{i(jysYH(j1cEn>x;lp(;_xp!m_hHFAv`B z4<({p#oe0`n)VoWh$FTlRY*n~GlLhhztkpf{DxFk=08>P zJ{2Yoessi-)Sn!F5?_;CnvVOVyY#*B#yB4Vr_WjG1Q=uESXV+J{Heibu$#|M2g1@t zjgautdD9#;bbEik6^*5XRorKS4|i1oBOXI+LP~z?$QY*Xq|KY_2xMb3axp|#^YPE% z@@dan$#w4rQ`Dv;KY7h_rVviCM%Q%=39t5B|1`Lo4JM3A}iBEJqh zOW>DBm64_)1V`{G$xnvQ7kEQt3HATf`LI-l7#c|UMsfULjHh1#Z(9(sk;(T2$OQsAckq zcij0#dFXlG$qa@&M$c9b#qri18O9`2Hl&0?Si-YUO4e6n(pJyMek}!49{SsXyOYr9 z9hrd^1`h@POby33!PdX?9y{LLOgEHAj;qxF^f}>{92=D>p6iEkX`R7~;nn))(j-AqeW{wk}n|`uUh;eCuIFuqt z`|kdCyyoY$UYyd#A8&7JZ%-0&Ugx7;SF5x#h2aG-R2ZEQe8|n>_9(F2bS*&jP6q67hg$aJJ+!if8P%=+;kd}gcD6v*BKdZA|2#^ zD@LR@3*v-SY$N#Y%~E`k0@b9xnb14P%{%t9h$*Owv8WEdP_0x@&`#rVvw2^bdnzl( zrOiD2ktu#${w{kZE|H$@SyGPyl{hnJ#}a1e0Zy9^k^`#YWlKpR(|4{5Z>X@-syE-J z$Y%6r-)w8N-OBi>&l+*kq^#NIAG<5d+_)p*YSU8@qMW|uB`{h<<-1D!&huIRGcYpfgD82S{l)07 z$;)5$kl*+oQ|_df zn1ROJl(|?NL(|C7aiaZ8wP02snO!s?;>GW*!VSaO7he{`hVrA^t|qnZ9AKaeLv|v7 zN(J=5Fs!fOA31{Hq)_I?x??B^D zh~ky?(j6$VW`!Wpk~9`&Ak<7z-`v)@-j;LNu z{Cy4l?3YQij;cB@cH{y=<@BXRel}cE98aAi>#5*IokypaS01AqC5`q-d7FXh9Kp!%L@kNsd|(}M zN}^PZjJ|iRCaS|+q+jg!816s}H#=BHvQsPhHLSWh?oT~YdyRP*I1E0p8>nfW5)4ZTX2|{ z_7^gFvp+#t#ihq8tD-3p2ML#~!cdpatbX`mXT(vK87YTZR;1~hQYDecwPR5&Zsa#g z=Fzd92}6R4D-$&|_Y({Lb_YJySwwyc{l#vciiv0e=uOcV4wZede)pPW^6ja;&}O>Z8q}RU{xMj zPMp9x+5ViifM7t3{j-segNkmY*AQ#q@y5|o2)RxpQll|a=7MNWp*<`dj9ZgMKkDH_Qx>fH@Aj0lb@F?S~%9bF6WR8t}FkKQP z3#Q=UNJ1gtn&2gU8zAHz^xBar*y7AmGHTU5=CGEy-cei$QzRAZlt6h+)QNPevbh;SaHEe$ae#*O3=OO%z)RRZrSnyC+iMv$8!16A5w0 zmP15o?%1<~ZLWQ=5-Rze^_^=2VUE@I4afEtZs-<8bRk`KPTSTYxb??w1OW#(x5F;z z*mR~82fA)K5Rh`AibquP4e^;^7H1;0JK9r-Am9!xNyYmG&)*Ix%)L7v?-6!lBb?{85r+o@>&mAMa@wy@v7J9?*C_`%5Q>QL7MBM$YR?Z=?- zq6YKz#i)+m>E+gQMqs7aCIh+&Z+{rFNqZhN2<|{Uc)D6|6N%-)gqMEx=6y+AWVQXG zh&CUnLu&9k7N+n?$n9}@7H57T&owkQ_r=!K`m1e1p0H3zs%_ZK1C&V)4q;@OFf0wPD-d~Cb` zg!Z26PC0EgI82~jnrvdHZ(~X>|K23I7l+EKm@!3hCE=x*;Xh*DF1>M&s_~%3B^rue zBZmgMN6m6^K+e9%Qc_0N@*j~zUOAbs4w~%mS6P@33wxhGn&viqO2F@(ro$`LKRisv z!7+DIGnB#^3*^y4HfO9@cbDz$nO~ktkcNFUM61=(v+gigBeZV$e4J0DADXxp-F_{V zz-(5>l2__?-87$VNb%e}0&P%Sm&O?XXwpXVF#Q%I#OcZU1@Cs+;sTVB>5$8T2I44{ zZ2I?QrKG4K52_aD1P|LX2(?b!P&t*4-17f6P6@$Pp04c=iwL9-3rO`}w;mhfFN zuc#VwEyA<2=QB;*%%a|YQs7o`@3oz^UUs!vd8DHLW44)j=xx&#czS+$u`#yJ@kjGv zlySA%1Xcg(9#FAlJgMJ|z`amR<*eN&i3t;xZDH{XK<2E8IQh70O^1W$q7OWfpR`#d$a-%|^8M9;Q0E~&D3zl_IK|oM2;~qL=n|l*GQ~2D;sW!&v>=@)>zCk z7+p}?=OGbyV@B*?eE?bJRlIY~*K$1;@2Fu<#}*3K>hBN9{-WWxqY6~t`5`Wys1j6FXEWRY|GqFfbma|=lA=CN+ z6@RKVY;3>(LeDp$f(ndfFX)Ut#<>usRHfy?ZZVqy==VMiu^~kNca25N*Del5bS!4u^)M-yJm8#l_gm%bo7lQ zyKbECpiJLf9nNOWu8siuVkKL5y*ykAtzPa9kGFOyY*th@e8eJUS7Nfn)Um??AHXb1 z6XRMPn{6p(dk5V-*kL)?z1{zR=&`q%d;kBr>jn=|gDlgyfyPK{t> zqo<|GH`T8lmVDbjqRGN&4@tSfL-ksva2tPme}_X4>9!hl-CZVd-4jpkUUjLFVjnoL0*%Bx2$t;X47V;R?t*jdI22g&4YshqP7>h zSCy0!f{|MLM{VNe8Y(!ruXo&|zY9V!nEj^zT+pB-5mLbxgsD2G)x7qbRZd;o|30cF zD}qc;0%Gq_WoM;${`0Gvj@MKG-A5y1%iA5&cuG-fPSj^(Wre{pTp(x1vF-9K4Hq!( z--P#7bJ^GDkk{Ve{JcsWPLw zoUXnxiSnzZ=p?ku_&uDGiM2JIudlDly{4P1Ym~)MJbM{hw(6qW%o|x*$17Tt*t!PF z;FF`kgBT-N5?rdg6B{JnCuRFiz*!LAbNo2$ewFzw2b*+(H^$?GLwz`6IB`d>?o98HVeXMr8IlmJz(&Mu?_qf`ZGF3=@ zj#3ORlQWkzj|b^i&r1UiOl#`}9uu+1alXQLUS@Hp9tz z=E3e^RoCG&-jK#T2RxgYN|Y4H6ZN3+F+49K-p7%6Dc$yy1urThu4A4Uh@f=NqH~!& z%WV=x3=x*K#pD#^ zf`-O4{plu2QEu9w7kq?Ps!WRJO#0c69y}yp0vWgC)zmB2ywbg{Ih$_0`o)MC4fo^^ zX2J9}Z-GOCwNaush(mF0tR5mk_l4=~!h`LFO@mR3xPs1qCh>t201D!J&Eg5NbQyP- z(5lCGNH^S?n|F)!hK0QH+t8XAai(SYMa%<}?=-z%5T^a>8XckuLDKIdR+@ z8@GN+=l3DxuC+0_NpDf{(5H-_t_2BYMg5zkgqhhH_ z{2*SCZx0Zn=!I*rm3!j4<=}puvf^AmoU4yQLMF%(pq|i4<-F!*o>W>=WlUvcZl;Zn z7~9#M32rv9c6=@E>`G=HZP}n(#7r5r&SKZu5rAq3lY!MX*a`TM- zN}y%41&)-KmYR=;K*PXYTny4zdOvYBx}a7bI$(bMc=mLE^(kBw?)@iq107R`31Yql z+{lbX)TCjS3+8A|Fl~C>WAN(o&g zB&6hv0cxNk@5j!NS7>Dpa$iALf)`tZM_gIg z+q>#(CK{`Zrl#n&@GgZ^;zj>N-gGv}FCy2UtQM^XTfrYxE>Q78v9~swMsD_DvdLb2>HL|C&=O^TAd99dDMS{;HOSo;sN-$Kq_4l;e6!*q@}5A* z)|O!%25#ao-D7X62xDYqWY+6wzS?BI$plra&Qkw)fmNF!HJQZ>oxb@N-MmIqwj3>y z!-nz;<>JgJ(aFfbT=)T1t3V?7x-%J-7i zuati_e4ye9bk2Xg0o6g9F4Z$WLqof|xhsfi1iev$PEJlHrN9%Hp-? z;qc_JwszX~N3;t-Qgywn2+0`HsnQdBb6E^F)Ztc3!<^9F2LlF9Aso1huP2(_9P(vT zN2bgsfdWM`x)X*zjL6uOl+K1U2X#bRSC5CWDivzSMu8O8wqJlyLMzYGegeH-znOM70xG@tRG4HgZosoMD=MOJ zn2j^tZ;_Q(zbbg;bYDd`)HgO}D;Ci`G#;$8|87&gaGI?#*Pbl~1O0>-;CUe9PLT$o zyP)$cxsO;XDN zS8VfsGQZ21nZ=Hm{3a^OwS$Ch&DXWFg}a?WO>8Z&zws^a@#%^FnUj|GSAO`_Het>s zdvl%^rm{-Y2JYk;1QL61uHbdPix@HoQrp>7T|M4mn555Z!#o6Q6DjIC6`f8fjK;;q z4KBdGeG6p^ATfdK{g14=GyFK%K8zX|K$VFBTk3ha+MNYGEv>L9R{&b)`2O<8%VM7= z)SoQ})ZH3t zs#~)bMq*t={N!}>jHrOa*jAKOGn{-0*{++O2~hLU{d^${A7ZKslZx#*KqzHG=))H# zaOY-gfr+`kb$M#O!N`^>4G?dC07#kZabHe>k%CF{U^_vyz67v6!0%B-pQ!R=+ zdw?)p4D|!j*mT|XWgW0^C*C6{i@LaK=)~Mr+C@79#iY%i}9q}oES$6eOWiwG{>g~f+IXw%1!sFmv?w5 ztH68gbveSm*_D&)NQ%I;iL7S#mGLv3A`KRmN%@dFt=uXwsWHJEwv|{}2<9}y$e{f` z`i!xkl-4qS|Ftp~M9Mm? zdLpZOwZ)4ewZuA-3{?(wru4hZWZ!(94UvcQ>Biq^k~9e!K!(=8q$K6%qIHhZV1i@Q zgEg1a0nMq<8gQKkhv9b=Pp^ufee4`B^~Q`E+pqYtRfCzGZM>|7&jC&N-3QDbTyfqEH&&vdf#%BIR}Gde`^~ZV{07i6T0*BNx9sA@tfo+Oq!s6btoTDJIn#%q zr(gdOYSiSD?RNIPQSC4}=Q`>BZVQ5Cv9N|Z5fQsvBuDYsn7oe1G3&6!pFXkMTE9Tx2tA2Iw=gt%d{nnE9HFP+QKGC>ChwmMLQM0>-5@XOjnwJ7 zn=*gi(e#Jh^Svj+>MpWb{jwvEXfjdn+Lg*xNb%uUxt*LzdbB6?+DZ5gE1!ERh7TDX zd^1=0T9Ke&R7K3)xLr2^kA!Z^LGPlu-#)t#7J7)0`9>{Emrhkhx+Fj5Dl~C8xLr;<6B!wKIB10Yc99z$M=J+BS9OjvUCr|V zQso1q6rHkItvg#n*5vkm)V;ZmW+= zv(BggYoRXG%5RPshbl?|t^L~0N|;?h2nPWL#TZaZzrDY&GU!8T@|tnkTh(p8?ezJ? ze?m!!&zD9b7Rl(e@P`R7aG_YVNt_l~ViAM}W0`_HY}X3;vdP-iFeaB5+Z>#nmG;x- zen6}Qi!tu@*0n(~!1gWE(?o~xZizjLe|@0FP3Q5-*(As9QO5?@3Rv}mX`Mtw7Z+sp zYH?13H$%WFgO95>UmEl-R760mND7->k(#895+G`K^#^$9hFu3jad?D@psD z&Pf|ULtVJsV%v~(DWhJfr=?)=#>CT;2WSmo+~Eg11=d})&bT6QCeG^XRj>95FUg76>UP?s z>kjk3w41(HZ^o$BT_4F4zP$u4wBW#;oCe?Y#1aYY>U7{glBaLc5;3`e*;ky1UovR4 zn`HEUM56pT58GYy-S&)AC2~lC&go3OKK7HRtg>@~QADlQ_j2gdenLUGtUeU8l?0l((CF-r+z%y(12v%(a7 z?|P05_gAZXy}Pe(^YG9^>Pv?YU=dt?(;G>!oTYVSj_qm%L(Bu%;QX5IO9a?KJ9nTKc%2g%{LIeRuS-{(yPpM$u z1osGVjYC2rjL);bh2inH4%L2da@uThgP1K>kwue`B=Z;*43m!zaKE9@u|0&lo@;2@lZ7uG(BM+;cc`&m4kQtan7VIw zGdt6+xlfgZl}py7?k+g@JR3fw0A#p_s{iL~GR2#ul z!v<9K4V`M0^`zRw-)L!T)xiK7q1(05_vT_=os}wAqr?r~d94F{HZAT~bl%Iu!^rIH z>^QO+Lme0PYGzS+5l9t1!P}XLSZ2=Yl$Si5SOPDN>gXne3Hw}~UyPV*^e&|wz!#133#mkf$Fv%h~hWB~D zf@Fc^0=9ur!7%JCyzTwvK9yVf)@1)J{OxQZ#Nc$zEyuUo@!+uC_ZlbQ&&~ON;bgQL z8pm48>EB&JsA~NVPlVWFCAjt9f4BJUhQrB5saOQm=kecSBIaw>^@rH%DJ9y($G&PN z3l)?(ovwg@7)bX#r|ZdLT_g|)X`2zU+_kkPNMtk(eZ(jpokeLS6`o=uXep|*ge0hdHOA1 z5F4v;f8N*JrY9J%U}9vXUxO8sVe^HWdT{4TohCt&sENfD1&?cM1B=4EX5qvaLo&a$ zvGKz~PSE#}Q0X$v4f|c%Z_S=_-Et;i9pa0EYOHkrxY0$c=_wVi{{EO*wRb^r>FFao zGI$b_l2mnNI^Y6bbq>w4+JOV+lb1NRL%E5)=l!sw!t(1~$kfiu`Ls6~DBUw<#k-a> ze}4>nNGn!+Ei=UqMT8awv`Hbown;{GzJq7OVDs#mO7t?!zWQn;!U!Rz4OaXbjd5}b zbg+8Q%{NK>r@T#p@n|OGX(!y?`^STK1g3RQpQc0AGsX z9J=hdJT`2$fEk=AgeYnJKa8xooEKt%Ukgsaw$I;zuYl&Wu*&6Ci}0rZw0ZoY@Ii^f z)%;N+vxEdDVj2{XU12nw!fKQj%u~e_o|IO@(jttst0cj9&U`r0u{$rwqBy;iAuhV1 zO1qw#BPw4w?rNrxQYFr2$fS3p(s;`E4CxHzx!S^TeQ*UxmX}n%oqMN4SK|rN zd})y6s`t}?)oPwpBCgX2)xXz%b9;L`RSzNgXRt9>QQm)AA+QNM(&b7-?k~#47RceE zJbHA5ZF(8$G*sEdoJ&~w@XK^l1$_{`u4<>xD^0R4^Aa)ph9u`*>t#J>(4F}?RfMMF zrPrgvi8E(^?P;C;nKBg+xC~c=3U?Pp8%Nog0qdIxA!;;`+ai&BF1_Qb|1{U)&Fc}7 z_e0U#Y^s(2*Qr&6sQ$*Rkxj*kAsUPht`vp$4#Z`~L6Sc>vDaBNxjqE!9Y(=QfjtR3 zb_?$?`h*%6wvxh8<3)ydold%(EtBp-SNOqm;cRRU-fSH~uQv(MQdhv2 zl(TwBKz@*m@fHlPHN%E`e~Ml#LXE>= zF&&Vnth(ro7$9^|VszznRR)7##9v+l4zr(8#`N;SM1%$YRE}B%UYJ&!&PivBB^a$m z)+h`sA|?OTDB+P}4y6pZ+X&4hXhzo(5fo2Df#F;!;ijQnPSm>Pb0at`Z`sDPXwG_< zH&=xD5G~*~VN#R^GBr zXVH{KMy5vBtLUC>Dq!Hge13!=_?LrWc8y9;PNf2w&G>#L{O4iYmNiOWrQj49fGt(?+IBj9 zI8@OMS&<>8kOa(YcQ^y?tyjkShVC@%ykTm)R$1QUS*7Ef`l$8=H(h%MUJwm+5(@rW z*f*KbtkLr^(95%Z8%ulMiDrKhK3VuZ@6Z!1OO)NuZWg2ga{Vxzah&0h(_lIAwq_I= zh9^<~4~0a3f(M+Jr_JGZpGJMpU!U8x!jDa9&&DO z&$pnxM~|c*B>x~EU3^CE&lYC&6Mms)G1!q-^?YJ&d#uVxpgmdZ!G7)n8h;IV4gvj| z+)n0AUVTrW$8-2q&xh}2?*RNUI&rK_2U4Vdovxzt2_Rajy|1F{HY~sd29=arQh~u} z8=|a7qYmJX zBAJg*@>P3$3i6fkj#=yL+rpgkIq_&l43f;LnLa7#df3cqs9u_|0QNEV0C-%Nc5`Cz z-!RJ2w}>vyUW1MLDk@A;BYun}YX>%3%#1s4aA}`Up!iH{%qw5(w>+5~;^Mleer{c|X`v^wETW2CsQv(e6+0tE8v#${8mn(7k&9fWA=K=T%AeV3wPqK!C9GMKU6Zj} zTU%7r%6W|qdF_M*51%3MXpcghoecv!~rs&gaoEWQ)W=L>=T?{obydumNas4wu_`bU?>>|LWFveFn%MD7y5cBl<#e2X2v{g;_gvfAG3e73) z=(Ckd3MMDYUi2%=yH5TI!P-WELTWGpST*Qgpp-2uP1H(r!|7Jd`{e|t%4a&8MdKYV z$MuGzLX9px+@+Ms`GN==_%1o$fP2!$RL*|(bkp@we`0yyZtrA1MpmXSDy;%Eik;ET z%^$FZlzBXpAP|5UP6xHE0OQemALnSrSA@Bgox2XAJ?FY*7Mt~MpWvX~VV>0y7hle% z09i{J?yk07OnZo(UD$~kjgax`_KhWqj_=44c(7#{Li&i%b`zxRslMVl<<_9q*B2?k z6gbnExU9t*)ne9sbyPJxj5;U;ggRL)W~6oQ5aHwy(u6n&OQt2KEWqbG#q;(|_{z%J zh#_f0b0M9`HuS9h$wl~)Qm}cr;GcRz!Veh5YFQH~Us!WgS}lQVE-;)tudPZnx@y1Aj!neA?Z!1x!GZM|&B*|Qj(M#YsyEe6|2L4~=0z3%JNwJs`Dw*Vy$|xYuIN`6=);wY;njkYgb&Qx z?ygpm#m4Zg?q*rtO0n&OnvPq58MCqKuabF@rCFj1NHdmhO~8~AMSts>OdW+zrmpav z28DUxpFi)nWKsX2&h@cNcU~X_TqghO9cIrSmPl;7Wh%#JxX0umz)71E9K-Vr@uG8l zL(Yj)`s{xUAhpHcClbbo&hk7pia>T-a1t4IF^Lv0-r(52y_dKbYb&4DJ~q~?pA75- znSeLuZ53zc_KXi>#(R^0qBG2axbRgq4|(8+=;(_BMB?r%k)Z^KwXrOSiaO)>kzZ(J z00BW_v0wfc2!sF0>9|=Hn@Vc{xP7%nTqQ-txke`>07^>8@OC9nDNjsHoZZ~?fqjVp zM4ai{#t$UjoLybTyI9CHR>TdMFUn@givww4Q5nLo?>3#^T1*H;rj>bvS_&WlHNLmd zfPu8))22CXRHJ!kxUYE9W`jnX!fpTroJ+OpA|?xB&#$hw(^p!~udjRc7%Hrnx$vJZcwX;QTtr|B&GjD4+oRwo1FXPnIFREK+@!k5Qe{fPgyBDM%=N!gz@Zs-rI#3O-MFCn|rb{My@3 z9JXko{F@>J*FdILE}Ce_g+Q7103u^_AJ&M$$ye}^>K`FRV0 zk1c)hhJoykHW}rl1Nv4&DU83cb={M3n5o-#mAcvmRDB?{lLazHJ3}};42I(2%`O(5 z^>%}(oIh0(cM$|co4rQ@-Rl{*vDA%W1v@qrFS0Bz`xhJwX~O{d+SV?boE zbbHQ5ZMohF>seu&B_ql$wOp()+U+j_g+jn%8XM&b0s7c9S=b-Zej9+xmLuJ*R9px+Q3| z&-j2ow2{Ny-`&9``k2dy8ekpXI7zZWgCCam&72O|g-Qh|t*x4=_%>>mG(ck}QgZT? zs3=gSf}Jdxyfgt> zR#y8-5>Q@FS~wnit(iUmCo2X`O^Q^@w5nTwi}Hff(rlfa$ZAQKtmghyD&_o$c5i$B1B+H?=u|8sD%N7_hC~c_TZ~XFdgFnqB4FF;yw3zy!XIseT%$w~ znH2AC@@Q2O8KXwQ1rbD33m&d)qy-zzIcL?eK`;4c7* zh(cV!b}xGnYYOro<0bV64B7j4NG5L5?*Y~_9;w8y1abBEKO7T#4^TTffNeB_RRh1` z*QV(!m7YSNJeDh!-HMd5=utP~@XGx@ARuSj+-CSH)!`?Y?>T+b7nRA)m7!Sc(tz}Q zkv*96NaoZegM3QNyY#o#$JYtw*S!w-j^ug29|9z*{tAgDpSL7iJf!@-?);lTt$up{ zQbhECURI2DnTvE@uRY4}bAOb7tKk6^FVcr38XNca|m``<{` zz?}xt?l08w6Fgd>eLxB~++JV^#*?dh=sP}=V~DbPQxlXRO3?Xfj``iN6Om#57>!cq zH`aHcYr<_B6_p%NUOE2NW82GOZ>oaBkv-VN462N(l8hv+N-gj8oSDbw=H?>8%KijW zeXERzQx4fHcB13Wy0=R6_6amOG9)iTGBgrV_(oB(ql%tPyRZGAn zA=-+&x~B7%6!kzCW13QV&ipoGV^2_#Vo5fKmFL1=)O9X~4X3W`-XG|RHy>a4d zDE2SRAJO_9%&+#>#7ASydtp36AMLyWv zOc+^FS+zU+gCL{F{AQWnC#95k@Xp=i%e=K9ON-36UYo-^^H6AJ<0`qH*fjl4Eh1?p z5Q;8X>X!~zUu3~AA*qKIGG7dVEYTc=`0u+aVclL2u>8GwLM@*kLDd|s7O=V}(!TbG zXxT9&APfrLu6F44?vo`6anr)(&_}(FH-LzBB>%Zce0myi#-%}A0d2CNAL~Ix7k^1| z%r8UBCijzhoDg4OHeetD8?e>Y6KaKFDusobf`|F7s^fDg0)oP@c17o4kj$gw^{R*C zPDaI8Nox#%9PLy&ynQ4xRj*vUvp28Rg3UWj*KWK5Lw!`R4P&j|42S533_^otNnFk4 z(MU@Ty&duG;N>RNbkTcRIxg`(h-SX|yV6tp5sBq!G^wv?6Vw3u_Od7`Dq+jxI`*@t z0q04SM;veWV=e7{+*61c2gZ&r`j?tNI6NB%J>I2vTRSlInZp~fLIwvS`_F~SdV--FPU?Q@w)S>m3bx{hjF{^kL$m3qA`GzNvr z@zl(GwJ{@L1v4{0Umw5Z^}>%R_QQ4c&?;JDa?m5E11O1!f=aTShPXHylJEtfO?}*; zsLv-gkVc6HTnaxh?t=|(fYImZ`=on3A?tvyX@nO|8OW?m76nQEC;SUVC9sYCv+j*F z=ln-)$d?f^Z25; z(kB2dK5GVjPmL$ebbvqTzhJLS$NQv7#lKa43(JQKp*N;WcJR_>l!n?)MU6SmFmYUs z$V7ul<76-4M*-zaa_2g4Va?l9MmjQ3qP*>ZsuQL320tfFhE(WqRP*+jbfH?zzyFJR zNo=4MS|!0cc<8v2FBPw`B)vMy+Ps{5@ww#x%>_uaX@jg%apC|`y&o$crx)!}#GY4I zl0k^6*t&I5Xg>@Lj;oT;+S51{_8i@t@E?ky2r!0E=DuS;I56G@`e)AWH*n{26B84w zD2Ad<&##1aBGw>W7m_^1KO+)TQ9&5+RP!>2q$utTslGOwEr^5;w82>MY;wBlaT4WC z_oW%P7oO#NHGNhl)%C(3Wzl@_S|y)4>``)QX5af~rIo6PKM;eRBR~S=F!C zIZJ7hmXyMB7t%vYR__>|LlnB4h&B{dUhYCoOfVhvL^**V2OYU z)=T2J$+-s|4^PTcnP%{cQMv*4CNV!RFaFM}q~=x^BS1(Y?-(jf)S$sCm#?n~3=}HJ z`W>^3wSdjd**c=r*@xov8cou(}I&yQ{me7UXWYPu@N z(t6B@?9DAxq$c_HJam|G=FM;X5Ri}M3Uy#vD0u7{N*5)ytDt!t|DgK(JR_&7-^qmm zDzn1Z9`9uy(_CXV_a&#&HQzk37DBy@jlX9H8!UE+$b!Vh_Ve>7u`|Db5_eYh;j4Nh>s12BVA<3tHb_iBu-a%oR7TWUKQuuGJeLjtc^6!SlA>L3)l>Ye zTDfk~>CBYc{ccs7B-ILU`{-z$;)`?J-MvNg)r=OV^~(S?n8B)7S^`mMj&#<@cJgpu zCXFS8$h+dH<<(bly!2onRBVir-~Spp2LS8_B7l z@On!C&MF;Td@EiywjH&NaYpSm#js?ZnmkW zti5hctY%wk()a-Q@_Qp~`bWSA11`2P03vpVLK^3Ge%w+g^J(2*0r*0NYDgxXDgIs>J?6ax;1hq7mcEqX)xC*AWAnF+DfvF72_*Op zS?szGW6BcPNg@Ad&j9~XFiCIW}_Y=%t@;|Sdro9=LbYf z{`U8GOin`bBV7OtDNT;CaDQc`V*!-t07#>Xnl0gb(+~PUnXiOd@2B=Ht2pG$&}cwR zco+l@!)2La{N3v?(?yBH@N@JtmowmsC}@@?MCXVC ziGbPUK_gLP@}eT53x622P6yqn#n=Il-BznBa3~q0XQ{zv`SN@vg*%8`CS|Nli@j+^ z8&gRUj2}QlupXyk5>V07C`sYRdte*Xi%>Y%N&LUrzO+IV?b$s1dt3SR&6|Neaj*CeEVxR!y^KNA_CHp{SDlb^eIw73Lc9^53np7@CSQjVL(XOtbSGr_rX^Dv_5d<0r zauhZ@g5Nbd9s7yq==Y7NcW&vx{13KA&UD-wi7%Jd`hLA^IgyKS*t**8vg$q9=w#t` zoh%VXbn_7?aukJWg9DO^l~zY1|1g_~^TtXpBr^kU_S(TgZ{`Es2ZHJ}!JB1@)Bo}k zi2Z@;pyPB8cZjI6a*cNKwJ))-tKMHUL`1~7s%^1}k=*DMO?)OGWs&6>`O$1SANlzi z`OISMCqT5Tn7+^`c*WK2s(-sCtrp|{n(qEzo!-B4J=QF~*N2-QPmc0~uUQ-G>ltj< zKD%Kf{x=#@#~IRE9SOByyw(aT4kj<^1Mtxni;zpG#rOvUh2H72 z+vjAyq6YuM4-*qiTcq!Zfl{A;Pg{gQAVBb2#0m-YbaMP_-t(CA78Vv(;9Q8ac4K|N zBc_XM~dfWceL{i~+qEulkc_nnb({PjS^5F>omY2kR~5@hKq#Qwcg zu$Htc7?X8oi4!Q)uy}>}P{1YBqZ^qb43sz~b5kG+OQ5}`wF4iugo{!cHC7Rv_2|9^ zg&W>$J<13OU1skL0lXb>kUzz|cRqI5`YTTUnzpg}=Rde_0FVs-6MqX`P36hEeF5I) zfA|dmMVDVFj9y&hm+Yk*)>^~s)oAAZSFie76(c%D0c4eHSmi!GvFH1}S@>fm1=hKl z+vYSL`I;`O9leHwj^3Fz_w_YOnkj1n(RA)R`5~+Pk>m@B#n#6O;HGt?$B8esTzmUU zFgQhG;BdwOL-%o)va%Bb)R>OEY#VI`slch?~IOT z3c{p&Zk!{+jsn^H=ztAie4Nt+Oa<*9rrAd9WwXGOFI7fX~XuJ2;6yP}kn!{eWW>p-hM+9O9;o)RV zilW>=3PRlJB}D#{b3?G2La!Em027;xdWR z5UeiPJCQe~tOoIsD>FZz>s=WM-4C}M?n(3M3cR{RMaa^7=)2sX+|9OddpJf`KWTsu z>hjeA+xSGC3Y;2j^2|rT$-eH0OY39gG^mKpl}(s0j)aT-)IJ`m+4bBS?rP{A7mB}E zK5;!<9rooV>WFGCgh5UYCks$Fdm}8aTahZSav~R6{Tgi)U;=x35cywYN!(2IN^;SWo~O z(J~v47y_|80^A=>R21+z{eOR#TF$7KB@G+L#I_*8%&Tx)l+NUT3%X$287xqFwIO^r z>s_|XdA1V%?2fg)Xn@e1k+KTMPj!yC(Tw!vK#Ms79yXKrznjp-kkLL!m2PCXJHf%| z7b*++(;Q|&MvygCojSi=2 zW3oB6fWvHZ&*P}`7i}>Q2Pmyc)i9{}F^($^D5;542&&3JuHCSB%}iVbnuuO-EpTfz3b%3_> z)q8=U7Pv!TMVW(Yjk;qZ?rK{ilMyHqSqRqEIsdJoC(UwmJCU!%Bl>O zrJA)AQPZg;Z?HExR*1SPL^gh82fwpBJGVHTyQ;zauKmR>i*_orTR#kL31z^dT|-ea zUNm%OGq?WsD}G700=(w0=ua}dDr6p%yc^_8aor3#(SIxS?yr>Of1u+yxqVqjM!B}q z>8oWr<&;9@w!I29nyXNcJAkqDIfmuCZPZy|0D?N17DwUADjtdHZFZ)|VK~fBihV<= z)<1wvitR->FZb^rZoO`I{o4Ois$c+N8r!9ox3pFw7$JwS&{aI4upepNkv-8f0E2@^XS2K?b)oG zXm!-L3z@+Y7j>vDlG8=|n_>0p6iF~%HcaHNE?uI$TmGPNa%n?L(m0~8op!ejVmx{b zy9pNN7aATG<)-sYIPncAl+TkDJcTd97;N+ySqCM-Q93#?ndAD|GqKqfA1K^5M-aVSIjk^ zSaUUn58evskuk`MVUZy+)Q2Lyo`122?loHGZ;nF4r`%c1dd9cog3jjs>ZMO{IBj4T zk(|^1uR_3yK-(b=?lIZYcG{n5zq|(#vaWP=io*{f%gQOoDlAiHB9wk#JTj-Y<>lUv)Qt8teesw&l%Ik}8+f&Rr5R*> z+;Av=G(0UZesYEu&XKWfv@|5FsrT)z*dBpX9%&!HfeNC@TA%?M(t;p~dW)JORu?hZtB2O7ZjBJb6%0Zrm^f6_e{)nK`3Kcfn_9uz3*G8&vb%FX$9vcXh5m&jm zq?*-ngVzBu=Ft*KEO?)Pr+04U39NQ(z*34vJ$3)s_>OVD85Iv*XxP921K;Clrnsx~ z_&ackx_faKc@>FT=M)}_1^a$JN%W}y=$HLd@;db*cHPKv6W0H!6)}PL;lk0V#Q5u_ zvxo)HRJ*I#@@I*+p!&EBq!BIlWKQ%CZ=y=!kd;V3XgblL2(EI9Vb1jzr60%ln>~jrjzM23$mAsCC2^TyXGxjtLidGoPAn)y!uwd`yk+-WN z{A>MKX>6{3)~G7W_h5*Rx@OoJ5!6+@2D8b}agb_a4s%(!J2&e2=`U?f?46zS@-A%& zFN=h+sIyylV0r-|_4oBXG_SC5KSr<_u;mD)bC1a@sK%#))Xh*b0eRv*Tc@?X$&)p7 z)T7hbS$8FE)BkJa6*&y|tDtUI>rj$UtAc_CubEEHmuH&VKUL1R&8WT~lE;bD|FZuc z8s(<;*;KZ>hR2BI!VX^DnCYVv71|h<@d#VForQn3GtLO6%qhkcI!Jfj5G9S0!Ity= zrSv69*95^@utM_JS`Spnqe3XdSnx_AQ)4CPgT1$%3}<`xVlUe4o`U9E;Dzj|QT(+* z$B!d(*(0uQ!Iq1Vhl7I(b$hk=)WwR^qFD>8-39v6*`A>x{fVBa!oJ=UNU70NQh>mJ z4`V|ta9cHni!p|2vKPi(oYI_ZKHTuh;H_n^-PjNp^UR0TBr?+B!L3x`Xu-M6EixGi zxadRmjw~n5IK3NvQn2S#In!!{A+KjQSM|b0Gq0zU(soI5=N+AKiq{y*(PK=%(MdE< zU_U!eo3Wdyj4?n6mNZ`yLQqiP@{0v`HY|wM_ezw^hc^n8EHr)t-5;>C^W}@tk7_2e zP{Sd$cGKuVBVf0Uj!NhaDWq4vvfa@A)AXwDoT*9*2~RvuGO#*T_&fi|i{R9uNB3PC zm@zWX;AG>}jk)!8h7y|ZZd@D|sxprct9$<$H;!l0H=nZjeb@u&h54f*k_q#7#(+6KQSG{00OeRpRo#R4A9>g zMMXt?t(09gAWOfgz?nHEo_w>T5nlmibE|rIU+4bXih(0y^~+o) zvZ`^DFC`k2fm3OQy_u0^>!aOpn~rYWR6!Lnic{i}eyx+z2#O z>cX>h5QJ}Ce08E49UU!NTpAf!zK1cZOmR#8r(_NA7oxgHxBw~uh1d(~Ztw+ecVvd@ z8=IO^@pQiWMDowQc~3w0e%9hAdBxwxOKhJLa+h<~-zUa<(r$xW>8Lj3lBy>A4lZ3OxT?$SXLND1GiF zr@&YIhX;a&n)2|q1s+$X+rhIo)fqO-lW}Z=Egj8Hs`aK*a;0zOu30c6K$deOn{CKIEgE+)v)f_IO<29J#yfC@ay|uY{8N$&yk4&c9eseL; z0%^NCS;}dtiZw5(O`M)?0(2v* zv#n0zJf&c%x>OA#P{#;fF3&(j_0-AeBJ;e5qsg8(?3Sjc4V=P}*E8?m(A2la1%5T= zM+QSK);Jf2Jg#&{6qls=K0eRGq#I+2f}oiWkCSTARH1he{rvGb!MeFLO6GFi`^MDekV0SS)YOoyeMf=_9yP0E{S-gD}hjzh!Q| zv^@5i@nB>P?6H}keG+(e8_HPvP*mNsRPpV|%S(9tKtR1B_|bJ=j=wp5WNX-zHBmJ- zx;>_MRq=V@2lxp+!RaWiqjKk_ zwDRKf8_)d_gI?jG3>}zXZQ*3E-j&I=yO%LuB8Q9`!1 zOkmHtcE(}zvVm3;=HIXR8fRq_E!fL}O%vEYzt$RK{^Y_ftW_QZHi)Q{$vjKe53JbX zVtxRbs%w(lU<$;%V5?=H6WJfIasKX)x5s)%2aJdNEv0kW-#4<(b(tuULut5jS9AS- zr103fV2dp@1Yg_Zv1}3Y)m)y=YCDg&$M~Dhv)%HON_;lk{iP@sUAy<-UhDKM?c2s~ z{gHvE`YZMMm{=0T{{?Pb7$-xyt(p%&Rv`8%hB%Fn;jt=}jZ zFZI569@e+OS0tGcac$STe1JUn!1{E%qPeMR#O$WqotXL1VvJ4dSNgoX=5~{(_Vxy$ z!jbkiWMPEEC(m^4nf(zZW66tZ@&t|IaK1Az=?AI!&V%Yf{au@s208a!1|5m*-GY)$ zppWey8}0AL)@E^h?DgE-#)&(JDp*n$>vxM-&4=B^_zvx`J53xjL$91zc7i8g@u$O^ zswy@+Y7O_-S> z`a2cuno+R_(Pv>K92gp{*FM*iUJqE2-R;Lm9>dntx~z$%s+*;+`BH!!!gTs1e1+vb zWo$*v1PJv{pxxG9EgwGIxhugchR*Ki0Zv!PWm~(NdGsg`YDRk)^_#spE?U~$0Lb3u zZ?5L=r{71j1_@+lyw1vSV^SX8l^~+C)@V(%?`RM4BbdXOHR{Q4p;t;ilQmvXgk(p} z;4}D%Fq!Pqpu^_($rg}X>2{Yic?J98$})g^2iMM}8;e2~-47xTj!M^ZaVfKW>>x-^ zVX6K8A4bgl8igPpzw_M4)5|pwhXMW}oq<5!oSP)APGdWn<1vW$c7TQVy#4yF`4<6D zFHGC(fbC(cOkAzTzF9R3akaV{=wIsbJ$C@s6$D514+yFE+d{ms zsnXxBVcK@KG+3(3aXHjcC;kO`_DSF32OJxo{pPsdz=7aEE&zcu74JIf7~M zE(dAJc%j&oOs$-n$<5zo>0&xg!k%%p#JMj~l+faOJex@VaO_9+PH>WH-6L1{PHJ<> zCdTW*k|>E||LxA=$#%y1wk*wTL*hJqI(3}X+NHVvM)(}ODO_HB*RpGwJ?}6^vbiCK zF)|tvdl<)(`fyx8Kv<(bnqPan%T+p=-H``0s&UoX)9az@I%$?9IR^;-F5FbeN|nwx z#4=CmmP5(%>`H*&92R;IsNJqxbk(sk<|p?kp_qMpV>R=QzVZ6`|AMB3kf}e-$1^9! zH?hUwlB5l+v>m|ux#C7Mpdxp}Ue1na+3?YkTIwLO?W4=IqM!u`|dPp0#Ecx)>D0x}9Lt zu6iy~V!XS7atMD^el5t?`Yk$vsWrH`I4t8$EReXk`d!Kjb(?ACFl-`RTwI8X`IldY zJCbNLvh#$_$LYLdU^r~JjZjiKJMy@VXLV(^ZmMi*XB$k8+B|Ey-e(y;j%()aRdK(p zaOJf6yi5uKwAmF%YVD9Tu;taSyFLx*Nqqd0^$ku1;k#hsJ5`DZ*wO( znPFD>SH|kIb_Pp#7wa`i56hy%t-ZAdHsy+IH%Y+o`!~1NF`k@GoizWv9~2xB(U8`h z#OSUMP|F7b+5#{b3|tW}+MMewTr87Ed$K-7Ycw=_JwDvsEaZ1zFwbM&751-@2x- zcLk)?2PmmGu#0N}FMu10)#>fk4`R*t)vzConG-*7V2vndh75|8L$4LqUO?EC&4c_5 z*7QZ$lfr)yXiaBZ-WOQ@rIBDrBgOxVM*8T%e?8>-k?$wn?glFOMI)0#NK2FjI|tEW z;ne*2%KP$hbLON$yoQ4Ti_n0I32axre=!}6Xuo2;n@}W6V%TDL!6gHP{}-RVLESEA zxY&Q87+3`z<4ZRb^148=L_vfM&djoY;e!7`P1}fylb%A6d-=fOp+Dfj-~SJ5{}jkm zBsLvxKCQjs#akV?r&0N03v+@y95lsW`EIRzKf^6YIjjE>S?_^z2sp5I&>5aH` z9>yRc(`~|9MoX3Rxj0i%NeW~ZnZMtzu^&6g0xTJ%^^s1D+ zvN#;w@X5IycgOtv6!Sp>ymQq8w(5T0Cpb-hmzl8|%x_koHrQY84K z1^G^5;lw)!DGTw8*028#^jn9JpAH+Pb5nsAsa(zF%WzOK%g+jo#yll}o29Vl4`cH- zX;5p5hyHK-O%l*b&_9Ipg`^w|xF)|hMaz6hT$)|f1}RmRcbQT0(4l6IiUOT0h?e({ z$SJXnX40!wv1(?2#;Jjt`VhY~JBQ1ZZ`N&8E|;ILYF{LM8z?#RhcSP#+NL;NV>9j9 zpQn(M*eF0v{p^>Q08-#C9F@bvCPy>y>)Nq}RX=SKs|PnLhl3}woYM80=+oy;6I zcy!{D=n3nvX$!*;S1@SspV?DVzDvaGVl#aEMz-YlwKZc|rVKOY-7z=X?@xNwTTb-^ z+zuwy%@IEE$nt7xpJc(FTZluQp?Dnk`+LhYfc`E31YfI*hrmFjBV^fvgNe2OJeqN2 z*ZgjFnC3+{-cfm;E(awB9`y=715x(`Q89(*ce2#OEUcjMa1Dh|gP)$g|N0*e0HGi6 zmsM_KyBxgMn$2t)E*w?MYG-rN)wu z@adA#o=Q;ODRoB}xbu$4&lP&THT%-x{h3#y@9KS5*MA_cJx|H$^dQEnF@GOCmczu6 zS8Qx;0QEF)hm1nlY27!_O5}BtCu#}|a%f1+ZK^w`?Hxk#8UrmIEj9i8APbj_f`S6P zAW*}GW8Q^=W8Q{hJX_{ylrb%Tu6JNSS3}5W32Z)=^@;c5e7vZb8VDi)JI#G?(>!0E zBXWU8!W{#YajNUzeX1KGI;?2DB=e1^g5pPl#c7v-F9p8yJ!ciJWxJea7#3ggZ~eZ4 zifzWvZ}wf7J_a0p-&4LCZCo3@P}(Ll`!XZ@{;&j7_VgpatB4r$BkfG}A?1|UhVVBj zT~$$df3X)*(&d%@ossXXWIwC~K5RR-k9w(!?X*5Fr+z@{Zk3<+XW{+?XFRObi7b%X zX1zA``?~BZ8^Zt4&ik{WA~GK-;3}bCEhSbm441PeP#m{--A|swU#mCcQDZRUq>pRM z;p~Krp5Ap>+N;RN)yp+vHVzj3)@5~S!@uY^Gb2oP#*Kr^LCDg5(<}s&j9V0_SVa3s!*o zM^cRsbxvg9YNlpWvH`Kqqmm7sOYXJ|UScj3y*aEJ;U5HZN2shGLVUYja(JDT;+P5q z#T0iCJCGI=n5Qd<{gxQOWBamvj*d&rdp|W?jK|*vUg`NdiT^VUcBeIfz+@rIY3!jz zhAqS?>zIL5y>)JxXd^b9JeXD5ZlPTnQiSYW2Ay$vhep^wc-HMAvOj&zdsc19iJ{`# z-%91K^}>S$lb3f8a`t>V&-Bu~TCa`Xs`>6*DD|zFsD)mEhXCcFDls4?5Q@teHW=|m z-8PdQPdxIro!-3?yE_eooRJwW5>cq$pQsm49j@hRjK@PyolZ#$H@*e^T={Cl<9-yL zPW$*Wo3|#c3|zdv%d*sS7=Cx*3g0jANN1o^A8xMfF|aS7Eq&eJf3W%xWj9is@MC?)`+{pT!YU zLfr0p%cM9(u=_148dI6?qgtPta<{6gYZo7cMYP;?9wc5( z&vLYWfB)X9t9#gRJ&?iyR+8cC#G-p_$pIhgUYs#rWlgiZXG5GU1_1r&7P%2X)dOmr zwSi}KB9+V42zi(oMfp(^G@WR9wS0O>4=ge~qj99`Frs}r<*`X3$n!czHmy%Cu$_h2 z12r_stg=-Q-U|BZis3SYj3f2R7kwY1Dd;EO?N5jGeP9-gChNiTeO?Q)PO7Ur4y6vy z^ZJK+3|h)A!J5qE-*!}nOicKMFVi=;kxn$`76hWMB9~ zPRA>ap}|gN3_6WYD;XaFqgRTnJ=xohE+UtcBSxmDlCreexB!c+m&K34hsaI@B(Mt% zHonz(a!N{777Kmf$sdSjJhn%sH91UQm3b1&|4EKUt?HPhQW`>kKozU_n}2A%Ob0fo zTy9u2!odl110T1eGE!u4AxAF<5VZKrhn9!D-IWJu4pcmA&dJD;i=#3@t9~f_)y_)KTyV#z1x#ck+?_kFEVKlBM5G80(&g|)M_w-aM%V!jk@t|7-idOMr zk!=3(r^trEXU{GmwHmIw2X6U1-*KXy6Er*j%-9%%(|k)JaNjFa^XP*d9B%n|ss-qY z`v7xssJb676ByG;$N zl_HL5$89DcEKDax-^)j`P1E{}%QT^52<=cDJk?TFJf~FuweOBv zPn4KB;LnQ-BQSrI0|3Q4dip{Q9dSoTHUO!7P!x9z4+X$UGPh%XXIjzuQFn{1)-YNM zlArVYWx&tv6abnm*1tSsfA@e=*|&+h=aw(8!xL*TzC~# zR20jZqK#A8}-_m+WrBLZSozz91}J zjkOMv_->M~#^**qA6fwHeU!r|&ZDZaUIKYNc%!8(eLX`5ppA691w@}Y@eY@FEllh> z=K2gBpOE&cATKbo85#(~rNOOZFZd`Oe#XVZzQDp-0B)6iN5P&n$XFR4_D*p!B7g2z z_c$i66=sgxvg3alc}TRMDlPuQDlGu6Wzpdm-~FO60XVXPEuB%iw$4_OQk63HF7Nd-_Zcv0LItN&36I2yJl8(*P9r8R#lz8`E!5(vT>G37&KE{ zrvCJ?-R3D{&;E3m@VPE5TSJu%)avIwZ}bxV<9oNpCWF=ylQ$GBSmwpCv$&x$c=v!~ zh&Lr#1R(GLmLH6{axnOcp)ux#Dbf?tsYw5qMqwOU5eZVgd3*>0#QL+f&QQi}V&De= zAq;hFyceiIbOL7?27!A9^xWzi?EiNAiwu&wik$HcyOVYB;{f>a zTwGpWLGAty6;R7{Cb+`IunO$#5`9+yUIjd9&YIW*P}sRq6tIA3M{)EI@!|ihVx)Gf zpu}Y>Q#->}MqFBynEsMdz6Bi8biHxnHIK$)&Z}0EqzJAW<*s0Xx9z~U-l?qoZ%GjxHVZuz&*f?-hpu2|vV z!;+@rh_zzEc`J?_P|B`yB{CvnIyDNsLplQV09DX29M$=t`n~pNfLD=x^h86O`~=Yy zg*@Ha@n=J=pi}g)?+^kQ5TFF<$IMZOf*U?kOu#jwsI1J)DKB$S?P!DYhN4}g0XMSS zuiw#kmr$i(MRIO))i+0sU;Cft0G|)^-ZNCxJ*RY(hO>zFwl;u8724e)ZBcn4Rw3F z980xvd6KGeSgpze!0@ZQvED=UWa!v-+_lARYS$n;%s$U0im^e9ql|Xy7e#Ar^2koK zCa#$W5icdf#8^$sAE3YSDQ2QZWV2ra_IIQfvec{0itxy}F6;EadA*Yx1%b2}U}u8P z=_CN&96;xxmy+o=8|>6i7&ip;Ew+t9?dh&bV<3S3v%j4-(ETn?Yy)nAN`f=CcLXA8 z*gFd4dYsH&YOk#)Ql?RER$O)3(^n)@gv?wtPe5{(qte9B<54kiZ!3zw;pg$pGgBzc z`OFV+najy)Hu(N!ahBy*d~PE52=24chN3t$Iwd6@fFPGw>NF~63%Ip!$MK#_44q8; zEM^2yWz0O4Lpk<#s^3#VK7(BVshV85(fgXL&}Q-n(3t=X?f?uB2?pdtS6Vd|rVtz; zig9NCp|3MI?8xM8T?9EUL8P@@u--RyZoaS)2b)DIRW{4PSSlpcFQ12{aQo53iNBEI zqr4tIy^DpM)^>A7qpPgjcp^htaRHDTAG-^{S+gnAO=;2r+^7q;Xu_b;hjHw9DKRX- zuTScA6AeWlnK_$PYgZlq@<)Su@@oOI+_l|sYWX3@wds;{=4c1dK_AT4B^2xDic1$X zb)nTEAtA~~P#0bpON{a3i~k1=SgP{~Qr1WFHx0?V(I=_(h)(!mOaJX}APQN;2JwOt!9G#sCRLMp})bxj$ zG^10U&+mAq5)xlB=g+TnptHz(ZNq%jm@b>G@K3@@Ur&ist#AKk)nn2{sEK_~ z%xxetO7l6FzyFErzTd)=Q_ghkc#%AWqc)qH-)P!%masAeZd^7-l1bCDXS>Jo)p$ih zvaoxPj*h;FnWhZM>;9j_L0%_qa{8)#2`!~-fyLbAtWh|m$~tXZ=jbJi(>v#3Vi6aE z4{Xw##XN!bzirUH+$UExykJfwus`}DI%1_gt0bjleaEcX6!=l# zA$bD5UiF;s>MBm5^lmtI-;F=kNxb04!B?9PsXz%W=jwyOyJ z^ip11L8Nhu8u?6n>wr;F(=i8g1SV%Uk82Yy+(*^m_Vz7~7Bz~jjtVO4h|Q}JgmJ1| z=VoptvSPzqYSe<}EzACbE%jiI=2jE#c>SaHZPF9McVBVF8sP`-`V+?v5hSU&37mvMB^lB2jJE0Q{ibRePyPIkN!5Y?N0 zSXgh=9BzWekmPMV+pzW25_^n~KXPL;KU;Qgstyv*PdWA0g# zY|gJW)K>^`q2M7kXGzZoD6ncvqKzLk15NAaWQ2XLYjFiM^;;!Urkn5awk_?2($4_* zjNt;2waxOq32TUSxc)JA!~wuD}A@$@A^EzfuP z7&?X83p?vo`C`cp!f9rH&SxrBb`RUzm(m#M+cvv5$&;9BF20n7gNbAN$xDLPNvLjK z;$j%tSvB!%2l29pbWTc!tN!2kc13;yO6dX3>;k;80ptES7ni5bab9K1Y|RUWOnIeP z?I$fW1CM8xBScR`l7?0x&ukH6g$HO)!w~i}I*_AqJPs`vrVp9fnhcKV=j<$2V5*ObwTtUMP)< z@6J-cHd(tY{7__n9-Otcu`9s_H+-OzMc}ek+Eyflw1>wYPDNYuSuIxc^PY_F#_Q5HKK|FOEhZP_iq%l@5cIeORNlg zH;zxvlqHLGy4VKM$?w0uFK}kizjg`u;Z?Zl*Tagd1s4NXdHB;^y1w9)BVNFs@{T)l z(7B_Ulo`Ikl7aS7duEC%V{~i)4GtwB0rhE! zpe7?G&x_?~@;MuWwv?u$oGP23Y@!3a0B=WjcJyhLhJ%`7^F;GA-L%-H@e*UshpGw` zGzHa%(^th4aGBZPcN4qWRHjz%zFxaxn$P2AQTo)?9c+22b?y35QrkzD4q4ve{ZLfK zD>8Iag_S&PeL_aj0138r zU{B+7)&^(1*majJ;O9)9-i71%Cz&34#TPD43Z9~rDQe#2C#@CJhV#BsqnqV5H%#iL z(Nj>Zde~b0;HbP@7u)RVO6O%s$;k&ub-*1ESA`Jp*VA6_MbJiHVPmq{7Ga9dB0C-_ zH*$b21oM#h@zTFn>#~g)azhH%WJw{az?qp8iU%OV)*|UV6oa%hR{`fNIBirA?E{m)##6# z6dLcBJS*X|hu>J-ihoUF4IG8(ZeCu1g6vGXL6^j#dTpFDCrh5k=pFu;x&SrUk zo!()DT(5vrYXInZo{aaBbJ${<#qX~<+e8aU=K<9<{2fdXeT2?Xu?)mHw|kA8nmV`B zX7Z}MBHVf|8yYYa-F@|?{as8y2+r?Ac-TrbBPI*$<~a%orjJq-ea5d|h@7^L%;eU9 zkcarPo*5n!w8Ar}C)jMXWi1$FE3rGWEa#@#8ySEa!VgZKwl`a!GGU50kYKEM zJzDPXY@W3opONw6rtMXI`2=`F01If_`8fl6Dj%gyD#0I%2)QT(X%`yH%mbCQ((s-THy^xR)bx7N?1YfJi?W_4}#z{7Y2x8kRm-kQK zxW8rkp!oN>OCz)UyOq%^-#^Er!Xc4F=2l-2S2V+>(Bpor41W|h4lS5o zWCTxzvO@G*jmlm9jH&$T{&}LXL-;AC&Z^@e$sKD^I0@c7PZ@t%Xcn13hriGPU%ekm zNt5Wt#bYEy9Km^(&1}OEgBO@YK&p?=X7?5V{=>fD{JG&huGoLN;I8Z9Ipc#KJZ0+H z5usCeNjwX8O>(^cW!*%Mq6GsEgN_`05PnrtMxr~ z2-p~;TNU8`&c|cA1=YicSqZ}2_S!YF1{1R0JDx5q6cZ7*Ps@dLM&rA2GirZUzdmJ=GuGF#_*ZDH;@QGGy7J;uC7o2kx(XlB z=SmUY4K&2&#qGf0fs0%NokNpr*j75iQ(6~H+n>i6IstVhVT@P_lG@@J@vsSj&hC_SzL%j#Ul7D; z=v44|j*O)yYH1d#A~@`)vFffsVh#mYE7?zH@jQ-@fl9JUh8ix0B1~m0TXyATJ{i&_ zWlomVJ5ZUo#NH305zT(}uN-Td+>)ksG$K7uEX0Dg@jcr;(3&Z+i4hx4#~@!Fu5HHP zzCc@0mvlGJcPoLL64@Yv2v1prlU@N`Upw#NhXei;MW7l>xF8;Ge{hUi*nzwE0`hMC?8np= z54ae6z~ zVl=#%8Q~)=)OK3U5nS;YDh;M$-anlwk0{P779zl2WW9_3{;aKntwz(^&NInBK&bZ{ zVXpJpY+&_l-Qx#_NL)+!4y~7*MQKsh?z(bHJOIX*_$=M3pJ1;|eYSCy>x6SP*P z5P^W12smR?_J*gR8}aWHAFbkt7naim`^swdTqCbR`HZYd1_C+c(SH%C}mt_fQY}n3FHW z&@#neUEblcR_aOLfV zaR7uLI3X{n6ySIBvdlqgPfK>2)p=ERK zbCQa=*A9z97=%o3MzeH6=(VtXUOeFjNeP>BY~Mp87#ch~)H~~fy50u7uOY0UP6xuo z*f`lUGQOx9wxg4&EecoNHrB&bwf;G1>IUYd`gxpIr)71Dwx|SF2zl3F#3bF!?q~+f zTPDXL>BWH9;`pw0zde_YUdtN3#j{9^19;KztmNN@m(;qaUWUdKF0e_za476@lw3S{ z(5u``oh15dWD>zb$V4EW!XEd##i+e_E~(Ak_|mM(5D=T$lZwO3s&PJDC3A{8Uki%=Ad#3^AML?? z-vhR1=AoUnct>C_STzo0BtMOMZa@BE5COa4Ul#D$iglk0=~btTX%ML}P_^UVuX2oy z)A*BBunGKXbpLUE!wD1F{a;?ng^VYu0PuzX^WVwu#N4>+Yj2P0(^8}QG?VO6l~ClVX&EWId%K*6 z`K<>|K(%@39N&k(sz@3tC9prkwci20|FfDmthw5h5*-^=*N$)?h9tkA9GMm zFVtBH(Ydvr9nM+*vIKa+MfL?|2Y?8B1Pa1-e^lFiB=cHmM?S`IOZyr06`Ua^vS@ol|L6xzz@Z<7X@$m!2PzpXK0BKZFpA z5QoD^!)^$<=GT<~DX-P%>Qxpy9F1dd-n>~A&}6_{Sy>5x@bC``A|u^Y zi+k~^SCQ%V z3ew%p;c~k_Uwd{8ZTGx4zb~K#p52|dM+SK)rbWZ2nz?Mb_kz>i9DkIB!oyP0v2b$OsUh-w7!@;hIn1i1R(LW;yMOjJw>2a|DNly``oOo|#dVm+xX#eNq5` zFcg=O@kU=?A7<&I1^A3NgM;wU$8WvSR4lHi>+R&i6YS^VUsi9$v+Ts!ZyuTd|O(yV}VD0hoy_22Am&7S0By+e{Hk2u1y%tw9eFd)H!jzQAaPr zdHFKRh=@2}5iz)Y)czOH7p(asTuf}Sh5Pi)&y&r^$JOfD7Z{6|&bL}-b7XYJ7TrQC zDy}`TIKfGL8qvt#f`fx~=BoE!cHJA2*C*>Xa|YySyTsF}r?jDdY3jYA`t0g5#K}GJ zf*1xU9_rX;`9NGe!7klwNyzH}O1XS7t2XO7&VmDefoXofCbD_tgGE@yaW&KOyeYkk zh6epn&5o0pYT@w04c4rYJ*^1}Z^NBZd6;>l2;Noj$d|cDDYyX!c^2)}R?q*(3 zt1E;-d5!Lt+3(68H#@dI<6xk;ZK^|k_u9!ljC#?QgTQ3YKc6_fv|Dh~L_?=q>CMOh zTG_C2g7I`zK_U5pcN$>M*?utTG=KH1@o-kM1cTw!$JdvA{;K0_-hC8LDxu1|F`+eU zp0pRQBvJvG9fV2{R@H4O5Xfj*P@on$CvbwjuEn)~kmK5N8T;kSmw612ag7Mwog_Oc zA?6~<<}~i8-Zhy}M?>6^`$@`quPBn~IhymwdxP_(V|*DtTP)NZ=hp`at*t9PO2Fgq z>MVy`x08Vx?Y-{fiFGU}Vur){5zvr^NT+G;D6NjTl8G2k9Svr0(Q}&5Uh)t6r&77z z&&7`4ga`uO&NT5& z5ZYGA(U{A%JKpkYzslGQ+q&2dMCJuE|{JgNA@Po|P4L zl5}fBijhJnU(iAWtUq9;8`|ZlI&+TIe zAk{^x3z$#QH#Zvw&t>ma52}%9^8jm#V|)xaT7MeaQp?Vl@+~jV^Nd`6S@G{+GqQjm zkb%-=W{T;OfBL@g@;?itodEn|7#K#BWRzrMElVhI!5&}luDihT!gq~}JpRA4(;V$0 z1wBx2`NFMCmHsNFpVVMHunvsb{sDylIzLb<)y(E8CV_G+3F#fQdF}{de$s1gI*XVo z$P+e^0%1;RdWO~}Bsf^YUauMgSj65iGyj%rjs(Kcz7x*|X#}bW6$(0A0D5Kk+@=&H zyH(iO&W;%#`KH@n2+++n-3M)&ZdZ_-bGvomjMeA9E=qk~EBoGk&tUU#`7?>gW4S`T z$g>{YsW11mZvQm;F1yKoVUOSyVb{a`E$lN)Oz3cG0Zj^-|?K0ear z^6R#C;YoJ0Bsc3MdqVE=^75X(q1CD@>}E4v^gO;YU}nHnn2h?aP!#`J4N*ooycC%l z>%A*!7(PbJ^?{V~o7O=mSyasmJl4D+5DAtE;GtZ+Uq7 z8TqlF0=A^2Wc*3TdFB+&Q+tDxFJ@X6E3HrO&YMrSGb2wfs~K9tArQ^QCL-wbDK>M& zJ(q(#uCJ*Y{hr0)S$t>j2s+uSi<-ICQvXccoE);$m@cx8ZmJKCb0VHh-=dlkLC5Gt z;gK@04W&YK&;qn;bba7*fKOswg{cgHf;GivNT4kH4cz=x)+C>mH^w)nKHU|+*X>=4 z-qPv5-pkXRu4QU4#nZs!?Y|`e@oJaOWtvQqf1@jD3@LtD8BkC;kdh(|Mz*FHRi5=H zus)r*0nKwXF{VpjW&U`aq-&_KpkiQrfiEdlkGgGt!FJ9yjPZWX-d4uM0||Y(W;SHt`*E?%mQ)76LAqoT3}9u-MTj2n}vH;1u26-#vDg<>x$i@E$bKFzO&e@ zOi0>hGKKSa({eD=Glt1eVIad#YEI2`a$jS$uRFK)fBO3BxTw0WZBPLP1O+K+Bt%jg zq=pccQjiiDKuWp?n2}JVq(r(!5R@)q=&qqVhVB}Ah8W^I=>6T#_xs-8^PWFvX3yUH z?6t3TU2C1Q7dGu)8W5X`rGgc;W9Igg?7yk!?VK~rhKGs$Kd`i}E^m#S)psm|*_z1z z1CfIUF*|1KNG>NZl=c^=$r86u3Y)UXpwpK54crzIcJy}cJJSRIpyk+?(6HLHO$p?N z)k=&@Lcu}DnKZ!yFGt(8EyEsU2xJhlWN1LOV}jj3(k)^N9e(l%2FjO$uloQNMyT6x z&ZA52-NU$j|JmzhSf9})FOk5OfjETB@S3yk!M5BCn7moa&(x8AT-mDW*@dGWhh&0s zLcOsds*q82gGU78wJ)(#IIb{gcp?3IO!XqRXDM2D{f>u%_2qJA!3T)Rg9qeq*mXc(qwEX-z{s6EhAuB*>HQ~1eY6vA!5u$w>4Qr^!wsyX-P2FQu>vGUz z$v+MY;;W?hd8W$>H3ytE2ckNk)PD zN~)Ty%2CtDkGmyOPi@)26xIwCLYo@L)X(Ct3$-H8y6;slHH^3p>8Z{`4di z=S8lU+Q;C}VeCTJ$gmjWo=rVEM;-sI4ZwcnuaG1tXgKeChkq`=-xve7>W%K&v*%F> znIkU@E~}}LqI8Im@qrC=>3Yd?kyJf*s8)m?}-|IT+R0Hz7z;}m2r9s4a{|- zpjiAI#F54O;FDi-5p3V-1kItSuyIMyWsOFjb5n-=<%)pMSrtVKFN6Dh`JZ6ca6=Q` z-$q5;qTnD=NPX(wbx;3G3Q+Z$DZ1bszvR42r(iUR%#@kzLW&VN5e&(;;2&(r(oPGzfbRTWC(OTI;npotDk7yc~^;e7DPn(A_ zQo9^laR-@jRp3{gir@1p$sKPbo0fje5MQn?{g{p*8VeHHUy(w~9FS&D*|6h(Kj`d`nWEXkBSTT2C=9};pu$Uce8e==w@j3)k!2mk!) zfwEqaGl^hGUW@B?yQ-*`8jIOxlW!MtAG5F5Z9w)S&}8x0upZZ70(CpKJE1WfBXY4>2yV{FuQ)PpQH32FPb5j! z19E|#IO2yCE^b4oeSVbVM~GzM{A|`M-7O)szFela7+t07`fKbBeJ%N5Yg+Huv)B`B z*E_Vdx&LnO6GbmK8gMn2jc9Rk{$XH%&;$Eq&sJlH4>4qz0-v;_(y#DU5}&llqn6>J zD|ZHnQuP{`-qB1_-t20Ne@X`i@GEsr_-g)F{1~`=OoLYu)!EMGnx0Q2GXAt+`QHDx zDN9&*z}V+xyx*#yUyi}PjvRU8fD3j0!v*i5gP#q3Oa14c#BG2sokhHh^0e!x``#A+ z{D(4XdUt&-PhXQa{%W+cv zjn@B3NyqqsAgI=-b%sZIV*jKr1Jl>lwb)7pHtwyzX#G^ZV*yBNYpDRMk0!}YNrE=I zK3~Uv5^7&)^qKHd@mABr@=Z$YS2siW>X?8^B0ybt;9S+NF@QTo{0F(#}DCa~IrLhVwo%+JNb-G{Qo==L)()1u)-(l+_ z;rIH^{!lsLNBwBfT49mDKlv7K;U0B?M%)f7zOEG`<17<;{JMV8R<%?E1NicSDb1%Y zw%iW6UtPVOQ*nR>ZYjU%sVf+U(mKU#DqC2v0~LjUxKhgQNw!PfMpE;<*gB+ejOf_D z%!~KG$opUQ9g2x!8Aan(IW%hafH46x>Dzd$=1N8!6-8os6}17xk>wAnzO)Tb)QFC5 zH3W65qQ~nb24CDrIIzc{%Js!hH<^fbcjn>|YpHCk7Ty97ZTXL==L1Cjg&D*gHL4)T z5*BY!nD6Iu*Em$7P;vnvpw^V=v+dsM?7oN9Y5`x!k=0Lami z-y}U0_5^+u69WjhkvlBejrJATfFE3c`x$N!8foTqP9$#r8Mpb(O*Oki z?IeZyJ3q_mjv*uEqGUjzdPibAH<%fHik7NzlYbRj#z(NLz!ZBsVTUWx{T&DKjW ztUSq;8QR&%o`7hF*QQm9mNQqW(oVj<+z|M1M4GZ_v1`VEgdxy#?HFUXv6yLGT(48r z;{&VraoQZd5?A_PfoRi6d-6uXCC3zYSV=N&D)C#%dER?x?xQeX>C_pScI?UHQp;<;uMhK4erlXg1lo9Dn1MW2F2CLB-ipg}c2i=sP3qEZ#eR zaWH&o6Cf=VxJo7v^V40q`*k2$OkD+2$4^#ZYSGYW)Z+V>0n8yuitkM7}d4B#&vn* zG>fv5!mGB-E{o>E2aa3ZnGLUGr+y}M zS7wWX?v>295_p(-G2j1Mg+k(wt)21r{K3Vwe&N8neMqn1 zIIf%ZHba+FaU2|`!#s~l)62?Zi&2&Om2TEL+A_3_Q$FI95-FTa$S~9MA6YYO7R!B8hm-L-2U5a5FxR4AdsWz6&>%WXz+HmwU-EJeeLLqAB7?KPx$QU$>KW%mTp+ZYL0Yqj}s*?+P+`xGA+6vw9oUJA$Ig2Z z*P`1KH_z$=^~#pKp4J_)iUw|R7;E9vL`l!hn{}MlK`Ui6JofI-Bn;dyS#>^-=__3; z_YCd!NXE{DFLy@Ny?v={lwSd@+7Qh8>nI14FRMsd;JrX1v?s^S%$#Z$X%d0e_B6N? z4btv!K0B|yF?!}M?IP3t7FjNA=E>ruH7%8~$n;g6S`2r~;CwhZV9X*iwJu^wCXAW+ zCeufd>C-`|t3;BNJTp`9($Z+%*dfj+>nUpmJ`;;bES&ciaDFmT@!fnsPO;a7%zoAd zr3LPYV#onK)i=9qd!P_bu^Tj(hJIcxbojp|HEb5FB3o8Hui$8A(RFU>e5dwK8k{Z4>-pWf5jSH2>@y|O!^5d%-g63mgM{f|DBhuPk z4uU`}c6#ywxx`~MJ=kbjXJ@)~tAox*xso$yid$GM#; z>RlK5LHE4R7;H#Rt*7~Y?$XG9kv2zvUH?NNGb3NX&)sHjdxW;{Ft#ni2z{Sbk<=ut z&cNb9?JCDZZVQqYE7BdAUD$a-94uZ1|LU(u1qD`qHYc(pL+McXO(y2xmSf_Ql0I$_ z>xC5wsmv*pJ28|Yj)H}(eZMU_m!ZP>sPsepfbsx6JcKz;r@=`*$MHqFbZ z7J7f1V|{wC#Jk<*?n+NGQsT{Eu1sMn*D%&z`}Tr}aZW+Pkd&-M&_7%-`sJp#)==}9 z$dC74JFB?^AY0qK|L6=V^vH57XLSjLoEEuJc40SDjiq{1VV^Ifu@oKSC7707SM4h^ zHIsCc$)*==aM>eP2X!(l-9Sy%`^eZ$rno;XOiu-f*0*vW*-fZ=$>|Jf!zMcCU)mP- zT{<%0-tgWvmdlfy%@0-3vox%5xH6*?=i(q} ze{D!8oxvNDN1{|9{gMTp$J-oz-&!W5_4~h0;6&BSvU+TY;ohgNWfn0p>bv5?ym3UZ z{)8jc8+G^hH9>Uhm*h$c3N7`Y0{o+rU=38VChoGSLK$emDdaX#jvkmRPBs>0~28 z)lUPpC5!mmGE*oxRgIiH!GRTfurhNegtnS(@Xs^%(A~aN4fcS zythqUig79ZoGOrO7hd9;B65of8qcn5MIkYf-Bq(iVkV>6!UQo5>c0OjdGeqZ|2aK( zyWP%oqukstx_X9KtdWW73sFD%SL)&rcsjJ_<+kUGSp%>ynlw^FKeFv;Z+0T2#M?dj6i+BH5hF(Qz`%% zn9~nK&IG6JOZ)3H8duQf-IMQt@Nt$^36!zMqtrhgC23~CNWZj!KDKnK{?pk**HgBP zeVMw>ci}gvn}3$SpG11?m)1BY_;;~LZHcYvQw zTR273-l4a@V;xVIGX<_|Z|;sDp2DhzB3{_O!d1CX-!Mmgy<({Av#>q5_YlPxV{C44 zi34q?{$#u$Hn*HYVXsXmbgSy&mkL-C_k;sKycWb%geDLzl|K6Fa0;$R{?OiDr;yFQ zBNn}C-b!T;p0U5i4$8mwtQLXr)xECo|6ENQukihXiA!fE(&+E9rLsS+8Et71>RDv$ zxj(8SmD`3=l3{G%&NDXs;6FnjLANt_z_WzPGfq2lq!^!kbF#UMBj+-8hVBtaJ)X?; zGNRRlYN2q8Q?B1U8R+RAVUV6Bs;@#kwSE%S+J$)L)z!10K@{a}$~FM~ST#k#eKD%+ z+9wOHoNmip!r|R9?r+*HaZ|!eU|X4AblqT(om01GfYvADo#2ZSmw%-;ejA_*w}i)F z2&T^1dK5S0M3d}rLuucoD=s?)k$kHkYd&`|4Aom}+_E=)p>9-YwyD5%S(w%s?q;q6 z%?Py=G}#pvX=_W2XD6<0da4l|*gj;SqPM_Y7#1@u{WO0Sz|1S-Ww3Gah?>SndY%rN zRt@srUXY2?_TEA7FA$k?^FHw`Gpz4g3LwE%u-pCOaQmA(Y`mr;vj!bm%d1SxG&;}h z=7vYYH}^1Gth@J6forq<%T&r&K`W+)|HMp-}iA9+}tEYd`L0Ur-sz}t2Gu) z_~z5tQ|9H)DT&JBg$ULXZ@**i)c}$BR)4I}(V5%D!AjNa$>XS_iw3<*122Mcm&~Id z+mw#!sN0J>p-`dl@g^hzlL$59Kovs~FXk-O{l;vtQZ8NN&s|6_EzbE7$L$jl*oqsI zKJ>O9`yEH_NTDVl0P! z=yz5NWCr~6Qed_4DB=YkcC~Lc!_-}=Wm^|P znKT-43p4 zRfw5Rk&_Z$NZpZj!M7+N=f@%?Men<`WVWzKKK$?sM8Ee>=!$teA1tWH5Q%UVOI-^B z4$fWH0wdJt-4I8wiyA39%;|}p-w-tPEpHvp5v61=jMJ^}mFzY+eO6bB>hO9e~({2NeOCRG8^RCddS75Iad@Q=5}!FA*7=1zHG z1ZuG^+)DK`D}07EHH+~WPC@Y-bf@K^)eyY?dVQQ)a_&$-!j9Zpo~r1Ouk&6}d$;$! z^&TbVwJ&NCoScLy7q+M5>NvaoWmeY20Q5(`5el=BP~90AyQyuoa=eV-Nb$f1r|!V6 zWg(jbY}W=jeJ@s<1LzqLIc~EFS#imdQ9noTXrWH%7m4LQ*OEVUeslz z02}qXHxhpUZWAp!DYSR3y|{5BM?@@{4ox`RN}Diz58I6WYxdfvXR4TVWbVq-%r zWwfG-S~$BC#XFmV;bXb2%NA#c_8;l z_p6iZPQKHYC_bHYLNtlKp*htJ;+Khoo=M6e$t=T>L6Q);6YRUu5xHXj*;~8aomYEuF|6 zb@r(r2)|vrnrV=FkY!89-P0b{t7)q~C8q)FkNCaQ#;m27RZjI}^hN7rB|q4-@vie+ zqK=O~-!gIWkIA$JEYAY%tu~9v6JRj3cJ6DC%{mftq=HQp6@2pXSZ>7jH)I)?+tEfEEg?B4%^~+v}O+LNJE?y5$ zsLV^IE7a>cv91I5XS~Nw?dnCt51N|2C0g4@yT{(lpA^Vp-YoJ3^u0gqY*!1y1qf`0 zR*L2V9lZ}$JBfpb`7E#YK~@t$PenFlj`)1Ohl;!!xfClPj%t^(h8b26fNfW&&7#^@ z;p21S?(MTlJ1eDDps-T{#C!*vNV%3DeYJA7W({T8As5(ViM|~9UA*2@S?ridW{1ze z2t0MtuS@3F2N|)an=M#sR?HnwT*d7=$)=MSD>PE~_Lc@}d_4K_z+pDhZF2R+7!dan zO7k&NT1EU(8xy2#glRmKyJqDMx@ZsNF_RZd`9o;5wPha20@1Ef(XEPv;O_SDNko0+C(s z%Y$BejoQ1tG_!gh(WsQ_E<{>yYtTA67~2vc?no!`y95|vpT0w_o5#s(zdvEJhpwY~ zs^^waNpyRF_1H?ck3}I*I|_{>QsgW3Fn+FFYK>yS;%GGAj2o6TzO6~aP!lVBPWrT0)%J+NRUGag%H~qkc9Bp_#Yp?a?|F?AVZ^6T zrCu{aGbiiA*Dceey?|5DRu&^<3XbOVMlw8ekR#Wx9^M)pmdmz!t8MuGSG%A$cb`~` z+bn$wVPEGS-n(xTHV1VpsMT`$8NMxEoTjQMYSQw#&G`4sb8aqI45t9 zF^s0H+Tt2{LHKeU8?v*5bH7%5&tmlaCE=~+N|!C!CKsK@*ohe1o^i!g7?*?31(7|D zK2<^7}P-pqANRjJsjtSecSnc&~MF-AWsWEU1o+wSZ#Vq7|=Z6z3uWu)u%RKgo5)H|JL zhXfujWbK^?&73e_UJO%FH}}e<>2~#<)tqU8r^%Jqd;OFKO`nO)%YrxSLM!()nsUK> zlHm}$)4gsjw5Bt~`3XuXiS*p*^^n>;22Zl_d_Mhv<{ZH*J(7Sgj~~wNW;>IC{(VRmPRl zdgv-50?0SpSshS_EM9C|UfC3Dv6pPA*CntWP{B9cERVyyINzi;X7y=*6pk+%U3CG+ z^L zP4jks+Y{W-V(*6&GEZx7L;Vu%=rPg4UpAdqo+N8k87IF?3H->aTqfwY2+Yn=hFyBP zFd$6iEjIM6bK0wR2WN+Q6o*XHU2uKTZAo%ShxY*&F#&01dJ+;@k_5UG1e{``6m7?vYxOysmUp3vC0 zZQL};CUAC|^qhF`g!~G@GHCo;)p{0LG}Hkl_|{ZEW&fb0v@|@i7ULQ)CUKPji~bh% zQVHp9mNHsNb~m!^U?(@|m>@S%HgjJ1cv-`tRQ)w_Fm; XCxv22i{d14fa|%UnnHn`@yGuIy^-`r literal 0 HcmV?d00001 diff --git a/README/images/drawio-font-2-select-custom.png b/README/images/drawio-font-2-select-custom.png new file mode 100644 index 0000000000000000000000000000000000000000..af9ed7ee3edd8502914a412322a2b7113c562c46 GIT binary patch literal 87699 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 aXS~~(EPo6YYB3>zhq$n`P=$c5-~Ry(7`4U# literal 0 HcmV?d00001 diff --git a/README/images/drawio-font-3-set-google-open-sans.png b/README/images/drawio-font-3-set-google-open-sans.png new file mode 100644 index 0000000000000000000000000000000000000000..6f4028777b34dd7905c5113116b127d8b5dfb541 GIT binary patch literal 99463 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

Q7E0L{LsV@aNwUUO8OaOj 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 Date: Fri, 19 May 2023 19:41:01 +0200 Subject: [PATCH 017/247] Explained using multiple identity stores Signed-off-by: Arjan Tijms --- .../asciidoc/security-refresh/security.adoc | 145 ++++++++++++++++++ 1 file changed, 145 insertions(+) diff --git a/src/main/asciidoc/security-refresh/security.adoc b/src/main/asciidoc/security-refresh/security.adoc index 4ece00b5..b19968b4 100644 --- a/src/main/asciidoc/security-refresh/security.adoc +++ b/src/main/asciidoc/security-refresh/security.adoc @@ -408,3 +408,148 @@ john : true The test itself is basically the same as that for the <> example. + +== Securing an endpoint with Basic Authentication and multiple identity stores + +In the following example we'll be securing a REST endpoint using Basic Authentication and two identity stores: the database identity store that is provided by Jakarta Security and a custom identity store. + +You'll learn the following things; + +1. How to define security constraints +2. How to set a provided authentication mechanisms +3. How to set a provided identity store that uses a database +4. How to populate and configure that identity store +5. How to set an additional identity store +6. How to use the Jakarta Security SecurityContext + +=== Write the application + +We'll use the same resource and same security constraints as we used for the <> example. + +==== Declare the authentication mechanism and identity store + +[source,java] +---- +@ApplicationScoped +@BasicAuthenticationMechanismDefinition( + realmName = "basicAuth" +) +@DatabaseIdentityStoreDefinition( + callerQuery = "select password from basic_auth_user where username = ?", + groupsQuery = "select name from basic_auth_group where username = ?", + hashAlgorithmParameters = { + "Pbkdf2PasswordHash.Iterations=3072", + "Pbkdf2PasswordHash.Algorithm=PBKDF2WithHmacSHA512", + "Pbkdf2PasswordHash.SaltSizeBytes=64" + } +) +@DeclareRoles("user") +@ApplicationPath("/rest") +public class ApplicationConfig extends Application { + +---- + +[source,java] +---- +@ApplicationScoped +public class CustomIdentityStore implements IdentityStore { + + public CredentialValidationResult validate(UsernamePasswordCredential usernamePasswordCredential) { + if (usernamePasswordCredential.compareTo("pete", "secret2")) { + return new CredentialValidationResult("pete", Set.of("user", "caller")); + } + + return INVALID_RESULT; + } + +} +---- + +In this example we have two enabled CDI beans implementing the `IdentityStore` interface. One of them will be implicitly enabled via the `@DatabaseIdentityStoreDefinition` annotation, while the other one is defined explicitly via the `CustomIdentityStore`. As with a single identity store, it doesn't matter how or where the CDI beans are defined, only that multiple enabled ones exist. + +When multiple identity stores are present, the security system will try them each in order of their priority. We didn't set a priority here, so the order will be undefined. The first store to validate wins, and will end the validation attempts. It's important to note that in the default validation algorithm a successful validation wins over a failed validation. This means we can have multiple identity stores that know about e.g. "pete". If "pete" fails validation in one store, but passes validation in another store, the end result is still that validation passed. + +In the two stores above however only one store knows about "pete" and that's the `CustomIdentityStore`. The store created from `@DatabaseIdentityStoreDefinition` doesn't know about "pete" at all, and will simply not validate it. + + +==== Populating the identity store + +In order to use the identity store we need to put some data in a database. This is done in the same as in <>. + +==== Test the application + +It's now time to test our application. A ready to test version is available from the Jakarta EE Examples project at https://github.com/eclipse-ee4j/jakartaee-examples. + +Download or clone this repo, then cd into the `focused` folder and execute: + +``` +mvn clean install -pl :restBasicAuthDBStoreAndCustomStore +``` + +This will run a test associated with the project, printing something like the following: + +``` +john : true +pete : true +[INFO] Tests run: 2, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 9.239 s - in jakartaee.examples.focused.security.restbasicauthdbstoreandcustomstore.RestBasicAuthDBStoreAndCustomStoreIT +``` + +Let's take a quick look at the actual test again: + +[source,java] +---- +@RunWith(Arquillian.class) +@RunAsClient +public class RestBasicAuthDBStoreAndCustomStoreIT extends ITBase { + + @ArquillianResource + private URL baseUrl; + + /** + * Test the call to a protected REST service + * + *

+ * This will use the "john" credentials, which should be validated by the DB store + * + * @throws Exception when a serious error occurs. + */ + @RunAsClient + @Test + public void testRestCall1() throws Exception { + DefaultCredentialsProvider credentialsProvider = new DefaultCredentialsProvider(); + credentialsProvider.addCredentials("john", "secret1"); + + webClient.setCredentialsProvider(credentialsProvider); + + TextPage page = webClient.getPage(baseUrl + "/rest/resource"); + String content = page.getContent(); + + System.out.println(content); + } + + /** + * Test the call to a protected REST service + * + *

+ * This will use the "pete" credentials, which should be validated by the custom store + * + * @throws Exception when a serious error occurs. + */ + @RunAsClient + @Test + public void testRestCall2() throws Exception { + DefaultCredentialsProvider credentialsProvider = new DefaultCredentialsProvider(); + credentialsProvider.addCredentials("pete", "secret2"); + + webClient.setCredentialsProvider(credentialsProvider); + + TextPage page = webClient.getPage(baseUrl + "/rest/resource"); + String content = page.getContent(); + + System.out.println(content); + } +} +---- + +We do two tests here; in one test we try to authenticate as "john", in the other test as "pete". As we have seen, each identity store only validates one of them. The fact that both tests pass demonstrates that each store will validate the right user, and that not recognising a username by any of them will not fail the overall validation. + From a6ac7bfe328bade817cb1047a7e5b9686eb1088e Mon Sep 17 00:00:00 2001 From: "Kito D. Mann" Date: Fri, 19 May 2023 17:45:38 -0400 Subject: [PATCH 018/247] JETUT-56 Fixed links to external anchors. --- .../AntoraConverter.java | 82 +++++++++++-------- .../CONVERTING_TO_ANTORA.adoc | 19 +---- .../security-advanced001.adoc | 10 +-- .../security-advanced002.adoc | 16 ++-- .../security-advanced003.adoc | 4 +- .../security-advanced005.adoc | 8 +- .../security-advanced006.adoc | 4 +- .../pages/security-api/security-api001.adoc | 8 +- .../pages/security-api/security-api003.adoc | 10 +-- .../pages/security-api/security-api004.adoc | 26 +++--- .../pages/security-api/security-api005.adoc | 20 ++--- .../security-intro/security-intro001.adoc | 36 ++++---- .../security-intro/security-intro002.adoc | 6 +- .../security-intro/security-intro003.adoc | 10 +-- .../security-intro/security-intro003a.adoc | 4 +- .../security-intro/security-intro004.adoc | 2 +- .../security-intro/security-intro005.adoc | 36 ++++---- .../security-intro/security-intro005a.adoc | 2 +- .../security-intro/security-intro006.adoc | 2 +- .../security-jakartaee002.adoc | 24 +++--- .../security-jakartaee003.adoc | 30 +++---- .../security-webtier/security-webtier.adoc | 2 +- .../security-webtier/security-webtier001.adoc | 20 ++--- .../security-webtier/security-webtier002.adoc | 34 ++++---- .../security-webtier/security-webtier003.adoc | 2 +- .../security-webtier/security-webtier004.adoc | 42 +++++----- 26 files changed, 230 insertions(+), 229 deletions(-) rename {atora-conversion => antora-conversion}/AntoraConverter.java (68%) rename {atora-conversion => antora-conversion}/CONVERTING_TO_ANTORA.adoc (75%) diff --git a/atora-conversion/AntoraConverter.java b/antora-conversion/AntoraConverter.java similarity index 68% rename from atora-conversion/AntoraConverter.java rename to antora-conversion/AntoraConverter.java index 6d76e447..58036bb0 100755 --- a/atora-conversion/AntoraConverter.java +++ b/antora-conversion/AntoraConverter.java @@ -2,25 +2,27 @@ //DEPS com.github.lalyos:jfiglet:0.0.8 import java.io.File; +import java.io.IOException; import java.nio.file.Files; import java.nio.file.Paths; import java.util.ArrayList; import java.util.HashMap; import java.util.Map; -import java.util.Optional; import java.util.function.BiFunction; import java.util.function.Consumer; class AntoraConverter { record PageLocation(String path, String page) { + public String getParentPage() { + return path + ".adoc"; + } public String toString() { - return path + "/" + page; + return path + "/" + getParentPage(); } } - static Map anchorMap = new HashMap<>(); - final static String START_PATH_PREFIX = "src/main/antora/modules/"; + static Map anchorMap = new HashMap<>(); public static String replaceBetween(String str, String start, String end, String prefix, String fromString, String toString, BiFunction contentUpdater) { @@ -36,8 +38,8 @@ public static String replaceBetween(String str, String start, String end, String // don't add the prefix if nothing has changed if (!substring.equals(updatedSubstring)) { // special case for anchors - if (updatedSubstring.startsWith("#")) { - updatedSubstring = updatedSubstring.replaceFirst("#", "#" + prefix); + if (updatedSubstring.startsWith("#")) { + updatedSubstring = updatedSubstring.replaceFirst("#", "#" + prefix); } else { updatedSubstring = prefix + updatedSubstring; } @@ -64,63 +66,73 @@ public static void processInbetween(String str, String start, String end, Consum } public static void main(String... args) throws Exception { - var dryRun = true; System.out.println("\uD83E\uDD16 Antora Converter: Convert raw Asciidoc files to Antora-compatible format"); System.out.println("Walks through all folders and subfolders from the specified startPath and converts all .adoc files"); - if (dryRun) { - System.out.println("=> dryRun is enabled; no files will be modified"); - } + var files = new ArrayList(); if (args.length == 0) { - System.out.println("Usage: AntoraConverter.java [startPath]"); - System.out.println(" Where [startPath] is relative to " + START_PATH_PREFIX); + System.out.println("Usage: AntoraConverter.java [startPath] dryRun?"); + System.out.println(" Where [startPath] is the root folder to search (usually a specific Antora module or component folder)"); + System.out.println(" If 'dryRun' is specified, no files will actually be modified, but you will see information about the changes that would take place"); System.exit(1); } - String startPath = START_PATH_PREFIX + args[0]; + String startPath = args[0]; System.out.println("Start path: " + startPath); + final var dryRun = args.length > 1 && args[1].equalsIgnoreCase("dryrun"); + if (dryRun) { + System.out.println("=> dryRun is enabled; no files will be modified"); + } Files.walk(Paths.get(startPath)).filter(Files::isRegularFile) .filter(path -> path.toString().endsWith(".adoc")) .forEach(path -> files.add(path.toFile())); System.out.println("\uD83E\uDD16 Pre-scanning files for anchors, links, etc."); + preProcess(startPath, files); + process(files, dryRun); + } + + private static void preProcess(String startPath, ArrayList files) throws IOException { for (File file : files) { System.out.println("\uD83D\uDD0E Pre-scanning file " + file.getAbsolutePath()); String content = new String(Files.readAllBytes(file.toPath())); System.out.println("=> Processing anchor names"); processInbetween(content, "[[", "]]", (anchor) -> { + // NOTE: This currently will only work for files within the same module. This will need + // to be updated for files in different modules. final var pageLocation = new PageLocation(file.getParentFile().getName(), file.getName()); anchorMap.put("#" + anchor, pageLocation); System.out.printf(" => Stored anchor \"%s\" for %s%n", anchor, pageLocation); }); } + } + private static void process(ArrayList files, boolean dryRun) throws IOException { System.out.println("\uD83E\uDD16 Updating files"); for (File file : files) { System.out.println("\uD83D\uDD0E Evaluating file " + file.getAbsolutePath()); - String content = new String(Files.readAllBytes(file.toPath())); + var content = new String(Files.readAllBytes(file.toPath())); int changeCount = 0; if (content.contains(("<<"))) { - System.out.println("=> Updating anchor links"); - String modifiedContent = replaceBetween(content, "<<", ">>", "_", "-", "_", null); - System.out.println(" => Updating anchor link"); + System.out.println("=> Updating in-page anchor references"); + content = replaceBetween(content, "<<", ">>", "_", "-", "_", null); if (!dryRun) { - Files.write(file.toPath(), modifiedContent.getBytes()); + Files.write(file.toPath(), content.getBytes()); } changeCount++; } if (content.contains(("[["))) { System.out.println("=> Updating anchor names"); - String modifiedContent = replaceBetween(content, "[[", "]]", "_", "-", "_", null); + content = replaceBetween(content, "[[", "]]", "_", "-", "_", null); if (!dryRun) { - Files.write(file.toPath(), modifiedContent.getBytes()); + Files.write(file.toPath(), content.getBytes()); } changeCount++; } if (content.contains(("link:#"))) { - System.out.println("=> Updating anchor links"); - String modifiedContent = replaceBetween(content, "link:", "[", "_", "-", "_", (originalLink, newLink) -> { + System.out.println("=> Updating external anchor references"); + content = replaceBetween(content, "link:", "[", "_", "-", "_", (originalLink, newLink) -> { var pageLocation = anchorMap.get(originalLink); if (pageLocation == null) { pageLocation = anchorMap.get(newLink); @@ -130,40 +142,42 @@ public static void main(String... args) throws Exception { originalLink, newLink); return newLink; } - // If it's a link to the current page, no need to reference another page. - if (pageLocation.page.equalsIgnoreCase(file.getName())) { + + // If this page name contains the parent's page name, it's either the parent page itself or an included page, + // so it's an internal reference. + if (file.getName().contains(pageLocation.getParentPage())) { return newLink; } - final var updatedLink = pageLocation + "#" + newLink; - System.out.printf(" => Updating anchor link from %s to %s%n", originalLink, updatedLink); + final var updatedLink = pageLocation + newLink; + System.out.printf(" => Updating anchor reference from %s to %s%n", originalLink, updatedLink); return updatedLink; }); if (!dryRun) { - Files.write(file.toPath(), modifiedContent.getBytes()); + Files.write(file.toPath(), content.getBytes()); } changeCount++; } if (content.contains("link:")) { - System.out.println("=> Converting links to use xrefs"); - String modifiedContent = content.replace("link:", "xref:"); + System.out.println("=> Converting links to xrefs"); + content = content.replace("link:", "xref:"); if (!dryRun) { - Files.write(file.toPath(), modifiedContent.getBytes()); + Files.write(file.toPath(), content.getBytes()); } changeCount++; } if (content.contains("image:")) { System.out.println("=> Converting inline image references to block image references and adding module prefix"); - String modifiedContent = content.replace("image:", "image::common:"); + content = content.replace("image:", "image::common:"); if (!dryRun) { - Files.write(file.toPath(), modifiedContent.getBytes()); + Files.write(file.toPath(), content.getBytes()); } changeCount++; } if (content.contains((".png["))) { System.out.println("=> Removing newlines from image captions"); - String modifiedContent = replaceBetween(content, ".png[", "]", "", System.getProperty("line.separator"), " ", null); + content = replaceBetween(content, ".png[", "]", "", System.getProperty("line.separator"), " ", null); if (!dryRun) { - Files.write(file.toPath(), modifiedContent.getBytes()); + Files.write(file.toPath(), content.getBytes()); } changeCount++; } diff --git a/atora-conversion/CONVERTING_TO_ANTORA.adoc b/antora-conversion/CONVERTING_TO_ANTORA.adoc similarity index 75% rename from atora-conversion/CONVERTING_TO_ANTORA.adoc rename to antora-conversion/CONVERTING_TO_ANTORA.adoc index 2d13b740..bf888e5b 100644 --- a/atora-conversion/CONVERTING_TO_ANTORA.adoc +++ b/antora-conversion/CONVERTING_TO_ANTORA.adoc @@ -8,6 +8,8 @@ The conversion script is written in Java and requires https://jbang.io[JBang] to == Migration Process +> TIP: Commit your changes after each step; that way you can easily rollback any mistakes. + Here’s the current process for migrating an individual module (i.e. security, bean validation, etc): 1. Check out the release/8 branch and create a new branch from it for your work. @@ -18,7 +20,7 @@ Here’s the current process for migrating an individual module (i.e. security, > NOTE: It's essential that you _move_ rather than copy the folders so that we keep the history intact. -5. Run the migration script from the root project folder. For example, for the Security module, you would run `jbang AntoraConverter.java security`. (The first parameter is the folder relative to `src/main/antora/modules`). +5. Run the migration script from the root project folder. For example, for the Security module, you would run `jbang antora-conversion/AntoraConverter.java security`. (The first parameter is the folder relative to `src/main/antora/modules`). 6. Create a new file called `nav.adoc` in the root of the module folder. For example, for the Security module, you would create a `security/nav.adoc`. 7. Copy all the include statements from the corresponding "part" file in the `src/main/asciidoc/` folder. For example, for the Security module, you would copy the include statements of `src/main/asciidoc/partsecurity.adoc` into the `security/nav.adoc` file. Here are the include statements for the Security module: @@ -55,18 +57,3 @@ After copying these into `nav.adoc`, replace "include::" with "* xref:" and add - modules/security/nav.adoc ``` -9. Check the links. For any links that refer to anchors in other files (usually within the same folder) you will need to fix them manually. For example, in the Security module, this link: - -```asciidoc -* link:#BNBYK[Chapter 52, "Getting Started Securing -Enterprise Applications"] -``` - -should be changed to this: - -```asciidoc -* xref:security-jakartaee/security-jakartaee.adoc#BNBYK[Chapter 52, "Getting Started Securing -Enterprise Applications"] -``` - -This is necessary because the entire module isn't a single file. Note the use of the `xref` here instead of `link`. We're referring to another folder within the `security` module's `pages` folder. (See the https://docs.antora.org/antora/latest/page/xref/[the Antora docs] for more info about xrefs.) diff --git a/src/main/antora/modules/security/pages/security-advanced/security-advanced001.adoc b/src/main/antora/modules/security/pages/security-advanced/security-advanced001.adoc index f5eab4d6..82cca287 100644 --- a/src/main/antora/modules/security/pages/security-advanced/security-advanced001.adoc +++ b/src/main/antora/modules/security/pages/security-advanced/security-advanced001.adoc @@ -49,7 +49,7 @@ private key could have been used to produce such a signature. Digital certificates are used with HTTPS to authenticate web clients. The HTTPS service of most web servers will not run unless a digital certificate has been installed. Use the procedure outlined in the next -section, link:#BNBYC[Creating a Server Certificate], to set up a digital +section, xref:security-advanced/security-advanced.adoc#BNBYC[Creating a Server Certificate], to set up a digital certificate that can be used by your application or web server to enable SSL. @@ -63,7 +63,7 @@ tool also allows users to cache the public keys, in the form of certificates, of their communicating peers. For a better understanding of `keytool` and public-key cryptography, see -link:#BABBGBBF[Further Information about +xref:security-advanced/security-advanced.adoc#BABBGBBF[Further Information about Advanced Security Topics] for a link to the `keytool` documentation. [[BNBYC]][[_creating_a_server_certificate]] @@ -202,13 +202,13 @@ In the `certificate` realm, user identity is set up in the GlassFish Server security context and populated with user data obtained from cryptographically verified client certificates. For step-by-step instructions for creating this type of certificate, see -link:#BNBYB[Working with Digital Certificates]. +xref:security-advanced/security-advanced.adoc#BNBYB[Working with Digital Certificates]. [[BNBYF]][[_using_a_different_server_certificate_with_glassfish_server]] === Using a Different Server Certificate with GlassFish Server -Follow the steps in link:#BNBYC[Creating a Server Certificate] to create +Follow the steps in xref:security-advanced/security-advanced.adoc#BNBYC[Creating a Server Certificate] to create your own server certificate, have it signed by a CA, and import the certificate into `keystore.jks`. @@ -233,7 +233,7 @@ follow these steps. 1. Start GlassFish Server if you haven't already done so. Information on starting the GlassFish Server can be found in -link:#BNADI[Starting and Stopping GlassFish Server]. +xref:#BNADI[Starting and Stopping GlassFish Server]. 2. Open the GlassFish Server Administration Console in a web browser at `http://localhost:4848`. 3. Expand Configurations, then expand server-config, then click JVM diff --git a/src/main/antora/modules/security/pages/security-advanced/security-advanced002.adoc b/src/main/antora/modules/security/pages/security-advanced/security-advanced002.adoc index 89df5ca6..6afb581b 100644 --- a/src/main/antora/modules/security/pages/security-advanced/security-advanced002.adoc +++ b/src/main/antora/modules/security/pages/security-advanced/security-advanced002.adoc @@ -23,7 +23,7 @@ certificate authority (CA), and provides identification for the bearer. Before using client authentication, make sure that the client has a valid public key certificate. For more information on creating and using public key certificates, read -link:#BNBYB[Working with Digital Certificates]. +xref:security-advanced/security-advanced.adoc#BNBYB[Working with Digital Certificates]. The following example shows how to declare client authentication in your deployment descriptor: @@ -38,7 +38,7 @@ Jakarta Security provides an alternative means to configure client authenticatio using the `HttpAuthenticationMechanism` interface. This interface defines an SPI for writing authentication mechanisms that can be provided with an application and -deployed using CDI. See link:#overview-of-the-http-authentication-mechanism-interface[Overview of +deployed using CDI. See xref:security-api/security-api.adoc#_overview_of_the_http_authentication_mechanism_interface[Overview of the HTTP Authentication Mechanism Interface]. [[GLIEL]][[_mutual_authentication]] @@ -48,8 +48,8 @@ the HTTP Authentication Mechanism Interface]. With mutual authentication, the server and the client authenticate each other. Mutual authentication is of two types: -* Certificate-based (see link:#GLIFJ[Figure 53-1]) -* User name/password-based (see link:#GLIGQ[Figure 53-2]) +* Certificate-based (see xref:security-advanced/security-advanced.adoc#GLIFJ[Figure 53-1]) +* User name/password-based (see xref:security-advanced/security-advanced.adoc#GLIGQ[Figure 53-2]) When using certificate-based mutual authentication, the following actions occur. @@ -62,13 +62,13 @@ actions occur. 6. If successful, the server grants access to the protected resource requested by the client. -link:#GLIFJ[Figure 53-1] shows what occurs during certificate-based +xref:security-advanced/security-advanced.adoc#GLIFJ[Figure 53-1] shows what occurs during certificate-based mutual authentication. [[GLIFJ]] .*Figure 53-1 Certificate-Based Mutual Authentication* -image::common:jakartaeett_dt_048.png["Diagram of six steps in mutual authentication with certificates"] +image::common::common:jakartaeett_dt_048.png["Diagram of six steps in mutual authentication with certificates"] In user name/password-based mutual authentication, the following actions occur. @@ -82,13 +82,13 @@ server. 6. If the verification is successful, the server grants access to the protected resource requested by the client. -link:#GLIGQ[Figure 53-2] shows what occurs during user +xref:security-advanced/security-advanced.adoc#GLIGQ[Figure 53-2] shows what occurs during user name/password-based mutual authentication. [[GLIGQ]] .*Figure 53-2 User Name/Password-Based Mutual Authentication* -image::common:jakartaeett_dt_049.png["Diagram of five steps in mutual authentication with user name andpassword"] +image::common::common:jakartaeett_dt_049.png["Diagram of five steps in mutual authentication with user name andpassword"] [[BNBYH]][[_enabling_mutual_authentication_over_ssl]] diff --git a/src/main/antora/modules/security/pages/security-advanced/security-advanced003.adoc b/src/main/antora/modules/security/pages/security-advanced/security-advanced003.adoc index b44dbe48..4388c879 100644 --- a/src/main/antora/modules/security/pages/security-advanced/security-advanced003.adoc +++ b/src/main/antora/modules/security/pages/security-advanced/security-advanced003.adoc @@ -28,9 +28,9 @@ user. Access to specific web application resources is granted to all users in a particular role, instead of enumerating a list of associated users. A user name can have any number of roles associated with it. -Two of the tutorial case studies, link:#GKAEE[Chapter +Two of the tutorial case studies, xref:#GKAEE[Chapter 61, "Duke's Tutoring Case Study Example,"] and -link:#GLNPW[Chapter 62, "Duke's Forest Case Study +xref:#GLNPW[Chapter 62, "Duke's Forest Case Study Example,"] use a JDBC realm for user authentication. [[sthref233]][[_to_configure_a_jdbc_authentication_realm]] diff --git a/src/main/antora/modules/security/pages/security-advanced/security-advanced005.adoc b/src/main/antora/modules/security/pages/security-advanced/security-advanced005.adoc index 3f0e0874..667b44c3 100644 --- a/src/main/antora/modules/security/pages/security-advanced/security-advanced005.adoc +++ b/src/main/antora/modules/security/pages/security-advanced/security-advanced005.adoc @@ -10,15 +10,15 @@ authentication is necessary when accessing unprotected web resources. When accessing protected web resources, the usual varieties of authentication can be used: HTTP basic authentication, HTTP login-form authentication, or SSL client authentication. -link:#BNCBN[Specifying an Authentication +xref:security-webtier/security-webtier.adoc#BNCBN[Specifying an Authentication Mechanism in the Deployment Descriptor] describes how to specify HTTP basic authentication and HTTP login-form authentication. -link:#GLIEQ[Client Authentication] describes how +xref:security-advanced/security-advanced.adoc#GLIEQ[Client Authentication] describes how to specify SSL client authentication. Authentication is required when accessing protected enterprise beans. The authentication mechanisms for enterprise beans are discussed in -link:#BNBYL[Securing Enterprise Beans]. +xref:security-jakartaee/security-jakartaee.adoc#BNBYL[Securing Enterprise Beans]. An application client makes use of an authentication service provided by the application client container for authenticating its users. The @@ -71,7 +71,7 @@ name. For more information on using JAAS for authentication in login modules, refer to the documentation listed in -link:#BABBGBBF[Further Information about +xref:security-advanced/security-advanced.adoc#BABBGBBF[Further Information about Advanced Security Topics]. [[GLIHQ]][[_using_programmatic_login]] diff --git a/src/main/antora/modules/security/pages/security-advanced/security-advanced006.adoc b/src/main/antora/modules/security/pages/security-advanced/security-advanced006.adoc index bb738084..eabd7e1f 100644 --- a/src/main/antora/modules/security/pages/security-advanced/security-advanced006.adoc +++ b/src/main/antora/modules/security/pages/security-advanced/security-advanced006.adoc @@ -21,7 +21,7 @@ establishing a connection to an EIS instance. sign-on by including code that performs the sign-on process to an EIS. You can also configure security for resource adapters. See -link:#GLIGS[Configuring Resource Adapter Security]. +xref:security-advanced/security-advanced.adoc#GLIGS[Configuring Resource Adapter Security]. [[GLIHL]][[_container_managed_sign_on]] @@ -155,7 +155,7 @@ in the connector specification. + For more information on the implementation of the security permission specification, see the security policy file documentation listed in -link:#BABBGBBF[Further Information about +xref:security-advanced/security-advanced.adoc#BABBGBBF[Further Information about Advanced Security Topics]. In addition to specifying resource adapter security in the `ra.xml` diff --git a/src/main/antora/modules/security/pages/security-api/security-api001.adoc b/src/main/antora/modules/security/pages/security-api/security-api001.adoc index 15df8c37..659de37a 100644 --- a/src/main/antora/modules/security/pages/security-api/security-api001.adoc +++ b/src/main/antora/modules/security/pages/security-api/security-api001.adoc @@ -11,22 +11,22 @@ Jakarta Security contains the following packages: * The `javax.security.enterprise` package is the main Jakarta Security package and contains classes and interfaces that span authentication, authorization, and -identity concerns. link:#main-classes-and-interfaces-in-enterprise[Table 51-1] lists +identity concerns. xref:security-api/security-api.adoc#_main_classes_and_interfaces_in_enterprise[Table 51-1] lists the main class and interfaces in this package. * The `javax.security.enterprise.authentication.mechanism.http` package contains classes and interfaces associated with HTTP-based authentication mechanisms that can interact with a caller or third-parties as part of an authentication protocol. -link:#main-classes-and-interfaces-in-authentication[Table 51-2] lists the main classes +xref:security-api/security-api.adoc#_main_classes_and_interfaces_in_authentication[Table 51-2] lists the main classes and interfaces in this package. * The `javax.javax.security.enterprise.credential` package contains classes and -interfaces for representing user credentials. link:#main-classes-and-interfaces-in-credential[Table 51-3] +interfaces for representing user credentials. xref:security-api/security-api.adoc#_main_classes_and_interfaces_in_credential[Table 51-3] lists the main classes and interfaces in this package. * The `javax.security.enterprise.identitystore` package contains classes and interfaces associated with identity stores that validate a caller's credentials -and lookup caller groups. link:#main-classes-and-interfaces-in-identitystore[Table 51-4] +and lookup caller groups. xref:security-api/security-api.adoc#_main_classes_and_interfaces_in_identitystore[Table 51-4] lists the main classes and interfaces in this package. diff --git a/src/main/antora/modules/security/pages/security-api/security-api003.adoc b/src/main/antora/modules/security/pages/security-api/security-api003.adoc index 316c2948..ad596795 100644 --- a/src/main/antora/modules/security/pages/security-api/security-api003.adoc +++ b/src/main/antora/modules/security/pages/security-api/security-api003.adoc @@ -2,8 +2,8 @@ == Overview of the Identity Store Interfaces The Identity Store Interfaces are described in the following sections: -* link:#the-identitystore-interface[The IdentityStore Interface] -* link:#the-remembermeidentitystore-interface[The RememberMeIdentityStore Interface] +* xref:security-api/security-api.adoc#_the_identitystore_interface[The IdentityStore Interface] +* xref:security-api/security-api.adoc#_the_remembermeidentitystore_interface[The RememberMeIdentityStore Interface] [[_the_identitystore_interface]] === The IdentityStore Interface @@ -28,14 +28,14 @@ and/or lookup user groups. * `DatabaseIdentityStoreDefinition` -- configures an identity store with the parameters necessary to connect to an external database, validate user credentials, and/or lookup user groups. You must supply a PasswordHash implementation when -configuring a Database Identity Store. See link:#the-passwordhash-interface[The PasswordHash Interface]. +configuring a Database Identity Store. See xref:security-api/security-api.adoc#_the_passwordhash_interface[The PasswordHash Interface]. An application can provide its own custom identity store, or use the built-in LDAP or database identity stores. For examples of both types, see: -* link:#running-the-built-in-database-identity-store-example[Running the Built-In Database Identity Store Example] +* xref:security-api/security-api.adoc#_running_the_built_in_database_identity_store_example[Running the Built-In Database Identity Store Example] -* link:#running-the-custom-identity-store-example[Running the Custom Identity Store Example] +* xref:security-api/security-api.adoc#_running_the_custom_identity_store_example[Running the Custom Identity Store Example] An implementation of `IdentityStore` must be a CDI bean to be recognized and deployed at runtime, and is assumed to be normal scoped. diff --git a/src/main/antora/modules/security/pages/security-api/security-api004.adoc b/src/main/antora/modules/security/pages/security-api/security-api004.adoc index ebea0223..e8be1ba2 100644 --- a/src/main/antora/modules/security/pages/security-api/security-api004.adoc +++ b/src/main/antora/modules/security/pages/security-api/security-api004.adoc @@ -5,8 +5,8 @@ identity store for credential validation. Topics include: -* link:#overview-of-the-built-in-database-identity-store-example[Overview of the Built-In Database Identity Store Example] -* link:#running-the-built-in-db-id-store-example[Running the built-in-db-identity-store Example] +* xref:security-api/security-api.adoc#_overview_of_the_built_in_database_identity_store_example[Overview of the Built-In Database Identity Store Example] +* xref:#_running_the_built_in_db_id_store_example[Running the built-in-db-identity-store Example] [[_overview_of_the_built_in_database_identity_store_example]] === Overview of the Built-In Database Identity Store Example @@ -26,10 +26,10 @@ The following sections describe the high-level process for configuring the already been completed in the application files, but is provided here to illustrate what you need to do to use the built-in database identity store. -* link:#define-the-users-and-groups-in-the-identity-store[Define the Users and Groups in the Identity Store] -* link:#map-the-databaseidentitystore-to-the-default-data-source[Map the DatabaseIdentityStore to the Default Data source] -* link:#specify-the-authentication-mechanism[Specify the Authentication Mechanism] -* link:#declare-roles-in-the-servlet-container[Declare Roles in the Servlet Container] +* xref:security-api/security-api.adoc#_define_the_users_and_groups_in_the_identity_store[Define the Users and Groups in the Identity Store] +* xref:security-api/security-api.adoc#_map_the_databaseidentitystore_to_the_default_data_source[Map the DatabaseIdentityStore to the Default Data source] +* xref:security-api/security-api.adoc#_specify_the_authentication_mechanism[Specify the Authentication Mechanism] +* xref:security-api/security-api.adoc#_declare_roles_in_the_servlet_container[Declare Roles in the Servlet Container] When a request that includes credentials is sent to the application, it triggers the configured authentication mechanism @@ -220,9 +220,9 @@ roles and groups. You can use either NetBeans IDE or Maven to build, package, deploy, and run the `built-in-db-identity-store` application as described in the following topics: -* link:#to-build-package-and-deploy-the-built-in-db-identity-store-example-using-netbeans-ide[To Build, Package, and Deploy the built-in-db-identity-store Example Using NetBeans IDE] -* link:#to-build-package-and-deploy-the-built-in-db-identity-store-example-using-using-maven[To Build, Package, and Deploy the built-in-db-identity-store Example Using Maven] -* link:#to-run-the-built-in-db-identity-store-example[To Run the built-in-db-identity-store Example] +* xref:security-api/security-api.adoc#_to_build_package_and_deploy_the_built_in_db_identity_store_example_using_netbeans_ide[To Build, Package, and Deploy the built-in-db-identity-store Example Using NetBeans IDE] +* xref:security-api/security-api.adoc#_to_build_package_and_deploy_the_built_in_db_identity_store_example_using_using_maven[To Build, Package, and Deploy the built-in-db-identity-store Example Using Maven] +* xref:security-api/security-api.adoc#_to_run_the_built_in_db_identity_store_example[To Run the built-in-db-identity-store Example] [[_to_build_package_and_deploy_the_built_in_db_identity_store_example_using_netbeans_ide]] @@ -230,10 +230,10 @@ as described in the following topics: 1. If you have not already done so, start the default database. This is necessary because we are using the DefaultDataSource bundled with GlassFish for `DatabaseIdentityStore`. -See link:#starting-and-stopping-the-java-db-server[Starting and Stopping Apache Derby]. +See xref:#_starting_and_stopping_the_java_db_server[Starting and Stopping Apache Derby]. 2. If you have not already done so, start the GlassFish server. See -link:#starting-and-stopping-glassfish-server[Starting and Stopping GlassFish Server]. +xref:#_starting_and_stopping_glassfish_server[Starting and Stopping GlassFish Server]. 3. From the File menu, choose Open Project. @@ -257,11 +257,11 @@ GlassFish Server instance. 1. If you have not already done so, start the default database. This is necessary because we are using the DefaultDataSource bundled with GlassFish for `DatabaseIdentityStore`. -See link:#starting-and-stopping-the-java-db-server[Starting and Stopping Apache Derby]. +See xref:#_starting_and_stopping_the_java_db_server[Starting and Stopping Apache Derby]. 2. If you have not already done so, start the GlassFish server. See -link:#starting-and-stopping-glassfish-server[Starting and Stopping GlassFish Server]. +xref:#_starting_and_stopping_glassfish_server[Starting and Stopping GlassFish Server]. 3. In a terminal window, go to: + diff --git a/src/main/antora/modules/security/pages/security-api/security-api005.adoc b/src/main/antora/modules/security/pages/security-api/security-api005.adoc index ea7a0bdc..7a55cc6a 100644 --- a/src/main/antora/modules/security/pages/security-api/security-api005.adoc +++ b/src/main/antora/modules/security/pages/security-api/security-api005.adoc @@ -5,8 +5,8 @@ identity store in your application for credential validation. Topics include: -* link:#overview-of-the-custom-identity-store-example[Overview of the Custom Identity Store Example] -* link:#running-the-custom-id-store-example[Running the custom-identity-store Example] +* xref:security-api/security-api.adoc#_overview_of_the_custom_identity_store_example[Overview of the Custom Identity Store Example] +* xref:security-api/security-api.adoc#_running_the_custom_id_store_example[Running the custom-identity-store Example] [[_overview_of_the_custom_identity_store_example]] === Overview of the Custom Identity Store Example @@ -26,9 +26,9 @@ the `TestIdentityStore`. Note that the configuration described in these sections already been completed in the application files, but is provided here to illustrate what you need to do to use a custom identity store. -* link:#define-the-users-and-groups-in-the-identity-store-2[Define the Users and Groups in the Identity Store] -* link:#specify-the-authentication-mechanism-2[Specify the Authentication Mechanism] -* link:#declare-roles-in-the-servlet-container-2[Declare Roles in the Servlet Container] +* xref:security-api/security-api.adoc#_define_the_users_and_groups_in_the_identity_store_2[Define the Users and Groups in the Identity Store] +* xref:security-api/security-api.adoc#_specify_the_authentication_mechanism_2[Specify the Authentication Mechanism] +* xref:security-api/security-api.adoc#_declare_roles_in_the_servlet_container_2[Declare Roles in the Servlet Container] When a request that includes credentials is sent to the application, the configured authentication mechanism comes into effect and authentication is performed @@ -147,16 +147,16 @@ and groups. You can use either NetBeans IDE or Maven to build, package, deploy, and run the `custom-identity-store` application as described in the following topics: -* link:#to-build-package-and-deploy-the-custom-identity-store-example-using-netbeans-ide[To Build, Package, and Deploy the custom-identity-store Example Using NetBeans IDE] -* link:#to-build-package-and-deploy-the-custom-identity-store-example-using-using-maven[To Build, Package, and Deploy the custom-identity-store Example Using Maven] -* link:#to-run-the-custom-identity-store-example[To Run the custom-identity-store Example] +* xref:security-api/security-api.adoc#_to_build_package_and_deploy_the_custom_identity_store_example_using_netbeans_ide[To Build, Package, and Deploy the custom-identity-store Example Using NetBeans IDE] +* xref:security-api/security-api.adoc#_to_build_package_and_deploy_the_custom_identity_store_example_using_using_maven[To Build, Package, and Deploy the custom-identity-store Example Using Maven] +* xref:security-api/security-api.adoc#_to_run_the_custom_identity_store_example[To Run the custom-identity-store Example] [[_to_build_package_and_deploy_the_custom_identity_store_example_using_netbeans_ide]] ==== To Build, Package, and Deploy the custom-identity-store Example Using NetBeans IDE 1. If you have not already done so, start the GlassFish server. See -link:#starting-and-stopping-glassfish-server[Starting and Stopping GlassFish Server]. +xref:#_starting_and_stopping_glassfish_server[Starting and Stopping GlassFish Server]. 2. From the File menu, choose Open Project. 3. In the Open Project dialog box, navigate to: + @@ -177,7 +177,7 @@ GlassFish Server instance. ==== To Build, Package, and Deploy the custom-identity-store Example Using Maven 1. If you have not already done so, start the GlassFish server. See -link:#starting-and-stopping-glassfish-server[Starting and Stopping GlassFish Server].. +xref:#_starting_and_stopping_glassfish_server[Starting and Stopping GlassFish Server].. 2. In a terminal window, go to: + [source,java] diff --git a/src/main/antora/modules/security/pages/security-intro/security-intro001.adoc b/src/main/antora/modules/security/pages/security-intro/security-intro001.adoc index 3d1a0741..f8912546 100644 --- a/src/main/antora/modules/security/pages/security-intro/security-intro001.adoc +++ b/src/main/antora/modules/security/pages/security-intro/security-intro001.adoc @@ -19,7 +19,7 @@ A deployment descriptor is an XML file that is external to the application and that expresses an application's security structure, including security roles, access control, and authentication requirements. For more information about deployment descriptors, read -link:#BNBXF[Using Deployment Descriptors for +xref:security-intro/security-intro.adoc#BNBXF[Using Deployment Descriptors for Declarative Security]. + Annotations, also called metadata, are used to specify information about @@ -30,13 +30,13 @@ declarative information inside XML descriptors. Instead, you simply put annotations on the code, and the required information gets generated. For this tutorial, annotations are used for securing applications wherever possible. For more information about annotations, see -link:#BNBXG[Using Annotations to Specify Security +xref:security-intro/security-intro.adoc#BNBXG[Using Annotations to Specify Security Information]. * Programmatic security is embedded in an application and is used to make security decisions. Programmatic security is useful when declarative security alone is not sufficient to express the security model of an application. For more information about programmatic -security, read link:#BNBXH[Using Programmatic +security, read xref:security-intro/security-intro.adoc#BNBXH[Using Programmatic Security]. Jakarta EE 8 includes a Security API specification that defines portable, @@ -51,13 +51,13 @@ in the chapter on security in the Jakarta EE 8 specification. Other chapters in this Part discuss security requirements in web tier and enterprise tier applications, and the Jakarta Security. -* link:#BNCAS[Chapter 51, "Getting Started Securing +* xref:security-webtier/security-webtier.adoc#BNCAS[Chapter 51, "Getting Started Securing Web Applications"] explains how to add security to web components, such as servlets. -* link:#BNBYK[Chapter 52, "Getting Started Securing +* xref:security-jakartaee/security-jakartaee.adoc#BNBYK[Chapter 52, "Getting Started Securing Enterprise Applications"] explains how to add security to Jakarta EE components, such as enterprise beans and application clients. -* link:#using-the-jakarta-ee-security-api[53 Using Jakarta Security] +* xref:security-api/security-api.adoc#_using_the_jakarta_ee_security_api[53 Using Jakarta Security] describes the authentication and credential validation funtionality provided by Jakarta Security, and provides examples. @@ -79,19 +79,19 @@ client and using it to establish an authenticated session. ==== Step 1: Initial Request In the first step of this example, the web client requests the main -application URL. This action is shown in link:#BNBWN[Figure 50-1]. +application URL. This action is shown in xref:security-intro/security-intro.adoc#BNBWN[Figure 50-1]. [[BNBWN]] .*Figure 50-1 Initial Request* -image::common:jakartaeett_dt_039.png["Diagram of initial request from web client to web server for access to aprotected resource"] +image::common::common:jakartaeett_dt_039.png["Diagram of initial request from web client to web server for access to aprotected resource"] Since the client has not yet authenticated itself to the application environment, the server responsible for delivering the web portion of the application, hereafter referred to as the web server, detects this and invokes the appropriate authentication mechanism for this resource. For more information on these mechanisms, see -link:#BNBWY[Security Mechanisms]. +xref:security-intro/security-intro.adoc#BNBWY[Security Mechanisms]. [[BNBWO]][[_step_2_initial_authentication]] @@ -100,7 +100,7 @@ link:#BNBWY[Security Mechanisms]. The web server returns a form that the web client uses to collect authentication data, such as user name and password, from the user. The web client forwards the authentication data to the web server, where it -is validated by the web server, as shown in link:#BNBWP[Figure 50-2]. +is validated by the web server, as shown in xref:security-intro/security-intro.adoc#BNBWP[Figure 50-2]. The validation mechanism may be local to a server or may leverage the underlying security services. On the basis of the validation, the web server sets a credential for the user. @@ -108,7 +108,7 @@ server sets a credential for the user. [[BNBWP]] .*Figure 50-2 Initial Authentication* -image::common:jakartaeett_dt_040.png["Diagram of initial authentication: server sends form to client, whichsends authentication data to server for validation"] +image::common::common:jakartaeett_dt_040.png["Diagram of initial authentication: server sends form to client, whichsends authentication data to server for validation"] [[BNBWQ]][[_step_3_url_authorization]] @@ -121,12 +121,12 @@ determine the security roles that are permitted access to the resource. The security policy is derived from annotations or from the deployment descriptor. The web container then tests the user's credential against each role to determine whether it can map the user to the role. -link:#BNBWR[Figure 50-3] shows this process. +xref:security-intro/security-intro.adoc#BNBWR[Figure 50-3] shows this process. [[BNBWR]] .*Figure 50-3 URL Authorization* -image::common:jakartaeett_dt_041.png["Diagram of URL authorization"] +image::common::common:jakartaeett_dt_041.png["Diagram of URL authorization"] The web server's evaluation stops with an "is authorized" outcome when the web server is able to map the user to a role. A "not authorized" @@ -138,17 +138,17 @@ the permitted roles. ==== Step 4: Fulfilling the Original Request If the user is authorized, the web server returns the result of the -original URL request, as shown in link:#BNBWT[Figure 50-4]. +original URL request, as shown in xref:security-intro/security-intro.adoc#BNBWT[Figure 50-4]. [[BNBWT]] .*Figure 50-4 Fulfilling the Original Request* -image::common:jakartaeett_dt_042.png["Diagram of request fulfillment, showing server returning result to client"] +image::common::common:jakartaeett_dt_042.png["Diagram of request fulfillment, showing server returning result to client"] In our example, the response URL of a web page is returned, enabling the user to post form data that needs to be handled by the business-logic component of the application. See -link:#BNCAS[Chapter 51, "Getting Started Securing +xref:security-webtier/security-webtier.adoc#BNCAS[Chapter 51, "Getting Started Securing Web Applications"] for more information on protecting web applications. [[BNBWU]][[_step_5_invoking_enterprise_bean_business_methods]] @@ -157,14 +157,14 @@ Web Applications"] for more information on protecting web applications. The web page performs the remote method call to the enterprise bean, using the user's credential to establish a secure association between -the web page and the enterprise bean, as shown in link:#BNBWV[Figure +the web page and the enterprise bean, as shown in xref:security-intro/security-intro.adoc#BNBWV[Figure 50-5]. The association is implemented as two related security contexts: one in the web server and one in the enterprise bean container. [[BNBWV]] .*Figure 50-5 Invoking an Enterprise Bean Business Method* -image::common:jakartaeett_dt_043.png["Diagram of authorization process between web component and enterprise bean"] +image::common::common:jakartaeett_dt_043.png["Diagram of authorization process between web component and enterprise bean"] The enterprise container is responsible for enforcing access control on the enterprise bean method. The container consults the security policy diff --git a/src/main/antora/modules/security/pages/security-intro/security-intro002.adoc b/src/main/antora/modules/security/pages/security-intro/security-intro002.adoc index 3aabf080..269f8622 100644 --- a/src/main/antora/modules/security/pages/security-intro/security-intro002.adoc +++ b/src/main/antora/modules/security/pages/security-intro/security-intro002.adoc @@ -58,7 +58,7 @@ For more information on Java SE security, visit Jakarta EE security services are provided by the component container and can be implemented by using declarative or programmatic techniques (see -link:#BNBXE[Securing Containers]). Jakarta EE security +xref:security-intro/security-intro.adoc#BNBXE[Securing Containers]). Jakarta EE security services provide a robust and easily configured security mechanism for authenticating users and authorizing access to application functions and associated data at many different layers. Jakarta EE security services are @@ -102,7 +102,7 @@ transferable between application types. * Data is close to or contained within the point of vulnerability. For more information on providing security at the application layer, see -link:#BNBXE[Securing Containers]. +xref:security-intro/security-intro.adoc#BNBXE[Securing Containers]. [[BNBXC]][[_transport_layer_security]] @@ -153,7 +153,7 @@ receives the message. * It is not an end-to-end solution, simply point-to-point. For more information on transport-layer security, see -link:#BNBXW[Establishing a Secure Connection Using +xref:security-intro/security-intro.adoc#BNBXW[Establishing a Secure Connection Using SSL]. [[BNBXD]][[_message_layer_security]] diff --git a/src/main/antora/modules/security/pages/security-intro/security-intro003.adoc b/src/main/antora/modules/security/pages/security-intro/security-intro003.adoc index e6f90c99..672c198e 100644 --- a/src/main/antora/modules/security/pages/security-intro/security-intro003.adoc +++ b/src/main/antora/modules/security/pages/security-intro/security-intro003.adoc @@ -20,14 +20,14 @@ application deployment descriptors. Specific annotations that can be used to specify security information within an enterprise bean class file are described in -link:#GJGDI[Securing an Enterprise Bean Using -Declarative Security]. link:#BNCAS[Chapter 51, +xref:security-jakartaee/security-jakartaee.adoc#GJGDI[Securing an Enterprise Bean Using +Declarative Security]. xref:security-webtier/security-webtier.adoc#BNCAS[Chapter 51, "Getting Started Securing Web Applications"], describes how to use annotations to secure web applications where possible. Deployment descriptors are described only where necessary. For more information on annotations, see -link:#BNBYJ[Further Information about Security]. +xref:security-intro/security-intro.adoc#BNBYJ[Further Information about Security]. [[BNBXF]][[_using_deployment_descriptors_for_declarative_security]] @@ -81,7 +81,7 @@ security role of the caller or remote user. Programmatic security is discussed in more detail in the following sections: -* link:#GJIIE[Using Programmatic Security with +* xref:security-webtier/security-webtier.adoc#GJIIE[Using Programmatic Security with Web Applications] -* link:#GJGCS[Securing an Enterprise Bean +* xref:security-jakartaee/security-jakartaee.adoc#GJGCS[Securing an Enterprise Bean Programmatically] diff --git a/src/main/antora/modules/security/pages/security-intro/security-intro003a.adoc b/src/main/antora/modules/security/pages/security-intro/security-intro003a.adoc index 14213f08..2c64f8dc 100644 --- a/src/main/antora/modules/security/pages/security-intro/security-intro003a.adoc +++ b/src/main/antora/modules/security/pages/security-intro/security-intro003a.adoc @@ -4,9 +4,9 @@ Jakarta EE includes two specifications that define SPI interfaces for pluggable security providers, JSR-196 and JSR-375. These specifications are described in more detail in the following sections: -* link:#jsr-196-java-authentication-service-provider-interface-for-containers-jaspic[JSR-196 Java +* xref:security-intro/security-intro.adoc#_jsr_196_java_authentication_service_provider_interface_for_containers_jaspic[JSR-196 Java Authentication Service Provider Interface for Containers (JASPIC)] -* link:#jsr-375-jakarta-ee-security-api[JSR-375 Jakarta EE Security API] +* xref:security-intro/security-intro.adoc#_jsr_375_jakarta_ee_security_api[JSR-375 Jakarta EE Security API] [[_jsr_196_java_authentication_service_provider_interface_for_containers_jaspic]] === JSR-196 Java Authentication Service Provider Interface for Containers (JASPIC) diff --git a/src/main/antora/modules/security/pages/security-intro/security-intro004.adoc b/src/main/antora/modules/security/pages/security-intro/security-intro004.adoc index f7934884..eec22312 100644 --- a/src/main/antora/modules/security/pages/security-intro/security-intro004.adoc +++ b/src/main/antora/modules/security/pages/security-intro/security-intro004.adoc @@ -9,7 +9,7 @@ security model. You can configure GlassFish Server for the following purposes. * Adding, deleting, or modifying authorized users. For more information -on this topic, see link:#BNBXJ[Working with Realms, +on this topic, see xref:security-intro/security-intro.adoc#BNBXJ[Working with Realms, Users, Groups, and Roles]. * Configuring secure HTTP and Internet Inter-Orb Protocol (IIOP) listeners. diff --git a/src/main/antora/modules/security/pages/security-intro/security-intro005.adoc b/src/main/antora/modules/security/pages/security-intro/security-intro005.adoc index d765f794..7a0151ec 100644 --- a/src/main/antora/modules/security/pages/security-intro/security-intro005.adoc +++ b/src/main/antora/modules/security/pages/security-intro/security-intro005.adoc @@ -3,7 +3,7 @@ == Working with Realms, Users, Groups, and Roles You often need to protect resources to ensure that only authorized users -have access. See link:#BNBWX[Characteristics of +have access. See xref:security-intro/security-intro.adoc#BNBWX[Characteristics of Application Security] for an introduction to the concepts of authentication, identification, and authorization. @@ -14,18 +14,18 @@ authenticate a user, you need to follow these basic steps. 1. The application developer writes code to prompt for a user name and password. The various methods of authentication are discussed in -link:#GKBSA[Specifying Authentication +xref:security-webtier/security-webtier.adoc#GKBSA[Specifying Authentication Mechanisms]. 2. The application developer communicates how to set up security for the deployed application by use of a metadata annotation or deployment -descriptor. This step is discussed in link:#BNBXU[Setting Up Security +descriptor. This step is discussed in xref:security-intro/security-intro.adoc#BNBXU[Setting Up Security Roles]. 3. The server administrator sets up authorized users and groups in -GlassFish Server. This is discussed in link:#BNBXR[Managing Users and +GlassFish Server. This is discussed in xref:security-intro/security-intro.adoc#BNBXR[Managing Users and Groups in GlassFish Server]. 4. The application deployer maps the application's security roles to users, groups, and principals defined in GlassFish Server. This topic is -discussed in link:#BNBXV[Mapping Roles to Users and Groups]. +discussed in xref:security-intro/security-intro.adoc#BNBXV[Mapping Roles to Users and Groups]. [width="100%",cols="100%",] |======================================================================= @@ -43,7 +43,7 @@ By default, group principal names are mapped to roles of the same name. A realm is a security policy domain defined for a web or application server. A realm contains a collection of users, who may or may not be assigned to a group. Managing users in GlassFish Server is discussed in -link:#BNBXR[Managing Users and Groups in GlassFish Server]. +xref:security-intro/security-intro.adoc#BNBXR[Managing Users and Groups in GlassFish Server]. An application will often prompt for a user name and password before allowing access to a protected resource. After the user name and @@ -51,20 +51,20 @@ password have been entered, that information is passed to the server, which either authenticates the user and sends the protected resource or does not authenticate the user, in which case access to the protected resource is denied. This type of user authentication is discussed in -link:#BNCBN[Specifying an Authentication +xref:security-webtier/security-webtier.adoc#BNCBN[Specifying an Authentication Mechanism in the Deployment Descriptor]. In some applications, authorized users are assigned to roles. In this situation, the role assigned to the user in the application must be mapped to a principal or group defined on the application server. -link:#BNBXL[Figure 50-6] shows this. More information on mapping roles -to users and groups can be found in link:#BNBXU[Setting Up Security +xref:security-intro/security-intro.adoc#BNBXL[Figure 50-6] shows this. More information on mapping roles +to users and groups can be found in xref:security-intro/security-intro.adoc#BNBXU[Setting Up Security Roles]. [[BNBXL]] .*Figure 50-6 Mapping Roles to Users and Groups* -image::common:jakartaeett_dt_044.png["Diagram of role mapping, showing creation of users and groups, definition of roles, and mapping of roles to users and groups"] +image::common::common:jakartaeett_dt_044.png["Diagram of role mapping, showing creation of users and groups, definition of roles, and mapping of roles to users and groups"] The following sections provide more information on realms, users, groups, and roles. @@ -97,7 +97,7 @@ uses certificates with HTTPS to authenticate web clients. To verify the identity of a user in the `certificate` realm, the authentication service verifies an X.509 certificate. For step-by-step instructions for creating this type of certificate, see -link:#BNBYB[Working with Digital Certificates]. +xref:security-advanced/security-advanced.adoc#BNBYB[Working with Digital Certificates]. The common name field of the X.509 certificate is used as the principal name. @@ -105,7 +105,7 @@ The `admin-realm` is also a `file` realm and stores administrator user credentials locally in a file named `admin-keyfile`. You can use the Administration Console to manage users in this realm in the same way you manage users in the `file` realm. For more information, see -link:#BNBXR[Managing Users and Groups in GlassFish Server]. +xref:security-intro/security-intro.adoc#BNBXR[Managing Users and Groups in GlassFish Server]. [[BNBXN]][[_what_is_a_user]] @@ -189,7 +189,7 @@ examples. 1. Start GlassFish Server, if you haven't already done so. + Information on starting GlassFish Server is available in -link:#BNADI[Starting and Stopping GlassFish Server]. +xref:#BNADI[Starting and Stopping GlassFish Server]. 2. Start the Administration Console, if you haven't already done so. + To start the Administration Console, open a web browser and specify the @@ -210,7 +210,7 @@ administrators of GlassFish Server. You cannot add users to the `certificate` realm by using the Administration Console. In the `certificate` realm, you can add only certificates. For information on adding (importing) certificates to the -`certificate` realm, see link:#GLIFW[Adding +`certificate` realm, see xref:security-advanced/security-advanced.adoc#GLIFW[Adding Users to the Certificate Realm]. 7. On the Edit Realm page, click Manage Users. 8. On the File Users or Admin Users page, click New to add a new user @@ -222,7 +222,7 @@ For the Admin Realm, the Group List field is read-only, and the group name is `asadmin`. Restart GlassFish Server and the Administration Console after you add a user to the Admin Realm. + -For more information on these properties, see link:#BNBXJ[Working with +For more information on these properties, see xref:security-intro/security-intro.adoc#BNBXJ[Working with Realms, Users, Groups, and Roles]. + For the example security applications, specify a user with any name and @@ -248,7 +248,7 @@ salary data. Each of these security roles is an abstract logical grouping of users that is defined by the person who assembles the application. When an application is deployed, the deployer will map the roles to security identities in the operational environment, as shown in -link:#BNBXL[Figure 50-6]. +xref:security-intro/security-intro.adoc#BNBXL[Figure 50-6]. For Jakarta EE components, you define security roles using the `@DeclareRoles` and `@RolesAllowed` metadata annotations. @@ -304,9 +304,9 @@ public class GreetingServlet extends HttpServlet { ---- These annotations are discussed in more detail in -link:#GJRMH[Specifying Security for Basic +xref:security-webtier/security-webtier.adoc#GJRMH[Specifying Security for Basic Authentication Using Annotations] and -link:#GJGDI[Securing an Enterprise Bean Using +xref:security-jakartaee/security-jakartaee.adoc#GJGDI[Securing an Enterprise Bean Using Declarative Security]. After users have provided their login information and the application diff --git a/src/main/antora/modules/security/pages/security-intro/security-intro005a.adoc b/src/main/antora/modules/security/pages/security-intro/security-intro005a.adoc index 1764dcf5..ef7ee136 100644 --- a/src/main/antora/modules/security/pages/security-intro/security-intro005a.adoc +++ b/src/main/antora/modules/security/pages/security-intro/security-intro005a.adoc @@ -28,4 +28,4 @@ authenticate against in a standard, portable way. An application can provide its own `IdentityStore`, or use the built in LDAP or Database identity store implementations of the interface. For details about the `IdentityStore` interfaces and examples of their usage, see -link:#overview-of-the-identity-store-interfaces[Overview of the Identity Store Interfaces]. +xref:security-api/security-api.adoc#_overview_of_the_identity_store_interfaces[Overview of the Identity Store Interfaces]. diff --git a/src/main/antora/modules/security/pages/security-intro/security-intro006.adoc b/src/main/antora/modules/security/pages/security-intro/security-intro006.adoc index ffc142a6..5aef4a20 100644 --- a/src/main/antora/modules/security/pages/security-intro/security-intro006.adoc +++ b/src/main/antora/modules/security/pages/security-intro/security-intro006.adoc @@ -4,7 +4,7 @@ Secure Sockets Layer (SSL) technology is security that is implemented at the transport layer (see -link:#BNBXC[Transport-Layer Security] for more +xref:security-intro/security-intro.adoc#BNBXC[Transport-Layer Security] for more information about transport-layer security). SSL allows web browsers and web servers to communicate over a secure connection. In this secure connection, the data is encrypted before being sent and then is diff --git a/src/main/antora/modules/security/pages/security-jakartaee/security-jakartaee002.adoc b/src/main/antora/modules/security/pages/security-jakartaee/security-jakartaee002.adoc index 1c62d1a2..831e4328 100644 --- a/src/main/antora/modules/security/pages/security-jakartaee/security-jakartaee002.adoc +++ b/src/main/antora/modules/security/pages/security-jakartaee/security-jakartaee002.adoc @@ -42,7 +42,7 @@ application and which methods would be accessible to which users. The application developer would then decorate classes or methods of the enterprise bean with annotations that specify the types of users authorized to access those methods. Using annotations to specify -authorized users is described in link:#GJGCQ[Specifying Authorized Users +authorized users is described in xref:security-jakartaee/security-jakartaee.adoc#GJGCQ[Specifying Authorized Users by Declaring Security Roles]. + When one of the annotations is used to define method permissions, the @@ -55,7 +55,7 @@ that are authorized to access the method. If the user is authenticated and found to have a role that is authorized to access that method, the data will be returned to the user. + -Using declarative security is discussed in link:#GJGDI[Securing an +Using declarative security is discussed in xref:security-jakartaee/security-jakartaee.adoc#GJGDI[Securing an Enterprise Bean Using Declarative Security]. * Programmatic security: For an enterprise bean, code embedded in a business method that is used to access a caller's identity @@ -71,13 +71,13 @@ business methods need to access the security-context information, such as when you want to grant access based on the time of day or other nontrivial condition checks for a particular role. + -Programmatic security is discussed in link:#GJGCS[Securing an Enterprise +Programmatic security is discussed in xref:security-jakartaee/security-jakartaee.adoc#GJGCS[Securing an Enterprise Bean Programmatically]. Some of the material in this chapter assumes that you have already read -link:#GIJSZ[Chapter 35, "Enterprise Beans"], -link:#GIJRE[Chapter 36, "Getting Started with -Enterprise Beans"], and link:#BNBWJ[Chapter 50, +xref:#GIJSZ[Chapter 35, "Enterprise Beans"], +xref:#GIJRE[Chapter 36, "Getting Started with +Enterprise Beans"], and xref:security-intro/security-intro.adoc#BNBWJ[Chapter 50, "Introduction to Security in the Jakarta EE Platform"]. This section discusses securing a Jakarta EE application where one or more @@ -96,7 +96,7 @@ end and the application is packaged into a WAR module as a Java class file, security for the application can be handled in the application's `web.xml` file. The enterprise bean in the WAR file can have its own deployment descriptor, `ejb-jar.xml`, if required. Securing web applications using -`web.xml` is discussed in link:#BNCAS[Chapter 51, +`web.xml` is discussed in xref:security-webtier/security-webtier.adoc#BNCAS[Chapter 51, "Getting Started Securing Web Applications"]. The following sections describe declarative and programmatic security @@ -148,7 +148,7 @@ you do not need to perform any additional steps to map the roles defined in the application to users, groups, and principals that are the components of the user database in the `file` realm. This mapping is set by default in the GlassFish Server Administration Console -as described in link:#BNBXV[Mapping +as described in xref:security-intro/security-intro.adoc#BNBXV[Mapping Roles to Users and Groups]. The following sections show how an application developer uses @@ -485,7 +485,7 @@ You would use programmatic security in this way to dynamically control access to a method, for example, when you want to deny access except during a particular time of day. An example application that uses the `getCallerPrincipal` and `isCallerInRole` methods is described in -link:#BNCAA[The converter-secure Example: Securing +xref:security-jakartaee/security-jakartaee.adoc#BNCAA[The converter-secure Example: Securing an Enterprise Bean with Programmatic Security]. [[BNBYR]][[_propagating_a_security_identity_run_as]] @@ -494,13 +494,13 @@ an Enterprise Bean with Programmatic Security]. You can specify whether a caller's security identity should be used for the execution of specified methods of an enterprise bean or whether a -specific run-as identity should be used. link:#BNBZA[Figure 52-1] +specific run-as identity should be used. xref:security-jakartaee/security-jakartaee.adoc#BNBZA[Figure 52-1] illustrates this concept. [[BNBZA]] .*Figure 52-1 Security Identity Propagation* -image::common:jakartaeett_dt_047.png["Diagram of security identity propagation from client to intermediatecontainer to target container"] +image::common::common:jakartaeett_dt_047.png["Diagram of security identity propagation from client to intermediatecontainer to target container"] In this illustration, an application client is making a call to an enterprise bean method in one enterprise bean container. This enterprise bean @@ -518,7 +518,7 @@ specific identity. To propagate an identity to the target enterprise bean, configure a run-as identity for the bean, as described in -link:#configuring-a-components-propagated-security-identity[Configuring a +xref:security-jakartaee/security-jakartaee.adoc#_configuring_a_components_propagated_security_identity[Configuring a Component's Propagated Security Identity]. Establishing a run-as identity for an enterprise bean does not affect the identities of its callers, which are the identities tested for permission to access the diff --git a/src/main/antora/modules/security/pages/security-jakartaee/security-jakartaee003.adoc b/src/main/antora/modules/security/pages/security-jakartaee/security-jakartaee003.adoc index 107dccf4..92313072 100644 --- a/src/main/antora/modules/security/pages/security-jakartaee/security-jakartaee003.adoc +++ b/src/main/antora/modules/security/pages/security-jakartaee/security-jakartaee003.adoc @@ -17,13 +17,13 @@ comparing them against a database of authorized users in GlassFish Server. If the topic of authentication is new to you, see -link:#GKBSA[Specifying Authentication +xref:security-webtier/security-webtier.adoc#GKBSA[Specifying Authentication Mechanisms]. This example demonstrates security by starting with the unsecured enterprise bean application, `cart`, which is found in the `_tut-install_/examples/ejb/cart/` directory and is discussed in -link:#BNBOD[The cart Example]. +xref:#BNBOD[The cart Example]. In general, the following steps are necessary to add user name/password authentication to an existing application that contains an enterprise @@ -32,21 +32,21 @@ steps have been completed for you and are listed here simply to show what needs to be done should you wish to create a similar application. 1. Create an application like the one in -link:#BNBOD[The cart Example]. The example in +xref:#BNBOD[The cart Example]. The example in this tutorial starts with this example and demonstrates adding basic authentication of the client to this application. The example application discussed in this section can be found at `_tut-install_/examples/security/cart-secure/`. 2. If you have not already done so, complete the steps in -link:#GJJLK[To Set Up Your System for Running the +xref:security-webtier/security-webtier.adoc#GJJLK[To Set Up Your System for Running the Security Examples] to configure your system for running the tutorial applications. 3. Modify the source code for the enterprise bean, `CartBean.java`, to specify which roles are authorized to access which protected methods. -This step is discussed in link:#BNBZL[Annotating the Bean]. +This step is discussed in xref:security-jakartaee/security-jakartaee.adoc#BNBZL[Annotating the Bean]. 4. Build, package, and deploy the enterprise bean; then build and run -the client application by following the steps in link:#BNBZN[To Run the -cart-secure Example Using NetBeans IDE] or link:#BNBZO[To Run the +the client application by following the steps in xref:security-jakartaee/security-jakartaee.adoc#BNBZN[To Run the +cart-secure Example Using NetBeans IDE] or xref:security-jakartaee/security-jakartaee.adoc#BNBZO[To Run the cart-secure Example Using Maven]. [[BNBZL]][[_annotating_the_bean]] @@ -158,7 +158,7 @@ type of authentication will be user name/password authentication. ==== To Run the cart-secure Example Using NetBeans IDE -1. Follow the steps in link:#GJJLK[To Set Up +1. Follow the steps in xref:security-webtier/security-webtier.adoc#GJJLK[To Set Up Your System for Running the Security Examples]. 2. From the File menu, choose Open Project. 3. In the Open Project dialog box, navigate to: @@ -203,7 +203,7 @@ reappears until you enter correct values. ==== To Run the cart-secure Example Using Maven -1. Follow the steps in link:#GJJLK[To Set Up +1. Follow the steps in xref:security-webtier/security-webtier.adoc#GJJLK[To Set Up Your System for Running the Security Examples]. 2. In a terminal window, go to: + @@ -255,13 +255,13 @@ This example can be found in the `_tut-install_/examples/security/converter-secure` directory. This example is based on the unsecured enterprise bean application, `converter`, which is discussed in -link:#GIJRE[Chapter 36, "Getting Started with +xref:#GIJRE[Chapter 36, "Getting Started with Enterprise Beans"] and is found in the `_tut-install_/examples/ejb/converter/` directory. This section builds on the example by adding the necessary elements to secure the application by using the `getCallerPrincipal` and `isCallerInRole` methods, which are discussed in more detail in -link:#securing-an-enterprise-bean-programmatically[Securing an Enterprise Bean Programmatically]. +xref:security-jakartaee/security-jakartaee.adoc#_securing_an_enterprise_bean_programmatically[Securing an Enterprise Bean Programmatically]. In general, the following steps are necessary when using the `getCallerPrincipal` and `isCallerInRole` methods with an enterprise @@ -273,13 +273,13 @@ application. 1. Create a simple enterprise bean application. 2. Set up a user on GlassFish Server in the `file` realm, in the group `TutorialUser`, and set up default principal to role mapping. To do -this, follow the steps in link:#GJJLK[To Set Up +this, follow the steps in xref:security-webtier/security-webtier.adoc#GJJLK[To Set Up Your System for Running the Security Examples]. 3. Modify the bean to add the `getCallerPrincipal` and `isCallerInRole` methods. 4. If the application contains a web client that is a servlet, specify security for the servlet, as described in -link:#GJRMH[Specifying Security for Basic +xref:security-webtier/security-webtier.adoc#GJRMH[Specifying Security for Basic Authentication Using Annotations]. 5. Build, package, deploy, and run the application. @@ -362,7 +362,7 @@ client, `ConverterServlet`: ==== To Run the converter-secure Example Using NetBeans IDE -1. Follow the steps in link:#GJJLK[To Set Up +1. Follow the steps in xref:security-webtier/security-webtier.adoc#GJJLK[To Set Up Your System for Running the Security Examples]. 2. From the File menu, choose Open Project. 3. In the Open Project dialog box, navigate to: @@ -382,7 +382,7 @@ GlassFish Server instance. ==== To Run the converter-secure Example Using Maven -1. Follow the steps in link:#GJJLK[To Set Up +1. Follow the steps in xref:security-webtier/security-webtier.adoc#GJJLK[To Set Up Your System for Running the Security Examples]. 2. In a terminal window, go to: + diff --git a/src/main/antora/modules/security/pages/security-webtier/security-webtier.adoc b/src/main/antora/modules/security/pages/security-webtier/security-webtier.adoc index 0ce13feb..43ed8572 100644 --- a/src/main/antora/modules/security/pages/security-webtier/security-webtier.adoc +++ b/src/main/antora/modules/security/pages/security-webtier/security-webtier.adoc @@ -4,7 +4,7 @@ This chapter describes in greater detail the ways to implement security for Jakarta EE web applications discussed in a general way in -link:#BNBXE[Securing Containers]. The detail and +xref:security-intro/security-intro.adoc#BNBXE[Securing Containers]. The detail and examples in this chapter explore these security services as they relate to web components. diff --git a/src/main/antora/modules/security/pages/security-webtier/security-webtier001.adoc b/src/main/antora/modules/security/pages/security-webtier/security-webtier001.adoc index f5e46690..dabdc296 100644 --- a/src/main/antora/modules/security/pages/security-webtier/security-webtier001.adoc +++ b/src/main/antora/modules/security/pages/security-webtier/security-webtier001.adoc @@ -4,7 +4,7 @@ A web application is accessed using a web browser over a network, such as the Internet or a company's intranet. As discussed in -link:#BNAAY[Distributed Multitiered Applications], the +xref:#BNAAY[Distributed Multitiered Applications], the Jakarta EE platform uses a distributed multitiered application model, and web applications run in the web tier. @@ -14,7 +14,7 @@ Internet. In such an environment, a substantial number of web applications will require some type of security. Securing applications and their clients in the business tier and the EIS -tier is discussed in link:#BNBYK[Chapter 52, "Getting +tier is discussed in xref:security-jakartaee/security-jakartaee.adoc#BNBYK[Chapter 52, "Getting Started Securing Enterprise Applications"]. In the Jakarta EE platform, web components provide the dynamic extension @@ -35,17 +35,17 @@ following ways. * Declarative security can be implemented using either metadata annotations or an application's deployment descriptor. See -link:#BNBWK[Overview of Jakarta Security] for more +xref:security-intro/security-intro.adoc#BNBWK[Overview of Jakarta Security] for more information. + Declarative security for web applications is described in -link:#GKBAA[Securing Web Applications]. +xref:security-webtier/security-webtier.adoc#GKBAA[Securing Web Applications]. * Programmatic security is embedded in an application and can be used to make security decisions when declarative security alone is not sufficient to express the security model of an application. Declarative security alone may not be sufficient when conditional login in a particular work flow, instead of for all cases, is required in the -middle of an application. See link:#BNBWK[Overview +middle of an application. See xref:security-intro/security-intro.adoc#BNBWK[Overview of Jakarta Security] for more information. + Servlet 4.0 provides the `authenticate`, `login`, and `logout` methods @@ -56,7 +56,7 @@ required for web applications but may still be used to further specify security requirements beyond the basic default values. + Programmatic security is discussed in -link:#GJIIE[Using Programmatic Security with Web +xref:security-webtier/security-webtier.adoc#GJIIE[Using Programmatic Security with Web Applications]. * Message security works with web services and incorporates security features, such as digital signatures and encryption, into the header of @@ -68,9 +68,9 @@ Some of the material in this chapter builds on material presented earlier in this tutorial. In particular, this chapter assumes that you are familiar with the information in the following chapters: -* link:#BNADR[Chapter 6, "Getting Started with Web +* xref:#BNADR[Chapter 6, "Getting Started with Web Applications"] -* link:#BNAPH[Chapter 7, "Jakarta Server Faces Technology"] -* link:#BNAFD[Chapter 18, "Jakarta Servlet Technology"] -* link:#BNBWJ[Chapter 50, "Introduction to Security in +* xref:#BNAPH[Chapter 7, "Jakarta Server Faces Technology"] +* xref:#BNAFD[Chapter 18, "Jakarta Servlet Technology"] +* xref:security-intro/security-intro.adoc#BNBWJ[Chapter 50, "Introduction to Security in the Jakarta EE Platform"] diff --git a/src/main/antora/modules/security/pages/security-webtier/security-webtier002.adoc b/src/main/antora/modules/security/pages/security-webtier/security-webtier002.adoc index b424e622..dafe41bf 100644 --- a/src/main/antora/modules/security/pages/security-webtier/security-webtier002.adoc +++ b/src/main/antora/modules/security/pages/security-webtier/security-webtier002.adoc @@ -50,14 +50,14 @@ patterns (the part of a URL after the host name and port you want to constrain) and HTTP operations (the methods within the files that match the URL pattern you want to constrain) that describe a set of resources to be protected. Web resource collections are discussed in -link:#GJJCD[Specifying a Web Resource Collection]. +xref:security-webtier/security-webtier.adoc#GJJCD[Specifying a Web Resource Collection]. * Authorization constraint (`auth-constraint`): Specifies whether authentication is to be used and names the roles authorized to perform the constrained requests. For more information about authorization -constraints, see link:#GJJCG[Specifying an Authorization Constraint]. +constraints, see xref:security-webtier/security-webtier.adoc#GJJCG[Specifying an Authorization Constraint]. * User data constraint (`user-data-constraint`): Specifies how data is protected when transported between a client and a server. User data -constraints are discussed in link:#BNCBM[Specifying a Secure +constraints are discussed in xref:security-webtier/security-webtier.adoc#BNCBM[Specifying a Secure Connection]. [[GJJCD]][[_specifying_a_web_resource_collection]] @@ -122,9 +122,9 @@ application. Role names are case sensitive. The roles defined for the application must be mapped to users and groups defined on the server, except when default principal-to-role mapping is used. -For more information about security roles, see link:#BNCAV[Declaring +For more information about security roles, see xref:security-webtier/security-webtier.adoc#BNCAV[Declaring Security Roles]. For information on mapping security roles, see -link:#BNBXV[Mapping Roles to Users and Groups]. +xref:security-intro/security-intro.adoc#BNBXV[Mapping Roles to Users and Groups]. For a servlet, the `@HttpConstraint` and `@HttpMethodConstraint` annotations accept a `rolesAllowed` element that specifies the @@ -176,7 +176,7 @@ passwords sent between a client and a server on an unprotected session can be viewed and intercepted by third parties. Using a user data constraint with the user authentication mechanism can alleviate this concern. Configuring a user authentication mechanism is described in -link:#BNCBN[Specifying an Authentication Mechanism in the Deployment +xref:security-webtier/security-webtier.adoc#BNCBN[Specifying an Authentication Mechanism in the Deployment Descriptor]. To guarantee that data is transported over a secure connection, ensure @@ -264,7 +264,7 @@ a| An alternative way to perform user authentication, including BASIC and FORM authentication, is to use the `HttpAuthenticationMechanism`, specified by Jakarta Security, and documented in -link:#using-the-jakarta-ee-security-api[Chapter 53, "Using Jakarta Security"]. +xref:security-api/security-api.adoc#_using_the_jakarta_ee_security_api[Chapter 53, "Using Jakarta Security"]. |======================================================================= @@ -284,7 +284,7 @@ method will apply to all constrained resources in an application. Before you can authenticate a user, you must have a database of user names, passwords, and roles configured on your web or application server. For information on setting up the user database, see -link:#BNBXR[Managing Users and Groups in GlassFish +xref:security-intro/security-intro.adoc#BNBXR[Managing Users and Groups in GlassFish Server]. The Jakarta EE platform supports the following authentication mechanisms: @@ -297,7 +297,7 @@ The Jakarta EE platform supports the following authentication mechanisms: Basic, form-based, and digest authentication are discussed in this section. Client and mutual authentication are discussed in -link:#GJJWX[Chapter 54, "Jakarta EE Security: Advanced +xref:security-advanced/security-advanced.adoc#GJJWX[Chapter 54, "Jakarta EE Security: Advanced Topics"]. HTTP basic authentication and form-based authentication are not very @@ -314,7 +314,7 @@ the network level, such as the Internet Protocol Security (IPsec) protocol or virtual private network (VPN) strategies, is used in conjunction with basic or form-based authentication, some of these concerns can be alleviated. To specify a secure transport mechanism, use -the elements described in link:#BNCBM[Specifying a Secure Connection]. +the elements described in xref:security-webtier/security-webtier.adoc#BNCBM[Specifying a Secure Connection]. [[BNCBO]][[_http_basic_authentication]] @@ -337,13 +337,13 @@ password. 4. The server authenticates the user in the specified realm and, if successful, returns the requested resource. -link:#BNCBP[Figure 51-1] shows what happens when you specify HTTP basic +xref:security-webtier/security-webtier.adoc#BNCBP[Figure 51-1] shows what happens when you specify HTTP basic authentication. [[BNCBP]] .*Figure 51-1 HTTP Basic Authentication* -image::common:jakartaeett_dt_045.png["Diagram of four steps in HTTP basic authentication between client andserver"] +image::common::common:jakartaeett_dt_045.png["Diagram of four steps in HTTP basic authentication between client andserver"] [[BNCBQ]][[_form_based_authentication]] @@ -366,16 +366,16 @@ the resource by using the stored URL path. * If authentication fails, the client is forwarded or redirected to an error page. -link:#GEXFA[Figure 51-2] shows what happens when you specify form-based +xref:security-webtier/security-webtier.adoc#GEXFA[Figure 51-2] shows what happens when you specify form-based authentication. [[GEXFA]] .*Figure 51-2 Form-Based Authentication* -image::common:jakartaeett_dt_046.png["Diagram of four steps in form-based authentication between client andserver"] +image::common::common:jakartaeett_dt_046.png["Diagram of four steps in form-based authentication between client andserver"] -The section link:#BNCBY[The hello1-formauth +The section xref:security-webtier/security-webtier.adoc#BNCBY[The hello1-formauth Example: Form-Based Authentication with a Jakarta Server Faces Application] is an example application that uses form-based authentication. @@ -433,7 +433,7 @@ a| Another way to specify form-based authentication is to use the `authenticate`, `login`, and `logout` methods of `HttpServletRequest`, -as discussed in link:#GIRCJ[Authenticating Users +as discussed in xref:security-webtier/security-webtier.adoc#GIRCJ[Authenticating Users Programmatically]. |======================================================================= @@ -465,7 +465,7 @@ your deployment descriptor: The login and error page locations are specified relative to the location of the deployment descriptor. Examples of login and error pages -are shown in link:#BNCCA[Creating the Login Form +are shown in xref:security-webtier/security-webtier.adoc#BNCCA[Creating the Login Form and the Error Page]. The following example shows how to declare digest authentication in your diff --git a/src/main/antora/modules/security/pages/security-webtier/security-webtier003.adoc b/src/main/antora/modules/security/pages/security-webtier/security-webtier003.adoc index 27c3b2fd..41f9eed4 100644 --- a/src/main/antora/modules/security/pages/security-webtier/security-webtier003.adoc +++ b/src/main/antora/modules/security/pages/security-webtier/security-webtier003.adoc @@ -184,7 +184,7 @@ security role. If no user has been authenticated, this method returns The `security-role-ref` element should be declared in the deployment descriptor with a `role-name` subelement containing the role name to be passed to the method. Using security role references is discussed in -link:#BNCBB[Declaring and Linking Role References]. +xref:security-webtier/security-webtier.adoc#BNCBB[Declaring and Linking Role References]. * `getUserPrincipal` determines the principal name of the current user and returns a `java.security.Principal` object. If no user has been authenticated, this method returns `null`. Calling the `getName` method diff --git a/src/main/antora/modules/security/pages/security-webtier/security-webtier004.adoc b/src/main/antora/modules/security/pages/security-webtier/security-webtier004.adoc index cdd59ed3..a3df8325 100644 --- a/src/main/antora/modules/security/pages/security-webtier/security-webtier004.adoc +++ b/src/main/antora/modules/security/pages/security-webtier/security-webtier004.adoc @@ -15,9 +15,9 @@ security to demonstrate adding security to existing web applications. Here are some other locations where you will find examples of securing various types of applications: -* link:#BNBZK[The cart-secure Example: Securing an +* xref:security-jakartaee/security-jakartaee.adoc#BNBZK[The cart-secure Example: Securing an Enterprise Bean with Declarative Security] -* link:#BNCAA[The converter-secure Example: +* xref:security-jakartaee/security-jakartaee.adoc#BNCAA[The converter-secure Example: Securing an Enterprise Bean with Programmatic Security] * Jakarta EE 8 Eclipse GlassFish samples: `https://github.com/eclipse-ee4j/glassfish-samples` @@ -29,9 +29,9 @@ To set up your system for running the security examples, you need to configure a user database that the application can use for authenticating users. Before continuing, follow these steps. -. Make sure that GlassFish Server has been started (see link:#BNADI[Starting and Stopping GlassFish Server]). +. Make sure that GlassFish Server has been started (see xref:#BNADI[Starting and Stopping GlassFish Server]). . Add an authorized user to GlassFish Server. For the examples in this -chapter and in link:#BNBYK[Chapter 52, "Getting +chapter and in xref:security-jakartaee/security-jakartaee.adoc#BNBYK[Chapter 52, "Getting Started Securing Enterprise Applications"], add a user to the `file` realm of GlassFish Server, and assign the user to the group `TutorialUser`. @@ -51,7 +51,7 @@ Be sure to write down the user name and password for the user you create so that you can use it for testing the example applications. Authentication is case sensitive for both the user name and password, so write down the user name and password exactly. This topic is discussed -more in link:#BNBXR[Managing Users and Groups in +more in xref:security-intro/security-intro.adoc#BNBXR[Managing Users and Groups in GlassFish Server]. + [width="100%",cols="100%",] @@ -80,27 +80,27 @@ requested web resource if the user is authorized to view it. In general, the following steps are necessary for adding basic authentication to an unsecured servlet, such as the ones described in -link:#BNADR[Chapter 6, "Getting Started with Web +xref:#BNADR[Chapter 6, "Getting Started with Web Applications"]. In the example application included with this tutorial, many of these steps have been completed for you and are listed here simply to show what needs to be done should you wish to create a similar application. This application can be found in the `_tut-install_/examples/security/hello2-basicauth/` directory. -1. Follow the steps in link:#GJJLK[To Set Up Your System for Running +1. Follow the steps in xref:security-webtier/security-webtier.adoc#GJJLK[To Set Up Your System for Running the Security Examples]. 2. Create a web module for the servlet example, `hello2`, as described -in link:#BNADR[Chapter 6, "Getting Started with Web +in xref:#BNADR[Chapter 6, "Getting Started with Web Applications"]. 3. Add the appropriate security annotations to the servlet. The -security annotations are described in link:#GJRMH[Specifying Security +security annotations are described in xref:security-webtier/security-webtier.adoc#GJRMH[Specifying Security for Basic Authentication Using Annotations]. 4. Build, package, and deploy the web application by following the -steps in link:#GJQYS[To Build, Package, and Deploy the hello2-basicauth -Example Using NetBeans IDE] or link:#GJQZH[To Build, Package, and Deploy +steps in xref:security-webtier/security-webtier.adoc#GJQYS[To Build, Package, and Deploy the hello2-basicauth +Example Using NetBeans IDE] or xref:security-webtier/security-webtier.adoc#GJQZH[To Build, Package, and Deploy the hello2-basicauth Example Using Maven]. 5. Run the web application by following the steps described in -link:#GJQZF[To Run the hello2-basicauth Example]. +xref:security-webtier/security-webtier.adoc#GJQZF[To Run the hello2-basicauth Example]. [[GJRMH]][[_specifying_security_for_basic_authentication_using_annotations]] @@ -161,7 +161,7 @@ for which you cannot use the `@ServletSecurity` annotation. ==== To Build, Package, and Deploy the hello2-basicauth Example Using NetBeans IDE -1. Follow the steps in link:#GJJLK[To Set Up Your System for Running +1. Follow the steps in xref:security-webtier/security-webtier.adoc#GJJLK[To Set Up Your System for Running the Security Examples]. 2. From the File menu, choose Open Project. 3. In the Open Project dialog box, navigate to: @@ -182,7 +182,7 @@ GlassFish Server instance. ==== To Build, Package, and Deploy the hello2-basicauth Example Using Maven -1. Follow the steps in link:#GJJLK[To Set Up Your System for Running +1. Follow the steps in xref:security-webtier/security-webtier.adoc#GJJLK[To Set Up Your System for Running the Security Examples]. 2. In a terminal window, go to: + @@ -258,17 +258,17 @@ user name and password are those of an authorized user and, if authorized, sends the requested web resource. This example, `hello1-formauth`, adds security to the basic Jakarta Server -Faces application shown in link:#BNADX[A Web Module That +Faces application shown in xref:#BNADX[A Web Module That Uses Jakarta Server Faces Technology: The hello1 Example]. In general, the steps necessary for adding form-based authentication to an unsecured Jakarta Server Faces application are similar to those described -in link:#BNCCK[The hello2-basicauth Example: Basic Authentication with a +in xref:security-webtier/security-webtier.adoc#BNCCK[The hello2-basicauth Example: Basic Authentication with a Servlet]. The major difference is that you must use a deployment descriptor to specify the use of form-based authentication, as described -in link:#BNCCB[Specifying Security for the Form-Based Authentication +in xref:security-webtier/security-webtier.adoc#BNCCB[Specifying Security for the Form-Based Authentication Example]. In addition, you must create a login form page and a login -error page, as described in link:#BNCCA[Creating the Login Form and the +error page, as described in xref:security-webtier/security-webtier.adoc#BNCCA[Creating the Login Form and the Error Page]. This application can be found in the @@ -282,7 +282,7 @@ When using form-based login mechanisms, you must specify a page that contains the form you want to use to obtain the user name and password, as well as a page to display if login authentication fails. This section discusses the login form and the error page used in this example. -link:#BNCCB[Specifying Security for the Form-Based Authentication +xref:security-webtier/security-webtier.adoc#BNCCB[Specifying Security for the Form-Based Authentication Example] shows how you specify these pages in the deployment descriptor. The login page can be an HTML page or a servlet, and it must return an @@ -408,7 +408,7 @@ deployment descriptor for this example, which can be found in ==== To Build, Package, and Deploy the hello1-formauth Example Using NetBeans IDE -1. Follow the steps in link:#GJJLK[To Set Up Your System for Running +1. Follow the steps in xref:security-webtier/security-webtier.adoc#GJJLK[To Set Up Your System for Running the Security Examples]. 2. From the File menu, choose Open Project. 3. In the Open Project dialog box, navigate to: @@ -429,7 +429,7 @@ GlassFish Server instance, then opens it in a browser. ==== To Build, Package, and Deploy the hello1-formauth Example Using Maven and the asadmin Command -1. Follow the steps in link:#GJJLK[To Set Up Your System for Running +1. Follow the steps in xref:security-webtier/security-webtier.adoc#GJJLK[To Set Up Your System for Running the Security Examples]. 2. In a terminal window, go to: + From 433969a3723e0b2fdaa7e7f07474ada06fd6e271 Mon Sep 17 00:00:00 2001 From: "Kito D. Mann" Date: Fri, 19 May 2023 17:55:24 -0400 Subject: [PATCH 019/247] JETUT-56 Fixed image references and code block types. --- antora-conversion/AntoraConverter.java | 6 +++--- .../security-advanced/security-advanced002.adoc | 12 ++++++------ .../pages/security-intro/security-intro001.adoc | 10 +++++----- .../pages/security-intro/security-intro005.adoc | 2 +- .../security-jakartaee/security-jakartaee002.adoc | 2 +- .../pages/security-webtier/security-webtier002.adoc | 8 ++++---- 6 files changed, 20 insertions(+), 20 deletions(-) diff --git a/antora-conversion/AntoraConverter.java b/antora-conversion/AntoraConverter.java index 58036bb0..4c1bebce 100755 --- a/antora-conversion/AntoraConverter.java +++ b/antora-conversion/AntoraConverter.java @@ -88,11 +88,11 @@ public static void main(String... args) throws Exception { System.out.println("\uD83E\uDD16 Pre-scanning files for anchors, links, etc."); - preProcess(startPath, files); + preProcess(files); process(files, dryRun); } - private static void preProcess(String startPath, ArrayList files) throws IOException { + private static void preProcess(ArrayList files) throws IOException { for (File file : files) { System.out.println("\uD83D\uDD0E Pre-scanning file " + file.getAbsolutePath()); String content = new String(Files.readAllBytes(file.toPath())); @@ -165,7 +165,7 @@ private static void process(ArrayList files, boolean dryRun) throws IOExce } changeCount++; } - if (content.contains("image:")) { + if (content.contains("image:") && !content.contains("image:common:")) { System.out.println("=> Converting inline image references to block image references and adding module prefix"); content = content.replace("image:", "image::common:"); if (!dryRun) { diff --git a/src/main/antora/modules/security/pages/security-advanced/security-advanced002.adoc b/src/main/antora/modules/security/pages/security-advanced/security-advanced002.adoc index 6afb581b..8a872b2f 100644 --- a/src/main/antora/modules/security/pages/security-advanced/security-advanced002.adoc +++ b/src/main/antora/modules/security/pages/security-advanced/security-advanced002.adoc @@ -68,7 +68,7 @@ mutual authentication. [[GLIFJ]] .*Figure 53-1 Certificate-Based Mutual Authentication* -image::common::common:jakartaeett_dt_048.png["Diagram of six steps in mutual authentication with certificates"] +image::common:jakartaeett_dt_048.png["Diagram of six steps in mutual authentication with certificates"] In user name/password-based mutual authentication, the following actions occur. @@ -88,7 +88,7 @@ name/password-based mutual authentication. [[GLIGQ]] .*Figure 53-2 User Name/Password-Based Mutual Authentication* -image::common::common:jakartaeett_dt_049.png["Diagram of five steps in mutual authentication with user name andpassword"] +image::common:jakartaeett_dt_049.png["Diagram of five steps in mutual authentication with user name andpassword"] [[BNBYH]][[_enabling_mutual_authentication_over_ssl]] @@ -162,19 +162,19 @@ certificate named `client.cer`, follow these steps. Do not put client certificates in the `cacerts.jks` file. Any certificate you add to the `cacerts` file effectively can be a trusted root for any and all certificate chains. After you have completed development, delete the development version of the `cacerts` file and replace it with the original copy. . Generate the client certificate. Enter the following command from the directory where you want to generate the client certificate: + -[source,xml] +[source,shell] ---- java-home\bin\keytool -genkey -alias client-alias -keyalg RSA -keypass changeit -storepass changeit -keystore client_keystore.jks ---- . Export the generated client certificate into the file `client.cer`: + -[source,xml] +[source,shell] ---- java-home\bin\keytool -export -alias client-alias -storepass changeit -file client.cer -keystore client_keystore.jks ---- . Add the certificate to the truststore file `domain-dir/config/cacerts.jks`. Run `keytool` from the directory where you created the keystore and client certificate. Use the following parameters: + -[source,xml] +[source,shell] ---- java-home\bin\keytool -import -v -trustcacerts -alias client-alias -file client.cer -keystore domain-dir/config/cacerts.jks @@ -183,7 +183,7 @@ java-home\bin\keytool -import -v -trustcacerts -alias client-alias + The `keytool` utility returns a message like this one: + -[source,xml] +[source,shell] ---- Owner: CN=localhost, OU=My Company, O=Software, L=Santa Clara, ST=CA, C=US Issuer: CN=localhost, OU=My Company, O=Software, L=Santa Clara, ST=CA, C=US diff --git a/src/main/antora/modules/security/pages/security-intro/security-intro001.adoc b/src/main/antora/modules/security/pages/security-intro/security-intro001.adoc index f8912546..d6b87377 100644 --- a/src/main/antora/modules/security/pages/security-intro/security-intro001.adoc +++ b/src/main/antora/modules/security/pages/security-intro/security-intro001.adoc @@ -84,7 +84,7 @@ application URL. This action is shown in xref:security-intro/security-intro.adoc [[BNBWN]] .*Figure 50-1 Initial Request* -image::common::common:jakartaeett_dt_039.png["Diagram of initial request from web client to web server for access to aprotected resource"] +image::common:jakartaeett_dt_039.png["Diagram of initial request from web client to web server for access to aprotected resource"] Since the client has not yet authenticated itself to the application environment, the server responsible for delivering the web portion of @@ -108,7 +108,7 @@ server sets a credential for the user. [[BNBWP]] .*Figure 50-2 Initial Authentication* -image::common::common:jakartaeett_dt_040.png["Diagram of initial authentication: server sends form to client, whichsends authentication data to server for validation"] +image::common:jakartaeett_dt_040.png["Diagram of initial authentication: server sends form to client, whichsends authentication data to server for validation"] [[BNBWQ]][[_step_3_url_authorization]] @@ -126,7 +126,7 @@ xref:security-intro/security-intro.adoc#BNBWR[Figure 50-3] shows this process. [[BNBWR]] .*Figure 50-3 URL Authorization* -image::common::common:jakartaeett_dt_041.png["Diagram of URL authorization"] +image::common:jakartaeett_dt_041.png["Diagram of URL authorization"] The web server's evaluation stops with an "is authorized" outcome when the web server is able to map the user to a role. A "not authorized" @@ -143,7 +143,7 @@ original URL request, as shown in xref:security-intro/security-intro.adoc#BNBWT[ [[BNBWT]] .*Figure 50-4 Fulfilling the Original Request* -image::common::common:jakartaeett_dt_042.png["Diagram of request fulfillment, showing server returning result to client"] +image::common:jakartaeett_dt_042.png["Diagram of request fulfillment, showing server returning result to client"] In our example, the response URL of a web page is returned, enabling the user to post form data that needs to be handled by the business-logic @@ -164,7 +164,7 @@ one in the web server and one in the enterprise bean container. [[BNBWV]] .*Figure 50-5 Invoking an Enterprise Bean Business Method* -image::common::common:jakartaeett_dt_043.png["Diagram of authorization process between web component and enterprise bean"] +image::common:jakartaeett_dt_043.png["Diagram of authorization process between web component and enterprise bean"] The enterprise container is responsible for enforcing access control on the enterprise bean method. The container consults the security policy diff --git a/src/main/antora/modules/security/pages/security-intro/security-intro005.adoc b/src/main/antora/modules/security/pages/security-intro/security-intro005.adoc index 7a0151ec..b8408219 100644 --- a/src/main/antora/modules/security/pages/security-intro/security-intro005.adoc +++ b/src/main/antora/modules/security/pages/security-intro/security-intro005.adoc @@ -64,7 +64,7 @@ Roles]. [[BNBXL]] .*Figure 50-6 Mapping Roles to Users and Groups* -image::common::common:jakartaeett_dt_044.png["Diagram of role mapping, showing creation of users and groups, definition of roles, and mapping of roles to users and groups"] +image::common:jakartaeett_dt_044.png["Diagram of role mapping, showing creation of users and groups, definition of roles, and mapping of roles to users and groups"] The following sections provide more information on realms, users, groups, and roles. diff --git a/src/main/antora/modules/security/pages/security-jakartaee/security-jakartaee002.adoc b/src/main/antora/modules/security/pages/security-jakartaee/security-jakartaee002.adoc index 831e4328..805aa68b 100644 --- a/src/main/antora/modules/security/pages/security-jakartaee/security-jakartaee002.adoc +++ b/src/main/antora/modules/security/pages/security-jakartaee/security-jakartaee002.adoc @@ -500,7 +500,7 @@ illustrates this concept. [[BNBZA]] .*Figure 52-1 Security Identity Propagation* -image::common::common:jakartaeett_dt_047.png["Diagram of security identity propagation from client to intermediatecontainer to target container"] +image::common:jakartaeett_dt_047.png["Diagram of security identity propagation from client to intermediatecontainer to target container"] In this illustration, an application client is making a call to an enterprise bean method in one enterprise bean container. This enterprise bean diff --git a/src/main/antora/modules/security/pages/security-webtier/security-webtier002.adoc b/src/main/antora/modules/security/pages/security-webtier/security-webtier002.adoc index dafe41bf..4e569a81 100644 --- a/src/main/antora/modules/security/pages/security-webtier/security-webtier002.adoc +++ b/src/main/antora/modules/security/pages/security-webtier/security-webtier002.adoc @@ -262,7 +262,7 @@ a| *Note*: An alternative way to perform user authentication, including BASIC -and FORM authentication, is to use the `HttpAuthenticationMechanism`, specified by +and FORM authentication, is to use the `HttpAuthenticationMechanism`, specified by Jakarta Security, and documented in xref:security-api/security-api.adoc#_using_the_jakarta_ee_security_api[Chapter 53, "Using Jakarta Security"]. |======================================================================= @@ -343,7 +343,7 @@ authentication. [[BNCBP]] .*Figure 51-1 HTTP Basic Authentication* -image::common::common:jakartaeett_dt_045.png["Diagram of four steps in HTTP basic authentication between client andserver"] +image::common:jakartaeett_dt_045.png["Diagram of four steps in HTTP basic authentication between client andserver"] [[BNCBQ]][[_form_based_authentication]] @@ -373,7 +373,7 @@ authentication. [[GEXFA]] .*Figure 51-2 Form-Based Authentication* -image::common::common:jakartaeett_dt_046.png["Diagram of four steps in form-based authentication between client andserver"] +image::common:jakartaeett_dt_046.png["Diagram of four steps in form-based authentication between client andserver"] The section xref:security-webtier/security-webtier.adoc#BNCBY[The hello1-formauth Example: Form-Based Authentication with a Jakarta Server Faces Application] @@ -389,7 +389,7 @@ requiring the server to specify the action field of the outbound form. The following code snippet shows how the form should be coded into the HTML page: -[source,java] +[source,html] ----

From 738131ae9780a3540de3167a7ddaad6e8430cebd Mon Sep 17 00:00:00 2001 From: "Kito D. Mann" Date: Sat, 20 May 2023 10:54:09 -0400 Subject: [PATCH 020/247] JETUT-56 Updated version number --- src/main/antora/antora.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/antora/antora.yml b/src/main/antora/antora.yml index 46eace97..7d8da3c5 100644 --- a/src/main/antora/antora.yml +++ b/src/main/antora/antora.yml @@ -1,6 +1,6 @@ name: jakarta-ee-docs title: Jakarta EE Documentation -version: 8 +version: 9.1 asciidoc: attributes: source-language: asciidoc@ From fa5ffc35838c6a53c2ff1c2b7cfcbaa386bf71a5 Mon Sep 17 00:00:00 2001 From: Arjan Tijms Date: Mon, 22 May 2023 18:03:08 +0200 Subject: [PATCH 021/247] Explain the form authentication mechanism Signed-off-by: Arjan Tijms --- .../asciidoc/security-refresh/security.adoc | 218 ++++++++++++++++++ 1 file changed, 218 insertions(+) diff --git a/src/main/asciidoc/security-refresh/security.adoc b/src/main/asciidoc/security-refresh/security.adoc index b19968b4..8e0d908a 100644 --- a/src/main/asciidoc/security-refresh/security.adoc +++ b/src/main/asciidoc/security-refresh/security.adoc @@ -553,3 +553,221 @@ public class RestBasicAuthDBStoreAndCustomStoreIT extends ITBase { We do two tests here; in one test we try to authenticate as "john", in the other test as "pete". As we have seen, each identity store only validates one of them. The fact that both tests pass demonstrates that each store will validate the right user, and that not recognising a username by any of them will not fail the overall validation. + +== Securing an endpoint with Form Authentication + +In the following example we'll be securing a REST endpoint using Form Authentication. + +You'll learn the following things; + +1. How to define security constraints +2. How to set a provided authentication mechanisms +3. How to define (and implicitly set) a custom identity store +4. How to use the Jakarta Security SecurityContext + +=== Write the application + +Let's start with defining a simple REST resource class for a `/rest/resource` endpoint: + +[source,java] +---- +@Path("/resource") +@RequestScoped +public class Resource { + + @Inject + private SecurityContext securityContext; + + @GET + @Produces(TEXT_PLAIN) + public String getCallerAndRole() { + return + securityContext.getCallerPrincipal().getName() + " : " + + securityContext.isCallerInRole("user"); + } + +} +---- + +This resource uses the injected Jakarta EE SecurityContext to obtain access to the current authenticated caller, which is represented by a `Principal` instance. For simplicity sake the code here does not check whether the caller principal is `null`. If the resource is also available to non-authenticated callers, this is something we have to do. The `getCallerPrincipal()` call would return `null` then. + +Also note that there is a Jakarta REST specific type that is also named `SecurityContext` and has similar methods as the ones we used here. From the point of view of Jakarta EE that is a deprecated type and replaced by the Jakarta Security version. + +==== Declare the security constraints + +Next we'll define the security constraints in `web.xml`, which are used to tell the security system that access to a given URL or URL pattern is protected, and hence authentication is required: + +[source,xml] +---- + + + + + + protected + /rest/* + + + user + + + + +---- + +This XML essentially says that to access any URL that starts with "/rest" requires the caller to have the role "user". Roles are opaque strings; merely identifiers. It's fully up to the application how broad or fine-grained they are. + +Note that in Jakarta EE, internally these XML constraints are transformed into `Permission` instances and made available via a specific type of the Permission Store that we explained above. Knowledge about this transformation is only needed for very advanced use cases. + +The observant reader may wonder if XML is really the only option here, given the strong feelings that exist in parts of the community around XML. The answer is yes and no. Jakarta EE does define the `@RolesAllowed` annotation that could be used to replace the XML shown above, but only the legacy Enterprise Beans has specified a behaviour for this when put on an Enterprise Bean. Jakarta REST has done no such thing, although the JWT API in MicroProfile has defined this for REST resources. In Jakarta EE however this remains a vendor specific extension. + +There are also a number of annotations and APIs in Jakarta EE to set these kinds of constraints for individual Servlets, but those won't help us much either here. + +==== Declare the authentication mechanism + +[source,java] +---- +@ApplicationScoped +@FormAuthenticationMechanismDefinition( + loginToContinue = @LoginToContinue( + loginPage="/login.html", + errorPage="/login-error.html" + ) +) +@DeclareRoles({ "user", "caller" }) +@ApplicationPath("/rest") +public class ApplicationConfig extends Application { + +} +---- + +To declare the usage of a specific authentication mechanism, Jakarta EE provides `[XYZ]MechanismDefinition` annotations. Such an annotation is picked up by the security system, and in response to it a CDI bean that implements the `HttpAuthenticationMechanism` is enabled for it. + +The annotation can be put on any bean, but in a REST application it fits particularly well on the `Application` subclass that also declares the path for REST resources. + +Contrary to the Basic HTTP authentication mechanism, the Form authentication mechanism allows us to customise the login dialog and to keep track of the authenticated session on the server (using a cookie). This also allows us to logout, something that for unknown reasons has never been specified for Basic HTTP authentication. + +In order to use this authentication mechanism we have to specify two paths to resources relative to our application; the one called to login (which the user is redirected to whenever a protected resource is accessed), and the one called when login fails (e.g. when the caller entered the credentials wrongly). Those two paths can be the same, and a request parameter can be used to distinguish between the two. Paths can point to anything our server can respond to; a static HTML file, a REST resource, or anything else. For simplicity we'll use two static HTML files here: + +[source,html] +---- + + + + + Login to continue + +

+ Username +

+ Password +

+ +

+ + +---- + +[source,html] +---- + + + + + Login failed! +
Try again + + +---- + + + +==== Define the identity store + +Finally, let's define a very simple identity store that the security system can use to validate provided credentials for a Form authentication: + +[source,java] +----- +@ApplicationScoped +public class CustomIdentityStore implements IdentityStore { + + public CredentialValidationResult validate(UsernamePasswordCredential usernamePasswordCredential) { + if (usernamePasswordCredential.compareTo("john", "secret1")) { + return new CredentialValidationResult("john", Set.of("user", "caller")); + } + + return INVALID_RESULT; + } + +} +----- + +This identity store only "contains" the single identity (user) "john", with password "secret1" and roles "user" and "caller". Defining this kind of identity store is often the simplest way to get started. Note that Jakarta Security does not define a simple identity store out of the box, because there are questions whether that would promote security best practices. + +Also note that the identity store is installed and used by the security system just by the virtue of being there; it picks up all enabled CDI beans that implement `IdentityStore`. Such beans can be enabled by the security system itself (following some configuration annotation), or can be programmatically added using the appropriate CDI APIs. Where the bean comes from doesn't matter for Jakarta Security, only the fact that it's there. + + +==== Test the application + +It's now time to test our application. A ready to test version is available from the Jakarta EE Examples project at https://github.com/eclipse-ee4j/jakartaee-examples. + +Download or clone this repo, then cd into the `focused` folder and execute: + +``` +mvn clean install -pl :restBasicAuthCustomStore +``` + +This will run a test associated with the project, printing something like the following: + +``` +john : true +[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 5.24 s - in jakartaee.examples.focused.security.restformauthcustomstore.RestFormAuthCustomStoreIT +``` + +Let's take a quick look at the actual test: + +[source,java] +---- +@RunWith(Arquillian.class) +@RunAsClient +public class RestFormAuthCustomStoreIT extends ITBase { + + @ArquillianResource + private URL baseUrl; + + /** + * Test the call to a protected REST service + * + * @throws Exception when a serious error occurs. + */ + @RunAsClient + @Test + public void testRestCall() throws Exception { + HtmlPage loginPage = webClient.getPage(baseUrl + "/rest/resource"); + System.out.println(loginPage.asXml()); + + HtmlForm form = loginPage.getForms() + .get(0); + + form.getInputByName("j_username") + .setValueAttribute("john"); + + form.getInputByName("j_password") + .setValueAttribute("secret1"); + + TextPage page = form.getInputByValue("Submit") + .click(); + + System.out.println(page.getContent()); + } +} +---- + +Using Arquillian, the test starts the default server (GlassFish 7), and deploys the actual output of the build process (a .war file) to it. The test runs in the integration test phase (and not the unit test phase) to make sure this output is indeed available. The test then does a request to the remote GlassFish server using a provided html unit web client. Note that anything that can do an HTTP request could have been used here as well. + +The test first does a request here to the protected resource, and as a response the server returns the HTML form we defined above. Using the HTMLUnit API it's easy to navigate the HTML DOM, fill out the username and password in the form, and programmatically click the submit button. The authentication mechanism is then able to detect this special postback (it's listening to the special virtual URL the postback is to), and like the basic authentication mechanism got the username and password from the headers, the form authentication mechanism gets them from the POST data. + + From 95f58ffcf18aa0bf5c7ae3f164a529dc6d9d6f3b Mon Sep 17 00:00:00 2001 From: "Kito D. Mann" Date: Fri, 26 May 2023 19:14:30 -0400 Subject: [PATCH 022/247] JETUT-56 Copy edits round 1 --- .../asciidoc/security-refresh/security.adoc | 132 +++++++++--------- 1 file changed, 65 insertions(+), 67 deletions(-) diff --git a/src/main/asciidoc/security-refresh/security.adoc b/src/main/asciidoc/security-refresh/security.adoc index 8e0d908a..37ffb411 100644 --- a/src/main/asciidoc/security-refresh/security.adoc +++ b/src/main/asciidoc/security-refresh/security.adoc @@ -1,81 +1,79 @@ = Jakarta Security -Jakarta Security is the overarching security API in Jakarta EE. +Jakarta Security is the overarching security API in Jakarta EE. -Due to historical and political reasons, a number of security features are distributed among several other APIs in Jakarta EE. Sometimes they overlap, sometimes such features are only accessible from these other APIs. In this chapter we will focus primarily on explaining Jakarta Security, and will mention when other APIs are needed to accomplish a certain task. +Due to historical and political reasons, a number of security features are distributed among several other APIs in Jakarta EE. Sometimes they overlap, and sometimes such features are only accessible from these other APIs. In this chapter, we'll focus primarily on explaining Jakarta Security, but we'll mention when other APIs are needed to accomplish a certain task. == Overview -Before we look at some practical examples, let's quickly go through some basics. +Before we look at some practical examples, let's quickly go through some basics. Some of the guiding principles in Jakarta Security are: -1. It should work directly out of the box, without requiring any kind of vendor specific configuration or activation. -2. It leverages Jakarta CDI as much as possible. Most artefacts are CDI beans and many features are done via CDI interceptors. -3. The difference between framework provided artefacts and custom (user provided) artefacts is minimal or non-existent. -4. It fully integrates with security features from other Jakarta EE APIs and proprietary (vendor specific) artefacts. +1. It should work directly out of the box, without requiring vendor-specific configuration. +2. It leverages Jakarta CDI as much as possible. Most artifacts are CDI beans, and many features are done via CDI interceptors. +3. The difference between framework-provided artifacts and custom (user provided) artifacts is minimal or non-existent. +4. It fully integrates with security features from other Jakarta EE APIs and proprietary (vendor-specific) artifacts. -Jakarta Security makes an important distinction between several distinct artefacts that play an important role in the security process: +Jakarta Security defines several distinct artifacts that play an important role in the security process: -1. The Authentication Mechanism -2. The Identity Store -3. The Permission Store +1. Authentication Mechanism +2. Identity Store +3. Permission Store The first two of these are used in the authentication process: -An _authentication mechanism_ is somewhat like a controller in the well-known MVC pattern; it’s the entity that interacts with the caller (typically a human) via some kind of view to collect credentials and with the model (business logic) to validate these credentials. An authentication mechanism knows about the environment that this caller uses to communicate with the server. An authentication mechanism for HTTP knows about URLs to redirect or forward to, or about response headers to send to the client. It also knows about the data coming back, such as cookies, request headers, and post data. Examples of authentication mechanisms are FORM authentication and BASIC authentication. +An _authentication mechanism_ is somewhat like a controller in the well-known MVC pattern; it is the entity that interacts with the caller (typically a human), via some kind of view to collect credentials, and with the model (business logic) to validate these credentials. An authentication mechanism knows about the environment this caller uses to communicate with the server. An authentication mechanism for HTTP knows about URLs to redirect or forward to, or about response headers to send to the client. It also knows about the data coming back, such as cookies, request headers, and post data. Examples of authentication mechanisms are Form authentication and Basic authentication. -An _identity store_ on its turn is more like the model in the MVC pattern. This entity strictly performs a business / data operation where credentials go in, and an identity comes out. The identity contains logic to validate said credentials, and embeds or contacts a database. This "database" contains user names, along with their credentials and (typically) roles. An identity store therefore knows nothing about the environment that this caller uses to communicate with the server; e.g. it doesn't know about HTTP or headers etc. +An _identity store_ is more like the model in the MVC pattern. This entity strictly performs a business / data operation where credentials go in, and an identity comes out. The identity contains logic to validate said credentials, and embeds or contacts a database. This "database" contains usernames, along with their credentials and (typically) roles. An identity store therefore knows nothing about the environment that this caller uses to communicate with the server; e.g., it doesn't know about HTTP or headers etc. Example of identity stores are services that contact SQL/JDBC databases, LDAP servers, files on the file-system, etc. - image::authentication_mvc.svg["Diagram illustrating the role of the authentication mechanism and identity store in an MVC like structure"] The third one is used for the authorization process: -A _permission store_ is another kind of model that stores permissions, typically either globally, or per role (role based permissions). This entity then performs a business / data operation where a query and an identity go in, and a yes/no answer goes out. For instance, a query such as "can access /foo/bar" along with the identity for user "John" with roles "bar" and "kaz". -Examples of permissions stores are the Jakarta Authorization usage of the Policy class, or the internal data structure where a Servlet Container such as Tomcat or Jetty stores the security constraints an application defined. +A _permission store_ is another kind of model that stores permissions, typically either globally, or per role (role-based permissions). This entity then performs a business / data operation where a query and an identity go in, and a yes/no answer goes out. For instance, a query such as "can access /foo/bar" along with the identity for user "John" with roles "bar" and "kaz". +Examples of permission stores are the Jakarta Authorization usage of the Policy class, or the internal data structure where a Servlet Container such as Tomcat or Jetty stores the security constraints an application defined. -== Provided authentication mechanisms and identity stores +== Provided authentication mechanisms and identity stores -Jakarta Security provides a number of build-in authentication mechanisms and identity stores. We'll enumerate them here first, and will look at them in more detail below. +Jakarta Security provides a number of built-in authentication mechanisms and identity stores. We'll enumerate them here first, and will look at them in more detail below. Authentication mechanisms: -1. The Basic Authentication Mechanism -2. The Form Authentication Mechanism -3. The Custom Form Authentication Mechanism -4. The Open ID Connect (OIDC) Authentication Mechanism +. Basic +. Form +. Custom Form +. Open ID Connect (OIDC) Identity stores: -1. The Database Identity Store -2. The LDAP Identity Store +. Database +. LDAP -== Custom authentication mechanisms and identity stores +== Custom authentication mechanisms and identity stores -When the provided authentication mechanisms and identity stores are not sufficient, we can easily define our own. The provided ones and our own ones use the exact same interfaces, and the system doesn't distinguish between calling our own one or one that was provided by the system. +When the provided authentication mechanisms and identity stores aren't sufficient, we can easily define custom ones. Both provided and custom ones use the same interfaces, and the system doesn't distinguish between them. == Authentication mechanisms and identity stores from other APIs -The Servlet specification defines the exact same Form and Basic authentication mechanisms. Authenticating with them will have the exact same result as authenticating with a Jakarta Security authentication mechanism. E.g. role checks will work exactly the same independent on which API was used to authenticate. - -A Servlet authentication mechanism however will not necessarily consult a Jakarta Security identity store. This is server dependent. The identity store that is called is server dependent as well. Calling this server dependent identity store is possible from Jakarta Security, but as an advanced feature. +The Servlet specification defines the exact same Form and Basic authentication mechanisms. Authenticating with them will have the exact same result as authenticating with a Jakarta Security authentication mechanism. (Role checks will work the same independent on which API was used to authenticate.) -Likewise, programmatic role checks can be done from various APIs, including Jakarta Security, Jakarta REST and Jakarta Servlet. These all return the same outcome, independent from whether authentication took place with a Jakarta Security Authentication Mechanism or a Servlet Authentication Mechanism. +A Servlet authentication mechanism, however, will not necessarily consult a Jakarta Security identity store. This is server dependent. The identity store that is called is server dependent as well. Calling this server-dependent identity store is possible from Jakarta Security, but as an advanced feature. +Likewise, programmatic role checks can be done from various APIs, including Jakarta Security, Jakarta REST and Jakarta Servlet. These all return the same outcome, independent of whether authentication took place with a Jakarta Security Authentication Mechanism or a Servlet Authentication Mechanism. -== Securing an endpoint with Basic Authentication +== Securing an endpoint with Basic authentication -In the following example we'll be securing a REST endpoint using Basic Authentication. +In the following example we'll be securing a REST endpoint using Basic authentication. -You'll learn the following things; +You'll learn how to: -1. How to define security constraints -2. How to set a provided authentication mechanisms -3. How to define (and implicitly set) a custom identity store -4. How to use the Jakarta Security SecurityContext +. Define security constraints +. Set a provided authentication mechanisms +. Define (and implicitly set) a custom identity store +. Use the Jakarta Security `SecurityContext` === Write the application @@ -101,9 +99,9 @@ public class Resource { } ---- -This resource uses the injected Jakarta EE SecurityContext to obtain access to the current authenticated caller, which is represented by a `Principal` instance. For simplicity sake the code here does not check whether the caller principal is `null`. If the resource is also available to non-authenticated callers, this is something we have to do. The `getCallerPrincipal()` call would return `null` then. +This resource uses the injected Jakarta EE `SecurityContext` to obtain access to the current authenticated caller, which is represented by a `Principal` instance. For simplicity, the code here doesn't check whether the caller principal is `null`. If the resource is also available to non-authenticated callers, this is something we have to do. The `getCallerPrincipal()` call would return `null` then. -Also note that there is a Jakarta REST specific type that is also named `SecurityContext` and has similar methods as the ones we used here. From the point of view of Jakarta EE that is a deprecated type and replaced by the Jakarta Security version. +Also note that there is a Jakarta REST-specific type that is also named `SecurityContext` and has similar methods as the ones we used here. From the Jakarta EE perspective, that is a deprecated type and has been replaced by the Jakarta Security version. ==== Declare the security constraints @@ -132,7 +130,7 @@ Next we'll define the security constraints in `web.xml`, which are used to tell This XML essentially says that to access any URL that starts with "/rest" requires the caller to have the role "user". Roles are opaque strings; merely identifiers. It's fully up to the application how broad or fine-grained they are. -Note that in Jakarta EE, internally these XML constraints are transformed into `Permission` instances and made available via a specific type of the Permission Store that we explained above. Knowledge about this transformation is only needed for very advanced use cases. +Note that in Jakarta EE, internally these XML constraints are transformed into `Permission` instances and made available via a specific type of permission store. Knowledge about this transformation is only needed for very advanced use cases. The observant reader may wonder if XML is really the only option here, given the strong feelings that exist in parts of the community around XML. The answer is yes and no. Jakarta EE does define the `@RolesAllowed` annotation that could be used to replace the XML shown above, but only the legacy Enterprise Beans has specified a behaviour for this when put on an Enterprise Bean. Jakarta REST has done no such thing, although the JWT API in MicroProfile has defined this for REST resources. In Jakarta EE however this remains a vendor specific extension. @@ -153,7 +151,7 @@ public class ApplicationConfig extends Application { To declare the usage of a specific authentication mechanism, Jakarta EE provides `[XYZ]MechanismDefinition` annotations. Such an annotation is picked up by the security system, and in response to it a CDI bean that implements the `HttpAuthenticationMechanism` is enabled for it. -The annotation can be put on any bean, but in a REST application it fits particularly well on the `Application` subclass that also declares the path for REST resources. +The annotation can be put on any bean, but in a REST application it fits particularly well on the `Application` subclass because it also declares the path for REST resources. ==== Define the identity store @@ -175,14 +173,14 @@ public class TestIdentityStore implements IdentityStore { } ---- -This identity store only "contains" the single identity (user) "john", with password "secret1" and roles "user" and "caller". Defining this kind of identity store is often the simplest way to get started. Note that Jakarta Security does not define a simple identity store out of the box, because there are questions whether that would promote security best practices. +This identity store only validates the single identity (user) "john", with password "secret1" and roles "user" and "caller". Defining this kind of identity store is often the simplest way to get started. Note that Jakarta Security doesn't define a simple identity store out of the box, because there are questions whether that would promote security best practices. Also note that the identity store is installed and used by the security system just by the virtue of being there; it picks up all enabled CDI beans that implement `IdentityStore`. Such beans can be enabled by the security system itself (following some configuration annotation), or can be programmatically added using the appropriate CDI APIs. Where the bean comes from doesn't matter for Jakarta Security, only the fact that it's there. ==== Test the application -It's now time to test our application. A ready to test version is available from the Jakarta EE Examples project at https://github.com/eclipse-ee4j/jakartaee-examples. +It's now time to test our application. A ready-to-test version is available from the Jakarta EE Examples project at https://github.com/eclipse-ee4j/jakartaee-examples. Download or clone this repo, then cd into the `focused` folder and execute: @@ -236,23 +234,23 @@ Using Arquillian, the test starts the default server (GlassFish 7), and deploys The `DefaultCredentialsProvider` used here makes sure that the headers for Basic authentication are added to the request. The Basic authentication mechanism that we defined for our applications reads those headers, extracts the username and password from them, and consults our identity store with them. -Alternatively, we can manually deploy the war file found in `security/restBasicAuthCustomStore/target/restBasicAuthCustomStore.war` to a server of our choice (e.g. GlassFish 7), and request the URL via a browser or a commandline util such as `curl`. +If you want to inspect the app yourself, you can manually deploy the WAR file (`security/restBasicAuthCustomStore/target/restBasicAuthCustomStore.war` )to the server of your choice (e.g. GlassFish 7), and request the URL via a browser or a commandline util such as `curl`. -== Securing an endpoint with Basic Authentication and a Database identity store +== Securing an endpoint with Basic authentication and a Database identity store -In the following example we'll be securing a REST endpoint using Basic Authentication and the database identity store that is provided by Jakarta Security. +In the following example we'll be securing a REST endpoint using Basic authentication and the database identity store that is provided by Jakarta Security. -You'll learn the following things; +You'll learn how to: -1. How to define security constraints -2. How to set a provided authentication mechanisms -3. How to set a provided identity store that uses a database -4. How to populate and configure that identity store -5. How to use the Jakarta Security SecurityContext +1. Define security constraints +2. Set a provided authentication mechanisms +3. Set a provided identity store that uses a database +4. Populate and configure that identity store +5. Use the Jakarta Security `SecurityContext` === Write the application -We'll use the same resource and same security constraints as we used for the <> example. +We'll use the same resource and same security constraints as we used for the <> example. ==== Declare the authentication mechanism and identity store @@ -406,25 +404,25 @@ john : true [INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 8.307 s - in jakartaee.examples.focused.security.restbasicauthdbstore.RestBasicAuthDBStoreIT ``` -The test itself is basically the same as that for the <> example. +The test itself is basically the same as that for the <> example. -== Securing an endpoint with Basic Authentication and multiple identity stores +== Securing an endpoint with Basic authentication and multiple identity stores -In the following example we'll be securing a REST endpoint using Basic Authentication and two identity stores: the database identity store that is provided by Jakarta Security and a custom identity store. +In the following example we'll be securing a REST endpoint using Basic authentication and two identity stores: the database identity store that is provided by Jakarta Security and a custom identity store. You'll learn the following things; 1. How to define security constraints -2. How to set a provided authentication mechanisms +2. How to set a provided authentication mechanisms 3. How to set a provided identity store that uses a database -4. How to populate and configure that identity store +4. How to populate and configure that identity store 5. How to set an additional identity store 6. How to use the Jakarta Security SecurityContext === Write the application -We'll use the same resource and same security constraints as we used for the <> example. +We'll use the same resource and same security constraints as we used for the <> example. ==== Declare the authentication mechanism and identity store @@ -474,7 +472,7 @@ In the two stores above however only one store knows about "pete" and that's the ==== Populating the identity store -In order to use the identity store we need to put some data in a database. This is done in the same as in <>. +In order to use the identity store we need to put some data in a database. This is done in the same as in <>. ==== Test the application @@ -551,7 +549,7 @@ public class RestBasicAuthDBStoreAndCustomStoreIT extends ITBase { } ---- -We do two tests here; in one test we try to authenticate as "john", in the other test as "pete". As we have seen, each identity store only validates one of them. The fact that both tests pass demonstrates that each store will validate the right user, and that not recognising a username by any of them will not fail the overall validation. +We do two tests here; in one test we try to authenticate as "john", in the other test as "pete". As we've seen, each identity store only validates one of them. The fact that both tests pass demonstrates that each store will validate the right user, and that not recognising a username by any of them will not fail the overall validation. == Securing an endpoint with Form Authentication @@ -561,7 +559,7 @@ In the following example we'll be securing a REST endpoint using Form Authentica You'll learn the following things; 1. How to define security constraints -2. How to set a provided authentication mechanisms +2. How to set a provided authentication mechanisms 3. How to define (and implicitly set) a custom identity store 4. How to use the Jakarta Security SecurityContext @@ -589,7 +587,7 @@ public class Resource { } ---- -This resource uses the injected Jakarta EE SecurityContext to obtain access to the current authenticated caller, which is represented by a `Principal` instance. For simplicity sake the code here does not check whether the caller principal is `null`. If the resource is also available to non-authenticated callers, this is something we have to do. The `getCallerPrincipal()` call would return `null` then. +This resource uses the injected Jakarta EE SecurityContext to obtain access to the current authenticated caller, which is represented by a `Principal` instance. For simplicity sake the code here doesn't check whether the caller principal is `null`. If the resource is also available to non-authenticated callers, this is something we have to do. The `getCallerPrincipal()` call would return `null` then. Also note that there is a Jakarta REST specific type that is also named `SecurityContext` and has similar methods as the ones we used here. From the point of view of Jakarta EE that is a deprecated type and replaced by the Jakarta Security version. @@ -622,7 +620,7 @@ This XML essentially says that to access any URL that starts with "/rest" requir Note that in Jakarta EE, internally these XML constraints are transformed into `Permission` instances and made available via a specific type of the Permission Store that we explained above. Knowledge about this transformation is only needed for very advanced use cases. -The observant reader may wonder if XML is really the only option here, given the strong feelings that exist in parts of the community around XML. The answer is yes and no. Jakarta EE does define the `@RolesAllowed` annotation that could be used to replace the XML shown above, but only the legacy Enterprise Beans has specified a behaviour for this when put on an Enterprise Bean. Jakarta REST has done no such thing, although the JWT API in MicroProfile has defined this for REST resources. In Jakarta EE however this remains a vendor specific extension. +The observant reader may wonder if XML is really the only option here, given the strong feelings that exist in parts of the community around XML. The answer is yes and no. Jakarta EE does define the `@RolesAllowed` annotation that could be used to replace the XML shown above, but only the legacy Enterprise Beans has specified a behaviour for this when put on an Enterprise Bean. Jakarta REST has done no such thing, although the JWT API in MicroProfile has defined this for REST resources. In Jakarta EE, however, this remains a vendor-specific extension. There are also a number of annotations and APIs in Jakarta EE to set these kinds of constraints for individual Servlets, but those won't help us much either here. @@ -683,7 +681,7 @@ In order to use this authentication mechanism we have to specify two paths to re ---- - + ==== Define the identity store @@ -705,7 +703,7 @@ public class CustomIdentityStore implements IdentityStore { } ----- -This identity store only "contains" the single identity (user) "john", with password "secret1" and roles "user" and "caller". Defining this kind of identity store is often the simplest way to get started. Note that Jakarta Security does not define a simple identity store out of the box, because there are questions whether that would promote security best practices. +This identity store only "contains" the single identity (user) "john", with password "secret1" and roles "user" and "caller". Defining this kind of identity store is often the simplest way to get started. Note that Jakarta Security doesn't define a simple identity store out of the box, because there are questions whether that would promote security best practices. Also note that the identity store is installed and used by the security system just by the virtue of being there; it picks up all enabled CDI beans that implement `IdentityStore`. Such beans can be enabled by the security system itself (following some configuration annotation), or can be programmatically added using the appropriate CDI APIs. Where the bean comes from doesn't matter for Jakarta Security, only the fact that it's there. @@ -768,6 +766,6 @@ public class RestFormAuthCustomStoreIT extends ITBase { Using Arquillian, the test starts the default server (GlassFish 7), and deploys the actual output of the build process (a .war file) to it. The test runs in the integration test phase (and not the unit test phase) to make sure this output is indeed available. The test then does a request to the remote GlassFish server using a provided html unit web client. Note that anything that can do an HTTP request could have been used here as well. -The test first does a request here to the protected resource, and as a response the server returns the HTML form we defined above. Using the HTMLUnit API it's easy to navigate the HTML DOM, fill out the username and password in the form, and programmatically click the submit button. The authentication mechanism is then able to detect this special postback (it's listening to the special virtual URL the postback is to), and like the basic authentication mechanism got the username and password from the headers, the form authentication mechanism gets them from the POST data. +The test first does a request here to the protected resource, and as a response the server returns the HTML form we defined above. Using the HTMLUnit API it's easy to navigate the HTML DOM, fill out the username and password in the form, and programmatically click the Submit button. The authentication mechanism is then able to detect this special postback (it's listening to the special virtual URL the postback is to), and like the basic authentication mechanism got the username and password from the headers, the form authentication mechanism gets them from the POST data. From 31ca604399a8cd4c5a9003e086bb56735763dccb Mon Sep 17 00:00:00 2001 From: "Kito D. Mann" Date: Mon, 29 May 2023 13:17:01 -0400 Subject: [PATCH 023/247] JETUT-19 Copy edits round 2 --- .../asciidoc/security-refresh/security.adoc | 166 +++++++++--------- 1 file changed, 83 insertions(+), 83 deletions(-) diff --git a/src/main/asciidoc/security-refresh/security.adoc b/src/main/asciidoc/security-refresh/security.adoc index 37ffb411..8f452895 100644 --- a/src/main/asciidoc/security-refresh/security.adoc +++ b/src/main/asciidoc/security-refresh/security.adoc @@ -23,7 +23,7 @@ Jakarta Security defines several distinct artifacts that play an important role The first two of these are used in the authentication process: -An _authentication mechanism_ is somewhat like a controller in the well-known MVC pattern; it is the entity that interacts with the caller (typically a human), via some kind of view to collect credentials, and with the model (business logic) to validate these credentials. An authentication mechanism knows about the environment this caller uses to communicate with the server. An authentication mechanism for HTTP knows about URLs to redirect or forward to, or about response headers to send to the client. It also knows about the data coming back, such as cookies, request headers, and post data. Examples of authentication mechanisms are Form authentication and Basic authentication. +An _authentication mechanism_ is somewhat like a controller in the well-known MVC pattern; it is the entity that interacts with the caller (typically a human), via some kind of view to collect credentials, and with the model (business logic) to validate `these` credentials. An authentication mechanism knows about the environment this caller uses to communicate with the server. An authentication mechanism for HTTP knows about URLs to redirect or forward to, or about response headers to send to the client. It also knows about the data coming back, such as cookies, request headers, and post data. Examples of authentication mechanisms are Form authentication and Basic authentication. An _identity store_ is more like the model in the MVC pattern. This entity strictly performs a business / data operation where credentials go in, and an identity comes out. The identity contains logic to validate said credentials, and embeds or contacts a database. This "database" contains usernames, along with their credentials and (typically) roles. An identity store therefore knows nothing about the environment that this caller uses to communicate with the server; e.g., it doesn't know about HTTP or headers etc. Example of identity stores are services that contact SQL/JDBC databases, LDAP servers, files on the file-system, etc. @@ -35,7 +35,6 @@ The third one is used for the authorization process: A _permission store_ is another kind of model that stores permissions, typically either globally, or per role (role-based permissions). This entity then performs a business / data operation where a query and an identity go in, and a yes/no answer goes out. For instance, a query such as "can access /foo/bar" along with the identity for user "John" with roles "bar" and "kaz". Examples of permission stores are the Jakarta Authorization usage of the Policy class, or the internal data structure where a Servlet Container such as Tomcat or Jetty stores the security constraints an application defined. - == Provided authentication mechanisms and identity stores Jakarta Security provides a number of built-in authentication mechanisms and identity stores. We'll enumerate them here first, and will look at them in more detail below. @@ -62,11 +61,11 @@ The Servlet specification defines the exact same Form and Basic authentication m A Servlet authentication mechanism, however, will not necessarily consult a Jakarta Security identity store. This is server dependent. The identity store that is called is server dependent as well. Calling this server-dependent identity store is possible from Jakarta Security, but as an advanced feature. -Likewise, programmatic role checks can be done from various APIs, including Jakarta Security, Jakarta REST and Jakarta Servlet. These all return the same outcome, independent of whether authentication took place with a Jakarta Security Authentication Mechanism or a Servlet Authentication Mechanism. +Likewise, programmatic role checks can be done from various APIs, including Jakarta Security, Jakarta REST, and Jakarta Servlet. These all return the same outcome, independent of whether authentication took place with a Jakarta Security Authentication Mechanism or a Servlet Authentication Mechanism. == Securing an endpoint with Basic authentication -In the following example we'll be securing a REST endpoint using Basic authentication. +In the following example, we'll be securing a REST endpoint using Basic authentication. You'll learn how to: @@ -99,13 +98,15 @@ public class Resource { } ---- -This resource uses the injected Jakarta EE `SecurityContext` to obtain access to the current authenticated caller, which is represented by a `Principal` instance. For simplicity, the code here doesn't check whether the caller principal is `null`. If the resource is also available to non-authenticated callers, this is something we have to do. The `getCallerPrincipal()` call would return `null` then. +This resource uses the injected Jakarta EE `SecurityContext` to obtain access to the current authenticated caller, which is represented by a `Principal` instance. + +If this resource were available to unauthenticated callers, `getCallerPrincipal()` would return `null` for unauthenticated requests, so we'd have to check for `null`. Our example, however, requires authentication for this resource, so we can skip that check. Also note that there is a Jakarta REST-specific type that is also named `SecurityContext` and has similar methods as the ones we used here. From the Jakarta EE perspective, that is a deprecated type and has been replaced by the Jakarta Security version. ==== Declare the security constraints -Next we'll define the security constraints in `web.xml`, which are used to tell the security system that access to a given URL or URL pattern is protected, and hence authentication is required: +Next we'll define the security constraints in `web.xml`, which tell the security system that access to a given URL or URL pattern is protected, and hence authentication is required: [source,xml] ---- @@ -132,7 +133,7 @@ This XML essentially says that to access any URL that starts with "/rest" requir Note that in Jakarta EE, internally these XML constraints are transformed into `Permission` instances and made available via a specific type of permission store. Knowledge about this transformation is only needed for very advanced use cases. -The observant reader may wonder if XML is really the only option here, given the strong feelings that exist in parts of the community around XML. The answer is yes and no. Jakarta EE does define the `@RolesAllowed` annotation that could be used to replace the XML shown above, but only the legacy Enterprise Beans has specified a behaviour for this when put on an Enterprise Bean. Jakarta REST has done no such thing, although the JWT API in MicroProfile has defined this for REST resources. In Jakarta EE however this remains a vendor specific extension. +The observant reader may wonder if XML is really the only option here, given the strong feelings that exist in parts of the community around XML. The answer is yes and no. Jakarta EE does define the `@RolesAllowed` annotation that could be used to replace the XML shown above, but only the legacy Enterprise Beans has specified a behaviour for this when put on an Enterprise Bean. Jakarta REST has done no such thing, although the JWT API in MicroProfile has defined this for REST resources. In Jakarta EE, however, this remains a vendor-specific extension. There are also a number of annotations and APIs in Jakarta EE to set these kinds of constraints for individual Servlets, but those won't help us much either here. @@ -155,7 +156,7 @@ The annotation can be put on any bean, but in a REST application it fits particu ==== Define the identity store -Finally, let's define a very simple identity store that the security system can use to validate provided credentials for a Basic authentication: +Finally, let's define a simple identity store that the security system can use to validate provided credentials for Basic authentication: [source,java] ---- @@ -173,27 +174,28 @@ public class TestIdentityStore implements IdentityStore { } ---- -This identity store only validates the single identity (user) "john", with password "secret1" and roles "user" and "caller". Defining this kind of identity store is often the simplest way to get started. Note that Jakarta Security doesn't define a simple identity store out of the box, because there are questions whether that would promote security best practices. +This identity store only validates the single identity (user) "john", with password "secret1" and roles "user" and "caller". Defining this kind of identity store is often the simplest way to get started. Note that Jakarta Security doesn't define a simple identity store out of the box, because there are questions about whether that would promote security best practices. Also note that the identity store is installed and used by the security system just by the virtue of being there; it picks up all enabled CDI beans that implement `IdentityStore`. Such beans can be enabled by the security system itself (following some configuration annotation), or can be programmatically added using the appropriate CDI APIs. Where the bean comes from doesn't matter for Jakarta Security, only the fact that it's there. - ==== Test the application It's now time to test our application. A ready-to-test version is available from the Jakarta EE Examples project at https://github.com/eclipse-ee4j/jakartaee-examples. Download or clone this repo, then cd into the `focused` folder and execute: -``` +[source] +---- mvn clean install -pl :restBasicAuthCustomStore -``` +---- This will run a test associated with the project, printing something like the following: -``` +[source] +---- john : true [INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 6.414 s - in jakartaee.examples.focused.security.restbasicauthcustomstore.RestBasicAuthCustomStoreIT -``` +---- Let's take a quick look at the actual test: @@ -230,23 +232,23 @@ public class RestBasicAuthCustomStoreIT extends ITBase { } ---- -Using Arquillian, the test starts the default server (GlassFish 7), and deploys the actual output of the build process (a .war file) to it. The test runs in the integration test phase (and not the unit test phase) to make sure this output is indeed available. The test then does a request to the remote GlassFish server using a provided html unit web client. Note that anything that can do an HTTP request could have been used here as well. +Using Arquillian, the test starts the default server (GlassFish 7), and deploys the output of the build process (a .war file) to it. The test runs in the integration test phase, rather than the unit test phase, to make sure this build output is available when it runs. The test then sends a request to the remote GlassFish server using the provided HtmlUnit `webClient`. Note that the `webClient` can be used for any other HTTP requests your test requires. The `DefaultCredentialsProvider` used here makes sure that the headers for Basic authentication are added to the request. The Basic authentication mechanism that we defined for our applications reads those headers, extracts the username and password from them, and consults our identity store with them. If you want to inspect the app yourself, you can manually deploy the WAR file (`security/restBasicAuthCustomStore/target/restBasicAuthCustomStore.war` )to the server of your choice (e.g. GlassFish 7), and request the URL via a browser or a commandline util such as `curl`. -== Securing an endpoint with Basic authentication and a Database identity store +== Securing an endpoint with Basic authentication and a database identity store -In the following example we'll be securing a REST endpoint using Basic authentication and the database identity store that is provided by Jakarta Security. +In the following example, we'll secure a REST endpoint using Basic authentication and the database identity store that is provided by Jakarta Security. You'll learn how to: -1. Define security constraints -2. Set a provided authentication mechanisms -3. Set a provided identity store that uses a database -4. Populate and configure that identity store -5. Use the Jakarta Security `SecurityContext` +. Define security constraints +. Use the provided Basic authentication mechanism +. Use the provided database identity store +. Populate and configure the identity store +. Use the Jakarta Security `SecurityContext` === Write the application @@ -281,20 +283,16 @@ Likewise, to declare the usage of a specific identity store, Jakarta EE provides The annotations can be put on any bean, but in a REST application it fits particularly well on the `Application` subclass that also declares the path for REST resources. -In the case of the `DatabaseIdentityStoreDefinition` we need to provide it with at least two queries: +You can use the provided `DatabaseIdentityStoreDefinition` with any authentication mechanism that validates username/password credentials. It requires at least two SQL queries: -1. The SQL query that returns a password for the username part of credentials entered by a caller. The returned password is compared with the password part of those credentials. If they match (of more typically, their hashes match) the credential is considered valid. -2. The query that returns a number of roles given that same username part of the credentials - -Although not required, it's a good practice to provide some parameters for the hash algorithm. Passwords should obviously never be stored in plain-text in a database. - -Note that the provided `DatabaseIdentityStoreDefinition` is suited for to be paired with any authentication mechanism that validates username/password credentials. +1. A query that returns a password for the username part of credentials. The returned password is compared with the password part of those credentials. If they match (of more typically, their hashes match) the credential is considered valid. +2. A query that returns a number of roles given that same username part of the credentials +Although not required, it's a good practice to provide some parameters for the hash algorithm. Passwords should never be stored in plain-text in a database. ==== Populating the identity store -In order to use the identity store we need to put some data in a database. The following code shows one way how to do that: - +In order to use the identity store, we need to put some data in a database. The following code shows one way how to do that: [source,java] ---- @@ -385,7 +383,7 @@ class Group { } ---- -The code above uses Jakarta Persistence, which generates SQL from java types. Jakarta Persistence is discussed in detail in its own chapter. For here it's important to note that the code takes advantage of the default datasource in Jakarta EE, so we don't have to explicitly install and configure an external database such as Postgres or MySQL. Without specifying a datasource, the `@DatabaseIdentityStoreDefinition` annotation defaults to using the default datasource, but if needed we can specify a different one using the `dataSourceLookup` attribute. +The code above uses Jakarta Persistence, which generates SQL from Java types. Jakarta Persistence is discussed in detail in its own chapter. Since we haven't specified a datasource, the `@DatabaseIdentityStoreDefinition` annotation will use the default datasource defined in Jakarta EE, so you don't have to explicitly install and configure an external database such as Postgres or MySQL. However, if necessary, you can configure a different one using the `dataSourceLookup` attribute. ==== Test the application @@ -393,32 +391,32 @@ It's now time to test our application. A ready to test version is available from Download or clone this repo, then cd into the `focused` folder and execute: -``` +[source] +---- mvn clean install -pl :restBasicAuthDBStore -``` +---- This will run a test associated with the project, printing something like the following: -``` +[source] +---- john : true [INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 8.307 s - in jakartaee.examples.focused.security.restbasicauthdbstore.RestBasicAuthDBStoreIT -``` +---- The test itself is basically the same as that for the <> example. - == Securing an endpoint with Basic authentication and multiple identity stores -In the following example we'll be securing a REST endpoint using Basic authentication and two identity stores: the database identity store that is provided by Jakarta Security and a custom identity store. +In the following example, we'll be securing a REST endpoint using Basic authentication and two identity stores: the database identity store that is provided by Jakarta Security and a custom identity store. -You'll learn the following things; +You'll learn how to: -1. How to define security constraints -2. How to set a provided authentication mechanisms -3. How to set a provided identity store that uses a database -4. How to populate and configure that identity store -5. How to set an additional identity store -6. How to use the Jakarta Security SecurityContext +. Define security constraints +. Use the provided Basic authentication mechanism +. Use the provided database identity store +. Create a custom identity store +. Use the Jakarta Security `SecurityContext` === Write the application @@ -463,16 +461,16 @@ public class CustomIdentityStore implements IdentityStore { } ---- -In this example we have two enabled CDI beans implementing the `IdentityStore` interface. One of them will be implicitly enabled via the `@DatabaseIdentityStoreDefinition` annotation, while the other one is defined explicitly via the `CustomIdentityStore`. As with a single identity store, it doesn't matter how or where the CDI beans are defined, only that multiple enabled ones exist. +In this example we have two enabled CDI beans implementing the `IdentityStore` interface. One of them will be implicitly enabled via the `@DatabaseIdentityStoreDefinition` annotation, while the other one is defined explicitly via the `CustomIdentityStore` class. As with a single identity store, it doesn't matter how or where the CDI beans are defined, only that multiple enabled ones exist. -When multiple identity stores are present, the security system will try them each in order of their priority. We didn't set a priority here, so the order will be undefined. The first store to validate wins, and will end the validation attempts. It's important to note that in the default validation algorithm a successful validation wins over a failed validation. This means we can have multiple identity stores that know about e.g. "pete". If "pete" fails validation in one store, but passes validation in another store, the end result is still that validation passed. +When multiple identity stores are present, the security system will try them in order of their priority. We didn't set a priority here, so the order will be undefined. If the default validation algorithm is used, a successful validation wins over a failed validation. For example, let's say we have multiple identity stores that know about the user "pete". If "pete" fails validation in one store, but passes validation in another store, the end result is still that validation passed. -In the two stores above however only one store knows about "pete" and that's the `CustomIdentityStore`. The store created from `@DatabaseIdentityStoreDefinition` doesn't know about "pete" at all, and will simply not validate it. +In the two stores above, however only one store knows about "pete" and that's the `CustomIdentityStore`. The store created from `@DatabaseIdentityStoreDefinition` doesn't know about "pete" at all, and will simply not validate it. ==== Populating the identity store -In order to use the identity store we need to put some data in a database. This is done in the same as in <>. +In order to use the identity store, we need to put some data in a database. This is done in the same as in <>. ==== Test the application @@ -480,17 +478,19 @@ It's now time to test our application. A ready to test version is available from Download or clone this repo, then cd into the `focused` folder and execute: -``` +[source] +---- mvn clean install -pl :restBasicAuthDBStoreAndCustomStore -``` +---- This will run a test associated with the project, printing something like the following: -``` +[source] +---- john : true pete : true [INFO] Tests run: 2, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 9.239 s - in jakartaee.examples.focused.security.restbasicauthdbstoreandcustomstore.RestBasicAuthDBStoreAndCustomStoreIT -``` +---- Let's take a quick look at the actual test again: @@ -549,19 +549,18 @@ public class RestBasicAuthDBStoreAndCustomStoreIT extends ITBase { } ---- -We do two tests here; in one test we try to authenticate as "john", in the other test as "pete". As we've seen, each identity store only validates one of them. The fact that both tests pass demonstrates that each store will validate the right user, and that not recognising a username by any of them will not fail the overall validation. +We have two tests here: in one test we try to authenticate as "john", in the other test as "pete". As we've seen, each identity store only validates one of them. The fact that both tests pass demonstrates that each store will validate the right user, and that not recognizing a username by any of them will not fail the overall validation. +== Securing an endpoint with Form authentication -== Securing an endpoint with Form Authentication +In the following example, we'll secure a REST endpoint using Form authentication. -In the following example we'll be securing a REST endpoint using Form Authentication. - -You'll learn the following things; +You'll learn how to: -1. How to define security constraints -2. How to set a provided authentication mechanisms -3. How to define (and implicitly set) a custom identity store -4. How to use the Jakarta Security SecurityContext +. Define security constraints +. Use the Form authentication mechanisms +. How to define (and implicitly set) a custom identity store +. Use the Jakarta Security `SecurityContext` === Write the application @@ -587,13 +586,15 @@ public class Resource { } ---- -This resource uses the injected Jakarta EE SecurityContext to obtain access to the current authenticated caller, which is represented by a `Principal` instance. For simplicity sake the code here doesn't check whether the caller principal is `null`. If the resource is also available to non-authenticated callers, this is something we have to do. The `getCallerPrincipal()` call would return `null` then. +This resource uses the injected Jakarta EE `SecurityContext` to obtain access to the current authenticated caller, which is represented by a `Principal` instance. + +If this resource were available to unauthenticated callers, `getCallerPrincipal()` would return `null` for unauthenticated requests, so we'd have to check for `null`. Our example, however, requires authentication for this resource, so we can skip that check. -Also note that there is a Jakarta REST specific type that is also named `SecurityContext` and has similar methods as the ones we used here. From the point of view of Jakarta EE that is a deprecated type and replaced by the Jakarta Security version. +Also note that there is a Jakarta REST-specific type that is also named `SecurityContext` and has similar methods as the ones we used here. From the point of view of Jakarta EE that is a deprecated type and replaced by the Jakarta Security version. ==== Declare the security constraints -Next we'll define the security constraints in `web.xml`, which are used to tell the security system that access to a given URL or URL pattern is protected, and hence authentication is required: +Next we'll define the security constraints in `web.xml`, which tell the security system that access to a given URL or URL pattern is protected, and hence authentication is required: [source,xml] ---- @@ -616,11 +617,11 @@ Next we'll define the security constraints in `web.xml`, which are used to tell ---- -This XML essentially says that to access any URL that starts with "/rest" requires the caller to have the role "user". Roles are opaque strings; merely identifiers. It's fully up to the application how broad or fine-grained they are. +This XML says that to access any URL that starts with "/rest" requires the caller to have the role "user". Roles are opaque strings; merely identifiers. It's fully up to the application how broad or fine-grained they are. Note that in Jakarta EE, internally these XML constraints are transformed into `Permission` instances and made available via a specific type of the Permission Store that we explained above. Knowledge about this transformation is only needed for very advanced use cases. -The observant reader may wonder if XML is really the only option here, given the strong feelings that exist in parts of the community around XML. The answer is yes and no. Jakarta EE does define the `@RolesAllowed` annotation that could be used to replace the XML shown above, but only the legacy Enterprise Beans has specified a behaviour for this when put on an Enterprise Bean. Jakarta REST has done no such thing, although the JWT API in MicroProfile has defined this for REST resources. In Jakarta EE, however, this remains a vendor-specific extension. +The observant reader may wonder if XML is really the only option here, given the strong feelings that exist in parts of the community around XML. The answer is yes and no. Jakarta EE does define the `@RolesAllowed` annotation that could be used to replace the XML shown above, but only the legacy Enterprise Beans has specified a behavior for this when put on an Enterprise Bean. Jakarta REST has done no such thing, although the JWT API in MicroProfile has defined this for REST resources. In Jakarta EE, however, this remains a vendor-specific extension. There are also a number of annotations and APIs in Jakarta EE to set these kinds of constraints for individual Servlets, but those won't help us much either here. @@ -646,13 +647,13 @@ To declare the usage of a specific authentication mechanism, Jakarta EE provides The annotation can be put on any bean, but in a REST application it fits particularly well on the `Application` subclass that also declares the path for REST resources. -Contrary to the Basic HTTP authentication mechanism, the Form authentication mechanism allows us to customise the login dialog and to keep track of the authenticated session on the server (using a cookie). This also allows us to logout, something that for unknown reasons has never been specified for Basic HTTP authentication. +Contrary to the Basic HTTP authentication mechanism, the Form authentication mechanism allows us to customize the login dialog and to keep track of the authenticated session on the server (using a cookie). This also allows us to logout, something that for unknown reasons has never been specified for Basic HTTP authentication. -In order to use this authentication mechanism we have to specify two paths to resources relative to our application; the one called to login (which the user is redirected to whenever a protected resource is accessed), and the one called when login fails (e.g. when the caller entered the credentials wrongly). Those two paths can be the same, and a request parameter can be used to distinguish between the two. Paths can point to anything our server can respond to; a static HTML file, a REST resource, or anything else. For simplicity we'll use two static HTML files here: +To use this authentication method, we need to designate two paths to resources that are relative to our application. One path is for the login page, which the user will be directed to when attempting to access a protected resource. The other path is for when login fails, such as when the user enters incorrect login credentials. If the paths are the same, a request parameter can be used to distinguish between them. Paths can point to anything our server can respond to; a static HTML file, a REST resource, or anything else. For simplicity, we'll use two static HTML files here: [source,html] ---- - + @@ -671,7 +672,7 @@ In order to use this authentication mechanism we have to specify two paths to re [source,html] ---- - + @@ -681,11 +682,9 @@ In order to use this authentication mechanism we have to specify two paths to re ---- - - ==== Define the identity store -Finally, let's define a very simple identity store that the security system can use to validate provided credentials for a Form authentication: +Finally, let's define a basic identity store that the security system can use to validate provided credentials for Form authentication: [source,java] ----- @@ -703,10 +702,9 @@ public class CustomIdentityStore implements IdentityStore { } ----- -This identity store only "contains" the single identity (user) "john", with password "secret1" and roles "user" and "caller". Defining this kind of identity store is often the simplest way to get started. Note that Jakarta Security doesn't define a simple identity store out of the box, because there are questions whether that would promote security best practices. - -Also note that the identity store is installed and used by the security system just by the virtue of being there; it picks up all enabled CDI beans that implement `IdentityStore`. Such beans can be enabled by the security system itself (following some configuration annotation), or can be programmatically added using the appropriate CDI APIs. Where the bean comes from doesn't matter for Jakarta Security, only the fact that it's there. +This identity store only validates the single identity (user) "john", with password "secret1" and roles "user" and "caller". Defining this kind of identity store is often the simplest way to get started. Note that Jakarta Security doesn't define a simple identity store out of the box, because there are questions about whether that would promote security best practices. +Also note that the identity store is installed and used by the security system just by the virtue of being there; it picks up all enabled CDI beans that implement `IdentityStore`. Such beans can be enabled by the security system itself via a configuration annotation, or programmatically added using the appropriate CDI APIs. Where the bean comes from doesn't matter for Jakarta Security, only the fact that it's there. ==== Test the application @@ -714,16 +712,18 @@ It's now time to test our application. A ready to test version is available from Download or clone this repo, then cd into the `focused` folder and execute: -``` +[source] +---- mvn clean install -pl :restBasicAuthCustomStore -``` +---- This will run a test associated with the project, printing something like the following: -``` +[source] +---- john : true [INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 5.24 s - in jakartaee.examples.focused.security.restformauthcustomstore.RestFormAuthCustomStoreIT -``` +---- Let's take a quick look at the actual test: @@ -764,8 +764,8 @@ public class RestFormAuthCustomStoreIT extends ITBase { } ---- -Using Arquillian, the test starts the default server (GlassFish 7), and deploys the actual output of the build process (a .war file) to it. The test runs in the integration test phase (and not the unit test phase) to make sure this output is indeed available. The test then does a request to the remote GlassFish server using a provided html unit web client. Note that anything that can do an HTTP request could have been used here as well. +Using Arquillian, the test starts the default server (GlassFish 7), and deploys the output of the build process (a .war file) to it. The test runs in the integration test phase, rather than the unit test phase, to make sure this build output is available when it runs. The test then sends a request to the remote GlassFish server using the provided HtmlUnit `webClient`. Note that the `webClient` can be used for any other HTTP requests your test requires. -The test first does a request here to the protected resource, and as a response the server returns the HTML form we defined above. Using the HTMLUnit API it's easy to navigate the HTML DOM, fill out the username and password in the form, and programmatically click the Submit button. The authentication mechanism is then able to detect this special postback (it's listening to the special virtual URL the postback is to), and like the basic authentication mechanism got the username and password from the headers, the form authentication mechanism gets them from the POST data. +The test first sends a request here to the protected resource, and the server responds with the HTML form we defined above. Using the `HtmlUnit` API, it's easy to navigate the HTML DOM, fill out the username and password in the form, and programmatically click the Submit button. The form posts back to a special "j_security_check" URL, where the authentication mechanism receives the request and retrieves the username and password from the POST data, much like the Basic authentication mechanism retrieves them from the HTTP headers. From 2ec5207cfe286300d857b2b15f308d16866f9d2e Mon Sep 17 00:00:00 2001 From: "Kito D. Mann" Date: Mon, 29 May 2023 13:47:36 -0400 Subject: [PATCH 024/247] JETUT-19 Changed numbered lists to asciidoc format --- .../asciidoc/security-refresh/security.adoc | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/main/asciidoc/security-refresh/security.adoc b/src/main/asciidoc/security-refresh/security.adoc index 8f452895..2c65905a 100644 --- a/src/main/asciidoc/security-refresh/security.adoc +++ b/src/main/asciidoc/security-refresh/security.adoc @@ -10,16 +10,16 @@ Before we look at some practical examples, let's quickly go through some basics. Some of the guiding principles in Jakarta Security are: -1. It should work directly out of the box, without requiring vendor-specific configuration. -2. It leverages Jakarta CDI as much as possible. Most artifacts are CDI beans, and many features are done via CDI interceptors. -3. The difference between framework-provided artifacts and custom (user provided) artifacts is minimal or non-existent. -4. It fully integrates with security features from other Jakarta EE APIs and proprietary (vendor-specific) artifacts. +. It should work directly out of the box, without requiring vendor-specific configuration. +. It leverages Jakarta CDI as much as possible. Most artifacts are CDI beans, and many features are done via CDI interceptors. +. The difference between framework-provided artifacts and custom (user provided) artifacts is minimal or non-existent. +. It fully integrates with security features from other Jakarta EE APIs and proprietary (vendor-specific) artifacts. Jakarta Security defines several distinct artifacts that play an important role in the security process: -1. Authentication Mechanism -2. Identity Store -3. Permission Store +. Authentication Mechanism +. Identity Store +. Permission Store The first two of these are used in the authentication process: @@ -285,8 +285,8 @@ The annotations can be put on any bean, but in a REST application it fits partic You can use the provided `DatabaseIdentityStoreDefinition` with any authentication mechanism that validates username/password credentials. It requires at least two SQL queries: -1. A query that returns a password for the username part of credentials. The returned password is compared with the password part of those credentials. If they match (of more typically, their hashes match) the credential is considered valid. -2. A query that returns a number of roles given that same username part of the credentials +. A query that returns a password for the username part of credentials. The returned password is compared with the password part of those credentials. If they match (of more typically, their hashes match) the credential is considered valid. +. A query that returns a number of roles given that same username part of the credentials Although not required, it's a good practice to provide some parameters for the hash algorithm. Passwords should never be stored in plain-text in a database. From 979a64afdc5a05110d54e9f9368b9f5205774104 Mon Sep 17 00:00:00 2001 From: "Kito D. Mann" Date: Mon, 29 May 2023 22:01:57 -0400 Subject: [PATCH 025/247] JETUT-56 Updated script and docs for processing Jakarta EE 9 versions of docs. --- antora-conversion/AntoraConverter.java | 129 +++++++++++++++++--- antora-conversion/CONVERTING_TO_ANTORA.adoc | 45 +++++-- 2 files changed, 145 insertions(+), 29 deletions(-) diff --git a/antora-conversion/AntoraConverter.java b/antora-conversion/AntoraConverter.java index 4c1bebce..ec6e2ec5 100755 --- a/antora-conversion/AntoraConverter.java +++ b/antora-conversion/AntoraConverter.java @@ -5,6 +5,7 @@ import java.io.IOException; import java.nio.file.Files; import java.nio.file.Paths; +import java.text.MessageFormat; import java.util.ArrayList; import java.util.HashMap; import java.util.Map; @@ -13,10 +14,11 @@ class AntoraConverter { - record PageLocation(String path, String page) { + record PageLocation(String path, String page, String linkText) { public String getParentPage() { return path + ".adoc"; } + public String toString() { return path + "/" + getParentPage(); } @@ -26,14 +28,14 @@ public String toString() { public static String replaceBetween(String str, String start, String end, String prefix, String fromString, String toString, BiFunction contentUpdater) { - StringBuilder result = new StringBuilder(); + final var result = new StringBuilder(); int index = 0; int startIndex, endIndex; while ((startIndex = str.indexOf(start, index)) != -1 && (endIndex = str.indexOf(end, startIndex + start.length())) != -1) { result.append(str, index, startIndex + start.length()); - String substring = str.substring(startIndex + start.length(), endIndex); - String updatedSubstring = substring.replace(fromString, toString); + var substring = str.substring(startIndex + start.length(), endIndex); + var updatedSubstring = substring.replace(fromString, toString); // don't add the prefix if nothing has changed if (!substring.equals(updatedSubstring)) { @@ -54,14 +56,57 @@ public static String replaceBetween(String str, String start, String end, String return result.toString(); } - public static void processInbetween(String str, String start, String end, Consumer updatedContentConsumer) { + public static String replaceInlineReferences(File file, String fileContent) { + StringBuilder result = new StringBuilder(); + int index = 0; + int startIndex, endIndex; + final String start = "<<"; + final String end = ">>"; + + while ((startIndex = fileContent.indexOf(start, index)) != -1 && (endIndex = fileContent.indexOf(end, startIndex + start.length())) != -1) { + result.append(fileContent, index, startIndex); + final var rawReference = fileContent.substring(startIndex, endIndex + end.length()); + var referenceBody = rawReference.substring(start.length(), rawReference.length() - end.length()); + var updatedReferenceBody = createAnchor(referenceBody); + String updatedReference; + + var pageLocation = anchorMap.get("#" + updatedReferenceBody) ; + pageLocation = pageLocation != null ? pageLocation : anchorMap.get("#" + referenceBody); + if (pageLocation == null) { + System.out.printf(" => WARNING: No page location found for anchor \"%s\" or \"%s\"; the file with the anchor may not have been within the startPath%n", + updatedReferenceBody, referenceBody); + updatedReference = rawReference; + } else { + if (isInlineReference(file, referenceBody, pageLocation)) { + updatedReference = start + updatedReferenceBody + end; + } else { + + updatedReference = String.format("xref:%s/%s#%s[%s]", pageLocation.getParentPage(), + pageLocation.getParentPage(), updatedReferenceBody, pageLocation.linkText()); + } + } + System.out.printf(" => Replacing inline reference \"%s\" with \"%s\"%n", rawReference, updatedReference); + result.append(updatedReference); + index = endIndex + end.length(); + } + result.append(fileContent, index, fileContent.length()); + return result.toString(); + } + + public static void processInbetween(String str, Integer iterations, String start, String end, Consumer updatedContentConsumer) { int index = 0; + int count = 0; int startIndex, endIndex; while ((startIndex = str.indexOf(start, index)) != -1 && (endIndex = str.indexOf(end, startIndex + start.length())) != -1) { String substring = str.substring(startIndex + start.length(), endIndex); updatedContentConsumer.accept(substring); index = endIndex; + if (iterations == null || count < iterations) { + count++; + } else { + break; + } } } @@ -69,7 +114,7 @@ public static void main(String... args) throws Exception { System.out.println("\uD83E\uDD16 Antora Converter: Convert raw Asciidoc files to Antora-compatible format"); System.out.println("Walks through all folders and subfolders from the specified startPath and converts all .adoc files"); - var files = new ArrayList(); + final var files = new ArrayList(); if (args.length == 0) { System.out.println("Usage: AntoraConverter.java [startPath] dryRun?"); System.out.println(" Where [startPath] is the root folder to search (usually a specific Antora module or component folder)"); @@ -97,16 +142,45 @@ private static void preProcess(ArrayList files) throws IOException { System.out.println("\uD83D\uDD0E Pre-scanning file " + file.getAbsolutePath()); String content = new String(Files.readAllBytes(file.toPath())); System.out.println("=> Processing anchor names"); - processInbetween(content, "[[", "]]", (anchor) -> { - // NOTE: This currently will only work for files within the same module. This will need - // to be updated for files in different modules. - final var pageLocation = new PageLocation(file.getParentFile().getName(), file.getName()); - anchorMap.put("#" + anchor, pageLocation); - System.out.printf(" => Stored anchor \"%s\" for %s%n", anchor, pageLocation); - }); + + processSectionHeadings(file, content); + processAnchors(file, content); + } + } + + private static void processSectionHeadings(File file, String content) { + // Start with the first heading (level 1 and 2) + processInbetween(content, 1, "= ", System.lineSeparator(), processSectionAnchor(file)); + processInbetween(content, 1, "== ", System.lineSeparator(), processSectionAnchor(file)); + // Then process all lower section headings + for (int i = 3; i < 7; i++) { + final var prefix = System.lineSeparator() + "=".repeat(i) + " "; + processInbetween(content, null, prefix, System.lineSeparator(), processSectionAnchor(file)); } } + private static void processAnchors(File file, String content) { + processInbetween(content, null, "[[", "]]", (anchor) -> { + final var pageLocation = new PageLocation(file.getParentFile().getName(), file.getName(), null); + anchorMap.put("#" + anchor, pageLocation); + System.out.printf(" => Stored anchor \"%s\" for %s%n", anchor, pageLocation); + }); + } + + private static Consumer processSectionAnchor(File file) { + return (heading) -> { + final String anchor = createAnchor(heading); + final var pageLocation = new PageLocation(file.getParentFile().getName(), file.getName(), heading); + anchorMap.put("#" + anchor, pageLocation); + System.out.printf(" => Stored anchor \"%s\" for section \"%s\" for %s%n", anchor, heading, pageLocation); + }; + } + + private static String createAnchor(String str) { + final var strWithPrefix = str.charAt(0) == '_' ? str : "_" + str; + return strWithPrefix.toLowerCase().replaceAll("[\\s-]", "_").replace(":", "").replaceAll("[?,&()]", ""); + } + private static void process(ArrayList files, boolean dryRun) throws IOException { System.out.println("\uD83E\uDD16 Updating files"); for (File file : files) { @@ -115,8 +189,9 @@ private static void process(ArrayList files, boolean dryRun) throws IOExce int changeCount = 0; if (content.contains(("<<"))) { - System.out.println("=> Updating in-page anchor references"); - content = replaceBetween(content, "<<", ">>", "_", "-", "_", null); + System.out.println("=> Updating in-page anchor links"); +// content = replaceBetween(content, "<<", ">>", "_", "-", "_", null); + content = replaceInlineReferences(file, content); if (!dryRun) { Files.write(file.toPath(), content.getBytes()); } @@ -143,9 +218,7 @@ private static void process(ArrayList files, boolean dryRun) throws IOExce return newLink; } - // If this page name contains the parent's page name, it's either the parent page itself or an included page, - // so it's an internal reference. - if (file.getName().contains(pageLocation.getParentPage())) { + if (isInlineReference(file, newLink, pageLocation)) { return newLink; } final var updatedLink = pageLocation + newLink; @@ -165,9 +238,17 @@ private static void process(ArrayList files, boolean dryRun) throws IOExce } changeCount++; } - if (content.contains("image:") && !content.contains("image:common:")) { + if (content.contains("xrefstyle=full")) { + System.out.println("=> Removing xrefstyle=full (it is now a global attribute)"); + content = content.replace("xrefstyle=full", ""); + if (!dryRun) { + Files.write(file.toPath(), content.getBytes()); + } + changeCount++; + } + if (content.contains("image::") && !content.contains("image::common:")) { System.out.println("=> Converting inline image references to block image references and adding module prefix"); - content = content.replace("image:", "image::common:"); + content = content.replace("image::", "image::common:"); if (!dryRun) { Files.write(file.toPath(), content.getBytes()); } @@ -188,4 +269,12 @@ private static void process(ArrayList files, boolean dryRun) throws IOExce } } } + + /** + * If this page name contains the parent's page name, it's either the parent page itself or an included page, + * so it's an internal reference. + **/ + private static boolean isInlineReference(File file, String newLink, PageLocation pageLocation) { + return file.getName().contains(pageLocation.getParentPage().split(".adoc")[0]); + } } diff --git a/antora-conversion/CONVERTING_TO_ANTORA.adoc b/antora-conversion/CONVERTING_TO_ANTORA.adoc index bf888e5b..2003f296 100644 --- a/antora-conversion/CONVERTING_TO_ANTORA.adoc +++ b/antora-conversion/CONVERTING_TO_ANTORA.adoc @@ -10,19 +10,31 @@ The conversion script is written in Java and requires https://jbang.io[JBang] to > TIP: Commit your changes after each step; that way you can easily rollback any mistakes. -Here’s the current process for migrating an individual module (i.e. security, bean validation, etc): +Here’s the current process for migrating an individual module (i.e. security, bean validation, etc). -1. Check out the release/8 branch and create a new branch from it for your work. -2. Select the module to migrate. We consider each Part of the current https://eclipse-ee4j.github.io/jakartaee-tutorial/[Jakata EE Tutorial] to be a module (for example, Introduction, Web Tier, Bean Validation, etc). -3. Create a new folder in the `src/main/antora/modules` folder with the name of the module you are migrating. For example, for the Security module, you would create a `security` folder. +=== Migrating the Jakarta EE 8 branch + +. Check out the release/8 branch and create a new branch from it for your work. + +. Select the module to migrate. We consider each Part of the current https://eclipse-ee4j.github.io/jakartaee-tutorial/[Jakata EE Tutorial] to be a module (for example, Introduction, Web Tier, Bean Validation, etc). + +. Create a new folder in the `src/main/antora/modules` folder with the name of the module you are migrating. For example, for the Security module, you would create a `security` folder. * Inside of this folder, create a `pages` folder. -4. Move all the folders for the module you are migrating into the new `pages` folder. For example, for the Security module, you would move all of the `src/main/asciidoc/security-*` folders into the `src/main/antora/modules/security/pages`. (Copy the entire folders, not just the `.adoc` files). + +. Move all the folders for the module you are migrating into the new `pages` folder. For example, for the Security module, you would move all of the `src/main/asciidoc/security-*` folders into the `src/main/antora/modules/security/pages`. (Copy the entire folders, not just the `.adoc` files). > NOTE: It's essential that you _move_ rather than copy the folders so that we keep the history intact. -5. Run the migration script from the root project folder. For example, for the Security module, you would run `jbang antora-conversion/AntoraConverter.java security`. (The first parameter is the folder relative to `src/main/antora/modules`). -6. Create a new file called `nav.adoc` in the root of the module folder. For example, for the Security module, you would create a `security/nav.adoc`. -7. Copy all the include statements from the corresponding "part" file in the `src/main/asciidoc/` folder. For example, for the Security module, you would copy the include statements of `src/main/asciidoc/partsecurity.adoc` into the `security/nav.adoc` file. Here are the include statements for the Security module: +. Run the migration script from the root project folder. For example, for the Security module, you would run: + +```shell +jbang antora-conversion/AntoraConverter.java jakartaee-tutorial/src/main/antora/modules/security +``` + +> TIP: You can use the "dryrun" parameter to see what changes will be made without actually making them. +. Create a new file called `nav.adoc` in the root of the module folder. For example, for the Security module, you would create a `security/nav.adoc`. + +. Copy all the include statements from the corresponding "part" file in the `src/main/asciidoc/` folder. For example, for the Security module, you would copy the include statements of `src/main/asciidoc/partsecurity.adoc` into the `security/nav.adoc` file. Here are the include statements for the Security module: ```asciidoc include::security-intro/security-intro.adoc[] @@ -51,9 +63,24 @@ After copying these into `nav.adoc`, replace "include::" with "* xref:" and add * xref:security-advanced/security-advanced.adoc[] ``` -8. Add this module to the `src/main/antora/antora.yml`. For example, for the Security module, you would add this line to the end of `src/main/antora/antora.yml` file: +. Add this module to the `src/main/antora/antora.yml`. For example, for the Security module, you would add this line to the end of `src/main/antora/antora.yml` file: ```yaml - modules/security/nav.adoc ``` +. Commit your changes, push, and raise a PR. You're done with the first part of the migration! + +=== Migrating the Jakarta EE 9 branch + +. Create a new branch from the migrated version of the `release/8` branch you just created. + +. Merge `release/9` into your new branch. Accept all changes from the `release/9` branch. + +. Run the migration script from the root project folder. For example, for the Security module, you would run: + +```shell +jbang antora-conversion/AntoraConverter.java jakartaee-tutorial/src/main/antora/modules/security +``` + +> TIP: You can use the "dryrun" parameter to see what changes will be made without actually making them. From 84adc76c50cc7a7ffea7cd1a6f643abc0072bb7a Mon Sep 17 00:00:00 2001 From: "Kito D. Mann" Date: Tue, 30 May 2023 14:06:06 -0400 Subject: [PATCH 026/247] JETUT-56 Added support for existing xrefs; other fixes --- antora-conversion/AntoraConverter.java | 58 ++++++++++++++------------ 1 file changed, 32 insertions(+), 26 deletions(-) diff --git a/antora-conversion/AntoraConverter.java b/antora-conversion/AntoraConverter.java index ec6e2ec5..09321267 100755 --- a/antora-conversion/AntoraConverter.java +++ b/antora-conversion/AntoraConverter.java @@ -5,7 +5,6 @@ import java.io.IOException; import java.nio.file.Files; import java.nio.file.Paths; -import java.text.MessageFormat; import java.util.ArrayList; import java.util.HashMap; import java.util.Map; @@ -56,12 +55,10 @@ public static String replaceBetween(String str, String start, String end, String return result.toString(); } - public static String replaceInlineReferences(File file, String fileContent) { + public static String replaceReferences(File file, String fileContent, String start, String end) { StringBuilder result = new StringBuilder(); int index = 0; int startIndex, endIndex; - final String start = "<<"; - final String end = ">>"; while ((startIndex = fileContent.indexOf(start, index)) != -1 && (endIndex = fileContent.indexOf(end, startIndex + start.length())) != -1) { result.append(fileContent, index, startIndex); @@ -81,11 +78,11 @@ public static String replaceInlineReferences(File file, String fileContent) { updatedReference = start + updatedReferenceBody + end; } else { - updatedReference = String.format("xref:%s/%s#%s[%s]", pageLocation.getParentPage(), + updatedReference = String.format("xref:%s/%s#%s[%s]", pageLocation.path, pageLocation.getParentPage(), updatedReferenceBody, pageLocation.linkText()); } } - System.out.printf(" => Replacing inline reference \"%s\" with \"%s\"%n", rawReference, updatedReference); + System.out.printf(" => Replacing reference \"%s\" with \"%s\"%n", rawReference, updatedReference); result.append(updatedReference); index = endIndex + end.length(); } @@ -93,7 +90,7 @@ public static String replaceInlineReferences(File file, String fileContent) { return result.toString(); } - public static void processInbetween(String str, Integer iterations, String start, String end, Consumer updatedContentConsumer) { + public static void processBetween(String str, Integer iterations, String start, String end, Consumer updatedContentConsumer) { int index = 0; int count = 0; int startIndex, endIndex; @@ -150,17 +147,17 @@ private static void preProcess(ArrayList files) throws IOException { private static void processSectionHeadings(File file, String content) { // Start with the first heading (level 1 and 2) - processInbetween(content, 1, "= ", System.lineSeparator(), processSectionAnchor(file)); - processInbetween(content, 1, "== ", System.lineSeparator(), processSectionAnchor(file)); + processBetween(content, 1, "= ", System.lineSeparator(), processSectionAnchor(file)); + processBetween(content, 1, "== ", System.lineSeparator(), processSectionAnchor(file)); // Then process all lower section headings for (int i = 3; i < 7; i++) { final var prefix = System.lineSeparator() + "=".repeat(i) + " "; - processInbetween(content, null, prefix, System.lineSeparator(), processSectionAnchor(file)); + processBetween(content, null, prefix, System.lineSeparator(), processSectionAnchor(file)); } } private static void processAnchors(File file, String content) { - processInbetween(content, null, "[[", "]]", (anchor) -> { + processBetween(content, null, "[[", "]]", (anchor) -> { final var pageLocation = new PageLocation(file.getParentFile().getName(), file.getName(), null); anchorMap.put("#" + anchor, pageLocation); System.out.printf(" => Stored anchor \"%s\" for %s%n", anchor, pageLocation); @@ -184,14 +181,32 @@ private static String createAnchor(String str) { private static void process(ArrayList files, boolean dryRun) throws IOException { System.out.println("\uD83E\uDD16 Updating files"); for (File file : files) { + if (file.getName().equals("nav.adoc")) { + continue; + } System.out.println("\uD83D\uDD0E Evaluating file " + file.getAbsolutePath()); var content = new String(Files.readAllBytes(file.toPath())); int changeCount = 0; + if (content.contains("xrefstyle=full")) { + System.out.println("=> Removing xrefstyle=full (it is now a global attribute)"); + content = content.replace("xrefstyle=full", ""); + if (!dryRun) { + Files.write(file.toPath(), content.getBytes()); + } + changeCount++; + } + if (content.contains(("xref:"))) { + System.out.println("=> Updating xrefs to reference other files if necessary"); + content = replaceReferences(file, content, "xref:", "[]"); + if (!dryRun) { + Files.write(file.toPath(), content.getBytes()); + } + changeCount++; + } if (content.contains(("<<"))) { - System.out.println("=> Updating in-page anchor links"); -// content = replaceBetween(content, "<<", ">>", "_", "-", "_", null); - content = replaceInlineReferences(file, content); + System.out.println("=> Updating in-page references"); + content = replaceReferences(file, content, "<<", ">>"); if (!dryRun) { Files.write(file.toPath(), content.getBytes()); } @@ -206,7 +221,7 @@ private static void process(ArrayList files, boolean dryRun) throws IOExce changeCount++; } if (content.contains(("link:#"))) { - System.out.println("=> Updating external anchor references"); + System.out.println("=> Changing links with anchors to xrefs"); content = replaceBetween(content, "link:", "[", "_", "-", "_", (originalLink, newLink) -> { var pageLocation = anchorMap.get(originalLink); if (pageLocation == null) { @@ -217,7 +232,6 @@ private static void process(ArrayList files, boolean dryRun) throws IOExce originalLink, newLink); return newLink; } - if (isInlineReference(file, newLink, pageLocation)) { return newLink; } @@ -231,21 +245,13 @@ private static void process(ArrayList files, boolean dryRun) throws IOExce changeCount++; } if (content.contains("link:")) { - System.out.println("=> Converting links to xrefs"); + System.out.println("=> Converting links without anchors to xrefs"); content = content.replace("link:", "xref:"); if (!dryRun) { Files.write(file.toPath(), content.getBytes()); } changeCount++; } - if (content.contains("xrefstyle=full")) { - System.out.println("=> Removing xrefstyle=full (it is now a global attribute)"); - content = content.replace("xrefstyle=full", ""); - if (!dryRun) { - Files.write(file.toPath(), content.getBytes()); - } - changeCount++; - } if (content.contains("image::") && !content.contains("image::common:")) { System.out.println("=> Converting inline image references to block image references and adding module prefix"); content = content.replace("image::", "image::common:"); @@ -275,6 +281,6 @@ private static void process(ArrayList files, boolean dryRun) throws IOExce * so it's an internal reference. **/ private static boolean isInlineReference(File file, String newLink, PageLocation pageLocation) { - return file.getName().contains(pageLocation.getParentPage().split(".adoc")[0]); + return file.getName().contains(pageLocation.path); } } From 59ba951691776ea9139afafeebc26b2bb3cc9c4c Mon Sep 17 00:00:00 2001 From: "Kito D. Mann" Date: Tue, 30 May 2023 14:06:29 -0400 Subject: [PATCH 027/247] JETUT-56 Initial upgrade of chapters using AntoraConverter --- .../security-advanced001.adoc | 8 ++-- .../security-advanced002.adoc | 20 ++++---- .../security-advanced003.adoc | 2 +- .../security-advanced005.adoc | 8 ++-- .../security-advanced006.adoc | 4 +- .../pages/security-api/security-api001.adoc | 16 +++---- .../pages/security-api/security-api003.adoc | 10 ++-- .../pages/security-api/security-api004.adoc | 18 ++++---- .../pages/security-api/security-api005.adoc | 14 +++--- .../security-intro/security-intro001.adoc | 46 +++++++++---------- .../security-intro/security-intro002.adoc | 6 +-- .../security-intro/security-intro003.adoc | 10 ++-- .../security-intro/security-intro003a.adoc | 2 +- .../security-intro/security-intro004.adoc | 2 +- .../security-intro/security-intro005.adoc | 32 ++++++------- .../security-intro/security-intro005a.adoc | 2 +- .../security-intro/security-intro006.adoc | 2 +- .../security-jakartaee002.adoc | 16 +++---- .../security-jakartaee003.adoc | 24 +++++----- .../security-webtier/security-webtier.adoc | 2 +- .../security-webtier/security-webtier001.adoc | 18 ++++---- .../security-webtier/security-webtier002.adoc | 36 +++++++-------- .../security-webtier/security-webtier003.adoc | 2 +- .../security-webtier/security-webtier004.adoc | 36 +++++++-------- 24 files changed, 168 insertions(+), 168 deletions(-) diff --git a/src/main/antora/modules/security/pages/security-advanced/security-advanced001.adoc b/src/main/antora/modules/security/pages/security-advanced/security-advanced001.adoc index 388cf282..708d9449 100644 --- a/src/main/antora/modules/security/pages/security-advanced/security-advanced001.adoc +++ b/src/main/antora/modules/security/pages/security-advanced/security-advanced001.adoc @@ -29,13 +29,13 @@ If the two values match, the client can trust that the signature is authentic, b Digital certificates are used with HTTPS to authenticate web clients. The HTTPS service of most web servers will not run unless a digital certificate has been installed. -Use the procedure outlined in the next section, <>, to set up a digital certificate that can be used by your application or web server to enable SSL. +Use the procedure outlined in the next section, <<_creating_a_server_certificate>>, to set up a digital certificate that can be used by your application or web server to enable SSL. One tool that can be used to set up a digital certificate is `keytool`, a key and certificate management utility that ships with the JDK. This tool enables users to administer their own public/private key pairs and associated certificates for use in self-authentication, whereby the user authenticates himself or herself to other users or services, or data integrity and authentication services, using digital signatures. The tool also allows users to cache the public keys, in the form of certificates, of their communicating peers. -For a better understanding of `keytool` and public-key cryptography, see <> for a link to the `keytool` documentation. +For a better understanding of `keytool` and public-key cryptography, see <<_further_information_about_advanced_security_topics>> for a link to the `keytool` documentation. === Creating a Server Certificate @@ -142,11 +142,11 @@ Certificate was added to keystore === Adding Users to the Certificate Realm In the `certificate` realm, user identity is set up in the GlassFish Server security context and populated with user data obtained from cryptographically verified client certificates. -For step-by-step instructions for creating this type of certificate, see <>. +For step-by-step instructions for creating this type of certificate, see <<_working_with_digital_certificates>>. === Using a Different Server Certificate with GlassFish Server -Follow the steps in <> to create your own server certificate, have it signed by a CA, and import the certificate into `keystore.jks`. +Follow the steps in <<_creating_a_server_certificate>> to create your own server certificate, have it signed by a CA, and import the certificate into `keystore.jks`. Make sure that when you create the certificate, you follow these rules. diff --git a/src/main/antora/modules/security/pages/security-advanced/security-advanced002.adoc b/src/main/antora/modules/security/pages/security-advanced/security-advanced002.adoc index 1fd7c843..bb2ac6f1 100644 --- a/src/main/antora/modules/security/pages/security-advanced/security-advanced002.adoc +++ b/src/main/antora/modules/security/pages/security-advanced/security-advanced002.adoc @@ -12,7 +12,7 @@ You can think of a public key certificate as the digital equivalent of a passpor The certificate is issued by a trusted organization, a certificate authority (CA), and provides identification for the bearer. Before using client authentication, make sure that the client has a valid public key certificate. -For more information on creating and using public key certificates, read <>. +For more information on creating and using public key certificates, read <<_working_with_digital_certificates>>. The following example shows how to declare client authentication in your deployment descriptor: @@ -25,16 +25,16 @@ The following example shows how to declare client authentication in your deploym Jakarta Security provides an alternative means to configure client authentication using the `HttpAuthenticationMechanism` interface. This interface defines an SPI for writing authentication mechanisms that can be provided with an application and deployed using CDI. -See <>. +See xref:security-api/security-api.adoc#_overview_of_the_http_authentication_mechanism_interface[Overview of the HTTP Authentication Mechanism Interface]. === Mutual Authentication With mutual authentication, the server and the client authenticate each other. Mutual authentication is of two types: -* Certificate-based (see <>) +* Certificate-based (see <<_certificate_based_mutual_authentication>>) -* User name/password-based (see <>) +* User name/password-based (see <<_username_password_based_mutual_authentication>>) When using certificate-based mutual authentication, the following actions occur. @@ -50,11 +50,11 @@ When using certificate-based mutual authentication, the following actions occur. . If successful, the server grants access to the protected resource requested by the client. -<> shows what occurs during certificate-based mutual authentication. +<<_certificate_based_mutual_authentication>> shows what occurs during certificate-based mutual authentication. -[[certificate-based-mutual-authentication]] +[[_certificate_based_mutual_authentication]] .Certificate-Based Mutual Authentication -image::jakartaeett_dt_048.svg["Diagram of six steps in mutual authentication with certificates"] +image::common:jakartaeett_dt_048.svg["Diagram of six steps in mutual authentication with certificates"] In user name/password-based mutual authentication, the following actions occur. @@ -70,11 +70,11 @@ In user name/password-based mutual authentication, the following actions occur. . If the verification is successful, the server grants access to the protected resource requested by the client. -<> shows what occurs during user name/password-based mutual authentication. +<<_username_password_based_mutual_authentication>> shows what occurs during user name/password-based mutual authentication. -[[username-password-based-mutual-authentication]] +[[_username_password_based_mutual_authentication]] .User Name/Password-Based Mutual Authentication -image::jakartaeett_dt_049.svg["Diagram of five steps in mutual authentication with user name and password"] +image::common:jakartaeett_dt_049.svg["Diagram of five steps in mutual authentication with user name and password"] ==== Enabling Mutual Authentication over SSL diff --git a/src/main/antora/modules/security/pages/security-advanced/security-advanced003.adoc b/src/main/antora/modules/security/pages/security-advanced/security-advanced003.adoc index ec447765..11ac6bf4 100644 --- a/src/main/antora/modules/security/pages/security-advanced/security-advanced003.adoc +++ b/src/main/antora/modules/security/pages/security-advanced/security-advanced003.adoc @@ -16,7 +16,7 @@ A realm can be thought of as a database of user names and passwords that identif Access to specific web application resources is granted to all users in a particular role, instead of enumerating a list of associated users. A user name can have any number of roles associated with it. -Two of the tutorial case studies, xref:dukes-tutoring-case-study-example[xrefstyle=full] and xref:dukes-forest-case-study-example[xrefstyle=full] use a JDBC realm for user authentication. +Two of the tutorial case studies, xref:dukes-tutoring-case-study-example[] and xref:dukes-forest-case-study-example[] use a JDBC realm for user authentication. === To Configure a JDBC Authentication Realm diff --git a/src/main/antora/modules/security/pages/security-advanced/security-advanced005.adoc b/src/main/antora/modules/security/pages/security-advanced/security-advanced005.adoc index 1ede10c2..3d357fe3 100644 --- a/src/main/antora/modules/security/pages/security-advanced/security-advanced005.adoc +++ b/src/main/antora/modules/security/pages/security-advanced/security-advanced005.adoc @@ -4,11 +4,11 @@ The Jakarta EE authentication requirements for application clients are the same No authentication is necessary when accessing unprotected web resources. When accessing protected web resources, the usual varieties of authentication can be used: HTTP basic authentication, HTTP login-form authentication, or SSL client authentication. -<> describes how to specify HTTP basic authentication and HTTP login-form authentication. -<> describes how to specify SSL client authentication. +xref:security-webtier/security-webtier.adoc#_specifying_an_authentication_mechanism_in_the_deployment_descriptor[Specifying an Authentication Mechanism in the Deployment Descriptor] describes how to specify HTTP basic authentication and HTTP login-form authentication. +<<_client_authentication>> describes how to specify SSL client authentication. Authentication is required when accessing protected enterprise beans. -The authentication mechanisms for enterprise beans are discussed in <>. +The authentication mechanisms for enterprise beans are discussed in xref:security-jakartaee/security-jakartaee.adoc#_securing_enterprise_beans[Securing Enterprise Beans]. An application client makes use of an authentication service provided by the application client container for authenticating its users. The container's service can be integrated with the native platform's authentication system so that a single sign-on capability is used. @@ -32,7 +32,7 @@ For example, the implementation of a callback handler for a GUI application migh The login module passes an array of appropriate callbacks to the callback handler's `handle` method, such as a `NameCallback` for the user name and a `PasswordCallback` for the password; the callback handler performs the requested user interaction and sets appropriate values in the callbacks. For example, to process a `NameCallback`, the `CallbackHandler` might prompt for a name, retrieve the value from the user, and call the `setName` method of the `NameCallback` to store the name. -For more information on using JAAS for authentication in login modules, refer to the documentation listed in <>. +For more information on using JAAS for authentication in login modules, refer to the documentation listed in <<_further_information_about_advanced_security_topics>>. === Using Programmatic Login diff --git a/src/main/antora/modules/security/pages/security-advanced/security-advanced006.adoc b/src/main/antora/modules/security/pages/security-advanced/security-advanced006.adoc index e650e2bb..f28ebda0 100644 --- a/src/main/antora/modules/security/pages/security-advanced/security-advanced006.adoc +++ b/src/main/antora/modules/security/pages/security-advanced/security-advanced006.adoc @@ -13,7 +13,7 @@ The container determines the user name and password for establishing a connectio * Component-managed sign-on: The application component code manages EIS sign-on by including code that performs the sign-on process to an EIS. You can also configure security for resource adapters. -See <>. +See <<_configuring_resource_adapter_security>>. === Container-Managed Sign-On @@ -115,7 +115,7 @@ You can, however, manually update the `server.policy` file to add the relevant p + The security permissions listed in the deployment descriptor are different from those required by the default permission set as specified in the connector specification. + -For more information on the implementation of the security permission specification, see the security policy file documentation listed in <>. +For more information on the implementation of the security permission specification, see the security policy file documentation listed in <<_further_information_about_advanced_security_topics>>. In addition to specifying resource adapter security in the `ra.xml` file, you can create a security map for a connector connection pool to map an application principal or a user group to a back-end EIS principal. The security map is usually used if one or more EIS back-end principals are used to execute operations (on the EIS) initiated by various principals or user groups in the application. diff --git a/src/main/antora/modules/security/pages/security-api/security-api001.adoc b/src/main/antora/modules/security/pages/security-api/security-api001.adoc index e5be4a50..beb38ba0 100644 --- a/src/main/antora/modules/security/pages/security-api/security-api001.adoc +++ b/src/main/antora/modules/security/pages/security-api/security-api001.adoc @@ -6,18 +6,18 @@ You can use the built-in implementations of these APIs, or define custom impleme Jakarta Security contains the following packages: * The `jakarta.security.enterprise` package is the main Jakarta Security package and contains classes and interfaces that span authentication, authorization, and identity concerns. -<> lists the main class and interfaces in this package. +<<_main_classes_and_interfaces_in_enterprise>> lists the main class and interfaces in this package. * The `jakarta.security.enterprise.authentication.mechanism.http` package contains classes and interfaces associated with HTTP-based authentication mechanisms that can interact with a caller or third-parties as part of an authentication protocol. -<> lists the main classes and interfaces in this package. +<<_main_classes_and_interfaces_in_authentication>> lists the main classes and interfaces in this package. * The `jakarta.security.enterprise.credential` package contains classes and interfaces for representing user credentials. -<> lists the main classes and interfaces in this package. +<<_main_classes_and_interfaces_in_credential>> lists the main classes and interfaces in this package. * The `jakarta.security.enterprise.identitystore` package contains classes and interfaces associated with identity stores that validate a caller's credentials and lookup caller groups. -<> lists the main classes and interfaces in this package. +<<_main_classes_and_interfaces_in_identitystore>> lists the main classes and interfaces in this package. -[[main-classes-and-interfaces-in-enterprise]] +[[_main_classes_and_interfaces_in_enterprise]] .Main Classes and Interfaces in `jakarta.security.enterprise` [width="99%",cols="25%,75%"] |=== @@ -32,7 +32,7 @@ Jakarta Security contains the following packages: |`AuthenticationException` |Indicates that a problem occurred during the authentication process. |=== -[[main-classes-and-interfaces-in-authentication]] +[[_main_classes_and_interfaces_in_authentication]] .Main Classes and Interfaces in `jakarta.security.enterprise.authentication.mechanism.http` [width="99%",cols="25%,75%"] |=== @@ -51,7 +51,7 @@ Developers can provide their own implementation of this interface, or use one of [NOTE] The `jakarta.security.enterprise.authentication.mechanism.http` package also includes a number of annotation classes that are used to configure/enable the built-in authentication mechanisms or to modify the behavior of an authentication mechanism. -[[main-classes-and-interfaces-in-credential]] +[[_main_classes_and_interfaces_in_credential]] .Main Classes and Interfaces in `jakarta.security.enterprise.credential` [width="99%",cols="25%,75%"] |=== @@ -73,7 +73,7 @@ All other classes in this package are implementations of the Credential interfac |`UsernamePasswordCredential` |Class that represents the credentials typically used by standard caller name/password authentication. |=== -[[main-classes-and-interfaces-in-identitystore]] +[[_main_classes_and_interfaces_in_identitystore]] .Main Classes and Interfaces in `jakarta.security.enterprise.identitystore` [width="99%",cols="25%,75%"] |=== diff --git a/src/main/antora/modules/security/pages/security-api/security-api003.adoc b/src/main/antora/modules/security/pages/security-api/security-api003.adoc index 3dd0da51..d60835da 100644 --- a/src/main/antora/modules/security/pages/security-api/security-api003.adoc +++ b/src/main/antora/modules/security/pages/security-api/security-api003.adoc @@ -2,9 +2,9 @@ The Identity Store Interfaces are described in the following sections: -* <> +* <<_the_identitystore_interface>> -* <> +* <<_the_remembermeidentitystore_interface>> === The IdentityStore Interface @@ -20,14 +20,14 @@ They are configured with the parameters necessary to communicate with an externa * `DatabaseIdentityStoreDefinition` -- configures an identity store with the parameters necessary to connect to an external database, validate user credentials, and/or lookup user groups. You must supply a PasswordHash implementation when configuring a Database Identity Store. -See <>. +See <<_the_passwordhash_interface>>. An application can provide its own custom identity store, or use the built-in LDAP or database identity stores. For examples of both types, see: -* <> +* <<_running_the_built_in_database_identity_store_example>> -* <> +* <<_running_the_custom_identity_store_example>> An implementation of `IdentityStore` must be a CDI bean to be recognized and deployed at runtime, and is assumed to be normal scoped. IdentityStores are primarily intended for use by implementations of `HttpAuthenticationMechanisms`, but this is not a requirement. diff --git a/src/main/antora/modules/security/pages/security-api/security-api004.adoc b/src/main/antora/modules/security/pages/security-api/security-api004.adoc index c6c9b566..7d56dfea 100644 --- a/src/main/antora/modules/security/pages/security-api/security-api004.adoc +++ b/src/main/antora/modules/security/pages/security-api/security-api004.adoc @@ -4,9 +4,9 @@ The example described in this section demonstrates how to use the built-in datab Topics include: -* <> +* <<_overview_of_the_built_in_database_identity_store_example>> -* <> +* <<_running_the_built_in_db_identity_store_example>> === Overview of the Built-In Database Identity Store Example @@ -21,13 +21,13 @@ The source code for this example is in the `_tut-install_/examples/security/secu The following sections describe the high-level process for configuring the `DatabaseIdentityStore`. Note that the configuration described in these sections has already been completed in the application files, but is provided here to illustrate what you need to do to use the built-in database identity store. -* <> +* <<_define_the_users_and_groups_in_the_identity_store>> -* <> +* <<_map_the_databaseidentitystore_to_the_default_data_source>> -* <> +* <<_specify_the_authentication_mechanism>> -* <> +* <<_declare_roles_in_the_servlet_container>> When a request that includes credentials is sent to the application, it triggers the configured authentication mechanism and authentication is performed against the `DatabaseIdentityStore` as defined in the application. @@ -198,11 +198,11 @@ Therefore, you do not need to bundle web.xml with the application to provide map You can use either NetBeans IDE or Maven to build, package, deploy, and run the `built-in-db-identity-store` application as described in the following topics: -* <> +* <<_to_build_package_and_deploy_the_built_in_db_identity_store_example_using_netbeans_ide>> -* <> +* <<_to_build_package_and_deploy_the_built_in_db_identity_store_example_using_maven>> -* <> +* <<_to_run_the_built_in_db_identity_store_example>> ==== To Build, Package, and Deploy the built-in-db-identity-store Example Using NetBeans IDE diff --git a/src/main/antora/modules/security/pages/security-api/security-api005.adoc b/src/main/antora/modules/security/pages/security-api/security-api005.adoc index 68557035..1e9c0d44 100644 --- a/src/main/antora/modules/security/pages/security-api/security-api005.adoc +++ b/src/main/antora/modules/security/pages/security-api/security-api005.adoc @@ -4,7 +4,7 @@ The example described in this section demonstrates how to bundle and use a custo Topics include: -* <> +* <<_overview_of_the_custom_identity_store_example>> * <> @@ -21,11 +21,11 @@ The source code for this example is in the `_tut-install_/examples/security/secu The following sections describe the high-level process for defining the `TestIdentityStore`. Note that the configuration described in these sections has already been completed in the application files, but is provided here to illustrate what you need to do to use a custom identity store. -* <> +* <<_define_the_users_and_groups_in_the_identity_store>> -* <> +* <<_specify_the_authentication_mechanism>> -* <> +* <<_declare_roles_in_the_servlet_container>> When a request that includes credentials is sent to the application, the configured authentication mechanism comes into effect and authentication is performed against the `TestIdentityStore` as defined in the application. @@ -123,11 +123,11 @@ Therefore, you do not need to bundle `web.xml` with the application to provide m You can use either NetBeans IDE or Maven to build, package, deploy, and run the `custom-identity-store` application as described in the following topics: -* <> +* <<_to_build_package_and_deploy_the_custom_identity_store_example_using_netbeans_ide>> -* <> +* <<_to_build_package_and_deploy_the_custom_identity_store_example_using_maven>> -* <> +* <<_to_run_the_custom_identity_store_example>> ==== To Build, Package, and Deploy the custom-identity-store Example Using NetBeans IDE diff --git a/src/main/antora/modules/security/pages/security-intro/security-intro001.adoc b/src/main/antora/modules/security/pages/security-intro/security-intro001.adoc index ddec4c09..9ec3f5d4 100644 --- a/src/main/antora/modules/security/pages/security-intro/security-intro001.adoc +++ b/src/main/antora/modules/security/pages/security-intro/security-intro001.adoc @@ -10,7 +10,7 @@ A container provides two kinds of security: declarative and programmatic. * Declarative security expresses an application component's security requirements by using either deployment descriptors or annotations. + A deployment descriptor is an XML file that is external to the application and that expresses an application's security structure, including security roles, access control, and authentication requirements. -For more information about deployment descriptors, read <>. +For more information about deployment descriptors, read <<_using_deployment_descriptors_for_declarative_security>>. + Annotations, also called metadata, are used to specify information about security within a class file. When the application is deployed, this information can be either used by or overridden by the application deployment descriptor. @@ -18,11 +18,11 @@ Annotations save you from having to write declarative information inside XML des Instead, you simply put annotations on the code, and the required information gets generated. For this tutorial, annotations are used for securing applications wherever possible. For more information about annotations, see -<>. +<<_using_annotations_to_specify_security_information>>. * Programmatic security is embedded in an application and is used to make security decisions. Programmatic security is useful when declarative security alone is not sufficient to express the security model of an application. -For more information about programmatic security, read <>. +For more information about programmatic security, read <<_using_programmatic_security>>. Jakarta EE 9 includes a Security API specification that defines portable, plug-in interfaces for authentication and identity stores, and a new injectable-type `SecurityContext` interface that provides an access point for programmatic security. You can use the built-in implementations of these APIs, or define custom implementations. @@ -31,11 +31,11 @@ More information on these concepts and mechanisms can be found in the chapter on Other chapters in this Part discuss security requirements in web tier and enterprise tier applications, and the Jakarta Security. -* xref:getting-started-securing-web-applications[xrefstyle=full] explains how to add security to web components, such as servlets. +* xref:security-webtier/security-webtier.adoc#_getting_started_securing_web_applications[Getting Started Securing Web Applications] explains how to add security to web components, such as servlets. -* xref:getting-started-securing-enterprise-applications[xrefstyle=full] explains how to add security to Jakarta EE components, such as enterprise beans and application clients. +* xref:security-jakartaee/security-jakartaee.adoc#_getting_started_securing_enterprise_applications[Getting Started Securing Enterprise Applications] explains how to add security to Jakarta EE components, such as enterprise beans and application clients. -* xref:using-jakarta-security[xrefstyle=full] describes the authentication and credential validation funtionality provided by Jakarta Security, and provides examples. +* xref:security-api/security-api.adoc#_using_jakarta_security[Using Jakarta Security] describes the authentication and credential validation funtionality provided by Jakarta Security, and provides examples. === A Simple Application Security Walkthrough @@ -46,25 +46,25 @@ In the following example, which is taken from the Jakarta EE Specification, the ==== Step 1: Initial Request In the first step of this example, the web client requests the main application URL. -This action is shown in <>. +This action is shown in <<_initial_request>>. -[[initial-request]] +[[_initial_request]] .Initial Request -image::jakartaeett_dt_039.svg["Diagram of initial request from web client to web server for access to a protected resource"] +image::common:jakartaeett_dt_039.svg["Diagram of initial request from web client to web server for access to a protected resource"] Since the client has not yet authenticated itself to the application environment, the server responsible for delivering the web portion of the application, hereafter referred to as the web server, detects this and invokes the appropriate authentication mechanism for this resource. -For more information on these mechanisms, see <>. +For more information on these mechanisms, see <<_security_mechanisms>>. ==== Step 2: Initial Authentication The web server returns a form that the web client uses to collect authentication data, such as user name and password, from the user. -The web client forwards the authentication data to the web server, where it is validated by the web server, as shown in <>. +The web client forwards the authentication data to the web server, where it is validated by the web server, as shown in <<_initial_authentication>>. The validation mechanism may be local to a server or may leverage the underlying security services. On the basis of the validation, the web server sets a credential for the user. -[[initial-authentication]] +[[_initial_authentication]] .Initial Authentication -image::jakartaeett_dt_040.svg["Diagram of initial authentication: server sends form to client, which sends authentication data to server for validation"] +image::common:jakartaeett_dt_040.svg["Diagram of initial authentication: server sends form to client, which sends authentication data to server for validation"] ==== Step 3: URL Authorization @@ -72,34 +72,34 @@ The credential is used for future determinations of whether the user is authoriz The web server consults the security policy associated with the web resource to determine the security roles that are permitted access to the resource. The security policy is derived from annotations or from the deployment descriptor. The web container then tests the user's credential against each role to determine whether it can map the user to the role. -<> shows this process. +<<_url_authorization>> shows this process. -[[url-authorization]] +[[_url_authorization]] .URL Authorization -image::jakartaeett_dt_041.svg["Diagram of URL authorization"] +image::common:jakartaeett_dt_041.svg["Diagram of URL authorization"] The web server's evaluation stops with an "is authorized" outcome when the web server is able to map the user to a role. A "not authorized" outcome is reached if the web server is unable to map the user to any of the permitted roles. ==== Step 4: Fulfilling the Original Request -If the user is authorized, the web server returns the result of the original URL request, as shown in <>. +If the user is authorized, the web server returns the result of the original URL request, as shown in <<_fulfilling_the_original_request>>. -[[fulfilling-the-original-request]] +[[_fulfilling_the_original_request]] .Fulfilling the Original Request -image::jakartaeett_dt_042.svg["Diagram of request fulfillment, showing server returning result to client"] +image::common:jakartaeett_dt_042.svg["Diagram of request fulfillment, showing server returning result to client"] In our example, the response URL of a web page is returned, enabling the user to post form data that needs to be handled by the business-logic component of the application. -See xref:getting-started-securing-web-applications[xrefstyle=full] for more information on protecting web applications. +See xref:security-webtier/security-webtier.adoc#_getting_started_securing_web_applications[Getting Started Securing Web Applications] for more information on protecting web applications. ==== Step 5: Invoking Enterprise Bean Business Methods -The web page performs the remote method call to the enterprise bean, using the user's credential to establish a secure association between the web page and the enterprise bean, as shown in <>. +The web page performs the remote method call to the enterprise bean, using the user's credential to establish a secure association between the web page and the enterprise bean, as shown in <<_invoking_an_enterprise_bean_business_method>>. The association is implemented as two related security contexts: one in the web server and one in the enterprise bean container. -[[invoking-an-enterprise-bean-business-method]] +[[_invoking_an_enterprise_bean_business_method]] .Invoking an Enterprise Bean Business Method -image::jakartaeett_dt_043.svg["Diagram of authorization process between web component and enterprise bean"] +image::common:jakartaeett_dt_043.svg["Diagram of authorization process between web component and enterprise bean"] The enterprise container is responsible for enforcing access control on the enterprise bean method. The container consults the security policy associated with the enterprise bean to determine the security roles that are permitted access to the method. diff --git a/src/main/antora/modules/security/pages/security-intro/security-intro002.adoc b/src/main/antora/modules/security/pages/security-intro/security-intro002.adoc index 83146b10..7d515110 100644 --- a/src/main/antora/modules/security/pages/security-intro/security-intro002.adoc +++ b/src/main/antora/modules/security/pages/security-intro/security-intro002.adoc @@ -32,7 +32,7 @@ For more information on Java SE security, visit https://docs.oracle.com/javase/8 === Jakarta EE Security Mechanisms -Jakarta EE security services are provided by the component container and can be implemented by using declarative or programmatic techniques (see <>). +Jakarta EE security services are provided by the component container and can be implemented by using declarative or programmatic techniques (see <<_securing_containers>>). Jakarta EE security services provide a robust and easily configured security mechanism for authenticating users and authorizing access to application functions and associated data at many different layers. Jakarta EE security services are separate from the security mechanisms of the operating system. @@ -59,7 +59,7 @@ The disadvantages of using application-layer security include the following. * Data is close to or contained within the point of vulnerability. -For more information on providing security at the application layer, see <>. +For more information on providing security at the application layer, see <<_securing_containers>>. ==== Transport-Layer Security @@ -101,7 +101,7 @@ Protection is removed automatically by the endpoint when it receives the message * It is not an end-to-end solution, simply point-to-point. -For more information on transport-layer security, see <>. +For more information on transport-layer security, see <<_establishing_a_secure_connection_using_ssl>>. ==== Message-Layer Security diff --git a/src/main/antora/modules/security/pages/security-intro/security-intro003.adoc b/src/main/antora/modules/security/pages/security-intro/security-intro003.adoc index c6379ae6..feab2c3f 100644 --- a/src/main/antora/modules/security/pages/security-intro/security-intro003.adoc +++ b/src/main/antora/modules/security/pages/security-intro/security-intro003.adoc @@ -11,11 +11,11 @@ GlassFish Server uses this information when the application is deployed. Not all security information can be specified by using annotations, however. Some information must be specified in the application deployment descriptors. -Specific annotations that can be used to specify security information within an enterprise bean class file are described in <>. -xref:getting-started-securing-web-applications[xrefstyle=full], describes how to use annotations to secure web applications where possible. +Specific annotations that can be used to specify security information within an enterprise bean class file are described in xref:security-jakartaee/security-jakartaee.adoc#_securing_an_enterprise_bean_using_declarative_security[Securing an Enterprise Bean Using Declarative Security]. +xref:security-webtier/security-webtier.adoc#_getting_started_securing_web_applications[Getting Started Securing Web Applications], describes how to use annotations to secure web applications where possible. Deployment descriptors are described only where necessary. -For more information on annotations, see <>. +For more information on annotations, see <<_further_information_about_security>>. === Using Deployment Descriptors for Declarative Security @@ -47,6 +47,6 @@ These methods allow components to make business-logic decisions based on the sec Programmatic security is discussed in more detail in the following sections: -* <> +* xref:security-webtier/security-webtier.adoc#_using_programmatic_security_with_web_applications[Using Programmatic Security with Web Applications] -* <> +* xref:security-jakartaee/security-jakartaee.adoc#_securing_an_enterprise_bean_programmatically[Securing an Enterprise Bean Programmatically] diff --git a/src/main/antora/modules/security/pages/security-intro/security-intro003a.adoc b/src/main/antora/modules/security/pages/security-intro/security-intro003a.adoc index 8247aab9..60d27821 100644 --- a/src/main/antora/modules/security/pages/security-intro/security-intro003a.adoc +++ b/src/main/antora/modules/security/pages/security-intro/security-intro003a.adoc @@ -3,7 +3,7 @@ Jakarta EE includes two specifications that define SPI interfaces for pluggable security providers, Jakarta Authentication and Jakarta Security. These specifications are described in more detail in the following sections: -* <> +* <<_jakarta_authentication>> * <> diff --git a/src/main/antora/modules/security/pages/security-intro/security-intro004.adoc b/src/main/antora/modules/security/pages/security-intro/security-intro004.adoc index eae3422e..7191162b 100644 --- a/src/main/antora/modules/security/pages/security-intro/security-intro004.adoc +++ b/src/main/antora/modules/security/pages/security-intro/security-intro004.adoc @@ -5,7 +5,7 @@ GlassFish Server supports the Jakarta EE 9 security model. You can configure GlassFish Server for the following purposes. * Adding, deleting, or modifying authorized users. -For more information on this topic, see <>. +For more information on this topic, see <<_working_with_realms_users_groups_and_roles>>. * Configuring secure HTTP and Internet Inter-Orb Protocol (IIOP) listeners. diff --git a/src/main/antora/modules/security/pages/security-intro/security-intro005.adoc b/src/main/antora/modules/security/pages/security-intro/security-intro005.adoc index 2e66e285..5484d562 100644 --- a/src/main/antora/modules/security/pages/security-intro/security-intro005.adoc +++ b/src/main/antora/modules/security/pages/security-intro/security-intro005.adoc @@ -1,19 +1,19 @@ == Working with Realms, Users, Groups, and Roles You often need to protect resources to ensure that only authorized users have access. -See <> for an introduction to the concepts of authentication, identification, and authorization. +See <<_characteristics_of_application_security>> for an introduction to the concepts of authentication, identification, and authorization. This section discusses setting up users so that they can be correctly identified and either given access to protected resources or denied access if they are not authorized to access the protected resources. To authenticate a user, you need to follow these basic steps. . The application developer writes code to prompt for a user name and password. -The various methods of authentication are discussed in <>. +The various methods of authentication are discussed in xref:security-webtier/security-webtier.adoc#_specifying_authentication_mechanisms[Specifying Authentication Mechanisms]. . The application developer communicates how to set up security for the deployed application by use of a metadata annotation or deployment descriptor. -This step is discussed in <>. +This step is discussed in <<_setting_up_security_roles>>. . The server administrator sets up authorized users and groups in GlassFish Server. -This is discussed in <>. +This is discussed in <<_managing_users_and_groups_in_glassfish_server>>. . The application deployer maps the application's security roles to users, groups, and principals defined in GlassFish Server. This topic is discussed in <>. @@ -25,20 +25,20 @@ By default, group principal names are mapped to roles of the same name. A realm is a security policy domain defined for a web or application server. A realm contains a collection of users, who may or may not be assigned to a group. -Managing users in GlassFish Server is discussed in <>. +Managing users in GlassFish Server is discussed in <<_managing_users_and_groups_in_glassfish_server>>. An application will often prompt for a user name and password before allowing access to a protected resource. After the user name and password have been entered, that information is passed to the server, which either authenticates the user and sends the protected resource or does not authenticate the user, in which case access to the protected resource is denied. -This type of user authentication is discussed in <>. +This type of user authentication is discussed in xref:security-webtier/security-webtier.adoc#_specifying_an_authentication_mechanism_in_the_deployment_descriptor[Specifying an Authentication Mechanism in the Deployment Descriptor]. In some applications, authorized users are assigned to roles. In this situation, the role assigned to the user in the application must be mapped to a principal or group defined on the application server. -<> shows this. -More information on mapping roles to users and groups can be found in <>. +<<_mapping_roles_to_users_and_groups>> shows this. +More information on mapping roles to users and groups can be found in <<_setting_up_security_roles>>. -[[mapping-roles-to-users-and-groups]] +[[_mapping_roles_to_users_and_groups]] .Mapping Roles to Users and Groups -image::jakartaeett_dt_044.svg["Diagram of role mapping, showing creation of users and groups, definition of roles, and mapping of roles to users and groups"] +image::common:jakartaeett_dt_044.svg["Diagram of role mapping, showing creation of users and groups, definition of roles, and mapping of roles to users and groups"] The following sections provide more information on realms, users, groups, and roles. @@ -58,12 +58,12 @@ This realm is used for the authentication of all clients except for web browser In the `certificate` realm, the server stores user credentials in a certificate database. When using the `certificate` realm, the server uses certificates with HTTPS to authenticate web clients. To verify the identity of a user in the `certificate` realm, the authentication service verifies an X.509 certificate. -For step-by-step instructions for creating this type of certificate, see <>. +For step-by-step instructions for creating this type of certificate, see xref:security-advanced/security-advanced.adoc#_working_with_digital_certificates[Working with Digital Certificates]. The common name field of the X.509 certificate is used as the principal name. The `admin-realm` is also a `file` realm and stores administrator user credentials locally in a file named `admin-keyfile`. You can use the Administration Console to manage users in this realm in the same way you manage users in the `file` realm. -For more information, see <>. +For more information, see <<_managing_users_and_groups_in_glassfish_server>>. ==== What Is a User? @@ -144,7 +144,7 @@ For the example security applications, select the `file` realm. + You cannot add users to the `certificate` realm by using the Administration Console. In the `certificate` realm, you can add only certificates. -For information on adding (importing) certificates to the `certificate` realm, see <>. +For information on adding (importing) certificates to the `certificate` realm, see xref:security-advanced/security-advanced.adoc#_adding_users_to_the_certificate_realm[Adding Users to the Certificate Realm]. . On the Edit Realm page, click Manage Users. @@ -155,7 +155,7 @@ For information on adding (importing) certificates to the `certificate` realm, s For the Admin Realm, the Group List field is read-only, and the group name is `asadmin`. Restart GlassFish Server and the Administration Console after you add a user to the Admin Realm. + -For more information on these properties, see <>. +For more information on these properties, see <<_working_with_realms_users_groups_and_roles>>. + For the example security applications, specify a user with any name and password you like, but make sure that the user is assigned to the group `TutorialUser`. The user name and password are case-sensitive. @@ -169,7 +169,7 @@ When you design an enterprise bean or web component, you should always think abo For example, a web application for a human resources department might have a different request URL for someone who has been assigned the role of `DEPT_ADMIN` than for someone who has been assigned the role of `DIRECTOR`. The `DEPT_ADMIN` role may let you view employee data, but the `DIRECTOR` role enables you to modify employee data, including salary data. Each of these security roles is an abstract logical grouping of users that is defined by the person who assembles the application. -When an application is deployed, the deployer will map the roles to security identities in the operational environment, as shown in <>. +When an application is deployed, the deployer will map the roles to security identities in the operational environment, as shown in <<_mapping_roles_to_users_and_groups>>. For Jakarta EE components, you define security roles using the `@DeclareRoles` and `@RolesAllowed` metadata annotations. @@ -218,7 +218,7 @@ For example, a servlet might be annotated as follows: public class GreetingServlet extends HttpServlet { ... } ---- -These annotations are discussed in more detail in <> and <>. +These annotations are discussed in more detail in xref:security-webtier/security-webtier.adoc#_specifying_security_for_basic_authentication_using_annotations[Specifying Security for Basic Authentication Using Annotations] and xref:security-jakartaee/security-jakartaee.adoc#_securing_an_enterprise_bean_using_declarative_security[Securing an Enterprise Bean Using Declarative Security]. After users have provided their login information and the application has declared what roles are authorized to access protected parts of an application, the next step is to map the security role to the name of a user, or principal. diff --git a/src/main/antora/modules/security/pages/security-intro/security-intro005a.adoc b/src/main/antora/modules/security/pages/security-intro/security-intro005a.adoc index 9223dc95..60ae2ff0 100644 --- a/src/main/antora/modules/security/pages/security-intro/security-intro005a.adoc +++ b/src/main/antora/modules/security/pages/security-intro/security-intro005a.adoc @@ -12,4 +12,4 @@ The `IdentityStore` interface is intended primarily for use by the `HttpAuthenti Using the `HttpAuthenticationMechanism` and `IdentityStore` implementations, both built-in and custom, provides a significant advantage over the BASIC and FORM mechanisms defined by Servlet 5.0 (and previous versions) and configured declaratively using `` in `web.xml`, because it allows an application to control the identity stores it will authenticate against in a standard, portable way. An application can provide its own `IdentityStore`, or use the built in LDAP or Database identity store implementations of the interface. -For details about the `IdentityStore` interfaces and examples of their usage, see <>. +For details about the `IdentityStore` interfaces and examples of their usage, see xref:security-api/security-api.adoc#_overview_of_the_identity_store_interfaces[Overview of the Identity Store Interfaces]. diff --git a/src/main/antora/modules/security/pages/security-intro/security-intro006.adoc b/src/main/antora/modules/security/pages/security-intro/security-intro006.adoc index cee5c28b..eb2e723a 100644 --- a/src/main/antora/modules/security/pages/security-intro/security-intro006.adoc +++ b/src/main/antora/modules/security/pages/security-intro/security-intro006.adoc @@ -1,6 +1,6 @@ == Establishing a Secure Connection Using SSL -Secure Sockets Layer (SSL) technology is security that is implemented at the transport layer (see <> for more information about transport-layer security). +Secure Sockets Layer (SSL) technology is security that is implemented at the transport layer (see <<_transport_layer_security>> for more information about transport-layer security). SSL allows web browsers and web servers to communicate over a secure connection. In this secure connection, the data is encrypted before being sent and then is decrypted upon receipt and before processing. Both the browser and the server encrypt all traffic before sending any data. diff --git a/src/main/antora/modules/security/pages/security-jakartaee/security-jakartaee002.adoc b/src/main/antora/modules/security/pages/security-jakartaee/security-jakartaee002.adoc index 75cc43a4..66e4d763 100644 --- a/src/main/antora/modules/security/pages/security-jakartaee/security-jakartaee002.adoc +++ b/src/main/antora/modules/security/pages/security-jakartaee/security-jakartaee002.adoc @@ -21,14 +21,14 @@ A security role is a grouping of permissions that a given type of application us For example, in a payroll application, some users will want to view their own payroll information (employee), some will need to view others' payroll information (manager), and some will need to be able to change others' payroll information (payrollDept). The application developer would determine the potential users of the application and which methods would be accessible to which users. The application developer would then decorate classes or methods of the enterprise bean with annotations that specify the types of users authorized to access those methods. -Using annotations to specify authorized users is described in <>. +Using annotations to specify authorized users is described in <<_specifying_authorized_users_by_declaring_security_roles>>. + When one of the annotations is used to define method permissions, the deployment system will automatically require user name/password authentication. In this type of authentication, a user is prompted to enter a user name and password, which will be compared against a database of known users. If the user is found and the password matches, the roles that the user is assigned will be compared against the roles that are authorized to access the method. If the user is authenticated and found to have a role that is authorized to access that method, the data will be returned to the user. + -Using declarative security is discussed in <>. +Using declarative security is discussed in <<_securing_an_enterprise_bean_using_declarative_security>>. * Programmatic security: For an enterprise bean, code embedded in a business method that is used to access a caller's identity programmatically and that uses this information to make security decisions. Programmatic security is useful when declarative security alone is not sufficient to express the security model of an application. @@ -36,9 +36,9 @@ Programmatic security is useful when declarative security alone is not sufficien In general, security management should be enforced by the container in a manner that is transparent to the enterprise beans' business methods. The programmatic security APIs described in this chapter should be used only in the less frequent situations in which the enterprise bean business methods need to access the security-context information, such as when you want to grant access based on the time of day or other nontrivial condition checks for a particular role. + -Programmatic security is discussed in <>. +Programmatic security is discussed in <<_securing_an_enterprise_bean_programmatically>>. -Some of the material in this chapter assumes that you have already read xref:enterprise-beans-2[xrefstyle=full], xref:getting-started-with-enterprise-beans[xrefstyle=full], and xref:introduction-to-security-in-the-jakarta-ee-platform[xrefstyle=full]. +Some of the material in this chapter assumes that you have already read xref:enterprise-beans-2[], xref:getting-started-with-enterprise-beans[], and xref:security-intro/security-intro.adoc#_introduction_to_security_in_the_jakarta_ee_platform[Introduction to Security in the Jakarta EE Platform]. This section discusses securing a Jakarta EE application where one or more modules, such as enterprise bean JAR files, are packaged into an EAR file, the archive file that holds the application. Security annotations will be used in the Java programming class files to specify authorized users and basic, or user name/password, authentication. @@ -340,16 +340,16 @@ public class PayrollBean implements Payroll { ---- You would use programmatic security in this way to dynamically control access to a method, for example, when you want to deny access except during a particular time of day. -An example application that uses the `getCallerPrincipal` and `isCallerInRole` methods is described in <>. +An example application that uses the `getCallerPrincipal` and `isCallerInRole` methods is described in <<_the_converter_secure_example_securing_an_enterprise_bean_with_programmatic_security>>. === Propagating a Security Identity (Run-As) You can specify whether a caller's security identity should be used for the execution of specified methods of an enterprise bean or whether a specific run-as identity should be used. -<> illustrates this concept. +<<_security_identity_propagation>> illustrates this concept. -[[security-identity-propagation]] +[[_security_identity_propagation]] .Security Identity Propagation -image::jakartaeett_dt_047.svg["Diagram of security identity propagation from client to intermediate container to target container"] +image::common:jakartaeett_dt_047.svg["Diagram of security identity propagation from client to intermediate container to target container"] In this illustration, an application client is making a call to an enterprise bean method in one enterprise bean container. This enterprise bean method, in turn, makes a call to an enterprise bean method in another container. diff --git a/src/main/antora/modules/security/pages/security-jakartaee/security-jakartaee003.adoc b/src/main/antora/modules/security/pages/security-jakartaee/security-jakartaee003.adoc index b501cdca..ff86ad09 100644 --- a/src/main/antora/modules/security/pages/security-jakartaee/security-jakartaee003.adoc +++ b/src/main/antora/modules/security/pages/security-jakartaee/security-jakartaee003.adoc @@ -7,7 +7,7 @@ The following examples show how to secure enterprise beans using declarative and This section discusses how to configure an enterprise bean for basic user name/password authentication. When a bean that is constrained in this way is requested, the server requests a user name and password from the client and verifies that the user name and password are valid by comparing them against a database of authorized users in GlassFish Server. -If the topic of authentication is new to you, see <>. +If the topic of authentication is new to you, see xref:security-webtier/security-webtier.adoc#_specifying_authentication_mechanisms[Specifying Authentication Mechanisms]. This example demonstrates security by starting with the unsecured enterprise bean application, `cart`, which is found in the `_tut-install_/examples/ejb/cart/` directory and is discussed in <>. @@ -18,12 +18,12 @@ In the example application included with this tutorial, these steps have been co The example in this tutorial starts with this example and demonstrates adding basic authentication of the client to this application. The example application discussed in this section can be found at `_tut-install_/examples/security/cart-secure/`. -. If you have not already done so, complete the steps in <> to configure your system for running the tutorial applications. +. If you have not already done so, complete the steps in xref:security-webtier/security-webtier.adoc#_to_set_up_your_system_for_running_the_security_examples[To Set Up Your System for Running the Security Examples] to configure your system for running the tutorial applications. . Modify the source code for the enterprise bean, `CartBean.java`, to specify which roles are authorized to access which protected methods. -This step is discussed in <>. +This step is discussed in <<_annotating_the_bean>>. -. Build, package, and deploy the enterprise bean; then build and run the client application by following the steps in <> or <>. +. Build, package, and deploy the enterprise bean; then build and run the client application by following the steps in <<_to_run_the_cart_secure_example_using_netbeans_ide>> or <<_to_run_the_cart_secure_example_using_maven>>. ==== Annotating the Bean @@ -123,7 +123,7 @@ If no authentication method is specified in the deployment descriptor, the type ==== To Run the cart-secure Example Using NetBeans IDE -. Follow the steps in <>. +. Follow the steps in xref:security-webtier/security-webtier.adoc#_to_set_up_your_system_for_running_the_security_examples[To Set Up Your System for Running the Security Examples]. . From the File menu, choose Open Project. @@ -162,7 +162,7 @@ If the user name and password are not authenticated, the dialog box reappears un ==== To Run the cart-secure Example Using Maven -. Follow the steps in <>. +. Follow the steps in xref:security-webtier/security-webtier.adoc#_to_set_up_your_system_for_running_the_security_examples[To Set Up Your System for Running the Security Examples]. . In a terminal window, go to: + @@ -200,8 +200,8 @@ This example demonstrates how to use the `getCallerPrincipal` and `isCallerInRol This example starts with a very simple enterprise bean application, `converter`, and modifies the methods of the `ConverterBean` so that currency conversion will occur only when the requester is in the role of `TutorialUser`. This example can be found in the `_tut-install_/examples/security/converter-secure` directory. -This example is based on the unsecured enterprise bean application, `converter`, which is discussed in xref:getting-started-with-enterprise-beans[xrefstyle=full] and is found in the `_tut-install_/examples/ejb/converter/` directory. -This section builds on the example by adding the necessary elements to secure the application by using the `getCallerPrincipal` and `isCallerInRole` methods, which are discussed in more detail in <>. +This example is based on the unsecured enterprise bean application, `converter`, which is discussed in xref:getting-started-with-enterprise-beans[] and is found in the `_tut-install_/examples/ejb/converter/` directory. +This section builds on the example by adding the necessary elements to secure the application by using the `getCallerPrincipal` and `isCallerInRole` methods, which are discussed in more detail in <<_securing_an_enterprise_bean_programmatically>>. In general, the following steps are necessary when using the `getCallerPrincipal` and `isCallerInRole` methods with an enterprise bean. In the example application included with this tutorial, many of these steps have been completed for you and are listed here simply to show what needs to be done should you wish to create a similar application. @@ -209,11 +209,11 @@ In the example application included with this tutorial, many of these steps have . Create a simple enterprise bean application. . Set up a user on GlassFish Server in the `file` realm, in the group `TutorialUser`, and set up default principal to role mapping. -To do this, follow the steps in <>. +To do this, follow the steps in xref:security-webtier/security-webtier.adoc#_to_set_up_your_system_for_running_the_security_examples[To Set Up Your System for Running the Security Examples]. . Modify the bean to add the `getCallerPrincipal` and `isCallerInRole` methods. -. If the application contains a web client that is a servlet, specify security for the servlet, as described in <>. +. If the application contains a web client that is a servlet, specify security for the servlet, as described in xref:security-webtier/security-webtier.adoc#_specifying_security_for_basic_authentication_using_annotations[Specifying Security for Basic Authentication Using Annotations]. . Build, package, deploy, and run the application. @@ -287,7 +287,7 @@ The following annotations specify security for the `converter` web client, `Conv ==== To Run the converter-secure Example Using NetBeans IDE -. Follow the steps in <>. +. Follow the steps in xref:security-webtier/security-webtier.adoc#_to_set_up_your_system_for_running_the_security_examples[To Set Up Your System for Running the Security Examples]. . From the File menu, choose Open Project. @@ -307,7 +307,7 @@ This command builds and deploys the example application to your GlassFish Server ==== To Run the converter-secure Example Using Maven -. Follow the steps in <>. +. Follow the steps in xref:security-webtier/security-webtier.adoc#_to_set_up_your_system_for_running_the_security_examples[To Set Up Your System for Running the Security Examples]. . In a terminal window, go to: + diff --git a/src/main/antora/modules/security/pages/security-webtier/security-webtier.adoc b/src/main/antora/modules/security/pages/security-webtier/security-webtier.adoc index 07ca9da8..5eeba341 100644 --- a/src/main/antora/modules/security/pages/security-webtier/security-webtier.adoc +++ b/src/main/antora/modules/security/pages/security-webtier/security-webtier.adoc @@ -1,6 +1,6 @@ = Getting Started Securing Web Applications -This chapter describes in greater detail the ways to implement security for Jakarta EE web applications discussed in a general way in <>. The detail and examples in this chapter explore these security services as they relate to web components. +This chapter describes in greater detail the ways to implement security for Jakarta EE web applications discussed in a general way in xref:security-intro/security-intro.adoc#_securing_containers[Securing Containers]. The detail and examples in this chapter explore these security services as they relate to web components. include::security-webtier001.adoc[] diff --git a/src/main/antora/modules/security/pages/security-webtier/security-webtier001.adoc b/src/main/antora/modules/security/pages/security-webtier/security-webtier001.adoc index 1759820e..a278c24f 100644 --- a/src/main/antora/modules/security/pages/security-webtier/security-webtier001.adoc +++ b/src/main/antora/modules/security/pages/security-webtier/security-webtier001.adoc @@ -7,7 +7,7 @@ Web applications contain resources that can be accessed by many users. These resources often traverse unprotected, open networks, such as the Internet. In such an environment, a substantial number of web applications will require some type of security. -Securing applications and their clients in the business tier and the EIS tier is discussed in xref:getting-started-securing-enterprise-applications[xrefstyle=full]. +Securing applications and their clients in the business tier and the EIS tier is discussed in xref:security-jakartaee/security-jakartaee.adoc#_getting_started_securing_enterprise_applications[Getting Started Securing Enterprise Applications]. In the Jakarta EE platform, web components provide the dynamic extension capabilities for a web server. Web components can be Jakarta servlets or Jakarta Faces pages. @@ -20,18 +20,18 @@ Any values explicitly specified in the deployment descriptor override any values Security for Jakarta EE web applications can be implemented in the following ways. * Declarative security can be implemented using either metadata annotations or an application's deployment descriptor. -See <> for more information. +See xref:security-intro/security-intro.adoc#_overview_of_jakarta_security[Overview of Jakarta Security] for more information. + -Declarative security for web applications is described in <>. +Declarative security for web applications is described in <<_securing_web_applications>>. * Programmatic security is embedded in an application and can be used to make security decisions when declarative security alone is not sufficient to express the security model of an application. Declarative security alone may not be sufficient when conditional login in a particular work flow, instead of for all cases, is required in the middle of an application. -See <> for more information. +See xref:security-intro/security-intro.adoc#_overview_of_jakarta_security[Overview of Jakarta Security] for more information. + Servlet 5.0 provides the `authenticate`, `login`, and `logout` methods of the `HttpServletRequest` interface. With the addition of the `authenticate`, `login`, and `logout` methods to the Servlet specification, an application deployment descriptor is no longer required for web applications but may still be used to further specify security requirements beyond the basic default values. + -Programmatic security is discussed in <>. +Programmatic security is discussed in <<_using_programmatic_security_with_web_applications>>. * Message security works with web services and incorporates security features, such as digital signatures and encryption, into the header of a SOAP message, working in the application layer, ensuring end-to-end security. Message security is not a component of Jakarta EE and is mentioned here for informational purposes only. @@ -39,10 +39,10 @@ Message security is not a component of Jakarta EE and is mentioned here for info Some of the material in this chapter builds on material presented earlier in this tutorial. In particular, this chapter assumes that you are familiar with the information in the following chapters: -* xref:getting-started-with-web-applications[xrefstyle=full] +* xref:getting-started-with-web-applications[] -* xref:jakarta-faces-technology-2[xrefstyle=full] +* xref:jakarta-faces-technology-2[] -* xref:jakarta-servlet-technology-2[xrefstyle=full] +* xref:jakarta-servlet-technology-2[] -* xref:introduction-to-security-in-the-jakarta-ee-platform[xrefstyle=full] +* xref:security-intro/security-intro.adoc#_introduction_to_security_in_the_jakarta_ee_platform[Introduction to Security in the Jakarta EE Platform] diff --git a/src/main/antora/modules/security/pages/security-webtier/security-webtier002.adoc b/src/main/antora/modules/security/pages/security-webtier/security-webtier002.adoc index caba70ec..9cda5dbc 100644 --- a/src/main/antora/modules/security/pages/security-webtier/security-webtier002.adoc +++ b/src/main/antora/modules/security/pages/security-webtier/security-webtier002.adoc @@ -25,13 +25,13 @@ The authentication mechanism cannot be expressed using annotations, so if you us The following subelements can be part of a `security-constraint`. * Web resource collection (`web-resource-collection`): A list of URL patterns (the part of a URL after the host name and port you want to constrain) and HTTP operations (the methods within the files that match the URL pattern you want to constrain) that describe a set of resources to be protected. -Web resource collections are discussed in <>. +Web resource collections are discussed in <<_specifying_a_web_resource_collection>>. * Authorization constraint (`auth-constraint`): Specifies whether authentication is to be used and names the roles authorized to perform the constrained requests. -For more information about authorization constraints, see <>. +For more information about authorization constraints, see <<_specifying_an_authorization_constraint>>. * User data constraint (`user-data-constraint`): Specifies how data is protected when transported between a client and a server. -User data constraints are discussed in <>. +User data constraints are discussed in <<_specifying_a_secure_connection>>. ==== Specifying a Web Resource Collection @@ -75,7 +75,7 @@ Each role name specified here must either correspond to the role name of one of Role names are case sensitive. The roles defined for the application must be mapped to users and groups defined on the server, except when default principal-to-role mapping is used. -For more information about security roles, see <>. +For more information about security roles, see <<_declaring_security_roles>>. For information on mapping security roles, see <>. For a servlet, the `@HttpConstraint` and `@HttpMethodConstraint` annotations accept a `rolesAllowed` element that specifies the authorized roles. @@ -101,7 +101,7 @@ In practice, Jakarta EE servers treat the `CONFIDENTIAL` and `INTEGRAL` transpor The user data constraint is handy to use in conjunction with basic and form-based user authentication. When the login authentication method is set to `BASIC` or `FORM`, passwords are not protected, meaning that passwords sent between a client and a server on an unprotected session can be viewed and intercepted by third parties. Using a user data constraint with the user authentication mechanism can alleviate this concern. -Configuring a user authentication mechanism is described in <>. +Configuring a user authentication mechanism is described in <<_specifying_an_authentication_mechanism_in_the_deployment_descriptor>>. To guarantee that data is transported over a secure connection, ensure that SSL support is configured for your server. SSL support is already configured for GlassFish Server. @@ -157,7 +157,7 @@ An example of a deployment descriptor that would demonstrate this functionality This section describes built-in authentication mechanisms defined by the Servlet specification. [NOTE] -An alternative way to perform user authentication, including BASIC and FORM authentication, is to use the `HttpAuthenticationMechanism`, specified by Jakarta Security, and documented in <>. +An alternative way to perform user authentication, including BASIC and FORM authentication, is to use the `HttpAuthenticationMechanism`, specified by Jakarta Security, and documented in xref:security-api/security-api.adoc#_using_jakarta_security[Using Jakarta Security]. A user authentication mechanism specifies: @@ -171,7 +171,7 @@ When an authentication mechanism is specified, the user must be authenticated be There can be multiple security constraints applying to multiple resources, but the same authentication method will apply to all constrained resources in an application. Before you can authenticate a user, you must have a database of user names, passwords, and roles configured on your web or application server. -For information on setting up the user database, see <>. +For information on setting up the user database, see xref:security-intro/security-intro.adoc#_managing_users_and_groups_in_glassfish_server[Managing Users and Groups in GlassFish Server]. The Jakarta EE platform supports the following authentication mechanisms: @@ -186,7 +186,7 @@ The Jakarta EE platform supports the following authentication mechanisms: * Mutual authentication Basic, form-based, and digest authentication are discussed in this section. -Client and mutual authentication are discussed in xref:jakarta-ee-security-advanced-topics[xrefstyle=full]. +Client and mutual authentication are discussed in xref:security-advanced/security-advanced.adoc#_jakarta_ee_security_advanced_topics[Jakarta EE Security: Advanced Topics]. HTTP basic authentication and form-based authentication are not very secure authentication mechanisms. Basic authentication sends user names and passwords over the Internet as Base64-encoded text. @@ -196,7 +196,7 @@ Therefore, these forms of authentication leave user data exposed and vulnerable. If someone can intercept the transmission, the user name and password information can easily be decoded. However, when a secure transport mechanism, such as SSL, or security at the network level, such as the Internet Protocol Security (IPsec) protocol or virtual private network (VPN) strategies, is used in conjunction with basic or form-based authentication, some of these concerns can be alleviated. -To specify a secure transport mechanism, use the elements described in <>. +To specify a secure transport mechanism, use the elements described in <<_specifying_a_secure_connection>>. ==== HTTP Basic Authentication @@ -214,11 +214,11 @@ When basic authentication is used, the following actions occur. . The server authenticates the user in the specified realm and, if successful, returns the requested resource. -<> shows what happens when you specify HTTP basic authentication. +<<_http_basic_authentication_2>> shows what happens when you specify HTTP basic authentication. -[[http-basic-authentication-2]] +[[_http_basic_authentication_2]] .HTTP Basic Authentication -image::jakartaeett_dt_045.svg["Diagram of four steps in HTTP basic authentication between client and server"] +image::common:jakartaeett_dt_045.svg["Diagram of four steps in HTTP basic authentication between client and server"] ==== Form-Based Authentication @@ -238,13 +238,13 @@ If the user is authorized, the server redirects the client to the resource by us * If authentication fails, the client is forwarded or redirected to an error page. -<> shows what happens when you specify form-based authentication. +<<_form_based_authentication_2>> shows what happens when you specify form-based authentication. -[[form-based-authentication-2]] +[[_form_based_authentication_2]] .Form-Based Authentication -image::jakartaeett_dt_046.svg["Diagram of four steps in form-based authentication between client and server"] +image::common:jakartaeett_dt_046.svg["Diagram of four steps in form-based authentication between client and server"] -The section <> is an example application that uses form-based authentication. +The section <<_the_hello1_formauth_example_form_based_authentication_with_a_jakarta_faces_application>> is an example application that uses form-based authentication. When you create a form-based login, be sure to maintain sessions using cookies or SSL session information. @@ -279,7 +279,7 @@ The element content must be either `NONE`, `BASIC`, `DIGEST`, `FORM`, or `CLIENT * The `form-login-config` subelement specifies the login and error pages that should be used when form-based login is specified. [NOTE] -Another way to specify form-based authentication is to use the `authenticate`, `login`, and `logout` methods of `HttpServletRequest`, as discussed in <>. +Another way to specify form-based authentication is to use the `authenticate`, `login`, and `logout` methods of `HttpServletRequest`, as discussed in <<_authenticating_users_programmatically>>. When you try to access a web resource that is constrained by a `security-constraint` element, the web container activates the authentication mechanism that has been configured for that resource. The authentication mechanism specifies how the user will be prompted to log in. @@ -301,7 +301,7 @@ The following example shows how to declare form-based authentication in your dep ---- The login and error page locations are specified relative to the location of the deployment descriptor. -Examples of login and error pages are shown in <>. +Examples of login and error pages are shown in <<_creating_the_login_form_and_the_error_page>>. The following example shows how to declare digest authentication in your deployment descriptor: diff --git a/src/main/antora/modules/security/pages/security-webtier/security-webtier003.adoc b/src/main/antora/modules/security/pages/security-webtier/security-webtier003.adoc index bedceaf6..2529fe3a 100644 --- a/src/main/antora/modules/security/pages/security-webtier/security-webtier003.adoc +++ b/src/main/antora/modules/security/pages/security-webtier/security-webtier003.adoc @@ -145,7 +145,7 @@ If no user has been authenticated, this method returns `false`. This method expects a `String` user `role-name` parameter. + The `security-role-ref` element should be declared in the deployment descriptor with a `role-name` subelement containing the role name to be passed to the method. -Using security role references is discussed in <>. +Using security role references is discussed in <<_declaring_and_linking_role_references>>. * `getUserPrincipal` determines the principal name of the current user and returns a `java.security.Principal` object. If no user has been authenticated, this method returns `null`. diff --git a/src/main/antora/modules/security/pages/security-webtier/security-webtier004.adoc b/src/main/antora/modules/security/pages/security-webtier/security-webtier004.adoc index 9ee42f06..c722e243 100644 --- a/src/main/antora/modules/security/pages/security-webtier/security-webtier004.adoc +++ b/src/main/antora/modules/security/pages/security-webtier/security-webtier004.adoc @@ -8,9 +8,9 @@ The examples use annotations, programmatic security, and/or declarative security Here are some other locations where you will find examples of securing various types of applications: -* <> +* xref:security-jakartaee/security-jakartaee.adoc#_the_cart_secure_example_securing_an_enterprise_bean_with_declarative_security[The cart-secure Example: Securing an Enterprise Bean with Declarative Security] -* <> +* xref:security-jakartaee/security-jakartaee.adoc#_the_converter_secure_example_securing_an_enterprise_bean_with_programmatic_security[The converter-secure Example: Securing an Enterprise Bean with Programmatic Security] * Eclipse GlassFish samples for Jakarta EE 9: https://github.com/eclipse-ee4j/glassfish-samples[^] @@ -22,7 +22,7 @@ Before continuing, follow these steps. . Make sure that GlassFish Server has been started (see <>). . Add an authorized user to GlassFish Server. -For the examples in this chapter and in <>, add a user to the `file` realm of GlassFish Server, and assign the user to the group `TutorialUser`. +For the examples in this chapter and in xref:security-jakartaee/security-jakartaee.adoc#_getting_started_securing_enterprise_applications[Getting Started Securing Enterprise Applications], add a user to the `file` realm of GlassFish Server, and assign the user to the group `TutorialUser`. .. From the Administration Console, expand the Configurations node, then expand the server-config node. @@ -46,7 +46,7 @@ For the examples in this chapter and in <>. +This topic is discussed more in xref:security-intro/security-intro.adoc#_managing_users_and_groups_in_glassfish_server[Managing Users and Groups in GlassFish Server]. + [NOTE] Jakarta Security requires that group principal names are mapped to roles of the same name by default. @@ -58,19 +58,19 @@ This example explains how to use basic authentication with a servlet. With basic authentication of a servlet, the web browser presents a standard login dialog box that is not customizable. When a user submits his or her name and password, the server determines whether the user name and password are those of an authorized user and sends the requested web resource if the user is authorized to view it. -In general, the following steps are necessary for adding basic authentication to an unsecured servlet, such as the ones described in xref:getting-started-with-web-applications[xrefstyle=full]. +In general, the following steps are necessary for adding basic authentication to an unsecured servlet, such as the ones described in xref:getting-started-with-web-applications[]. In the example application included with this tutorial, many of these steps have been completed for you and are listed here simply to show what needs to be done should you wish to create a similar application. This application can be found in the `_tut-install_/examples/security/hello2-basicauth/` directory. -. Follow the steps in <>. +. Follow the steps in <<_to_set_up_your_system_for_running_the_security_examples>>. -. Create a web module for the servlet example, `hello2`, as described in xref:getting-started-with-web-applications[xrefstyle=full]. +. Create a web module for the servlet example, `hello2`, as described in xref:getting-started-with-web-applications[]. -. Add the appropriate security annotations to the servlet. The security annotations are described in <>. +. Add the appropriate security annotations to the servlet. The security annotations are described in <<_specifying_security_for_basic_authentication_using_annotations>>. -. Build, package, and deploy the web application by following the steps in <> or <>. +. Build, package, and deploy the web application by following the steps in <<_to_build_package_and_deploy_the_hello2_basicauth_example_using_netbeans_ide>> or <<_to_build_package_and_deploy_the_hello2_basicauth_example_using_maven>>. -. Run the web application by following the steps described in <>. +. Run the web application by following the steps described in <<_to_run_the_hello2_basicauth_example>>. ==== Specifying Security for Basic Authentication Using Annotations @@ -111,7 +111,7 @@ Use the deployment descriptor to specify settings for nondefault authentication ==== To Build, Package, and Deploy the hello2-basicauth Example Using NetBeans IDE -. Follow the steps in <>. +. Follow the steps in <<_to_set_up_your_system_for_running_the_security_examples>>. . From the File menu, choose Open Project. @@ -131,7 +131,7 @@ This command builds and deploys the example application to your GlassFish Server ==== To Build, Package, and Deploy the hello2-basicauth Example Using Maven -. Follow the steps in <>. +. Follow the steps in <<_to_set_up_your_system_for_running_the_security_examples>>. . In a terminal window, go to: + @@ -192,9 +192,9 @@ When a user submits his or her name and password, the server determines whether This example, `hello1-formauth`, adds security to the basic Jakarta Faces application shown in <>. -In general, the steps necessary for adding form-based authentication to an unsecured Jakarta Faces application are similar to those described in <>. -The major difference is that you must use a deployment descriptor to specify the use of form-based authentication, as described in <>. -In addition, you must create a login form page and a login error page, as described in <>. +In general, the steps necessary for adding form-based authentication to an unsecured Jakarta Faces application are similar to those described in <<_the_hello2_basicauth_example_basic_authentication_with_a_servlet>>. +The major difference is that you must use a deployment descriptor to specify the use of form-based authentication, as described in <<_specifying_security_for_the_form_based_authentication_example>>. +In addition, you must create a login form page and a login error page, as described in <<_creating_the_login_form_and_the_error_page>>. This application can be found in the `_tut-install_/examples/security/hello1-formauth/` directory. @@ -202,7 +202,7 @@ This application can be found in the `_tut-install_/examples/security/hello1-for When using form-based login mechanisms, you must specify a page that contains the form you want to use to obtain the user name and password, as well as a page to display if login authentication fails. This section discusses the login form and the error page used in this example. -<> shows how you specify these pages in the deployment descriptor. +<<_specifying_security_for_the_form_based_authentication_example>> shows how you specify these pages in the deployment descriptor. The login page can be an HTML page or a servlet, and it must return an HTML page containing a form that conforms to specific naming conventions (see the Jakarta Servlet 5.0 specification for more information on these requirements). To do this, include the elements that accept user name and password information between `
` tags in your login page. @@ -311,7 +311,7 @@ The following sample code shows the security elements added to the deployment de ==== To Build, Package, and Deploy the hello1-formauth Example Using NetBeans IDE -. Follow the steps in <>. +. Follow the steps in <<_to_set_up_your_system_for_running_the_security_examples>>. . From the File menu, choose Open Project. @@ -331,7 +331,7 @@ This command builds and deploys the example application to your GlassFish Server ==== To Build, Package, and Deploy the hello1-formauth Example Using Maven and the asadmin Command -. Follow the steps in <>. +. Follow the steps in <<_to_set_up_your_system_for_running_the_security_examples>>. . In a terminal window, go to: + From 889fbae7af5b3ef901f38f0066df5e79da6ba05c Mon Sep 17 00:00:00 2001 From: "Kito D. Mann" Date: Tue, 30 May 2023 14:06:54 -0400 Subject: [PATCH 028/247] JETUT-56 Removed figure-caption and added global xrefstyle:full attribute --- src/main/antora/antora.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/antora/antora.yml b/src/main/antora/antora.yml index 7d8da3c5..53ac1909 100644 --- a/src/main/antora/antora.yml +++ b/src/main/antora/antora.yml @@ -5,7 +5,7 @@ asciidoc: attributes: source-language: asciidoc@ table-caption: false - figure-caption: false + xrefstyle: full nav: - modules/ROOT/nav.adoc - modules/security/nav.adoc From 141655631ad2975332d0b35f10c1219ba8752123 Mon Sep 17 00:00:00 2001 From: "Kito D. Mann" Date: Tue, 30 May 2023 15:27:54 -0400 Subject: [PATCH 029/247] JETUT-56 Made a few manual edits for some straggling references. --- .../pages/security-api/security-api005.adoc | 2 +- .../pages/security-intro/security-intro003a.adoc | 2 +- .../pages/security-intro/security-intro005.adoc | 2 +- .../security-jakartaee002.adoc | 16 ++++++++-------- .../security-webtier/security-webtier002.adoc | 2 +- 5 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/main/antora/modules/security/pages/security-api/security-api005.adoc b/src/main/antora/modules/security/pages/security-api/security-api005.adoc index 1e9c0d44..4f533b22 100644 --- a/src/main/antora/modules/security/pages/security-api/security-api005.adoc +++ b/src/main/antora/modules/security/pages/security-api/security-api005.adoc @@ -6,7 +6,7 @@ Topics include: * <<_overview_of_the_custom_identity_store_example>> -* <> +* <<_running_the_custom_identity_store_example>> === Overview of the Custom Identity Store Example diff --git a/src/main/antora/modules/security/pages/security-intro/security-intro003a.adoc b/src/main/antora/modules/security/pages/security-intro/security-intro003a.adoc index 60d27821..2f3feb55 100644 --- a/src/main/antora/modules/security/pages/security-intro/security-intro003a.adoc +++ b/src/main/antora/modules/security/pages/security-intro/security-intro003a.adoc @@ -5,7 +5,7 @@ These specifications are described in more detail in the following sections: * <<_jakarta_authentication>> -* <> +* <<_jakarta_security>> === Jakarta Authentication diff --git a/src/main/antora/modules/security/pages/security-intro/security-intro005.adoc b/src/main/antora/modules/security/pages/security-intro/security-intro005.adoc index 5484d562..bed57608 100644 --- a/src/main/antora/modules/security/pages/security-intro/security-intro005.adoc +++ b/src/main/antora/modules/security/pages/security-intro/security-intro005.adoc @@ -16,7 +16,7 @@ This step is discussed in <<_setting_up_security_roles>>. This is discussed in <<_managing_users_and_groups_in_glassfish_server>>. . The application deployer maps the application's security roles to users, groups, and principals defined in GlassFish Server. -This topic is discussed in <>. +This topic is discussed in <<_mapping_roles_to_users_and_groups>>. [NOTE] By default, group principal names are mapped to roles of the same name. diff --git a/src/main/antora/modules/security/pages/security-jakartaee/security-jakartaee002.adoc b/src/main/antora/modules/security/pages/security-jakartaee/security-jakartaee002.adoc index 66e4d763..70ac17c0 100644 --- a/src/main/antora/modules/security/pages/security-jakartaee/security-jakartaee002.adoc +++ b/src/main/antora/modules/security/pages/security-jakartaee/security-jakartaee002.adoc @@ -75,7 +75,7 @@ It is important to keep in mind that security roles are used to define the logic They should not be confused with the user groups, users, principals, and other concepts that exist in GlassFish Server. Note that the Jakarta Security requires that group principal names be mapped to roles of the same name by default, but that implementations of the standard may allow configuration of a different default. In GlassFish Server, you do not need to perform any additional steps to map the roles defined in the application to users, groups, and principals that are the components of the user database in the `file` realm. -This mapping is set by default in the GlassFish Server Administration Console as described in <>. +This mapping is set by default in the GlassFish Server Administration Console as described in xref:security-intro/security-intro.adoc#_mapping_roles_to_users_and_groups[Mapping Roles to Users and Groups]>. The following sections show how an application developer uses declarative security to either secure an application or to create a security view to pass along to the deployer. @@ -218,7 +218,7 @@ public class SomeClass { ... } -@Stateless +@Stateless public class MyBean extends SomeClass implements A { @RolesAllowed("HR") @@ -277,12 +277,12 @@ The following code sample illustrates the use of the `getCallerPrincipal` method + [source,java] ---- -@Stateless +@Stateless public class EmployeeServiceBean implements EmployeeService { - @Resource + @Resource SessionContext ctx; - - @PersistenceContext + + @PersistenceContext EntityManager em; public void changePhoneNumber(...) { @@ -318,9 +318,9 @@ The following code sample illustrates the use of the `isCallerInRole` method: + [source,java] ---- -@Stateless +@Stateless public class PayrollBean implements Payroll { - @Resource + @Resource SessionContext ctx; public void updateEmployeeInfo(EmplInfo info) { diff --git a/src/main/antora/modules/security/pages/security-webtier/security-webtier002.adoc b/src/main/antora/modules/security/pages/security-webtier/security-webtier002.adoc index 9cda5dbc..b0f88861 100644 --- a/src/main/antora/modules/security/pages/security-webtier/security-webtier002.adoc +++ b/src/main/antora/modules/security/pages/security-webtier/security-webtier002.adoc @@ -76,7 +76,7 @@ Role names are case sensitive. The roles defined for the application must be mapped to users and groups defined on the server, except when default principal-to-role mapping is used. For more information about security roles, see <<_declaring_security_roles>>. -For information on mapping security roles, see <>. +For information on mapping security roles, see xref:security-intro/security-intro.adoc#_mapping_roles_to_users_and_groups[Mapping Roles to Users and Groups]. For a servlet, the `@HttpConstraint` and `@HttpMethodConstraint` annotations accept a `rolesAllowed` element that specifies the authorized roles. From a000c70e280f6e16078cfc64f892185f46c46b5f Mon Sep 17 00:00:00 2001 From: "Kito D. Mann" Date: Tue, 30 May 2023 15:33:04 -0400 Subject: [PATCH 030/247] JETUT-56 Updated Antora instructions. --- antora-conversion/CONVERTING_TO_ANTORA.adoc | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/antora-conversion/CONVERTING_TO_ANTORA.adoc b/antora-conversion/CONVERTING_TO_ANTORA.adoc index 2003f296..34e43954 100644 --- a/antora-conversion/CONVERTING_TO_ANTORA.adoc +++ b/antora-conversion/CONVERTING_TO_ANTORA.adoc @@ -28,7 +28,7 @@ Here’s the current process for migrating an individual module (i.e. security, . Run the migration script from the root project folder. For example, for the Security module, you would run: ```shell -jbang antora-conversion/AntoraConverter.java jakartaee-tutorial/src/main/antora/modules/security +jbang antora-conversion/AntoraConverter.java src/main/antora/modules/security ``` > TIP: You can use the "dryrun" parameter to see what changes will be made without actually making them. @@ -69,7 +69,7 @@ After copying these into `nav.adoc`, replace "include::" with "* xref:" and add - modules/security/nav.adoc ``` -. Commit your changes, push, and raise a PR. You're done with the first part of the migration! +. Commit your changes, push, and raise a PR to merge into the `release/8` branch. You're done with the first part of the migration! === Migrating the Jakarta EE 9 branch @@ -84,3 +84,11 @@ jbang antora-conversion/AntoraConverter.java jakartaee-tutorial/src/main/antora/ ``` > TIP: You can use the "dryrun" parameter to see what changes will be made without actually making them. + +. If there are any changes the script didn't make, either make them manually or update the script to handle them. + +. Commit your changes, push, and raise a PR to merge into the `release/9.1` branch. + +. Raise a PR to merge `release/9.1` into `main`. + +. You're done! From c70794325b27b1114d3c875eec4966d79d7cc1ee Mon Sep 17 00:00:00 2001 From: "Kito D. Mann" Date: Tue, 30 May 2023 15:41:04 -0400 Subject: [PATCH 031/247] JETUT-56 Added a couple of notes to the Antora instructions. --- antora-conversion/CONVERTING_TO_ANTORA.adoc | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/antora-conversion/CONVERTING_TO_ANTORA.adoc b/antora-conversion/CONVERTING_TO_ANTORA.adoc index 34e43954..924f98dc 100644 --- a/antora-conversion/CONVERTING_TO_ANTORA.adoc +++ b/antora-conversion/CONVERTING_TO_ANTORA.adoc @@ -27,16 +27,21 @@ Here’s the current process for migrating an individual module (i.e. security, . Run the migration script from the root project folder. For example, for the Security module, you would run: -```shell +[source,shell] +---- jbang antora-conversion/AntoraConverter.java src/main/antora/modules/security -``` +---- > TIP: You can use the "dryrun" parameter to see what changes will be made without actually making them. + +> NOTE: References to chapters that haven't yet been converted will not work until they have been converted. + . Create a new file called `nav.adoc` in the root of the module folder. For example, for the Security module, you would create a `security/nav.adoc`. . Copy all the include statements from the corresponding "part" file in the `src/main/asciidoc/` folder. For example, for the Security module, you would copy the include statements of `src/main/asciidoc/partsecurity.adoc` into the `security/nav.adoc` file. Here are the include statements for the Security module: -```asciidoc +[source,asciidoc] +---- include::security-intro/security-intro.adoc[] include::security-webtier/security-webtier.adoc[] @@ -46,7 +51,7 @@ include::security-jakartaee/security-jakartaee.adoc[] include::security-api/security-api.adoc[] include::security-advanced/security-advanced.adoc[] -``` +---- After copying these into `nav.adoc`, replace "include::" with "* xref:" and add a header with the module name: @@ -85,8 +90,13 @@ jbang antora-conversion/AntoraConverter.java jakartaee-tutorial/src/main/antora/ > TIP: You can use the "dryrun" parameter to see what changes will be made without actually making them. +> NOTE: References to chapters that haven't yet been converted will not work until they have been converted. + . If there are any changes the script didn't make, either make them manually or update the script to handle them. +> TIP: If you're using the Antora IDE plugin, it helps to review its errors and updating before committing. With IntellJ, +these are run automatically before pushing. + . Commit your changes, push, and raise a PR to merge into the `release/9.1` branch. . Raise a PR to merge `release/9.1` into `main`. From 03eaf12f0c825a2eb86ca0a830357b02fcce9850 Mon Sep 17 00:00:00 2001 From: "Kito D. Mann" Date: Tue, 30 May 2023 22:08:20 -0400 Subject: [PATCH 032/247] JETUT-56 Renamed Antora component to be "jakarta-ee-tutorial". --- src/main/antora/antora.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/antora/antora.yml b/src/main/antora/antora.yml index 46eace97..e2e0548a 100644 --- a/src/main/antora/antora.yml +++ b/src/main/antora/antora.yml @@ -1,5 +1,5 @@ -name: jakarta-ee-docs -title: Jakarta EE Documentation +name: jakarta-ee-tutorial +title: Jakarta EE Tutorial version: 8 asciidoc: attributes: From df770b88edce731dadb2f029746232557b9df452 Mon Sep 17 00:00:00 2001 From: "Kito D. Mann" Date: Tue, 30 May 2023 22:09:08 -0400 Subject: [PATCH 033/247] JETUT-56 Removed extra test page and made the initial page the preface. --- src/main/antora/modules/ROOT/nav.adoc | 1 - src/main/antora/modules/ROOT/pages/index.adoc | 6 +++--- src/main/antora/modules/ROOT/pages/page2.adoc | 3 --- 3 files changed, 3 insertions(+), 7 deletions(-) delete mode 100644 src/main/antora/modules/ROOT/pages/page2.adoc diff --git a/src/main/antora/modules/ROOT/nav.adoc b/src/main/antora/modules/ROOT/nav.adoc index 73c45032..31f850ee 100644 --- a/src/main/antora/modules/ROOT/nav.adoc +++ b/src/main/antora/modules/ROOT/nav.adoc @@ -1,2 +1 @@ * xref:index.adoc[] -* xref:page2.adoc[] diff --git a/src/main/antora/modules/ROOT/pages/index.adoc b/src/main/antora/modules/ROOT/pages/index.adoc index 7aebdccd..43854246 100644 --- a/src/main/antora/modules/ROOT/pages/index.adoc +++ b/src/main/antora/modules/ROOT/pages/index.adoc @@ -1,5 +1,5 @@ -= Overview += Preface -Hey there! This is a version the Jakarta EE Tutorial built using https://antora.org/[Antora] (and still using Asciidoc). +Hello there! This is a version of the Jakarta EE Tutorial built using https://antora.org/[Antora] (and still using https://asciidoctor.org[Asciidoc]). -This is a work in progress. +This is a work in progress. We will be migrating all chapters to this new format. diff --git a/src/main/antora/modules/ROOT/pages/page2.adoc b/src/main/antora/modules/ROOT/pages/page2.adoc deleted file mode 100644 index b782b1e4..00000000 --- a/src/main/antora/modules/ROOT/pages/page2.adoc +++ /dev/null @@ -1,3 +0,0 @@ -= Page 2 - -Lorem ipsum blah blah blah blah blah foo bar baz baz foo. From de6cdb862210b8e4c35f9ccc482227e662920235 Mon Sep 17 00:00:00 2001 From: "Kito D. Mann" Date: Tue, 30 May 2023 22:08:20 -0400 Subject: [PATCH 034/247] JETUT-56 Renamed Antora component to be "jakarta-ee-tutorial". --- src/main/antora/antora.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/antora/antora.yml b/src/main/antora/antora.yml index 53ac1909..72ad9be2 100644 --- a/src/main/antora/antora.yml +++ b/src/main/antora/antora.yml @@ -1,5 +1,5 @@ -name: jakarta-ee-docs -title: Jakarta EE Documentation +name: jakarta-ee-tutorial +title: Jakarta EE Tutorial version: 9.1 asciidoc: attributes: From 806376405ac1a99a9b7afb215e129810c78dcb39 Mon Sep 17 00:00:00 2001 From: "Kito D. Mann" Date: Tue, 30 May 2023 22:09:08 -0400 Subject: [PATCH 035/247] JETUT-56 Removed extra test page and made the initial page the preface. --- src/main/antora/modules/ROOT/nav.adoc | 1 - src/main/antora/modules/ROOT/pages/index.adoc | 6 +++--- src/main/antora/modules/ROOT/pages/page2.adoc | 3 --- 3 files changed, 3 insertions(+), 7 deletions(-) delete mode 100644 src/main/antora/modules/ROOT/pages/page2.adoc diff --git a/src/main/antora/modules/ROOT/nav.adoc b/src/main/antora/modules/ROOT/nav.adoc index 73c45032..31f850ee 100644 --- a/src/main/antora/modules/ROOT/nav.adoc +++ b/src/main/antora/modules/ROOT/nav.adoc @@ -1,2 +1 @@ * xref:index.adoc[] -* xref:page2.adoc[] diff --git a/src/main/antora/modules/ROOT/pages/index.adoc b/src/main/antora/modules/ROOT/pages/index.adoc index 7aebdccd..43854246 100644 --- a/src/main/antora/modules/ROOT/pages/index.adoc +++ b/src/main/antora/modules/ROOT/pages/index.adoc @@ -1,5 +1,5 @@ -= Overview += Preface -Hey there! This is a version the Jakarta EE Tutorial built using https://antora.org/[Antora] (and still using Asciidoc). +Hello there! This is a version of the Jakarta EE Tutorial built using https://antora.org/[Antora] (and still using https://asciidoctor.org[Asciidoc]). -This is a work in progress. +This is a work in progress. We will be migrating all chapters to this new format. diff --git a/src/main/antora/modules/ROOT/pages/page2.adoc b/src/main/antora/modules/ROOT/pages/page2.adoc deleted file mode 100644 index b782b1e4..00000000 --- a/src/main/antora/modules/ROOT/pages/page2.adoc +++ /dev/null @@ -1,3 +0,0 @@ -= Page 2 - -Lorem ipsum blah blah blah blah blah foo bar baz baz foo. From 95f01a1a1b1f16908bc2c56495c9e5c5401a385c Mon Sep 17 00:00:00 2001 From: "Kito D. Mann" Date: Wed, 31 May 2023 09:50:35 -0400 Subject: [PATCH 036/247] JETUT-56 Updated the Antora component version --- src/main/antora/antora.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/antora/antora.yml b/src/main/antora/antora.yml index 72ad9be2..093dea2f 100644 --- a/src/main/antora/antora.yml +++ b/src/main/antora/antora.yml @@ -1,6 +1,6 @@ name: jakarta-ee-tutorial title: Jakarta EE Tutorial -version: 9.1 +version: 10 asciidoc: attributes: source-language: asciidoc@ From 2e268680da849627f713382d4fe57d2321ae99f2 Mon Sep 17 00:00:00 2001 From: "Kito D. Mann" Date: Wed, 31 May 2023 09:50:48 -0400 Subject: [PATCH 037/247] JETUT-56 Updated preface prose for Jakarta EE 10 --- src/main/antora/modules/ROOT/pages/index.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/antora/modules/ROOT/pages/index.adoc b/src/main/antora/modules/ROOT/pages/index.adoc index 43854246..d89dbed8 100644 --- a/src/main/antora/modules/ROOT/pages/index.adoc +++ b/src/main/antora/modules/ROOT/pages/index.adoc @@ -2,4 +2,4 @@ Hello there! This is a version of the Jakarta EE Tutorial built using https://antora.org/[Antora] (and still using https://asciidoctor.org[Asciidoc]). -This is a work in progress. We will be migrating all chapters to this new format. +This is a work in progress. We will be migrating all chapters to this new format and also revising the content for Jakarta EE 10 and beyond. From ccd27529d0d3c9b0cd1a56bce7f50d5264758e00 Mon Sep 17 00:00:00 2001 From: "Kito D. Mann" Date: Wed, 31 May 2023 10:04:33 -0400 Subject: [PATCH 038/247] JETUT-56 Removed accidental commit of Github workflow. This is handled by the playbook. --- .github/workflows/build.yml | 36 ------------------------------------ 1 file changed, 36 deletions(-) delete mode 100644 .github/workflows/build.yml diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml deleted file mode 100644 index f94044c0..00000000 --- a/.github/workflows/build.yml +++ /dev/null @@ -1,36 +0,0 @@ -name: build - -on: - push: - branches: - - master - - release/* - pull_request: - branches: - - master - -jobs: - - build: - runs-on: ubuntu-latest - steps: - - - uses: actions/checkout@v1 - - - name: Set up JDK 1.8 - uses: actions/setup-java@v1 - with: - java-version: 1.8 - - - name: Build Docs - run: mvn clean package --file pom.xml #-Ppublish-site - - - name: Deploy 🚀 - uses: JamesIves/github-pages-deploy-action@3.7.1 - with: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - BRANCH: gh-pages # The branch the action should deploy to. - FOLDER: target/generated-docs # The folder the action should deploy. - CLEAN: true # Automatically remove deleted files from the deploy folder - - From c03c917096871127c5ac9aeaca4d07a9c0076122 Mon Sep 17 00:00:00 2001 From: "Kito D. Mann" Date: Wed, 31 May 2023 10:12:51 -0400 Subject: [PATCH 039/247] JETUT-56 Removed autoxref-treeprocessor (for now). --- src/main/ruby/autoxref-treeprocessor.rb | 140 ------------------------ 1 file changed, 140 deletions(-) delete mode 100644 src/main/ruby/autoxref-treeprocessor.rb diff --git a/src/main/ruby/autoxref-treeprocessor.rb b/src/main/ruby/autoxref-treeprocessor.rb deleted file mode 100644 index ca692baf..00000000 --- a/src/main/ruby/autoxref-treeprocessor.rb +++ /dev/null @@ -1,140 +0,0 @@ -# coding: utf-8 -# autoxref-treeprocessor.rb: Automatic cross-reference generator. -# -# Copyright (c) 2016, 2021 Takahiro Yoshimura -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions -# are met: -# -# 1. Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# -# 2. Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# -# 3. Neither the name of the copyright holder nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -# POSSIBILITY OF SUCH DAMAGE. -require 'asciidoctor/extensions' - -include Asciidoctor - -Extensions.register do - treeprocessor AutoXrefTreeprocessor -end - -# A treeprocessor that allows refering sections and titled -# images/listings/tables with their reference number (e.g. Figure -# .1, .2, ... for images). -# -# Works by assigning reference number-based captions (RNBCs) for -# targets, and updates reference table in the document with them. -# -# Run using: -# -# asciidoctor -r ./lib/autoxref-treeprocessor.rb lib/autoxref-treeprocessor/sample.adoc -class AutoXrefTreeprocessor < Extensions::Treeprocessor - def process document - # The initial value of the chapter counter. - initial_chapter = attr_of(document, 'autoxref-chapter') { 1 } - - # The section level we should treat as chapters. - chapter_section_level = (document.attr 'autoxref-chaptersectlevel', 2).to_i - - # Captions should we use. - captions = { - :section => (document.attr 'autoxref-sectcaption', "Section %d.%d"), - :image => (document.attr 'autoxref-imagecaption', "Figure %d.%d"), - :listing => (document.attr 'autoxref-listingcaption', "Listing %d.%d"), - :table => (document.attr 'autoxref-tablecaption', "Table %d.%d") - } - - # Reference number counter. Reference numbers are reset by chapters. - counter = { - :chapter => initial_chapter, - :section => 1, - :image => 1, - :listing => 1, - :table => 1 - } - - seen = false - - # Scan for chapters. - document.find_by(context: :section).each do |chapter| - next unless not seen or chapter.numbered && chapter.level == chapter_section_level - seen = true - - # XXX crude care for chapterless documents - if chapter.level != chapter_section_level then - chapter = document - end - - # Assign chapter number and reset our reference numbers. - chap = attr_of(chapter, 'autoxref-chapter') { get_and_tally_counter_of(:chapter, counter) } - counter.update( - { - :section => 1, - :image => 1, - :listing => 1, - :table => 1 - } - ) - - # Scan for sections, titled images/listings/tables in the chapter. - [:section, :image, :listing, :table].each do |type| - chapter.find_by(context: type).each do |el| - # Generate RNBCs for eligible targets and update reference table in the document. For non-sections, we also overwrite their captions with RNBCs. - if type != :section then - if el.title? then - replaced = captions[type] % [chap, get_and_tally_counter_of(type, counter)] - replaced_caption = replaced + ' ' - el.attributes['caption'] = replaced_caption - el.attributes['reftext'] = replaced - el.caption = replaced_caption - document.references[:ids][el.attributes['id']] = replaced - end - elsif el.level == chapter_section_level + 1 then - replaced = captions[type] % [chap, get_and_tally_counter_of(type, counter)] - document.references[:ids][el.attributes['id']] = replaced - end - end - end - end - nil - end - - # Gets and increments the value for the given type in the given - # counter. - def get_and_tally_counter_of type, counter - t = counter[type] - counter[type] = counter[type] + 1 - t - end - - # Retrieves the associated value for the given key. Lazily retrieve - # default value if no attr is set on the given key. - def attr_of target, key, &default - begin - (target.attr key, :none).to_i - rescue NoMethodError - if not default.nil? then default.call else 0 end - end - end -end \ No newline at end of file From 1b34650da11326ef5d77d3ddb6be77c924153835 Mon Sep 17 00:00:00 2001 From: "Kito D. Mann" Date: Wed, 31 May 2023 10:51:49 -0400 Subject: [PATCH 040/247] JETUT-56 Added refreshed security chapter and commented out old chapters --- src/main/antora/modules/security/nav.adoc | 12 +++++++----- .../modules/security/pages}/security.adoc | 4 ++-- 2 files changed, 9 insertions(+), 7 deletions(-) rename src/main/{asciidoc/security-refresh => antora/modules/security/pages}/security.adoc (99%) diff --git a/src/main/antora/modules/security/nav.adoc b/src/main/antora/modules/security/nav.adoc index 746f93a7..24276def 100644 --- a/src/main/antora/modules/security/nav.adoc +++ b/src/main/antora/modules/security/nav.adoc @@ -1,8 +1,10 @@ .Security -* xref:security-intro/security-intro.adoc[] -* xref:security-webtier/security-webtier.adoc[] -* xref:security-jakartaee/security-jakartaee.adoc[] -* xref:security-api/security-api.adoc[] -* xref:security-advanced/security-advanced.adoc[] +* xref:security.adoc[] +// We can add these back as needed for any chapters that we intend to keep +// * xref:security-intro/security-intro.adoc[] +// * xref:security-webtier/security-webtier.adoc[] +// * xref:security-jakartaee/security-jakartaee.adoc[] +// * xref:security-api/security-api.adoc[] +// * xref:security-advanced/security-advanced.adoc[] diff --git a/src/main/asciidoc/security-refresh/security.adoc b/src/main/antora/modules/security/pages/security.adoc similarity index 99% rename from src/main/asciidoc/security-refresh/security.adoc rename to src/main/antora/modules/security/pages/security.adoc index 2c65905a..5430db6c 100644 --- a/src/main/asciidoc/security-refresh/security.adoc +++ b/src/main/antora/modules/security/pages/security.adoc @@ -26,9 +26,9 @@ The first two of these are used in the authentication process: An _authentication mechanism_ is somewhat like a controller in the well-known MVC pattern; it is the entity that interacts with the caller (typically a human), via some kind of view to collect credentials, and with the model (business logic) to validate `these` credentials. An authentication mechanism knows about the environment this caller uses to communicate with the server. An authentication mechanism for HTTP knows about URLs to redirect or forward to, or about response headers to send to the client. It also knows about the data coming back, such as cookies, request headers, and post data. Examples of authentication mechanisms are Form authentication and Basic authentication. An _identity store_ is more like the model in the MVC pattern. This entity strictly performs a business / data operation where credentials go in, and an identity comes out. The identity contains logic to validate said credentials, and embeds or contacts a database. This "database" contains usernames, along with their credentials and (typically) roles. An identity store therefore knows nothing about the environment that this caller uses to communicate with the server; e.g., it doesn't know about HTTP or headers etc. -Example of identity stores are services that contact SQL/JDBC databases, LDAP servers, files on the file-system, etc. +Some examples of identity stores are services that contact SQL/JDBC databases, LDAP servers, files on the file-system, etc. -image::authentication_mvc.svg["Diagram illustrating the role of the authentication mechanism and identity store in an MVC like structure"] +image::common:authentication_mvc.svg["Diagram illustrating the role of the authentication mechanism and identity store in an MVC like structure"] The third one is used for the authorization process: From b5ea9d39048f9bde84fd75a3c1cb27014101637c Mon Sep 17 00:00:00 2001 From: "Kito D. Mann" Date: Wed, 31 May 2023 18:09:26 -0400 Subject: [PATCH 041/247] JETUT-56 Changed component name to "jakartaee-tutorial" to be more consistent with repo names. --- src/main/antora/antora.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/antora/antora.yml b/src/main/antora/antora.yml index 093dea2f..cd1b3833 100644 --- a/src/main/antora/antora.yml +++ b/src/main/antora/antora.yml @@ -1,4 +1,4 @@ -name: jakarta-ee-tutorial +name: jakartaee-tutorial title: Jakarta EE Tutorial version: 10 asciidoc: From 27aa9405a93a311a42a8188848b5076131d0a720 Mon Sep 17 00:00:00 2001 From: "Kito D. Mann" Date: Wed, 31 May 2023 18:11:26 -0400 Subject: [PATCH 042/247] JETUT-56 Changed component name to "jakartaee-tutorial" to be more consistent with repo names. --- src/main/antora/antora.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/antora/antora.yml b/src/main/antora/antora.yml index e2e0548a..690feab4 100644 --- a/src/main/antora/antora.yml +++ b/src/main/antora/antora.yml @@ -1,4 +1,4 @@ -name: jakarta-ee-tutorial +name: jakartaee-tutorial title: Jakarta EE Tutorial version: 8 asciidoc: From 2fc6e0c43671bcbe49116d23078b3406da3cdedb Mon Sep 17 00:00:00 2001 From: "Kito D. Mann" Date: Wed, 31 May 2023 18:14:11 -0400 Subject: [PATCH 043/247] JETUT-56 Changed component name to "jakartaee-tutorial" to be more consistent with repo names. --- src/main/antora/antora.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/antora/antora.yml b/src/main/antora/antora.yml index 72ad9be2..6b0737b4 100644 --- a/src/main/antora/antora.yml +++ b/src/main/antora/antora.yml @@ -1,4 +1,4 @@ -name: jakarta-ee-tutorial +name: jakartaee-tutorial title: Jakarta EE Tutorial version: 9.1 asciidoc: From 3d1cd53bfd319d70d2064e5f573d74d10825b96d Mon Sep 17 00:00:00 2001 From: "Kito D. Mann" Date: Thu, 1 Jun 2023 11:56:13 -0400 Subject: [PATCH 044/247] JETUT-120 Moved web tier chapters --- .../modules/web/pages}/jsf-advanced-cc/jsf-advanced-cc.adoc | 0 .../modules/web/pages}/jsf-advanced-cc/jsf-advanced-cc001.adoc | 0 .../modules/web/pages}/jsf-advanced-cc/jsf-advanced-cc002.adoc | 0 .../modules/web/pages}/jsf-advanced-cc/jsf-advanced-cc003.adoc | 0 .../modules/web/pages}/jsf-advanced-cc/jsf-advanced-cc004.adoc | 0 .../{asciidoc => antora/modules/web/pages}/jsf-ajax/jsf-ajax.adoc | 0 .../modules/web/pages}/jsf-ajax/jsf-ajax001.adoc | 0 .../modules/web/pages}/jsf-ajax/jsf-ajax002.adoc | 0 .../modules/web/pages}/jsf-ajax/jsf-ajax003.adoc | 0 .../modules/web/pages}/jsf-ajax/jsf-ajax004.adoc | 0 .../modules/web/pages}/jsf-ajax/jsf-ajax005.adoc | 0 .../modules/web/pages}/jsf-ajax/jsf-ajax006.adoc | 0 .../modules/web/pages}/jsf-ajax/jsf-ajax007.adoc | 0 .../modules/web/pages}/jsf-ajax/jsf-ajax008.adoc | 0 .../modules/web/pages}/jsf-ajax/jsf-ajax009.adoc | 0 .../modules/web/pages}/jsf-ajax/jsf-ajax010.adoc | 0 .../modules/web/pages}/jsf-ajax/jsf-ajax011.adoc | 0 .../modules/web/pages}/jsf-ajax/jsf-ajax012.adoc | 0 .../modules/web/pages}/jsf-configure/jsf-configure.adoc | 0 .../modules/web/pages}/jsf-configure/jsf-configure001.adoc | 0 .../modules/web/pages}/jsf-configure/jsf-configure002.adoc | 0 .../modules/web/pages}/jsf-configure/jsf-configure003.adoc | 0 .../modules/web/pages}/jsf-configure/jsf-configure004.adoc | 0 .../modules/web/pages}/jsf-configure/jsf-configure005.adoc | 0 .../modules/web/pages}/jsf-configure/jsf-configure006.adoc | 0 .../modules/web/pages}/jsf-configure/jsf-configure007.adoc | 0 .../modules/web/pages}/jsf-configure/jsf-configure008.adoc | 0 .../modules/web/pages}/jsf-configure/jsf-configure009.adoc | 0 .../modules/web/pages}/jsf-configure/jsf-configure010.adoc | 0 .../modules/web/pages}/jsf-configure/jsf-configure011.adoc | 0 .../modules/web/pages}/jsf-configure/jsf-configure012.adoc | 0 .../modules/web/pages}/jsf-configure/jsf-configure013.adoc | 0 .../modules/web/pages}/jsf-custom/jsf-custom.adoc | 0 .../modules/web/pages}/jsf-custom/jsf-custom001.adoc | 0 .../modules/web/pages}/jsf-custom/jsf-custom002.adoc | 0 .../modules/web/pages}/jsf-custom/jsf-custom003.adoc | 0 .../modules/web/pages}/jsf-custom/jsf-custom004.adoc | 0 .../modules/web/pages}/jsf-custom/jsf-custom005.adoc | 0 .../modules/web/pages}/jsf-custom/jsf-custom006.adoc | 0 .../modules/web/pages}/jsf-custom/jsf-custom007.adoc | 0 .../modules/web/pages}/jsf-custom/jsf-custom008.adoc | 0 .../modules/web/pages}/jsf-custom/jsf-custom009.adoc | 0 .../modules/web/pages}/jsf-custom/jsf-custom010.adoc | 0 .../modules/web/pages}/jsf-custom/jsf-custom011.adoc | 0 .../modules/web/pages}/jsf-custom/jsf-custom012.adoc | 0 .../modules/web/pages}/jsf-custom/jsf-custom013.adoc | 0 .../modules/web/pages}/jsf-custom/jsf-custom014.adoc | 0 .../modules/web/pages}/jsf-develop/jsf-develop.adoc | 0 .../modules/web/pages}/jsf-develop/jsf-develop001.adoc | 0 .../modules/web/pages}/jsf-develop/jsf-develop002.adoc | 0 .../modules/web/pages}/jsf-develop/jsf-develop003.adoc | 0 .../{asciidoc => antora/modules/web/pages}/jsf-el/jsf-el.adoc | 0 .../{asciidoc => antora/modules/web/pages}/jsf-el/jsf-el001.adoc | 0 .../{asciidoc => antora/modules/web/pages}/jsf-el/jsf-el002.adoc | 0 .../{asciidoc => antora/modules/web/pages}/jsf-el/jsf-el003.adoc | 0 .../{asciidoc => antora/modules/web/pages}/jsf-el/jsf-el004.adoc | 0 .../{asciidoc => antora/modules/web/pages}/jsf-el/jsf-el005.adoc | 0 .../{asciidoc => antora/modules/web/pages}/jsf-el/jsf-el006.adoc | 0 .../{asciidoc => antora/modules/web/pages}/jsf-el/jsf-el007.adoc | 0 .../{asciidoc => antora/modules/web/pages}/jsf-el/jsf-el008.adoc | 0 .../modules/web/pages}/jsf-facelets/jsf-facelets.adoc | 0 .../modules/web/pages}/jsf-facelets/jsf-facelets001.adoc | 0 .../modules/web/pages}/jsf-facelets/jsf-facelets002.adoc | 0 .../modules/web/pages}/jsf-facelets/jsf-facelets003.adoc | 0 .../modules/web/pages}/jsf-facelets/jsf-facelets004.adoc | 0 .../modules/web/pages}/jsf-facelets/jsf-facelets005.adoc | 0 .../modules/web/pages}/jsf-facelets/jsf-facelets006.adoc | 0 .../modules/web/pages}/jsf-facelets/jsf-facelets007.adoc | 0 .../modules/web/pages}/jsf-facelets/jsf-facelets008.adoc | 0 .../modules/web/pages}/jsf-facelets/jsf-facelets009.adoc | 0 .../modules/web/pages}/jsf-intro/jsf-intro.adoc | 0 .../modules/web/pages}/jsf-intro/jsf-intro001.adoc | 0 .../modules/web/pages}/jsf-intro/jsf-intro002.adoc | 0 .../modules/web/pages}/jsf-intro/jsf-intro003.adoc | 0 .../modules/web/pages}/jsf-intro/jsf-intro004.adoc | 0 .../modules/web/pages}/jsf-intro/jsf-intro005.adoc | 0 .../modules/web/pages}/jsf-intro/jsf-intro006.adoc | 0 .../modules/web/pages}/jsf-intro/jsf-intro007.adoc | 0 .../modules/web/pages}/jsf-intro/jsf-intro008.adoc | 0 .../modules/web/pages}/jsf-intro/jsf-intro009.adoc | 0 .../modules/web/pages}/jsf-page-core/jsf-page-core.adoc | 0 .../modules/web/pages}/jsf-page-core/jsf-page-core001.adoc | 0 .../modules/web/pages}/jsf-page-core/jsf-page-core002.adoc | 0 .../modules/web/pages}/jsf-page-core/jsf-page-core003.adoc | 0 .../modules/web/pages}/jsf-page-core/jsf-page-core004.adoc | 0 .../{asciidoc => antora/modules/web/pages}/jsf-page/jsf-page.adoc | 0 .../modules/web/pages}/jsf-page/jsf-page001.adoc | 0 .../modules/web/pages}/jsf-page/jsf-page002.adoc | 0 .../modules/web/pages}/jsf-page/jsf-page003.adoc | 0 .../{asciidoc => antora/modules/web/pages}/jsf-ws/jsf-ws.adoc | 0 .../{asciidoc => antora/modules/web/pages}/jsf-ws/jsf-ws001.adoc | 0 .../{asciidoc => antora/modules/web/pages}/jsf-ws/jsf-ws002.adoc | 0 .../{asciidoc => antora/modules/web/pages}/jsf-ws/jsf-ws003.adoc | 0 .../{asciidoc => antora/modules/web/pages}/jsf-ws/jsf-ws004.adoc | 0 .../{asciidoc => antora/modules/web/pages}/jsf-ws/jsf-ws005.adoc | 0 .../{asciidoc => antora/modules/web/pages}/jsf-ws/jsf-ws006.adoc | 0 .../{asciidoc => antora/modules/web/pages}/jsf-ws/jsf-ws007.adoc | 0 src/main/{asciidoc => antora/modules/web/pages}/jsonb/jsonb.adoc | 0 .../{asciidoc => antora/modules/web/pages}/jsonb/jsonb001.adoc | 0 .../{asciidoc => antora/modules/web/pages}/jsonb/jsonb002.adoc | 0 .../{asciidoc => antora/modules/web/pages}/jsonb/jsonb003.adoc | 0 .../{asciidoc => antora/modules/web/pages}/jsonb/jsonb004.adoc | 0 src/main/{asciidoc => antora/modules/web/pages}/jsonp/jsonp.adoc | 0 .../{asciidoc => antora/modules/web/pages}/jsonp/jsonp001.adoc | 0 .../{asciidoc => antora/modules/web/pages}/jsonp/jsonp002.adoc | 0 .../{asciidoc => antora/modules/web/pages}/jsonp/jsonp003.adoc | 0 .../{asciidoc => antora/modules/web/pages}/jsonp/jsonp004.adoc | 0 .../{asciidoc => antora/modules/web/pages}/jsonp/jsonp005.adoc | 0 .../{asciidoc => antora/modules/web/pages}/jsonp/jsonp006.adoc | 0 .../{asciidoc => antora/modules/web/pages}/jsonp/jsonp007.adoc | 0 .../{asciidoc => antora/modules/web/pages}/jsonp/jsonp008.adoc | 0 .../{asciidoc => antora/modules/web/pages}/servlets/servlets.adoc | 0 .../modules/web/pages}/servlets/servlets001.adoc | 0 .../modules/web/pages}/servlets/servlets002.adoc | 0 .../modules/web/pages}/servlets/servlets003.adoc | 0 .../modules/web/pages}/servlets/servlets004.adoc | 0 .../modules/web/pages}/servlets/servlets005.adoc | 0 .../modules/web/pages}/servlets/servlets006.adoc | 0 .../modules/web/pages}/servlets/servlets007.adoc | 0 .../modules/web/pages}/servlets/servlets008.adoc | 0 .../modules/web/pages}/servlets/servlets009.adoc | 0 .../modules/web/pages}/servlets/servlets010.adoc | 0 .../modules/web/pages}/servlets/servlets011.adoc | 0 .../modules/web/pages}/servlets/servlets012.adoc | 0 .../modules/web/pages}/servlets/servlets013.adoc | 0 .../modules/web/pages}/servlets/servlets014.adoc | 0 .../modules/web/pages}/servlets/servlets014a.adoc | 0 .../modules/web/pages}/servlets/servlets014b.adoc | 0 .../modules/web/pages}/servlets/servlets015.adoc | 0 .../modules/web/pages}/servlets/servlets016.adoc | 0 .../modules/web/pages}/servlets/servlets017.adoc | 0 .../modules/web/pages}/servlets/servlets018.adoc | 0 .../{asciidoc => antora/modules/web/pages}/webapp/webapp.adoc | 0 .../{asciidoc => antora/modules/web/pages}/webapp/webapp001.adoc | 0 .../{asciidoc => antora/modules/web/pages}/webapp/webapp002.adoc | 0 .../{asciidoc => antora/modules/web/pages}/webapp/webapp003.adoc | 0 .../{asciidoc => antora/modules/web/pages}/webapp/webapp004.adoc | 0 .../{asciidoc => antora/modules/web/pages}/webapp/webapp005.adoc | 0 .../{asciidoc => antora/modules/web/pages}/webapp/webapp006.adoc | 0 .../{asciidoc => antora/modules/web/pages}/webi18n/webi18n.adoc | 0 .../modules/web/pages}/webi18n/webi18n001.adoc | 0 .../modules/web/pages}/webi18n/webi18n002.adoc | 0 .../modules/web/pages}/webi18n/webi18n003.adoc | 0 .../modules/web/pages}/webi18n/webi18n004.adoc | 0 144 files changed, 0 insertions(+), 0 deletions(-) rename src/main/{asciidoc => antora/modules/web/pages}/jsf-advanced-cc/jsf-advanced-cc.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/jsf-advanced-cc/jsf-advanced-cc001.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/jsf-advanced-cc/jsf-advanced-cc002.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/jsf-advanced-cc/jsf-advanced-cc003.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/jsf-advanced-cc/jsf-advanced-cc004.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/jsf-ajax/jsf-ajax.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/jsf-ajax/jsf-ajax001.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/jsf-ajax/jsf-ajax002.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/jsf-ajax/jsf-ajax003.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/jsf-ajax/jsf-ajax004.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/jsf-ajax/jsf-ajax005.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/jsf-ajax/jsf-ajax006.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/jsf-ajax/jsf-ajax007.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/jsf-ajax/jsf-ajax008.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/jsf-ajax/jsf-ajax009.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/jsf-ajax/jsf-ajax010.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/jsf-ajax/jsf-ajax011.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/jsf-ajax/jsf-ajax012.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/jsf-configure/jsf-configure.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/jsf-configure/jsf-configure001.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/jsf-configure/jsf-configure002.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/jsf-configure/jsf-configure003.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/jsf-configure/jsf-configure004.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/jsf-configure/jsf-configure005.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/jsf-configure/jsf-configure006.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/jsf-configure/jsf-configure007.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/jsf-configure/jsf-configure008.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/jsf-configure/jsf-configure009.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/jsf-configure/jsf-configure010.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/jsf-configure/jsf-configure011.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/jsf-configure/jsf-configure012.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/jsf-configure/jsf-configure013.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/jsf-custom/jsf-custom.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/jsf-custom/jsf-custom001.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/jsf-custom/jsf-custom002.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/jsf-custom/jsf-custom003.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/jsf-custom/jsf-custom004.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/jsf-custom/jsf-custom005.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/jsf-custom/jsf-custom006.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/jsf-custom/jsf-custom007.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/jsf-custom/jsf-custom008.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/jsf-custom/jsf-custom009.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/jsf-custom/jsf-custom010.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/jsf-custom/jsf-custom011.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/jsf-custom/jsf-custom012.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/jsf-custom/jsf-custom013.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/jsf-custom/jsf-custom014.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/jsf-develop/jsf-develop.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/jsf-develop/jsf-develop001.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/jsf-develop/jsf-develop002.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/jsf-develop/jsf-develop003.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/jsf-el/jsf-el.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/jsf-el/jsf-el001.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/jsf-el/jsf-el002.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/jsf-el/jsf-el003.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/jsf-el/jsf-el004.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/jsf-el/jsf-el005.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/jsf-el/jsf-el006.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/jsf-el/jsf-el007.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/jsf-el/jsf-el008.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/jsf-facelets/jsf-facelets.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/jsf-facelets/jsf-facelets001.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/jsf-facelets/jsf-facelets002.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/jsf-facelets/jsf-facelets003.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/jsf-facelets/jsf-facelets004.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/jsf-facelets/jsf-facelets005.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/jsf-facelets/jsf-facelets006.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/jsf-facelets/jsf-facelets007.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/jsf-facelets/jsf-facelets008.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/jsf-facelets/jsf-facelets009.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/jsf-intro/jsf-intro.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/jsf-intro/jsf-intro001.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/jsf-intro/jsf-intro002.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/jsf-intro/jsf-intro003.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/jsf-intro/jsf-intro004.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/jsf-intro/jsf-intro005.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/jsf-intro/jsf-intro006.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/jsf-intro/jsf-intro007.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/jsf-intro/jsf-intro008.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/jsf-intro/jsf-intro009.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/jsf-page-core/jsf-page-core.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/jsf-page-core/jsf-page-core001.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/jsf-page-core/jsf-page-core002.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/jsf-page-core/jsf-page-core003.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/jsf-page-core/jsf-page-core004.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/jsf-page/jsf-page.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/jsf-page/jsf-page001.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/jsf-page/jsf-page002.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/jsf-page/jsf-page003.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/jsf-ws/jsf-ws.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/jsf-ws/jsf-ws001.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/jsf-ws/jsf-ws002.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/jsf-ws/jsf-ws003.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/jsf-ws/jsf-ws004.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/jsf-ws/jsf-ws005.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/jsf-ws/jsf-ws006.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/jsf-ws/jsf-ws007.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/jsonb/jsonb.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/jsonb/jsonb001.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/jsonb/jsonb002.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/jsonb/jsonb003.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/jsonb/jsonb004.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/jsonp/jsonp.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/jsonp/jsonp001.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/jsonp/jsonp002.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/jsonp/jsonp003.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/jsonp/jsonp004.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/jsonp/jsonp005.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/jsonp/jsonp006.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/jsonp/jsonp007.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/jsonp/jsonp008.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/servlets/servlets.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/servlets/servlets001.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/servlets/servlets002.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/servlets/servlets003.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/servlets/servlets004.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/servlets/servlets005.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/servlets/servlets006.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/servlets/servlets007.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/servlets/servlets008.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/servlets/servlets009.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/servlets/servlets010.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/servlets/servlets011.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/servlets/servlets012.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/servlets/servlets013.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/servlets/servlets014.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/servlets/servlets014a.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/servlets/servlets014b.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/servlets/servlets015.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/servlets/servlets016.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/servlets/servlets017.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/servlets/servlets018.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/webapp/webapp.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/webapp/webapp001.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/webapp/webapp002.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/webapp/webapp003.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/webapp/webapp004.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/webapp/webapp005.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/webapp/webapp006.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/webi18n/webi18n.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/webi18n/webi18n001.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/webi18n/webi18n002.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/webi18n/webi18n003.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/webi18n/webi18n004.adoc (100%) diff --git a/src/main/asciidoc/jsf-advanced-cc/jsf-advanced-cc.adoc b/src/main/antora/modules/web/pages/jsf-advanced-cc/jsf-advanced-cc.adoc similarity index 100% rename from src/main/asciidoc/jsf-advanced-cc/jsf-advanced-cc.adoc rename to src/main/antora/modules/web/pages/jsf-advanced-cc/jsf-advanced-cc.adoc diff --git a/src/main/asciidoc/jsf-advanced-cc/jsf-advanced-cc001.adoc b/src/main/antora/modules/web/pages/jsf-advanced-cc/jsf-advanced-cc001.adoc similarity index 100% rename from src/main/asciidoc/jsf-advanced-cc/jsf-advanced-cc001.adoc rename to src/main/antora/modules/web/pages/jsf-advanced-cc/jsf-advanced-cc001.adoc diff --git a/src/main/asciidoc/jsf-advanced-cc/jsf-advanced-cc002.adoc b/src/main/antora/modules/web/pages/jsf-advanced-cc/jsf-advanced-cc002.adoc similarity index 100% rename from src/main/asciidoc/jsf-advanced-cc/jsf-advanced-cc002.adoc rename to src/main/antora/modules/web/pages/jsf-advanced-cc/jsf-advanced-cc002.adoc diff --git a/src/main/asciidoc/jsf-advanced-cc/jsf-advanced-cc003.adoc b/src/main/antora/modules/web/pages/jsf-advanced-cc/jsf-advanced-cc003.adoc similarity index 100% rename from src/main/asciidoc/jsf-advanced-cc/jsf-advanced-cc003.adoc rename to src/main/antora/modules/web/pages/jsf-advanced-cc/jsf-advanced-cc003.adoc diff --git a/src/main/asciidoc/jsf-advanced-cc/jsf-advanced-cc004.adoc b/src/main/antora/modules/web/pages/jsf-advanced-cc/jsf-advanced-cc004.adoc similarity index 100% rename from src/main/asciidoc/jsf-advanced-cc/jsf-advanced-cc004.adoc rename to src/main/antora/modules/web/pages/jsf-advanced-cc/jsf-advanced-cc004.adoc diff --git a/src/main/asciidoc/jsf-ajax/jsf-ajax.adoc b/src/main/antora/modules/web/pages/jsf-ajax/jsf-ajax.adoc similarity index 100% rename from src/main/asciidoc/jsf-ajax/jsf-ajax.adoc rename to src/main/antora/modules/web/pages/jsf-ajax/jsf-ajax.adoc diff --git a/src/main/asciidoc/jsf-ajax/jsf-ajax001.adoc b/src/main/antora/modules/web/pages/jsf-ajax/jsf-ajax001.adoc similarity index 100% rename from src/main/asciidoc/jsf-ajax/jsf-ajax001.adoc rename to src/main/antora/modules/web/pages/jsf-ajax/jsf-ajax001.adoc diff --git a/src/main/asciidoc/jsf-ajax/jsf-ajax002.adoc b/src/main/antora/modules/web/pages/jsf-ajax/jsf-ajax002.adoc similarity index 100% rename from src/main/asciidoc/jsf-ajax/jsf-ajax002.adoc rename to src/main/antora/modules/web/pages/jsf-ajax/jsf-ajax002.adoc diff --git a/src/main/asciidoc/jsf-ajax/jsf-ajax003.adoc b/src/main/antora/modules/web/pages/jsf-ajax/jsf-ajax003.adoc similarity index 100% rename from src/main/asciidoc/jsf-ajax/jsf-ajax003.adoc rename to src/main/antora/modules/web/pages/jsf-ajax/jsf-ajax003.adoc diff --git a/src/main/asciidoc/jsf-ajax/jsf-ajax004.adoc b/src/main/antora/modules/web/pages/jsf-ajax/jsf-ajax004.adoc similarity index 100% rename from src/main/asciidoc/jsf-ajax/jsf-ajax004.adoc rename to src/main/antora/modules/web/pages/jsf-ajax/jsf-ajax004.adoc diff --git a/src/main/asciidoc/jsf-ajax/jsf-ajax005.adoc b/src/main/antora/modules/web/pages/jsf-ajax/jsf-ajax005.adoc similarity index 100% rename from src/main/asciidoc/jsf-ajax/jsf-ajax005.adoc rename to src/main/antora/modules/web/pages/jsf-ajax/jsf-ajax005.adoc diff --git a/src/main/asciidoc/jsf-ajax/jsf-ajax006.adoc b/src/main/antora/modules/web/pages/jsf-ajax/jsf-ajax006.adoc similarity index 100% rename from src/main/asciidoc/jsf-ajax/jsf-ajax006.adoc rename to src/main/antora/modules/web/pages/jsf-ajax/jsf-ajax006.adoc diff --git a/src/main/asciidoc/jsf-ajax/jsf-ajax007.adoc b/src/main/antora/modules/web/pages/jsf-ajax/jsf-ajax007.adoc similarity index 100% rename from src/main/asciidoc/jsf-ajax/jsf-ajax007.adoc rename to src/main/antora/modules/web/pages/jsf-ajax/jsf-ajax007.adoc diff --git a/src/main/asciidoc/jsf-ajax/jsf-ajax008.adoc b/src/main/antora/modules/web/pages/jsf-ajax/jsf-ajax008.adoc similarity index 100% rename from src/main/asciidoc/jsf-ajax/jsf-ajax008.adoc rename to src/main/antora/modules/web/pages/jsf-ajax/jsf-ajax008.adoc diff --git a/src/main/asciidoc/jsf-ajax/jsf-ajax009.adoc b/src/main/antora/modules/web/pages/jsf-ajax/jsf-ajax009.adoc similarity index 100% rename from src/main/asciidoc/jsf-ajax/jsf-ajax009.adoc rename to src/main/antora/modules/web/pages/jsf-ajax/jsf-ajax009.adoc diff --git a/src/main/asciidoc/jsf-ajax/jsf-ajax010.adoc b/src/main/antora/modules/web/pages/jsf-ajax/jsf-ajax010.adoc similarity index 100% rename from src/main/asciidoc/jsf-ajax/jsf-ajax010.adoc rename to src/main/antora/modules/web/pages/jsf-ajax/jsf-ajax010.adoc diff --git a/src/main/asciidoc/jsf-ajax/jsf-ajax011.adoc b/src/main/antora/modules/web/pages/jsf-ajax/jsf-ajax011.adoc similarity index 100% rename from src/main/asciidoc/jsf-ajax/jsf-ajax011.adoc rename to src/main/antora/modules/web/pages/jsf-ajax/jsf-ajax011.adoc diff --git a/src/main/asciidoc/jsf-ajax/jsf-ajax012.adoc b/src/main/antora/modules/web/pages/jsf-ajax/jsf-ajax012.adoc similarity index 100% rename from src/main/asciidoc/jsf-ajax/jsf-ajax012.adoc rename to src/main/antora/modules/web/pages/jsf-ajax/jsf-ajax012.adoc diff --git a/src/main/asciidoc/jsf-configure/jsf-configure.adoc b/src/main/antora/modules/web/pages/jsf-configure/jsf-configure.adoc similarity index 100% rename from src/main/asciidoc/jsf-configure/jsf-configure.adoc rename to src/main/antora/modules/web/pages/jsf-configure/jsf-configure.adoc diff --git a/src/main/asciidoc/jsf-configure/jsf-configure001.adoc b/src/main/antora/modules/web/pages/jsf-configure/jsf-configure001.adoc similarity index 100% rename from src/main/asciidoc/jsf-configure/jsf-configure001.adoc rename to src/main/antora/modules/web/pages/jsf-configure/jsf-configure001.adoc diff --git a/src/main/asciidoc/jsf-configure/jsf-configure002.adoc b/src/main/antora/modules/web/pages/jsf-configure/jsf-configure002.adoc similarity index 100% rename from src/main/asciidoc/jsf-configure/jsf-configure002.adoc rename to src/main/antora/modules/web/pages/jsf-configure/jsf-configure002.adoc diff --git a/src/main/asciidoc/jsf-configure/jsf-configure003.adoc b/src/main/antora/modules/web/pages/jsf-configure/jsf-configure003.adoc similarity index 100% rename from src/main/asciidoc/jsf-configure/jsf-configure003.adoc rename to src/main/antora/modules/web/pages/jsf-configure/jsf-configure003.adoc diff --git a/src/main/asciidoc/jsf-configure/jsf-configure004.adoc b/src/main/antora/modules/web/pages/jsf-configure/jsf-configure004.adoc similarity index 100% rename from src/main/asciidoc/jsf-configure/jsf-configure004.adoc rename to src/main/antora/modules/web/pages/jsf-configure/jsf-configure004.adoc diff --git a/src/main/asciidoc/jsf-configure/jsf-configure005.adoc b/src/main/antora/modules/web/pages/jsf-configure/jsf-configure005.adoc similarity index 100% rename from src/main/asciidoc/jsf-configure/jsf-configure005.adoc rename to src/main/antora/modules/web/pages/jsf-configure/jsf-configure005.adoc diff --git a/src/main/asciidoc/jsf-configure/jsf-configure006.adoc b/src/main/antora/modules/web/pages/jsf-configure/jsf-configure006.adoc similarity index 100% rename from src/main/asciidoc/jsf-configure/jsf-configure006.adoc rename to src/main/antora/modules/web/pages/jsf-configure/jsf-configure006.adoc diff --git a/src/main/asciidoc/jsf-configure/jsf-configure007.adoc b/src/main/antora/modules/web/pages/jsf-configure/jsf-configure007.adoc similarity index 100% rename from src/main/asciidoc/jsf-configure/jsf-configure007.adoc rename to src/main/antora/modules/web/pages/jsf-configure/jsf-configure007.adoc diff --git a/src/main/asciidoc/jsf-configure/jsf-configure008.adoc b/src/main/antora/modules/web/pages/jsf-configure/jsf-configure008.adoc similarity index 100% rename from src/main/asciidoc/jsf-configure/jsf-configure008.adoc rename to src/main/antora/modules/web/pages/jsf-configure/jsf-configure008.adoc diff --git a/src/main/asciidoc/jsf-configure/jsf-configure009.adoc b/src/main/antora/modules/web/pages/jsf-configure/jsf-configure009.adoc similarity index 100% rename from src/main/asciidoc/jsf-configure/jsf-configure009.adoc rename to src/main/antora/modules/web/pages/jsf-configure/jsf-configure009.adoc diff --git a/src/main/asciidoc/jsf-configure/jsf-configure010.adoc b/src/main/antora/modules/web/pages/jsf-configure/jsf-configure010.adoc similarity index 100% rename from src/main/asciidoc/jsf-configure/jsf-configure010.adoc rename to src/main/antora/modules/web/pages/jsf-configure/jsf-configure010.adoc diff --git a/src/main/asciidoc/jsf-configure/jsf-configure011.adoc b/src/main/antora/modules/web/pages/jsf-configure/jsf-configure011.adoc similarity index 100% rename from src/main/asciidoc/jsf-configure/jsf-configure011.adoc rename to src/main/antora/modules/web/pages/jsf-configure/jsf-configure011.adoc diff --git a/src/main/asciidoc/jsf-configure/jsf-configure012.adoc b/src/main/antora/modules/web/pages/jsf-configure/jsf-configure012.adoc similarity index 100% rename from src/main/asciidoc/jsf-configure/jsf-configure012.adoc rename to src/main/antora/modules/web/pages/jsf-configure/jsf-configure012.adoc diff --git a/src/main/asciidoc/jsf-configure/jsf-configure013.adoc b/src/main/antora/modules/web/pages/jsf-configure/jsf-configure013.adoc similarity index 100% rename from src/main/asciidoc/jsf-configure/jsf-configure013.adoc rename to src/main/antora/modules/web/pages/jsf-configure/jsf-configure013.adoc diff --git a/src/main/asciidoc/jsf-custom/jsf-custom.adoc b/src/main/antora/modules/web/pages/jsf-custom/jsf-custom.adoc similarity index 100% rename from src/main/asciidoc/jsf-custom/jsf-custom.adoc rename to src/main/antora/modules/web/pages/jsf-custom/jsf-custom.adoc diff --git a/src/main/asciidoc/jsf-custom/jsf-custom001.adoc b/src/main/antora/modules/web/pages/jsf-custom/jsf-custom001.adoc similarity index 100% rename from src/main/asciidoc/jsf-custom/jsf-custom001.adoc rename to src/main/antora/modules/web/pages/jsf-custom/jsf-custom001.adoc diff --git a/src/main/asciidoc/jsf-custom/jsf-custom002.adoc b/src/main/antora/modules/web/pages/jsf-custom/jsf-custom002.adoc similarity index 100% rename from src/main/asciidoc/jsf-custom/jsf-custom002.adoc rename to src/main/antora/modules/web/pages/jsf-custom/jsf-custom002.adoc diff --git a/src/main/asciidoc/jsf-custom/jsf-custom003.adoc b/src/main/antora/modules/web/pages/jsf-custom/jsf-custom003.adoc similarity index 100% rename from src/main/asciidoc/jsf-custom/jsf-custom003.adoc rename to src/main/antora/modules/web/pages/jsf-custom/jsf-custom003.adoc diff --git a/src/main/asciidoc/jsf-custom/jsf-custom004.adoc b/src/main/antora/modules/web/pages/jsf-custom/jsf-custom004.adoc similarity index 100% rename from src/main/asciidoc/jsf-custom/jsf-custom004.adoc rename to src/main/antora/modules/web/pages/jsf-custom/jsf-custom004.adoc diff --git a/src/main/asciidoc/jsf-custom/jsf-custom005.adoc b/src/main/antora/modules/web/pages/jsf-custom/jsf-custom005.adoc similarity index 100% rename from src/main/asciidoc/jsf-custom/jsf-custom005.adoc rename to src/main/antora/modules/web/pages/jsf-custom/jsf-custom005.adoc diff --git a/src/main/asciidoc/jsf-custom/jsf-custom006.adoc b/src/main/antora/modules/web/pages/jsf-custom/jsf-custom006.adoc similarity index 100% rename from src/main/asciidoc/jsf-custom/jsf-custom006.adoc rename to src/main/antora/modules/web/pages/jsf-custom/jsf-custom006.adoc diff --git a/src/main/asciidoc/jsf-custom/jsf-custom007.adoc b/src/main/antora/modules/web/pages/jsf-custom/jsf-custom007.adoc similarity index 100% rename from src/main/asciidoc/jsf-custom/jsf-custom007.adoc rename to src/main/antora/modules/web/pages/jsf-custom/jsf-custom007.adoc diff --git a/src/main/asciidoc/jsf-custom/jsf-custom008.adoc b/src/main/antora/modules/web/pages/jsf-custom/jsf-custom008.adoc similarity index 100% rename from src/main/asciidoc/jsf-custom/jsf-custom008.adoc rename to src/main/antora/modules/web/pages/jsf-custom/jsf-custom008.adoc diff --git a/src/main/asciidoc/jsf-custom/jsf-custom009.adoc b/src/main/antora/modules/web/pages/jsf-custom/jsf-custom009.adoc similarity index 100% rename from src/main/asciidoc/jsf-custom/jsf-custom009.adoc rename to src/main/antora/modules/web/pages/jsf-custom/jsf-custom009.adoc diff --git a/src/main/asciidoc/jsf-custom/jsf-custom010.adoc b/src/main/antora/modules/web/pages/jsf-custom/jsf-custom010.adoc similarity index 100% rename from src/main/asciidoc/jsf-custom/jsf-custom010.adoc rename to src/main/antora/modules/web/pages/jsf-custom/jsf-custom010.adoc diff --git a/src/main/asciidoc/jsf-custom/jsf-custom011.adoc b/src/main/antora/modules/web/pages/jsf-custom/jsf-custom011.adoc similarity index 100% rename from src/main/asciidoc/jsf-custom/jsf-custom011.adoc rename to src/main/antora/modules/web/pages/jsf-custom/jsf-custom011.adoc diff --git a/src/main/asciidoc/jsf-custom/jsf-custom012.adoc b/src/main/antora/modules/web/pages/jsf-custom/jsf-custom012.adoc similarity index 100% rename from src/main/asciidoc/jsf-custom/jsf-custom012.adoc rename to src/main/antora/modules/web/pages/jsf-custom/jsf-custom012.adoc diff --git a/src/main/asciidoc/jsf-custom/jsf-custom013.adoc b/src/main/antora/modules/web/pages/jsf-custom/jsf-custom013.adoc similarity index 100% rename from src/main/asciidoc/jsf-custom/jsf-custom013.adoc rename to src/main/antora/modules/web/pages/jsf-custom/jsf-custom013.adoc diff --git a/src/main/asciidoc/jsf-custom/jsf-custom014.adoc b/src/main/antora/modules/web/pages/jsf-custom/jsf-custom014.adoc similarity index 100% rename from src/main/asciidoc/jsf-custom/jsf-custom014.adoc rename to src/main/antora/modules/web/pages/jsf-custom/jsf-custom014.adoc diff --git a/src/main/asciidoc/jsf-develop/jsf-develop.adoc b/src/main/antora/modules/web/pages/jsf-develop/jsf-develop.adoc similarity index 100% rename from src/main/asciidoc/jsf-develop/jsf-develop.adoc rename to src/main/antora/modules/web/pages/jsf-develop/jsf-develop.adoc diff --git a/src/main/asciidoc/jsf-develop/jsf-develop001.adoc b/src/main/antora/modules/web/pages/jsf-develop/jsf-develop001.adoc similarity index 100% rename from src/main/asciidoc/jsf-develop/jsf-develop001.adoc rename to src/main/antora/modules/web/pages/jsf-develop/jsf-develop001.adoc diff --git a/src/main/asciidoc/jsf-develop/jsf-develop002.adoc b/src/main/antora/modules/web/pages/jsf-develop/jsf-develop002.adoc similarity index 100% rename from src/main/asciidoc/jsf-develop/jsf-develop002.adoc rename to src/main/antora/modules/web/pages/jsf-develop/jsf-develop002.adoc diff --git a/src/main/asciidoc/jsf-develop/jsf-develop003.adoc b/src/main/antora/modules/web/pages/jsf-develop/jsf-develop003.adoc similarity index 100% rename from src/main/asciidoc/jsf-develop/jsf-develop003.adoc rename to src/main/antora/modules/web/pages/jsf-develop/jsf-develop003.adoc diff --git a/src/main/asciidoc/jsf-el/jsf-el.adoc b/src/main/antora/modules/web/pages/jsf-el/jsf-el.adoc similarity index 100% rename from src/main/asciidoc/jsf-el/jsf-el.adoc rename to src/main/antora/modules/web/pages/jsf-el/jsf-el.adoc diff --git a/src/main/asciidoc/jsf-el/jsf-el001.adoc b/src/main/antora/modules/web/pages/jsf-el/jsf-el001.adoc similarity index 100% rename from src/main/asciidoc/jsf-el/jsf-el001.adoc rename to src/main/antora/modules/web/pages/jsf-el/jsf-el001.adoc diff --git a/src/main/asciidoc/jsf-el/jsf-el002.adoc b/src/main/antora/modules/web/pages/jsf-el/jsf-el002.adoc similarity index 100% rename from src/main/asciidoc/jsf-el/jsf-el002.adoc rename to src/main/antora/modules/web/pages/jsf-el/jsf-el002.adoc diff --git a/src/main/asciidoc/jsf-el/jsf-el003.adoc b/src/main/antora/modules/web/pages/jsf-el/jsf-el003.adoc similarity index 100% rename from src/main/asciidoc/jsf-el/jsf-el003.adoc rename to src/main/antora/modules/web/pages/jsf-el/jsf-el003.adoc diff --git a/src/main/asciidoc/jsf-el/jsf-el004.adoc b/src/main/antora/modules/web/pages/jsf-el/jsf-el004.adoc similarity index 100% rename from src/main/asciidoc/jsf-el/jsf-el004.adoc rename to src/main/antora/modules/web/pages/jsf-el/jsf-el004.adoc diff --git a/src/main/asciidoc/jsf-el/jsf-el005.adoc b/src/main/antora/modules/web/pages/jsf-el/jsf-el005.adoc similarity index 100% rename from src/main/asciidoc/jsf-el/jsf-el005.adoc rename to src/main/antora/modules/web/pages/jsf-el/jsf-el005.adoc diff --git a/src/main/asciidoc/jsf-el/jsf-el006.adoc b/src/main/antora/modules/web/pages/jsf-el/jsf-el006.adoc similarity index 100% rename from src/main/asciidoc/jsf-el/jsf-el006.adoc rename to src/main/antora/modules/web/pages/jsf-el/jsf-el006.adoc diff --git a/src/main/asciidoc/jsf-el/jsf-el007.adoc b/src/main/antora/modules/web/pages/jsf-el/jsf-el007.adoc similarity index 100% rename from src/main/asciidoc/jsf-el/jsf-el007.adoc rename to src/main/antora/modules/web/pages/jsf-el/jsf-el007.adoc diff --git a/src/main/asciidoc/jsf-el/jsf-el008.adoc b/src/main/antora/modules/web/pages/jsf-el/jsf-el008.adoc similarity index 100% rename from src/main/asciidoc/jsf-el/jsf-el008.adoc rename to src/main/antora/modules/web/pages/jsf-el/jsf-el008.adoc diff --git a/src/main/asciidoc/jsf-facelets/jsf-facelets.adoc b/src/main/antora/modules/web/pages/jsf-facelets/jsf-facelets.adoc similarity index 100% rename from src/main/asciidoc/jsf-facelets/jsf-facelets.adoc rename to src/main/antora/modules/web/pages/jsf-facelets/jsf-facelets.adoc diff --git a/src/main/asciidoc/jsf-facelets/jsf-facelets001.adoc b/src/main/antora/modules/web/pages/jsf-facelets/jsf-facelets001.adoc similarity index 100% rename from src/main/asciidoc/jsf-facelets/jsf-facelets001.adoc rename to src/main/antora/modules/web/pages/jsf-facelets/jsf-facelets001.adoc diff --git a/src/main/asciidoc/jsf-facelets/jsf-facelets002.adoc b/src/main/antora/modules/web/pages/jsf-facelets/jsf-facelets002.adoc similarity index 100% rename from src/main/asciidoc/jsf-facelets/jsf-facelets002.adoc rename to src/main/antora/modules/web/pages/jsf-facelets/jsf-facelets002.adoc diff --git a/src/main/asciidoc/jsf-facelets/jsf-facelets003.adoc b/src/main/antora/modules/web/pages/jsf-facelets/jsf-facelets003.adoc similarity index 100% rename from src/main/asciidoc/jsf-facelets/jsf-facelets003.adoc rename to src/main/antora/modules/web/pages/jsf-facelets/jsf-facelets003.adoc diff --git a/src/main/asciidoc/jsf-facelets/jsf-facelets004.adoc b/src/main/antora/modules/web/pages/jsf-facelets/jsf-facelets004.adoc similarity index 100% rename from src/main/asciidoc/jsf-facelets/jsf-facelets004.adoc rename to src/main/antora/modules/web/pages/jsf-facelets/jsf-facelets004.adoc diff --git a/src/main/asciidoc/jsf-facelets/jsf-facelets005.adoc b/src/main/antora/modules/web/pages/jsf-facelets/jsf-facelets005.adoc similarity index 100% rename from src/main/asciidoc/jsf-facelets/jsf-facelets005.adoc rename to src/main/antora/modules/web/pages/jsf-facelets/jsf-facelets005.adoc diff --git a/src/main/asciidoc/jsf-facelets/jsf-facelets006.adoc b/src/main/antora/modules/web/pages/jsf-facelets/jsf-facelets006.adoc similarity index 100% rename from src/main/asciidoc/jsf-facelets/jsf-facelets006.adoc rename to src/main/antora/modules/web/pages/jsf-facelets/jsf-facelets006.adoc diff --git a/src/main/asciidoc/jsf-facelets/jsf-facelets007.adoc b/src/main/antora/modules/web/pages/jsf-facelets/jsf-facelets007.adoc similarity index 100% rename from src/main/asciidoc/jsf-facelets/jsf-facelets007.adoc rename to src/main/antora/modules/web/pages/jsf-facelets/jsf-facelets007.adoc diff --git a/src/main/asciidoc/jsf-facelets/jsf-facelets008.adoc b/src/main/antora/modules/web/pages/jsf-facelets/jsf-facelets008.adoc similarity index 100% rename from src/main/asciidoc/jsf-facelets/jsf-facelets008.adoc rename to src/main/antora/modules/web/pages/jsf-facelets/jsf-facelets008.adoc diff --git a/src/main/asciidoc/jsf-facelets/jsf-facelets009.adoc b/src/main/antora/modules/web/pages/jsf-facelets/jsf-facelets009.adoc similarity index 100% rename from src/main/asciidoc/jsf-facelets/jsf-facelets009.adoc rename to src/main/antora/modules/web/pages/jsf-facelets/jsf-facelets009.adoc diff --git a/src/main/asciidoc/jsf-intro/jsf-intro.adoc b/src/main/antora/modules/web/pages/jsf-intro/jsf-intro.adoc similarity index 100% rename from src/main/asciidoc/jsf-intro/jsf-intro.adoc rename to src/main/antora/modules/web/pages/jsf-intro/jsf-intro.adoc diff --git a/src/main/asciidoc/jsf-intro/jsf-intro001.adoc b/src/main/antora/modules/web/pages/jsf-intro/jsf-intro001.adoc similarity index 100% rename from src/main/asciidoc/jsf-intro/jsf-intro001.adoc rename to src/main/antora/modules/web/pages/jsf-intro/jsf-intro001.adoc diff --git a/src/main/asciidoc/jsf-intro/jsf-intro002.adoc b/src/main/antora/modules/web/pages/jsf-intro/jsf-intro002.adoc similarity index 100% rename from src/main/asciidoc/jsf-intro/jsf-intro002.adoc rename to src/main/antora/modules/web/pages/jsf-intro/jsf-intro002.adoc diff --git a/src/main/asciidoc/jsf-intro/jsf-intro003.adoc b/src/main/antora/modules/web/pages/jsf-intro/jsf-intro003.adoc similarity index 100% rename from src/main/asciidoc/jsf-intro/jsf-intro003.adoc rename to src/main/antora/modules/web/pages/jsf-intro/jsf-intro003.adoc diff --git a/src/main/asciidoc/jsf-intro/jsf-intro004.adoc b/src/main/antora/modules/web/pages/jsf-intro/jsf-intro004.adoc similarity index 100% rename from src/main/asciidoc/jsf-intro/jsf-intro004.adoc rename to src/main/antora/modules/web/pages/jsf-intro/jsf-intro004.adoc diff --git a/src/main/asciidoc/jsf-intro/jsf-intro005.adoc b/src/main/antora/modules/web/pages/jsf-intro/jsf-intro005.adoc similarity index 100% rename from src/main/asciidoc/jsf-intro/jsf-intro005.adoc rename to src/main/antora/modules/web/pages/jsf-intro/jsf-intro005.adoc diff --git a/src/main/asciidoc/jsf-intro/jsf-intro006.adoc b/src/main/antora/modules/web/pages/jsf-intro/jsf-intro006.adoc similarity index 100% rename from src/main/asciidoc/jsf-intro/jsf-intro006.adoc rename to src/main/antora/modules/web/pages/jsf-intro/jsf-intro006.adoc diff --git a/src/main/asciidoc/jsf-intro/jsf-intro007.adoc b/src/main/antora/modules/web/pages/jsf-intro/jsf-intro007.adoc similarity index 100% rename from src/main/asciidoc/jsf-intro/jsf-intro007.adoc rename to src/main/antora/modules/web/pages/jsf-intro/jsf-intro007.adoc diff --git a/src/main/asciidoc/jsf-intro/jsf-intro008.adoc b/src/main/antora/modules/web/pages/jsf-intro/jsf-intro008.adoc similarity index 100% rename from src/main/asciidoc/jsf-intro/jsf-intro008.adoc rename to src/main/antora/modules/web/pages/jsf-intro/jsf-intro008.adoc diff --git a/src/main/asciidoc/jsf-intro/jsf-intro009.adoc b/src/main/antora/modules/web/pages/jsf-intro/jsf-intro009.adoc similarity index 100% rename from src/main/asciidoc/jsf-intro/jsf-intro009.adoc rename to src/main/antora/modules/web/pages/jsf-intro/jsf-intro009.adoc diff --git a/src/main/asciidoc/jsf-page-core/jsf-page-core.adoc b/src/main/antora/modules/web/pages/jsf-page-core/jsf-page-core.adoc similarity index 100% rename from src/main/asciidoc/jsf-page-core/jsf-page-core.adoc rename to src/main/antora/modules/web/pages/jsf-page-core/jsf-page-core.adoc diff --git a/src/main/asciidoc/jsf-page-core/jsf-page-core001.adoc b/src/main/antora/modules/web/pages/jsf-page-core/jsf-page-core001.adoc similarity index 100% rename from src/main/asciidoc/jsf-page-core/jsf-page-core001.adoc rename to src/main/antora/modules/web/pages/jsf-page-core/jsf-page-core001.adoc diff --git a/src/main/asciidoc/jsf-page-core/jsf-page-core002.adoc b/src/main/antora/modules/web/pages/jsf-page-core/jsf-page-core002.adoc similarity index 100% rename from src/main/asciidoc/jsf-page-core/jsf-page-core002.adoc rename to src/main/antora/modules/web/pages/jsf-page-core/jsf-page-core002.adoc diff --git a/src/main/asciidoc/jsf-page-core/jsf-page-core003.adoc b/src/main/antora/modules/web/pages/jsf-page-core/jsf-page-core003.adoc similarity index 100% rename from src/main/asciidoc/jsf-page-core/jsf-page-core003.adoc rename to src/main/antora/modules/web/pages/jsf-page-core/jsf-page-core003.adoc diff --git a/src/main/asciidoc/jsf-page-core/jsf-page-core004.adoc b/src/main/antora/modules/web/pages/jsf-page-core/jsf-page-core004.adoc similarity index 100% rename from src/main/asciidoc/jsf-page-core/jsf-page-core004.adoc rename to src/main/antora/modules/web/pages/jsf-page-core/jsf-page-core004.adoc diff --git a/src/main/asciidoc/jsf-page/jsf-page.adoc b/src/main/antora/modules/web/pages/jsf-page/jsf-page.adoc similarity index 100% rename from src/main/asciidoc/jsf-page/jsf-page.adoc rename to src/main/antora/modules/web/pages/jsf-page/jsf-page.adoc diff --git a/src/main/asciidoc/jsf-page/jsf-page001.adoc b/src/main/antora/modules/web/pages/jsf-page/jsf-page001.adoc similarity index 100% rename from src/main/asciidoc/jsf-page/jsf-page001.adoc rename to src/main/antora/modules/web/pages/jsf-page/jsf-page001.adoc diff --git a/src/main/asciidoc/jsf-page/jsf-page002.adoc b/src/main/antora/modules/web/pages/jsf-page/jsf-page002.adoc similarity index 100% rename from src/main/asciidoc/jsf-page/jsf-page002.adoc rename to src/main/antora/modules/web/pages/jsf-page/jsf-page002.adoc diff --git a/src/main/asciidoc/jsf-page/jsf-page003.adoc b/src/main/antora/modules/web/pages/jsf-page/jsf-page003.adoc similarity index 100% rename from src/main/asciidoc/jsf-page/jsf-page003.adoc rename to src/main/antora/modules/web/pages/jsf-page/jsf-page003.adoc diff --git a/src/main/asciidoc/jsf-ws/jsf-ws.adoc b/src/main/antora/modules/web/pages/jsf-ws/jsf-ws.adoc similarity index 100% rename from src/main/asciidoc/jsf-ws/jsf-ws.adoc rename to src/main/antora/modules/web/pages/jsf-ws/jsf-ws.adoc diff --git a/src/main/asciidoc/jsf-ws/jsf-ws001.adoc b/src/main/antora/modules/web/pages/jsf-ws/jsf-ws001.adoc similarity index 100% rename from src/main/asciidoc/jsf-ws/jsf-ws001.adoc rename to src/main/antora/modules/web/pages/jsf-ws/jsf-ws001.adoc diff --git a/src/main/asciidoc/jsf-ws/jsf-ws002.adoc b/src/main/antora/modules/web/pages/jsf-ws/jsf-ws002.adoc similarity index 100% rename from src/main/asciidoc/jsf-ws/jsf-ws002.adoc rename to src/main/antora/modules/web/pages/jsf-ws/jsf-ws002.adoc diff --git a/src/main/asciidoc/jsf-ws/jsf-ws003.adoc b/src/main/antora/modules/web/pages/jsf-ws/jsf-ws003.adoc similarity index 100% rename from src/main/asciidoc/jsf-ws/jsf-ws003.adoc rename to src/main/antora/modules/web/pages/jsf-ws/jsf-ws003.adoc diff --git a/src/main/asciidoc/jsf-ws/jsf-ws004.adoc b/src/main/antora/modules/web/pages/jsf-ws/jsf-ws004.adoc similarity index 100% rename from src/main/asciidoc/jsf-ws/jsf-ws004.adoc rename to src/main/antora/modules/web/pages/jsf-ws/jsf-ws004.adoc diff --git a/src/main/asciidoc/jsf-ws/jsf-ws005.adoc b/src/main/antora/modules/web/pages/jsf-ws/jsf-ws005.adoc similarity index 100% rename from src/main/asciidoc/jsf-ws/jsf-ws005.adoc rename to src/main/antora/modules/web/pages/jsf-ws/jsf-ws005.adoc diff --git a/src/main/asciidoc/jsf-ws/jsf-ws006.adoc b/src/main/antora/modules/web/pages/jsf-ws/jsf-ws006.adoc similarity index 100% rename from src/main/asciidoc/jsf-ws/jsf-ws006.adoc rename to src/main/antora/modules/web/pages/jsf-ws/jsf-ws006.adoc diff --git a/src/main/asciidoc/jsf-ws/jsf-ws007.adoc b/src/main/antora/modules/web/pages/jsf-ws/jsf-ws007.adoc similarity index 100% rename from src/main/asciidoc/jsf-ws/jsf-ws007.adoc rename to src/main/antora/modules/web/pages/jsf-ws/jsf-ws007.adoc diff --git a/src/main/asciidoc/jsonb/jsonb.adoc b/src/main/antora/modules/web/pages/jsonb/jsonb.adoc similarity index 100% rename from src/main/asciidoc/jsonb/jsonb.adoc rename to src/main/antora/modules/web/pages/jsonb/jsonb.adoc diff --git a/src/main/asciidoc/jsonb/jsonb001.adoc b/src/main/antora/modules/web/pages/jsonb/jsonb001.adoc similarity index 100% rename from src/main/asciidoc/jsonb/jsonb001.adoc rename to src/main/antora/modules/web/pages/jsonb/jsonb001.adoc diff --git a/src/main/asciidoc/jsonb/jsonb002.adoc b/src/main/antora/modules/web/pages/jsonb/jsonb002.adoc similarity index 100% rename from src/main/asciidoc/jsonb/jsonb002.adoc rename to src/main/antora/modules/web/pages/jsonb/jsonb002.adoc diff --git a/src/main/asciidoc/jsonb/jsonb003.adoc b/src/main/antora/modules/web/pages/jsonb/jsonb003.adoc similarity index 100% rename from src/main/asciidoc/jsonb/jsonb003.adoc rename to src/main/antora/modules/web/pages/jsonb/jsonb003.adoc diff --git a/src/main/asciidoc/jsonb/jsonb004.adoc b/src/main/antora/modules/web/pages/jsonb/jsonb004.adoc similarity index 100% rename from src/main/asciidoc/jsonb/jsonb004.adoc rename to src/main/antora/modules/web/pages/jsonb/jsonb004.adoc diff --git a/src/main/asciidoc/jsonp/jsonp.adoc b/src/main/antora/modules/web/pages/jsonp/jsonp.adoc similarity index 100% rename from src/main/asciidoc/jsonp/jsonp.adoc rename to src/main/antora/modules/web/pages/jsonp/jsonp.adoc diff --git a/src/main/asciidoc/jsonp/jsonp001.adoc b/src/main/antora/modules/web/pages/jsonp/jsonp001.adoc similarity index 100% rename from src/main/asciidoc/jsonp/jsonp001.adoc rename to src/main/antora/modules/web/pages/jsonp/jsonp001.adoc diff --git a/src/main/asciidoc/jsonp/jsonp002.adoc b/src/main/antora/modules/web/pages/jsonp/jsonp002.adoc similarity index 100% rename from src/main/asciidoc/jsonp/jsonp002.adoc rename to src/main/antora/modules/web/pages/jsonp/jsonp002.adoc diff --git a/src/main/asciidoc/jsonp/jsonp003.adoc b/src/main/antora/modules/web/pages/jsonp/jsonp003.adoc similarity index 100% rename from src/main/asciidoc/jsonp/jsonp003.adoc rename to src/main/antora/modules/web/pages/jsonp/jsonp003.adoc diff --git a/src/main/asciidoc/jsonp/jsonp004.adoc b/src/main/antora/modules/web/pages/jsonp/jsonp004.adoc similarity index 100% rename from src/main/asciidoc/jsonp/jsonp004.adoc rename to src/main/antora/modules/web/pages/jsonp/jsonp004.adoc diff --git a/src/main/asciidoc/jsonp/jsonp005.adoc b/src/main/antora/modules/web/pages/jsonp/jsonp005.adoc similarity index 100% rename from src/main/asciidoc/jsonp/jsonp005.adoc rename to src/main/antora/modules/web/pages/jsonp/jsonp005.adoc diff --git a/src/main/asciidoc/jsonp/jsonp006.adoc b/src/main/antora/modules/web/pages/jsonp/jsonp006.adoc similarity index 100% rename from src/main/asciidoc/jsonp/jsonp006.adoc rename to src/main/antora/modules/web/pages/jsonp/jsonp006.adoc diff --git a/src/main/asciidoc/jsonp/jsonp007.adoc b/src/main/antora/modules/web/pages/jsonp/jsonp007.adoc similarity index 100% rename from src/main/asciidoc/jsonp/jsonp007.adoc rename to src/main/antora/modules/web/pages/jsonp/jsonp007.adoc diff --git a/src/main/asciidoc/jsonp/jsonp008.adoc b/src/main/antora/modules/web/pages/jsonp/jsonp008.adoc similarity index 100% rename from src/main/asciidoc/jsonp/jsonp008.adoc rename to src/main/antora/modules/web/pages/jsonp/jsonp008.adoc diff --git a/src/main/asciidoc/servlets/servlets.adoc b/src/main/antora/modules/web/pages/servlets/servlets.adoc similarity index 100% rename from src/main/asciidoc/servlets/servlets.adoc rename to src/main/antora/modules/web/pages/servlets/servlets.adoc diff --git a/src/main/asciidoc/servlets/servlets001.adoc b/src/main/antora/modules/web/pages/servlets/servlets001.adoc similarity index 100% rename from src/main/asciidoc/servlets/servlets001.adoc rename to src/main/antora/modules/web/pages/servlets/servlets001.adoc diff --git a/src/main/asciidoc/servlets/servlets002.adoc b/src/main/antora/modules/web/pages/servlets/servlets002.adoc similarity index 100% rename from src/main/asciidoc/servlets/servlets002.adoc rename to src/main/antora/modules/web/pages/servlets/servlets002.adoc diff --git a/src/main/asciidoc/servlets/servlets003.adoc b/src/main/antora/modules/web/pages/servlets/servlets003.adoc similarity index 100% rename from src/main/asciidoc/servlets/servlets003.adoc rename to src/main/antora/modules/web/pages/servlets/servlets003.adoc diff --git a/src/main/asciidoc/servlets/servlets004.adoc b/src/main/antora/modules/web/pages/servlets/servlets004.adoc similarity index 100% rename from src/main/asciidoc/servlets/servlets004.adoc rename to src/main/antora/modules/web/pages/servlets/servlets004.adoc diff --git a/src/main/asciidoc/servlets/servlets005.adoc b/src/main/antora/modules/web/pages/servlets/servlets005.adoc similarity index 100% rename from src/main/asciidoc/servlets/servlets005.adoc rename to src/main/antora/modules/web/pages/servlets/servlets005.adoc diff --git a/src/main/asciidoc/servlets/servlets006.adoc b/src/main/antora/modules/web/pages/servlets/servlets006.adoc similarity index 100% rename from src/main/asciidoc/servlets/servlets006.adoc rename to src/main/antora/modules/web/pages/servlets/servlets006.adoc diff --git a/src/main/asciidoc/servlets/servlets007.adoc b/src/main/antora/modules/web/pages/servlets/servlets007.adoc similarity index 100% rename from src/main/asciidoc/servlets/servlets007.adoc rename to src/main/antora/modules/web/pages/servlets/servlets007.adoc diff --git a/src/main/asciidoc/servlets/servlets008.adoc b/src/main/antora/modules/web/pages/servlets/servlets008.adoc similarity index 100% rename from src/main/asciidoc/servlets/servlets008.adoc rename to src/main/antora/modules/web/pages/servlets/servlets008.adoc diff --git a/src/main/asciidoc/servlets/servlets009.adoc b/src/main/antora/modules/web/pages/servlets/servlets009.adoc similarity index 100% rename from src/main/asciidoc/servlets/servlets009.adoc rename to src/main/antora/modules/web/pages/servlets/servlets009.adoc diff --git a/src/main/asciidoc/servlets/servlets010.adoc b/src/main/antora/modules/web/pages/servlets/servlets010.adoc similarity index 100% rename from src/main/asciidoc/servlets/servlets010.adoc rename to src/main/antora/modules/web/pages/servlets/servlets010.adoc diff --git a/src/main/asciidoc/servlets/servlets011.adoc b/src/main/antora/modules/web/pages/servlets/servlets011.adoc similarity index 100% rename from src/main/asciidoc/servlets/servlets011.adoc rename to src/main/antora/modules/web/pages/servlets/servlets011.adoc diff --git a/src/main/asciidoc/servlets/servlets012.adoc b/src/main/antora/modules/web/pages/servlets/servlets012.adoc similarity index 100% rename from src/main/asciidoc/servlets/servlets012.adoc rename to src/main/antora/modules/web/pages/servlets/servlets012.adoc diff --git a/src/main/asciidoc/servlets/servlets013.adoc b/src/main/antora/modules/web/pages/servlets/servlets013.adoc similarity index 100% rename from src/main/asciidoc/servlets/servlets013.adoc rename to src/main/antora/modules/web/pages/servlets/servlets013.adoc diff --git a/src/main/asciidoc/servlets/servlets014.adoc b/src/main/antora/modules/web/pages/servlets/servlets014.adoc similarity index 100% rename from src/main/asciidoc/servlets/servlets014.adoc rename to src/main/antora/modules/web/pages/servlets/servlets014.adoc diff --git a/src/main/asciidoc/servlets/servlets014a.adoc b/src/main/antora/modules/web/pages/servlets/servlets014a.adoc similarity index 100% rename from src/main/asciidoc/servlets/servlets014a.adoc rename to src/main/antora/modules/web/pages/servlets/servlets014a.adoc diff --git a/src/main/asciidoc/servlets/servlets014b.adoc b/src/main/antora/modules/web/pages/servlets/servlets014b.adoc similarity index 100% rename from src/main/asciidoc/servlets/servlets014b.adoc rename to src/main/antora/modules/web/pages/servlets/servlets014b.adoc diff --git a/src/main/asciidoc/servlets/servlets015.adoc b/src/main/antora/modules/web/pages/servlets/servlets015.adoc similarity index 100% rename from src/main/asciidoc/servlets/servlets015.adoc rename to src/main/antora/modules/web/pages/servlets/servlets015.adoc diff --git a/src/main/asciidoc/servlets/servlets016.adoc b/src/main/antora/modules/web/pages/servlets/servlets016.adoc similarity index 100% rename from src/main/asciidoc/servlets/servlets016.adoc rename to src/main/antora/modules/web/pages/servlets/servlets016.adoc diff --git a/src/main/asciidoc/servlets/servlets017.adoc b/src/main/antora/modules/web/pages/servlets/servlets017.adoc similarity index 100% rename from src/main/asciidoc/servlets/servlets017.adoc rename to src/main/antora/modules/web/pages/servlets/servlets017.adoc diff --git a/src/main/asciidoc/servlets/servlets018.adoc b/src/main/antora/modules/web/pages/servlets/servlets018.adoc similarity index 100% rename from src/main/asciidoc/servlets/servlets018.adoc rename to src/main/antora/modules/web/pages/servlets/servlets018.adoc diff --git a/src/main/asciidoc/webapp/webapp.adoc b/src/main/antora/modules/web/pages/webapp/webapp.adoc similarity index 100% rename from src/main/asciidoc/webapp/webapp.adoc rename to src/main/antora/modules/web/pages/webapp/webapp.adoc diff --git a/src/main/asciidoc/webapp/webapp001.adoc b/src/main/antora/modules/web/pages/webapp/webapp001.adoc similarity index 100% rename from src/main/asciidoc/webapp/webapp001.adoc rename to src/main/antora/modules/web/pages/webapp/webapp001.adoc diff --git a/src/main/asciidoc/webapp/webapp002.adoc b/src/main/antora/modules/web/pages/webapp/webapp002.adoc similarity index 100% rename from src/main/asciidoc/webapp/webapp002.adoc rename to src/main/antora/modules/web/pages/webapp/webapp002.adoc diff --git a/src/main/asciidoc/webapp/webapp003.adoc b/src/main/antora/modules/web/pages/webapp/webapp003.adoc similarity index 100% rename from src/main/asciidoc/webapp/webapp003.adoc rename to src/main/antora/modules/web/pages/webapp/webapp003.adoc diff --git a/src/main/asciidoc/webapp/webapp004.adoc b/src/main/antora/modules/web/pages/webapp/webapp004.adoc similarity index 100% rename from src/main/asciidoc/webapp/webapp004.adoc rename to src/main/antora/modules/web/pages/webapp/webapp004.adoc diff --git a/src/main/asciidoc/webapp/webapp005.adoc b/src/main/antora/modules/web/pages/webapp/webapp005.adoc similarity index 100% rename from src/main/asciidoc/webapp/webapp005.adoc rename to src/main/antora/modules/web/pages/webapp/webapp005.adoc diff --git a/src/main/asciidoc/webapp/webapp006.adoc b/src/main/antora/modules/web/pages/webapp/webapp006.adoc similarity index 100% rename from src/main/asciidoc/webapp/webapp006.adoc rename to src/main/antora/modules/web/pages/webapp/webapp006.adoc diff --git a/src/main/asciidoc/webi18n/webi18n.adoc b/src/main/antora/modules/web/pages/webi18n/webi18n.adoc similarity index 100% rename from src/main/asciidoc/webi18n/webi18n.adoc rename to src/main/antora/modules/web/pages/webi18n/webi18n.adoc diff --git a/src/main/asciidoc/webi18n/webi18n001.adoc b/src/main/antora/modules/web/pages/webi18n/webi18n001.adoc similarity index 100% rename from src/main/asciidoc/webi18n/webi18n001.adoc rename to src/main/antora/modules/web/pages/webi18n/webi18n001.adoc diff --git a/src/main/asciidoc/webi18n/webi18n002.adoc b/src/main/antora/modules/web/pages/webi18n/webi18n002.adoc similarity index 100% rename from src/main/asciidoc/webi18n/webi18n002.adoc rename to src/main/antora/modules/web/pages/webi18n/webi18n002.adoc diff --git a/src/main/asciidoc/webi18n/webi18n003.adoc b/src/main/antora/modules/web/pages/webi18n/webi18n003.adoc similarity index 100% rename from src/main/asciidoc/webi18n/webi18n003.adoc rename to src/main/antora/modules/web/pages/webi18n/webi18n003.adoc diff --git a/src/main/asciidoc/webi18n/webi18n004.adoc b/src/main/antora/modules/web/pages/webi18n/webi18n004.adoc similarity index 100% rename from src/main/asciidoc/webi18n/webi18n004.adoc rename to src/main/antora/modules/web/pages/webi18n/webi18n004.adoc From cd62ddd2172c1652d549b8f4e652695e8a1dc0ed Mon Sep 17 00:00:00 2001 From: "Kito D. Mann" Date: Thu, 1 Jun 2023 11:59:54 -0400 Subject: [PATCH 045/247] JETUT-120 Updated conversion docs to match `main` --- antora-conversion/CONVERTING_TO_ANTORA.adoc | 69 +++++++++++++++++---- 1 file changed, 57 insertions(+), 12 deletions(-) diff --git a/antora-conversion/CONVERTING_TO_ANTORA.adoc b/antora-conversion/CONVERTING_TO_ANTORA.adoc index bf888e5b..00cdc5e8 100644 --- a/antora-conversion/CONVERTING_TO_ANTORA.adoc +++ b/antora-conversion/CONVERTING_TO_ANTORA.adoc @@ -1,6 +1,6 @@ = Antora Migration Notes -As part of the documentation upgrade process, we are migrating the existing content to Antora. This will allow us to go back to previous versions of the docs (currently 9.1 and 8.0) from within the docs site. +As part of the documentation upgrade process, we're migrating the existing content to Antora. This will allow us to go back to previous versions of the docs (currently 9.1 and 8.0) from within the docs site. == Setup @@ -10,21 +10,38 @@ The conversion script is written in Java and requires https://jbang.io[JBang] to > TIP: Commit your changes after each step; that way you can easily rollback any mistakes. -Here’s the current process for migrating an individual module (i.e. security, bean validation, etc): +Here’s the current process for migrating an individual module (i.e. security, bean validation, etc). -1. Check out the release/8 branch and create a new branch from it for your work. -2. Select the module to migrate. We consider each Part of the current https://eclipse-ee4j.github.io/jakartaee-tutorial/[Jakata EE Tutorial] to be a module (for example, Introduction, Web Tier, Bean Validation, etc). -3. Create a new folder in the `src/main/antora/modules` folder with the name of the module you are migrating. For example, for the Security module, you would create a `security` folder. +=== Migrating the Jakarta EE 8 branch + +. Check out the release/8 branch and create a new branch from it for your work. + +. Select the module to migrate. We consider each Part of the current https://eclipse-ee4j.github.io/jakartaee-tutorial/[Jakata EE Tutorial] to be a module (for example, Introduction, Web Tier, Bean Validation, etc). + +. Create a new folder in the `src/main/antora/modules` folder with the name of the module you are migrating. For example, for the Security module, you would create a `security` folder. * Inside of this folder, create a `pages` folder. -4. Move all the folders for the module you are migrating into the new `pages` folder. For example, for the Security module, you would move all of the `src/main/asciidoc/security-*` folders into the `src/main/antora/modules/security/pages`. (Copy the entire folders, not just the `.adoc` files). + +. Move all the folders for the module you are migrating into the new `pages` folder. For example, for the Security module, you would move all of the `src/main/asciidoc/security-*` folders into the `src/main/antora/modules/security/pages`. (Copy the entire folders, not just the `.adoc` files). > NOTE: It's essential that you _move_ rather than copy the folders so that we keep the history intact. -5. Run the migration script from the root project folder. For example, for the Security module, you would run `jbang antora-conversion/AntoraConverter.java security`. (The first parameter is the folder relative to `src/main/antora/modules`). -6. Create a new file called `nav.adoc` in the root of the module folder. For example, for the Security module, you would create a `security/nav.adoc`. -7. Copy all the include statements from the corresponding "part" file in the `src/main/asciidoc/` folder. For example, for the Security module, you would copy the include statements of `src/main/asciidoc/partsecurity.adoc` into the `security/nav.adoc` file. Here are the include statements for the Security module: +. Run the migration script from the root project folder. For example, for the Security module, you would run: -```asciidoc +[source,shell] +---- +jbang antora-conversion/AntoraConverter.java src/main/antora/modules/security +---- + +> TIP: You can use the "dryrun" parameter to see what changes will be made without actually making them. + +> NOTE: References to chapters that haven't yet been converted will not work until they have been converted. + +. Create a new file called `nav.adoc` in the root of the module folder. For example, for the Security module, you would create a `security/nav.adoc`. + +. Copy all the include statements from the corresponding "part" file in the `src/main/asciidoc/` folder. For example, for the Security module, you would copy the include statements of `src/main/asciidoc/partsecurity.adoc` into the `security/nav.adoc` file. Here are the include statements for the Security module: + +[source,asciidoc] +---- include::security-intro/security-intro.adoc[] include::security-webtier/security-webtier.adoc[] @@ -34,7 +51,7 @@ include::security-jakartaee/security-jakartaee.adoc[] include::security-api/security-api.adoc[] include::security-advanced/security-advanced.adoc[] -``` +---- After copying these into `nav.adoc`, replace "include::" with "* xref:" and add a header with the module name: @@ -51,9 +68,37 @@ After copying these into `nav.adoc`, replace "include::" with "* xref:" and add * xref:security-advanced/security-advanced.adoc[] ``` -8. Add this module to the `src/main/antora/antora.yml`. For example, for the Security module, you would add this line to the end of `src/main/antora/antora.yml` file: +. Add this module to the `src/main/antora/antora.yml`. For example, for the Security module, you would add this line to the end of `src/main/antora/antora.yml` file: ```yaml - modules/security/nav.adoc ``` +. Commit your changes, push, and raise a PR to merge into the `release/8` branch. You're done with the first part of the migration! + +=== Migrating the Jakarta EE 9 branch + +. Create a new branch from the migrated version of the `release/8` branch you just created. + +. Merge `release/9` into your new branch. Accept all changes from the `release/9` branch. + +. Run the migration script from the root project folder. For example, for the Security module, you would run: + +```shell +jbang antora-conversion/AntoraConverter.java jakartaee-tutorial/src/main/antora/modules/security +``` + +> TIP: You can use the "dryrun" parameter to see what changes will be made without actually making them. + +> NOTE: References to chapters that haven't yet been converted will not work until they have been converted. + +. If there are any changes the script didn't make, either make them manually or update the script to handle them. + +> TIP: If you're using the Antora IDE plugin, it helps to review its errors and updating before committing. With IntellJ, +these are run automatically before pushing. + +. Commit your changes, push, and raise a PR to merge into the `release/9.1` branch. + +. Raise a PR to merge `release/9.1` into `main`. + +. You're done! From b52fc5a42ac01fac11c229980d62ee2577ee0163 Mon Sep 17 00:00:00 2001 From: "Kito D. Mann" Date: Thu, 1 Jun 2023 12:29:54 -0400 Subject: [PATCH 046/247] JETUT-120 Replaced olink with raw external links --- .../modules/web/pages/jsf-custom/jsf-custom009.adoc | 2 +- .../modules/web/pages/jsf-page-core/jsf-page-core004.adoc | 2 +- .../antora/modules/web/pages/jsf-page/jsf-page001.adoc | 6 +++--- .../antora/modules/web/pages/jsf-page/jsf-page002.adoc | 8 ++++---- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/main/antora/modules/web/pages/jsf-custom/jsf-custom009.adoc b/src/main/antora/modules/web/pages/jsf-custom/jsf-custom009.adoc index 05b9f1b2..b45eda58 100644 --- a/src/main/antora/modules/web/pages/jsf-custom/jsf-custom009.adoc +++ b/src/main/antora/modules/web/pages/jsf-custom/jsf-custom009.adoc @@ -6,7 +6,7 @@ To use a custom tag, you declare it in a Tag Library Descriptor (TLD). The TLD file defines how the custom tag is used in a Jakarta Server Faces page. The web container uses the TLD to validate the tag. The set of tags that are part of the HTML render kit are defined in the HTML_BASIC -TLD, available in the olink:JSFRK[Jakarta Server Faces standard HTML tag +TLD, available in the https://jakarta.ee/specifications/faces/2.3/vdldoc/[Jakarta Server Faces standard HTML tag library]. The TLD file name must end with `taglib.xml`. In the Duke's Bookstore diff --git a/src/main/antora/modules/web/pages/jsf-page-core/jsf-page-core004.adoc b/src/main/antora/modules/web/pages/jsf-page-core/jsf-page-core004.adoc index 34fdd161..4091eee6 100644 --- a/src/main/antora/modules/web/pages/jsf-page-core/jsf-page-core004.adoc +++ b/src/main/antora/modules/web/pages/jsf-page-core/jsf-page-core004.adoc @@ -36,7 +36,7 @@ attributes. The component tag refers to a managed bean method using a method expression as a value of one of the attributes. The method referenced by an attribute must follow a particular signature, which is defined by the -tag attribute's definition in the olink:JSFTL[Jakarta Server Faces Facelets +tag attribute's definition in the https://jakarta.ee/specifications/faces/2.3/vdldoc/[Jakarta Server Faces Facelets Tag Library documentation]. For example, the definition of the `validator` attribute of the `inputText` tag is the following: diff --git a/src/main/antora/modules/web/pages/jsf-page/jsf-page001.adoc b/src/main/antora/modules/web/pages/jsf-page/jsf-page001.adoc index 38d298fd..8f8dc51b 100644 --- a/src/main/antora/modules/web/pages/jsf-page/jsf-page001.adoc +++ b/src/main/antora/modules/web/pages/jsf-page/jsf-page001.adoc @@ -12,13 +12,13 @@ libraries To add the Jakarta Server Faces components to your web page, you need to provide the page access to the two standard tag libraries: the Jakarta Server Faces HTML render kit tag library and the Jakarta Server Faces -core tag library. The olink:JSFRK[Jakarta Server Faces standard HTML tag -library] defines tags that represent common HTML user interface +core tag library. The Jakarta Server Faces standard HTML tag +library defines tags that represent common HTML user interface components. The Jakarta Server Faces core tag library defines tags that perform core actions and are independent of a particular render kit. For a complete list of Jakarta Server Faces Facelets tags and their -attributes, refer to the olink:JSFTL[Jakarta Server Faces Facelets Tag +attributes, refer to the https://jakarta.ee/specifications/faces/2.3/vdldoc/[Jakarta Server Faces Facelets Tag Library documentation]. To use any of the Jakarta Server Faces tags, you need to include appropriate diff --git a/src/main/antora/modules/web/pages/jsf-page/jsf-page002.adoc b/src/main/antora/modules/web/pages/jsf-page/jsf-page002.adoc index dc155b1a..d7ebbae5 100644 --- a/src/main/antora/modules/web/pages/jsf-page/jsf-page002.adoc +++ b/src/main/antora/modules/web/pages/jsf-page/jsf-page002.adoc @@ -114,7 +114,7 @@ Properties] explains how to write a bean property bound to that particular component or its value. For reference information about the tags and their attributes, see the -olink:JSFTL[Jakarta Server Faces Facelets Tag Library documentation]. +https://jakarta.ee/specifications/faces/2.3/vdldoc/[Jakarta Server Faces Facelets Tag Library documentation]. [[BNARG]][[common-component-tag-attributes]] @@ -469,7 +469,7 @@ The input tags support the tag attributes shown in link:#GKCNH[Table 10-4] in addition to those described in link:#BNARG[Common Component Tag Attributes]. Note that this table does not include all the attributes supported by the input tags but just those that are used most often. For -the complete list of attributes, refer to the olink:JSFTL[Jakarta Server +the complete list of attributes, refer to the https://jakarta.ee/specifications/faces/2.3/vdldoc/[Jakarta Server Faces Facelets Tag Library documentation]. [[sthref45]][[GKCNH]] @@ -1508,7 +1508,7 @@ message. In the example in this section, the text will be a shade of red, New Century Schoolbook, serif font family, and oblique style, and a line will appear over the text. The message and messages tags support many other attributes for defining styles. For more information on these -attributes, refer to the olink:JSFTL[Jakarta Server Faces Facelets Tag +attributes, refer to the https://jakarta.ee/specifications/faces/2.3/vdldoc/[Jakarta Server Faces Facelets Tag Library documentation]. Another attribute supported by the `h:messages` tag is the `layout` @@ -1741,7 +1741,7 @@ Resource relocation can be defined with the following HTML tags: These tags have `name` and `target` attributes, which can be used to define the render location. For a complete list of attributes for these -tags, see theolink:JSFTL[Jakarta Server Faces Facelets Tag Library +tags, see the https://jakarta.ee/specifications/faces/2.3/vdldoc/[Jakarta Server Faces Facelets Tag Library documentation]. For the `h:outputScript` tag, the `name` and `target` attributes define From 205b8f24f6ba857c59c97be360804449a27e978a Mon Sep 17 00:00:00 2001 From: Bauke Scholtz Date: Thu, 1 Jun 2023 13:21:09 -0400 Subject: [PATCH 047/247] JETUT-72: rewrite associated adocs as preparement of new introduction of web profile -- NOTE it must be said that from the current perspective it's really odd to see Jakarta Validation and Security being listed *before* Jakarta Servlet and Faces while the introduction basically introduces Jakarta Servlet and Faces --- src/main/asciidoc/partwebtier.adoc | 12 ++++- src/main/asciidoc/webapp/webapp.adoc | 3 +- src/main/asciidoc/webapp/webapp001.adoc | 70 +++++++++++++------------ src/main/asciidoc/webapp/webapp002.adoc | 44 ++++++++-------- 4 files changed, 69 insertions(+), 60 deletions(-) diff --git a/src/main/asciidoc/partwebtier.adoc b/src/main/asciidoc/partwebtier.adoc index b949eccf..57a6546f 100644 --- a/src/main/asciidoc/partwebtier.adoc +++ b/src/main/asciidoc/partwebtier.adoc @@ -1,6 +1,14 @@ -= The Web Tier += Web Profile -Part III explores the technologies in the web tier. +The Web Profile extends the Core Profile with the following technologies: + +- Jakarta Validation +- Jakarta Security +- Jakarta Servlet +- Jakarta Faces +- Jakarta Websocket +- Jakarta Persistence +- Jakarta Enterprise Beans Lite :leveloffset: +1 diff --git a/src/main/asciidoc/webapp/webapp.adoc b/src/main/asciidoc/webapp/webapp.adoc index 1323bdab..957efae8 100644 --- a/src/main/asciidoc/webapp/webapp.adoc +++ b/src/main/asciidoc/webapp/webapp.adoc @@ -1,6 +1,6 @@ = Getting Started with Web Applications -This chapter introduces web applications, which typically use Jakarta Faces technology and/or Jakarta Servlet technology. +The Web Profile allows you to get started developing Java web applications, which typically use Jakarta Servlet technology as corner stone. include::webapp001.adoc[] @@ -13,4 +13,3 @@ include::webapp004.adoc[] include::webapp005.adoc[] include::webapp006.adoc[] - diff --git a/src/main/asciidoc/webapp/webapp001.adoc b/src/main/asciidoc/webapp/webapp001.adoc index e7325a6c..eafb3dd9 100644 --- a/src/main/asciidoc/webapp/webapp001.adoc +++ b/src/main/asciidoc/webapp/webapp001.adoc @@ -1,46 +1,50 @@ == Web Applications -A web application is a dynamic extension of a web or application server. +A web application, also known as a web app, is a software application that runs on one or more web servers. +It is typically accessed through a web browser over a network, such as the Internet. +The advantage over traditional desktop applications is being platform-independent, as it can be accessed and used on different devices. Web applications are of the following types: Presentation-oriented:: -A presentation-oriented web application generates interactive web pages containing various types of markup language (HTML, XHTML, XML, and so on) and dynamic content in response to requests. -Development of presentation-oriented web applications is covered in xref:jakarta-faces-technology-2[xrefstyle=full] through xref:jakarta-servlet-technology-2[xrefstyle=full] +A presentation-oriented web application generates interactive web pages containing dynamic content in response to HTTP requests. +The response is usually represented as a HTML document along with assets. +Development of presentation-oriented web applications is covered in [TBD] Service-oriented:: -A service-oriented web application implements the endpoint of a web service. +A service-oriented web application generates dynamic data structures in response to HTTP requests. +The response is usually represented as a JSON object or as a XML document. Presentation-oriented applications are often clients of service-oriented web applications. -Development of service-oriented web applications is covered in xref:building-web-services-with-jakarta-xml-web-services[xrefstyle=full] and xref:building-restful-web-services-with-jakarta-rest[xrefstyle=full] in xref:web-services[xrefstyle=full] - -In the Jakarta EE platform, web components provide the dynamic extension capabilities for a web server. -Web components can be Jakarta servlets, web pages implemented with Jakarta Faces technology, web service endpoints, or Jakarta Server Pages. -xref:jakarta-web-application-request-handling[xrefstyle=short] illustrates the interaction between a web client and a web application that uses a servlet. -The client sends an HTTP request to the web server. -A web server that implements Jakarta Servlet and Jakarta Server Pages technology converts the request into an `HTTPServletRequest` object. -This object is delivered to a web component, which can interact with JavaBeans components or a database to generate dynamic content. -The web component can then generate an `HTTPServletResponse` or can pass the request to another web component. -A web component eventually generates a `HTTPServletResponse` object. -The web server converts this object to an HTTP response and returns it to the client. +Development of service-oriented web applications is covered in [TBD] + +In the Jakarta EE platform, web applications are represented by web components as seen in xref:jakarta-web-application-request-handling[xrefstyle=short]. +A web component can be represented by Jakarta Servlet, Jakarta Faces or Jakarta REST. [[jakarta-web-application-request-handling]] .Jakarta Web Application Request Handling image::jakartaeett_dt_013.svg["Diagram of web application request handling. Clients and servlets communicate using HttpServletRequest and HttpServletResponse."] -Servlets are Java programming language classes that dynamically process requests and construct responses. -Java technologies, such as Jakarta Faces and Facelets, are used for building interactive web applications. -(Frameworks can also be used for this purpose.) -Although servlets and Jakarta Faces and Facelets pages can be used to accomplish similar things, each has its own strengths. -Servlets are best suited for service-oriented applications (web service endpoints can be implemented as servlets) and the control functions of a presentation-oriented application, such as dispatching requests and handling nontextual data. -Jakarta Faces and Facelets pages are more appropriate for generating text-based markup, such as XHTML, and are generally used for presentation-oriented applications. - -Web components are supported by the services of a runtime platform called a web container. -A web container provides such services as request dispatching, security, concurrency, and lifecycle management. -A web container also gives web components access to such APIs as naming, transactions, and email. - -Certain aspects of web application behavior can be configured when the application is installed, or deployed, to the web container. -The configuration information can be specified using Jakarta EE annotations or can be maintained in a text file in XML format called a web application deployment descriptor (DD). -A web application DD must conform to the schema described in the Jakarta Servlet specification. - -This chapter gives a brief overview of the activities involved in developing web applications. -First, it summarizes the web application lifecycle and explains how to package and deploy very simple web applications on GlassFish Server. -The chapter then moves on to configuring web applications and discusses how to specify the most commonly used configuration parameters. +. The client sends an HTTP request to the web server. +. The web server module that supports Jakarta Servlet based web components is called a servlet container. +. The servlet container converts the HTTP request into an `HttpServletRequest` object and prepares the `HttpServletResponse` object. +. These objects are delivered to a web component, which can interact with JavaBeans components or a database to generate dynamic content. +. The web component can then fill the `HttpServletResponse` object with the generated dynamic content or can pass the object to another web component to fill it. +. The servlet container ultimately converts the `HttpServletResponse` object to an HTTP response and the web server returns it to the client. + +Jakarta Servlet is a barebones web framework that can act as a presentation-oriented as well as a service-oriented web application. +Jakarta Faces is a component based MVC framework that can be executed on a servlet container and act as a presentation-oriented web application. +Jakarta Faces intends to reduce the boilerplate code needed to apply the request values, convert and validate them, update the JavaBean properties, invoke the JavaBean methods and generate HTML output. +Jakarta Faces is designed as such that it can be exuected on a non-servlet container such as a portlet container. +Jakarta REST is a RESTful web service framework that can be executed on a servlet container and act as a service-oriented web application. +Jakarta REST intends to reduce the boilerplate code needed to convert the request values to a JavaBean and further convert it to the desired response such as JSON or XML. +Jakarta REST is designed as such that it can be exuected on a non-servlet container such as a microservice. + +A servlet container is a kind of a web container that can be part of an application server. +The application server gives web components access to such APIs as naming, validation, security, web sockets, persistence transactions, concurrency, and email. + +Certain aspects of web application behavior can be configured when the application is installed, or deployed, to a web container. +The configuration information can be specified using annotations or can be maintained in a XML file called a deployment descriptor (DD). +A DD must conform to the schema described in the associated specification. +When the same configuration is specified using annotations and in a XML file, then the configuration in the XML file will always have precedence. + +This chapter gives a brief overview of the activities involved in developing Jakarta Servlet based web applications. +It explains how to compile, develop, package, deploy, and run Jakarta Servlet based web applications in a servlet container. diff --git a/src/main/asciidoc/webapp/webapp002.adoc b/src/main/asciidoc/webapp/webapp002.adoc index 3bb0a473..ae8c58b2 100644 --- a/src/main/asciidoc/webapp/webapp002.adoc +++ b/src/main/asciidoc/webapp/webapp002.adoc @@ -1,32 +1,30 @@ -== Web Application Lifecycle +== The Web Application Archive -A web application consists of web components; static resource files, such as images and cascading style sheets (CSS); and helper classes and libraries. -The web container provides many supporting services that enhance the capabilities of web components and make them easier to develop. -However, because a web application must take these services into account, the process for creating and running a web application is different from that of traditional stand-alone Java classes. +A Jakarta Servlet based web application can contain one or more of the following parts: -The process for creating, deploying, and executing a web application can be summarized as follows: +* one or more web components, which can be represented by Jakarta Servlet, Jakarta Faces or Jakarta REST +* assets (also called static resource files), such Cascading Style Sheets (CSS), JavaScript (JS) and images +* helper libraries +* DD files -. Develop the web component code. - -. Develop the web application deployment descriptor, if necessary. - -. Compile the web application components and helper classes referenced by the components. - -. Optionally, package the application into a deployable unit. +The process for creating, deploying, and executing a Jakarta Servlet based web application is different from that of Java classes which are packaged and executed as a Java application archive (JAR). +It can be summarized as follows: -. Deploy the application into a web container. - -. Access a URL that references the web application. - -Developing web component code is covered in the later chapters. -Steps 2 through 6 are expanded on in the following sections and illustrated with a Hello, World–style, presentation-oriented application. +. Develop the web component code. +. Develop the DD files, if necessary. +. Compile the web component code against the libraries of the servlet container and the helper libraries, if any. +. Package the compiled code along with helper libraries, assets and DD files, if any, into a deployable unit, called a web application archive (WAR). +. Deploy the WAR into a servlet container. +. Run the web application by accessing a URL that references the web component. + +Developing the web component code and DD files is covered in the later chapters. +Steps 3 through 6 are expanded on in the following sections and illustrated with a Hello World–style, web application. This application allows a user to enter a name into an HTML form and then displays a greeting after the name is submitted. -The Hello application contains two web components that generate the greeting and the response. +The Hello World application contains two web components that generate the greeting and the response. This chapter discusses the following simple applications: -* `hello1`, a Jakarta Faces technology–based application that uses two XHTML pages and a managed bean - -* `hello2`, a servlet-based web application in which the components are implemented by two servlet classes +* `helloFaces`, a Jakarta Faces based presentation-oriented web application +* `helloServlet`, a Jakarta Servlet based service-oriented web application -The applications are used to illustrate tasks involved in packaging, deploying, configuring, and running an application that contains web components. +The applications are used to illustrate tasks involved in compiling, packaging, deploying, and running a Jakarta Servlet based web application that contains web components. From 7158e3ab237a72d0747e09f2e173b6045ff064c3 Mon Sep 17 00:00:00 2001 From: "Kito D. Mann" Date: Thu, 1 Jun 2023 13:24:25 -0400 Subject: [PATCH 048/247] JETUT-120 Added web module and navigation --- src/main/antora/antora.yml | 1 + src/main/antora/modules/web/nav.adoc | 38 ++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+) create mode 100644 src/main/antora/modules/web/nav.adoc diff --git a/src/main/antora/antora.yml b/src/main/antora/antora.yml index 690feab4..a13660cd 100644 --- a/src/main/antora/antora.yml +++ b/src/main/antora/antora.yml @@ -9,4 +9,5 @@ asciidoc: nav: - modules/ROOT/nav.adoc - modules/security/nav.adoc + - modules/web/nav.adoc diff --git a/src/main/antora/modules/web/nav.adoc b/src/main/antora/modules/web/nav.adoc new file mode 100644 index 00000000..65f55caa --- /dev/null +++ b/src/main/antora/modules/web/nav.adoc @@ -0,0 +1,38 @@ +.The Web Tier + +* xref:webapp/webapp.adoc[] + +* xref:jsf-intro/jsf-intro.adoc[] + +* xref:jsf-facelets/jsf-facelets.adoc[] + +* xref:jsf-el/jsf-el.adoc[] + +* xref:jsf-page/jsf-page.adoc[] + +* xref:jsf-page-core/jsf-page-core.adoc[] + +* xref:jsf-develop/jsf-develop.adoc[] + +* xref:jsf-ajax/jsf-ajax.adoc[] + +* xref:jsf-advanced-cc/jsf-advanced-cc.adoc[] + +* xref:jsf-custom/jsf-custom.adoc[] + +* xref:jsf-configure/jsf-configure.adoc[] + +* xref:jsf-ws/jsf-ws.adoc[] + +* xref:servlets/servlets.adoc[] + +* xref:websocket/websocket.adoc[] + +* xref:jsonp/jsonp.adoc[] + +* xref:jsonb/jsonb.adoc[] + +* xref:webi18n/webi18n.adoc[] + + + From 0480c5a461c58a46956c722faded9c0fbb9fe8dc Mon Sep 17 00:00:00 2001 From: "Kito D. Mann" Date: Thu, 1 Jun 2023 13:26:07 -0400 Subject: [PATCH 049/247] JETUT-120 Moved websocket to web module --- .../modules/web/pages}/websocket/websocket.adoc | 0 .../modules/web/pages}/websocket/websocket001.adoc | 0 .../modules/web/pages}/websocket/websocket002.adoc | 0 .../modules/web/pages}/websocket/websocket003.adoc | 0 .../modules/web/pages}/websocket/websocket004.adoc | 0 .../modules/web/pages}/websocket/websocket005.adoc | 0 .../modules/web/pages}/websocket/websocket006.adoc | 0 .../modules/web/pages}/websocket/websocket007.adoc | 0 .../modules/web/pages}/websocket/websocket008.adoc | 0 .../modules/web/pages}/websocket/websocket009.adoc | 0 .../modules/web/pages}/websocket/websocket010.adoc | 0 .../modules/web/pages}/websocket/websocket011.adoc | 0 .../modules/web/pages}/websocket/websocket012.adoc | 0 .../modules/web/pages}/websocket/websocket013.adoc | 0 14 files changed, 0 insertions(+), 0 deletions(-) rename src/main/{asciidoc => antora/modules/web/pages}/websocket/websocket.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/websocket/websocket001.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/websocket/websocket002.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/websocket/websocket003.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/websocket/websocket004.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/websocket/websocket005.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/websocket/websocket006.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/websocket/websocket007.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/websocket/websocket008.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/websocket/websocket009.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/websocket/websocket010.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/websocket/websocket011.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/websocket/websocket012.adoc (100%) rename src/main/{asciidoc => antora/modules/web/pages}/websocket/websocket013.adoc (100%) diff --git a/src/main/asciidoc/websocket/websocket.adoc b/src/main/antora/modules/web/pages/websocket/websocket.adoc similarity index 100% rename from src/main/asciidoc/websocket/websocket.adoc rename to src/main/antora/modules/web/pages/websocket/websocket.adoc diff --git a/src/main/asciidoc/websocket/websocket001.adoc b/src/main/antora/modules/web/pages/websocket/websocket001.adoc similarity index 100% rename from src/main/asciidoc/websocket/websocket001.adoc rename to src/main/antora/modules/web/pages/websocket/websocket001.adoc diff --git a/src/main/asciidoc/websocket/websocket002.adoc b/src/main/antora/modules/web/pages/websocket/websocket002.adoc similarity index 100% rename from src/main/asciidoc/websocket/websocket002.adoc rename to src/main/antora/modules/web/pages/websocket/websocket002.adoc diff --git a/src/main/asciidoc/websocket/websocket003.adoc b/src/main/antora/modules/web/pages/websocket/websocket003.adoc similarity index 100% rename from src/main/asciidoc/websocket/websocket003.adoc rename to src/main/antora/modules/web/pages/websocket/websocket003.adoc diff --git a/src/main/asciidoc/websocket/websocket004.adoc b/src/main/antora/modules/web/pages/websocket/websocket004.adoc similarity index 100% rename from src/main/asciidoc/websocket/websocket004.adoc rename to src/main/antora/modules/web/pages/websocket/websocket004.adoc diff --git a/src/main/asciidoc/websocket/websocket005.adoc b/src/main/antora/modules/web/pages/websocket/websocket005.adoc similarity index 100% rename from src/main/asciidoc/websocket/websocket005.adoc rename to src/main/antora/modules/web/pages/websocket/websocket005.adoc diff --git a/src/main/asciidoc/websocket/websocket006.adoc b/src/main/antora/modules/web/pages/websocket/websocket006.adoc similarity index 100% rename from src/main/asciidoc/websocket/websocket006.adoc rename to src/main/antora/modules/web/pages/websocket/websocket006.adoc diff --git a/src/main/asciidoc/websocket/websocket007.adoc b/src/main/antora/modules/web/pages/websocket/websocket007.adoc similarity index 100% rename from src/main/asciidoc/websocket/websocket007.adoc rename to src/main/antora/modules/web/pages/websocket/websocket007.adoc diff --git a/src/main/asciidoc/websocket/websocket008.adoc b/src/main/antora/modules/web/pages/websocket/websocket008.adoc similarity index 100% rename from src/main/asciidoc/websocket/websocket008.adoc rename to src/main/antora/modules/web/pages/websocket/websocket008.adoc diff --git a/src/main/asciidoc/websocket/websocket009.adoc b/src/main/antora/modules/web/pages/websocket/websocket009.adoc similarity index 100% rename from src/main/asciidoc/websocket/websocket009.adoc rename to src/main/antora/modules/web/pages/websocket/websocket009.adoc diff --git a/src/main/asciidoc/websocket/websocket010.adoc b/src/main/antora/modules/web/pages/websocket/websocket010.adoc similarity index 100% rename from src/main/asciidoc/websocket/websocket010.adoc rename to src/main/antora/modules/web/pages/websocket/websocket010.adoc diff --git a/src/main/asciidoc/websocket/websocket011.adoc b/src/main/antora/modules/web/pages/websocket/websocket011.adoc similarity index 100% rename from src/main/asciidoc/websocket/websocket011.adoc rename to src/main/antora/modules/web/pages/websocket/websocket011.adoc diff --git a/src/main/asciidoc/websocket/websocket012.adoc b/src/main/antora/modules/web/pages/websocket/websocket012.adoc similarity index 100% rename from src/main/asciidoc/websocket/websocket012.adoc rename to src/main/antora/modules/web/pages/websocket/websocket012.adoc diff --git a/src/main/asciidoc/websocket/websocket013.adoc b/src/main/antora/modules/web/pages/websocket/websocket013.adoc similarity index 100% rename from src/main/asciidoc/websocket/websocket013.adoc rename to src/main/antora/modules/web/pages/websocket/websocket013.adoc From 88bb1e1440b820434b7b82925c8dbe54c0726987 Mon Sep 17 00:00:00 2001 From: "Kito D. Mann" Date: Thu, 1 Jun 2023 13:35:05 -0400 Subject: [PATCH 050/247] JETUT-120 Updated web module files with the script --- .../jsf-advanced-cc/jsf-advanced-cc.adoc | 2 +- .../jsf-advanced-cc/jsf-advanced-cc001.adoc | 6 +- .../jsf-advanced-cc/jsf-advanced-cc002.adoc | 4 +- .../jsf-advanced-cc/jsf-advanced-cc003.adoc | 6 +- .../jsf-advanced-cc/jsf-advanced-cc004.adoc | 24 +-- .../modules/web/pages/jsf-ajax/jsf-ajax.adoc | 2 +- .../web/pages/jsf-ajax/jsf-ajax001.adoc | 4 +- .../web/pages/jsf-ajax/jsf-ajax002.adoc | 4 +- .../web/pages/jsf-ajax/jsf-ajax003.adoc | 10 +- .../web/pages/jsf-ajax/jsf-ajax004.adoc | 14 +- .../web/pages/jsf-ajax/jsf-ajax005.adoc | 4 +- .../web/pages/jsf-ajax/jsf-ajax006.adoc | 4 +- .../web/pages/jsf-ajax/jsf-ajax007.adoc | 2 +- .../web/pages/jsf-ajax/jsf-ajax008.adoc | 4 +- .../web/pages/jsf-ajax/jsf-ajax009.adoc | 2 +- .../web/pages/jsf-ajax/jsf-ajax010.adoc | 16 +- .../web/pages/jsf-ajax/jsf-ajax011.adoc | 26 +-- .../web/pages/jsf-ajax/jsf-ajax012.adoc | 4 +- .../pages/jsf-configure/jsf-configure.adoc | 2 +- .../pages/jsf-configure/jsf-configure001.adoc | 10 +- .../pages/jsf-configure/jsf-configure002.adoc | 12 +- .../pages/jsf-configure/jsf-configure003.adoc | 6 +- .../pages/jsf-configure/jsf-configure004.adoc | 48 +++-- .../pages/jsf-configure/jsf-configure005.adoc | 38 ++-- .../pages/jsf-configure/jsf-configure006.adoc | 10 +- .../pages/jsf-configure/jsf-configure007.adoc | 2 +- .../pages/jsf-configure/jsf-configure008.adoc | 8 +- .../pages/jsf-configure/jsf-configure009.adoc | 8 +- .../pages/jsf-configure/jsf-configure010.adoc | 6 +- .../pages/jsf-configure/jsf-configure011.adoc | 6 +- .../pages/jsf-configure/jsf-configure012.adoc | 6 +- .../pages/jsf-configure/jsf-configure013.adoc | 22 +-- .../web/pages/jsf-custom/jsf-custom.adoc | 2 +- .../web/pages/jsf-custom/jsf-custom001.adoc | 6 +- .../web/pages/jsf-custom/jsf-custom002.adoc | 26 +-- .../web/pages/jsf-custom/jsf-custom003.adoc | 26 +-- .../web/pages/jsf-custom/jsf-custom004.adoc | 10 +- .../web/pages/jsf-custom/jsf-custom005.adoc | 26 +-- .../web/pages/jsf-custom/jsf-custom006.adoc | 16 +- .../web/pages/jsf-custom/jsf-custom007.adoc | 16 +- .../web/pages/jsf-custom/jsf-custom008.adoc | 10 +- .../web/pages/jsf-custom/jsf-custom009.adoc | 4 +- .../web/pages/jsf-custom/jsf-custom010.adoc | 4 +- .../web/pages/jsf-custom/jsf-custom011.adoc | 20 +- .../web/pages/jsf-custom/jsf-custom012.adoc | 26 +-- .../web/pages/jsf-custom/jsf-custom013.adoc | 16 +- .../web/pages/jsf-custom/jsf-custom014.adoc | 8 +- .../web/pages/jsf-develop/jsf-develop.adoc | 2 +- .../web/pages/jsf-develop/jsf-develop001.adoc | 20 +- .../web/pages/jsf-develop/jsf-develop002.adoc | 60 +++--- .../web/pages/jsf-develop/jsf-develop003.adoc | 26 +-- .../modules/web/pages/jsf-el/jsf-el.adoc | 2 +- .../modules/web/pages/jsf-el/jsf-el001.adoc | 4 +- .../modules/web/pages/jsf-el/jsf-el002.adoc | 6 +- .../modules/web/pages/jsf-el/jsf-el003.adoc | 18 +- .../modules/web/pages/jsf-el/jsf-el004.adoc | 2 +- .../modules/web/pages/jsf-el/jsf-el005.adoc | 2 +- .../modules/web/pages/jsf-el/jsf-el006.adoc | 2 +- .../modules/web/pages/jsf-el/jsf-el007.adoc | 4 +- .../modules/web/pages/jsf-el/jsf-el008.adoc | 2 +- .../web/pages/jsf-facelets/jsf-facelets.adoc | 2 +- .../pages/jsf-facelets/jsf-facelets001.adoc | 10 +- .../pages/jsf-facelets/jsf-facelets002.adoc | 6 +- .../pages/jsf-facelets/jsf-facelets003.adoc | 24 +-- .../pages/jsf-facelets/jsf-facelets004.adoc | 4 +- .../pages/jsf-facelets/jsf-facelets005.adoc | 8 +- .../pages/jsf-facelets/jsf-facelets006.adoc | 2 +- .../pages/jsf-facelets/jsf-facelets007.adoc | 4 +- .../pages/jsf-facelets/jsf-facelets008.adoc | 20 +- .../pages/jsf-facelets/jsf-facelets009.adoc | 30 +-- .../web/pages/jsf-intro/jsf-intro.adoc | 2 +- .../web/pages/jsf-intro/jsf-intro001.adoc | 2 +- .../web/pages/jsf-intro/jsf-intro002.adoc | 9 +- .../web/pages/jsf-intro/jsf-intro003.adoc | 13 +- .../web/pages/jsf-intro/jsf-intro004.adoc | 12 +- .../web/pages/jsf-intro/jsf-intro005.adoc | 40 ++-- .../web/pages/jsf-intro/jsf-intro006.adoc | 8 +- .../web/pages/jsf-intro/jsf-intro007.adoc | 47 +++-- .../web/pages/jsf-intro/jsf-intro008.adoc | 4 +- .../web/pages/jsf-intro/jsf-intro009.adoc | 2 +- .../pages/jsf-page-core/jsf-page-core.adoc | 2 +- .../pages/jsf-page-core/jsf-page-core001.adoc | 30 +-- .../pages/jsf-page-core/jsf-page-core002.adoc | 16 +- .../pages/jsf-page-core/jsf-page-core003.adoc | 22 +-- .../pages/jsf-page-core/jsf-page-core004.adoc | 22 +-- .../modules/web/pages/jsf-page/jsf-page.adoc | 4 +- .../web/pages/jsf-page/jsf-page001.adoc | 6 +- .../web/pages/jsf-page/jsf-page002.adoc | 187 +++++++++--------- .../web/pages/jsf-page/jsf-page003.adoc | 38 ++-- .../modules/web/pages/jsf-ws/jsf-ws.adoc | 2 +- .../modules/web/pages/jsf-ws/jsf-ws001.adoc | 2 +- .../modules/web/pages/jsf-ws/jsf-ws002.adoc | 6 +- .../modules/web/pages/jsf-ws/jsf-ws003.adoc | 6 +- .../modules/web/pages/jsf-ws/jsf-ws004.adoc | 2 +- .../modules/web/pages/jsf-ws/jsf-ws005.adoc | 6 +- .../modules/web/pages/jsf-ws/jsf-ws006.adoc | 2 +- .../modules/web/pages/jsf-ws/jsf-ws007.adoc | 2 +- .../antora/modules/web/pages/jsonb/jsonb.adoc | 6 +- .../modules/web/pages/jsonb/jsonb001.adoc | 14 +- .../modules/web/pages/jsonb/jsonb002.adoc | 14 +- .../modules/web/pages/jsonb/jsonb003.adoc | 8 +- .../modules/web/pages/jsonb/jsonb004.adoc | 2 +- .../antora/modules/web/pages/jsonp/jsonp.adoc | 2 +- .../modules/web/pages/jsonp/jsonp001.adoc | 10 +- .../modules/web/pages/jsonp/jsonp002.adoc | 12 +- .../modules/web/pages/jsonp/jsonp003.adoc | 22 +-- .../modules/web/pages/jsonp/jsonp004.adoc | 6 +- .../modules/web/pages/jsonp/jsonp005.adoc | 8 +- .../modules/web/pages/jsonp/jsonp006.adoc | 20 +- .../modules/web/pages/jsonp/jsonp007.adoc | 18 +- .../modules/web/pages/jsonp/jsonp008.adoc | 2 +- .../modules/web/pages/servlets/servlets.adoc | 2 +- .../web/pages/servlets/servlets001.adoc | 2 +- .../web/pages/servlets/servlets002.adoc | 16 +- .../web/pages/servlets/servlets003.adoc | 14 +- .../web/pages/servlets/servlets004.adoc | 2 +- .../web/pages/servlets/servlets005.adoc | 10 +- .../web/pages/servlets/servlets006.adoc | 22 +-- .../web/pages/servlets/servlets007.adoc | 6 +- .../web/pages/servlets/servlets008.adoc | 2 +- .../web/pages/servlets/servlets009.adoc | 14 +- .../web/pages/servlets/servlets010.adoc | 8 +- .../web/pages/servlets/servlets011.adoc | 6 +- .../web/pages/servlets/servlets012.adoc | 8 +- .../web/pages/servlets/servlets013.adoc | 18 +- .../web/pages/servlets/servlets014.adoc | 8 +- .../web/pages/servlets/servlets014a.adoc | 2 +- .../web/pages/servlets/servlets014b.adoc | 2 +- .../web/pages/servlets/servlets015.adoc | 14 +- .../web/pages/servlets/servlets016.adoc | 16 +- .../web/pages/servlets/servlets017.adoc | 28 +-- .../web/pages/servlets/servlets018.adoc | 2 +- .../modules/web/pages/webapp/webapp.adoc | 2 +- .../modules/web/pages/webapp/webapp001.adoc | 18 +- .../modules/web/pages/webapp/webapp002.adoc | 2 +- .../modules/web/pages/webapp/webapp003.adoc | 38 ++-- .../modules/web/pages/webapp/webapp004.adoc | 18 +- .../modules/web/pages/webapp/webapp005.adoc | 36 ++-- .../modules/web/pages/webapp/webapp006.adoc | 2 +- .../modules/web/pages/webi18n/webi18n.adoc | 2 +- .../modules/web/pages/webi18n/webi18n001.adoc | 4 +- .../modules/web/pages/webi18n/webi18n002.adoc | 14 +- .../modules/web/pages/webi18n/webi18n003.adoc | 4 +- .../modules/web/pages/webi18n/webi18n004.adoc | 6 +- .../web/pages/websocket/websocket.adoc | 2 +- .../web/pages/websocket/websocket001.adoc | 2 +- .../web/pages/websocket/websocket002.adoc | 4 +- .../web/pages/websocket/websocket003.adoc | 2 +- .../web/pages/websocket/websocket004.adoc | 6 +- .../web/pages/websocket/websocket005.adoc | 12 +- .../web/pages/websocket/websocket006.adoc | 2 +- .../web/pages/websocket/websocket007.adoc | 6 +- .../web/pages/websocket/websocket008.adoc | 2 +- .../web/pages/websocket/websocket009.adoc | 2 +- .../web/pages/websocket/websocket010.adoc | 2 +- .../web/pages/websocket/websocket011.adoc | 24 +-- .../web/pages/websocket/websocket012.adoc | 50 ++--- .../web/pages/websocket/websocket013.adoc | 2 +- 158 files changed, 940 insertions(+), 962 deletions(-) diff --git a/src/main/antora/modules/web/pages/jsf-advanced-cc/jsf-advanced-cc.adoc b/src/main/antora/modules/web/pages/jsf-advanced-cc/jsf-advanced-cc.adoc index e5e7203e..7dedaf51 100644 --- a/src/main/antora/modules/web/pages/jsf-advanced-cc/jsf-advanced-cc.adoc +++ b/src/main/antora/modules/web/pages/jsf-advanced-cc/jsf-advanced-cc.adoc @@ -1,6 +1,6 @@ = Composite Components: Advanced Topics and an Example -[[GKHXA]][[composite-components-advanced-topics-and-an-example]] +[[GKHXA]][[_composite_components_advanced_topics_and_an_example]] This chapter describes the advanced features of composite components in Jakarta Server Faces technology. diff --git a/src/main/antora/modules/web/pages/jsf-advanced-cc/jsf-advanced-cc001.adoc b/src/main/antora/modules/web/pages/jsf-advanced-cc/jsf-advanced-cc001.adoc index bfb51a2e..db355fa2 100644 --- a/src/main/antora/modules/web/pages/jsf-advanced-cc/jsf-advanced-cc001.adoc +++ b/src/main/antora/modules/web/pages/jsf-advanced-cc/jsf-advanced-cc001.adoc @@ -1,14 +1,14 @@ -[[GKHWV]][[attributes-of-a-composite-component]] +[[GKHWV]][[_attributes_of_a_composite_component]] == Attributes of a Composite Component A composite component is a special type of Jakarta Server Faces template that acts as a component. If you are new to composite components, see -link:#GIQZR[Composite Components] before you proceed +xref:jsf-facelets/jsf-facelets.adoc#GIQZR[Composite Components] before you proceed with this chapter. You define an attribute of a composite component by using the -`composite:attribute` tag. link:#GKHVF[Table 14-1] lists the commonly +`composite:attribute` tag. xref:jsf-advanced-cc/jsf-advanced-cc.adoc#GKHVF[Table 14-1] lists the commonly used attributes of this tag. [[sthref74]][[GKHVF]] diff --git a/src/main/antora/modules/web/pages/jsf-advanced-cc/jsf-advanced-cc002.adoc b/src/main/antora/modules/web/pages/jsf-advanced-cc/jsf-advanced-cc002.adoc index 6ea1be57..58e252cd 100644 --- a/src/main/antora/modules/web/pages/jsf-advanced-cc/jsf-advanced-cc002.adoc +++ b/src/main/antora/modules/web/pages/jsf-advanced-cc/jsf-advanced-cc002.adoc @@ -1,4 +1,4 @@ -[[GKHUO]][[invoking-a-managed-bean]] +[[GKHUO]][[_invoking_a_managed_bean]] == Invoking a Managed Bean @@ -9,7 +9,7 @@ To enable a composite component to handle server-side data * Directly use the properties of the managed bean. + The example application described in -link:#GKHVN[The compositecomponentexample Example +xref:jsf-advanced-cc/jsf-advanced-cc.adoc#GKHVN[The compositecomponentexample Example Application] shows how to use a managed bean with a composite component by passing the reference of the managed bean to the component. diff --git a/src/main/antora/modules/web/pages/jsf-advanced-cc/jsf-advanced-cc003.adoc b/src/main/antora/modules/web/pages/jsf-advanced-cc/jsf-advanced-cc003.adoc index 0a961755..1ccf01bd 100644 --- a/src/main/antora/modules/web/pages/jsf-advanced-cc/jsf-advanced-cc003.adoc +++ b/src/main/antora/modules/web/pages/jsf-advanced-cc/jsf-advanced-cc003.adoc @@ -1,4 +1,4 @@ -[[GKHWO]][[validating-composite-component-values]] +[[GKHWO]][[_validating_composite_component_values]] == Validating Composite Component Values @@ -7,8 +7,8 @@ Jakarta Server Faces provides the following tags for validating values of input components. These tags can be used with the `composite:valueHolder` or the `composite:editableValueHolder` tag. -link:#GKHVG[Table 14-2] lists commonly used validator tags. See -link:#BNATC[Using the Standard Validators] for +xref:jsf-advanced-cc/jsf-advanced-cc.adoc#GKHVG[Table 14-2] lists commonly used validator tags. See +xref:jsf-page-core/jsf-page-core.adoc#BNATC[Using the Standard Validators] for details and a complete list. [[sthref75]][[GKHVG]] diff --git a/src/main/antora/modules/web/pages/jsf-advanced-cc/jsf-advanced-cc004.adoc b/src/main/antora/modules/web/pages/jsf-advanced-cc/jsf-advanced-cc004.adoc index badda355..2da833da 100644 --- a/src/main/antora/modules/web/pages/jsf-advanced-cc/jsf-advanced-cc004.adoc +++ b/src/main/antora/modules/web/pages/jsf-advanced-cc/jsf-advanced-cc004.adoc @@ -1,4 +1,4 @@ -[[GKHVN]][[the-compositecomponentexample-example-application]] +[[GKHVN]][[_the_compositecomponentexample_example_application]] == The compositecomponentexample Example Application @@ -15,7 +15,7 @@ file, a using page, and a managed bean. The source code for this application is in the `_tut-install_/examples/web/jsf/compositecomponentexample/` directory. -[[GKHUU]][[the-composite-component-file]] +[[GKHUU]][[_the_composite_component_file]] === The Composite Component File @@ -91,7 +91,7 @@ prime or not is rendered only if the input value is validated. ---- -[[GKHVX]][[the-using-page]] +[[GKHVX]][[_the_using_page]] === The Using Page @@ -108,7 +108,7 @@ along with the managed bean. It validates the user's input. ---- -[[GKHVQ]][[the-managed-bean]] +[[GKHVQ]][[_the_managed_bean]] === The Managed Bean @@ -123,8 +123,8 @@ same value as its lowercase equivalent. The bean specifies the minimum and maximum size of the `name` string, which is enforced by the Bean Validation `@Size` constraint. The bean uses the `@Model` annotation, a shortcut for `@Named` and -`@RequestScoped`, as described in Step link:#CHDCABHC[7] of -link:#GJWTV[To View the hello1 Web Module Using NetBeans +`@RequestScoped`, as described in Step xref:webapp/webapp.adoc#CHDCABHC[7] of +xref:webapp/webapp.adoc#GJWTV[To View the hello1 Web Module Using NetBeans IDE]. [source,java] @@ -142,19 +142,19 @@ public class PrimeBean implements Serializable { } ---- -[[GLECV]][[running-the-compositecomponentexample-example]] +[[GLECV]][[_running_the_compositecomponentexample_example]] === Running the compositecomponentexample Example You can use either NetBeans IDE or Maven to build, package, deploy, and run the `compositecomponentexample` example. -[[GKHVC]][[to-build-package-and-deploy-the-compositecomponentexample-example-using-netbeans-ide]] +[[GKHVC]][[_to_build_package_and_deploy_the_compositecomponentexample_example_using_netbeans_ide]] ==== To Build, Package, and Deploy the compositecomponentexample Example Using NetBeans IDE 1. Make sure that GlassFish Server has been started (see -link:#BNADI[Starting and Stopping GlassFish +xref:#BNADI[Starting and Stopping GlassFish Server]). 2. From the File menu, choose Open Project. 3. In the Open Project dialog box, navigate to: @@ -170,12 +170,12 @@ project and select Build. + This command builds and deploys the application. -[[GLEAE]][[to-build-package-and-deploy-the-compositecomponentexample-example-using-maven]] +[[GLEAE]][[_to_build_package_and_deploy_the_compositecomponentexample_example_using_maven]] ==== To Build, Package, and Deploy the compositecomponentexample Example Using Maven 1. Make sure that GlassFish Server has been started (see -link:#BNADI[Starting and Stopping GlassFish +xref:#BNADI[Starting and Stopping GlassFish Server]). 2. In a terminal window, go to: + @@ -190,7 +190,7 @@ tut-install/examples/web/jsf/compositecomponentexample/ mvn install ---- -[[GLEEU]][[to-run-the-compositecomponentexample-example]] +[[GLEEU]][[_to_run_the_compositecomponentexample_example]] ==== To Run the compositecomponentexample Example diff --git a/src/main/antora/modules/web/pages/jsf-ajax/jsf-ajax.adoc b/src/main/antora/modules/web/pages/jsf-ajax/jsf-ajax.adoc index bf038eba..3c549809 100644 --- a/src/main/antora/modules/web/pages/jsf-ajax/jsf-ajax.adoc +++ b/src/main/antora/modules/web/pages/jsf-ajax/jsf-ajax.adoc @@ -1,6 +1,6 @@ = Using Ajax with Jakarta Server Faces Technology -[[GKIOW]][[using-ajax-with-javaserver-faces-technology]] +[[GKIOW]][[_using_ajax_with_javaserver_faces_technology]] This chapter describes using Ajax functionality in Jakarta Server Faces web applications. Ajax is an acronym for Asynchronous JavaScript and XML, a diff --git a/src/main/antora/modules/web/pages/jsf-ajax/jsf-ajax001.adoc b/src/main/antora/modules/web/pages/jsf-ajax/jsf-ajax001.adoc index 878b31a9..deaf4a37 100644 --- a/src/main/antora/modules/web/pages/jsf-ajax/jsf-ajax001.adoc +++ b/src/main/antora/modules/web/pages/jsf-ajax/jsf-ajax001.adoc @@ -1,4 +1,4 @@ -[[GKIGR]][[overview-of-ajax]] +[[GKIGR]][[_overview_of_ajax]] == Overview of Ajax @@ -29,7 +29,7 @@ format of an XML document. The term Ajax refers to this interaction between the client and server. The server response need not be in XML only; it can also be in other -formats, such as JSON (see link:#BABEECIB[Introduction to +formats, such as JSON (see xref:#BABEECIB[Introduction to JSON] and `http://www.json.org/`). This tutorial does not focus on the response formats. diff --git a/src/main/antora/modules/web/pages/jsf-ajax/jsf-ajax002.adoc b/src/main/antora/modules/web/pages/jsf-ajax/jsf-ajax002.adoc index f08e2c58..6d70dbd6 100644 --- a/src/main/antora/modules/web/pages/jsf-ajax/jsf-ajax002.adoc +++ b/src/main/antora/modules/web/pages/jsf-ajax/jsf-ajax002.adoc @@ -1,4 +1,4 @@ -[[GKINL]][[using-ajax-functionality-with-javaserver-faces-technology]] +[[GKINL]][[_using_ajax_functionality_with_javaserver_faces_technology]] == Using Ajax Functionality with Jakarta Server Faces Technology @@ -24,7 +24,7 @@ In addition, because the Jakarta Server Faces technology component model can be extended, custom components can be created with Ajax functionality. The tutorial examples include an Ajax version of the `guessnumber` -application, `ajaxguessnumber`. See link:#GKOKB[The +application, `ajaxguessnumber`. See xref:jsf-ajax/jsf-ajax.adoc#GKOKB[The ajaxguessnumber Example Application] for more information. The Ajax specific `f:ajax` tag and its attributes are explained in the diff --git a/src/main/antora/modules/web/pages/jsf-ajax/jsf-ajax003.adoc b/src/main/antora/modules/web/pages/jsf-ajax/jsf-ajax003.adoc index ab1e14c3..796ce8dc 100644 --- a/src/main/antora/modules/web/pages/jsf-ajax/jsf-ajax003.adoc +++ b/src/main/antora/modules/web/pages/jsf-ajax/jsf-ajax003.adoc @@ -1,4 +1,4 @@ -[[GKABR]][[using-ajax-with-facelets]] +[[GKABR]][[_using_ajax_with_facelets]] == Using Ajax with Facelets @@ -19,7 +19,7 @@ server-side methods from a view. The component generates a JavaScript function with a given name that when invoked, in turn invokes, a given server-side method via Ajax. -[[GKAFN]][[using-the-fajax-tag]] +[[GKAFN]][[_using_the_fajax_tag]] === Using the f:ajax Tag @@ -39,7 +39,7 @@ In this example, although Ajax is enabled, the other attributes of the `f:ajax` tag are not defined. If an event is not defined, the default action for the component is performed. For the `inputText` component, when no `event` attribute is specified, the default event is -`valueChange`. link:#GKDER[Table 13-1] lists the attributes of the +`valueChange`. xref:jsf-ajax/jsf-ajax.adoc#GKDER[Table 13-1] lists the attributes of the `f:ajax` tag and their default actions. [[sthref69]][[GKDER]] @@ -98,7 +98,7 @@ is `@none`. |======================================================================= -The keywords listed in link:#GKNLK[Table 13-2] can be used with the +The keywords listed in xref:jsf-ajax/jsf-ajax.adoc#GKNLK[Table 13-2] can be used with the `execute` and `render` attributes of the `f:ajax` tag. [[sthref70]][[GKNLK]] @@ -118,4 +118,4 @@ The keywords listed in link:#GKNLK[Table 13-2] can be used with the Note that when you use the `f:ajax` tag in a Facelets page, the JavaScript resource library is loaded implicitly. This resource library can also be loaded explicitly as described in -link:#GKAAM[Loading JavaScript as a Resource]. +xref:jsf-ajax/jsf-ajax.adoc#GKAAM[Loading JavaScript as a Resource]. diff --git a/src/main/antora/modules/web/pages/jsf-ajax/jsf-ajax004.adoc b/src/main/antora/modules/web/pages/jsf-ajax/jsf-ajax004.adoc index 2a05bfc9..76938818 100644 --- a/src/main/antora/modules/web/pages/jsf-ajax/jsf-ajax004.adoc +++ b/src/main/antora/modules/web/pages/jsf-ajax/jsf-ajax004.adoc @@ -1,4 +1,4 @@ -[[GKACE]][[sending-an-ajax-request]] +[[GKACE]][[_sending_an_ajax_request]] == Sending an Ajax Request @@ -7,7 +7,7 @@ request and send it to the server. The server then processes the request. The application uses the attributes of the `f:ajax` tag listed in -link:#GKDER[Table 13-1] to create the Ajax request. The +xref:jsf-ajax/jsf-ajax.adoc#GKDER[Table 13-1] to create the Ajax request. The following sections explain the process of creating and sending an Ajax request using some of these attributes. @@ -24,7 +24,7 @@ posts the request to the Jakarta Server Faces lifecycle. |======================================================================= -[[GKHVT]][[using-the-event-attribute]] +[[GKHVT]][[_using_the_event_attribute]] === Using the event Attribute @@ -65,7 +65,7 @@ not have the `on` prefix. For a command button, the default event is `click`, so you do not actually need to specify `event="click"` to obtain the desired behavior. -[[GKHUZ]][[using-the-execute-attribute]] +[[GKHUZ]][[_using_the_execute_attribute]] === Using the execute Attribute @@ -97,7 +97,7 @@ The following code specifies that the `h:inputText` component with the ---- -[[GKHWM]][[using-the-immediate-attribute]] +[[GKHWM]][[_using_the_immediate_attribute]] === Using the immediate Attribute @@ -109,7 +109,7 @@ broadcast during the Invoke Application phase. If not defined, the default value of this attribute is `false`. -[[GKHZS]][[using-the-listener-attribute]] +[[GKHZS]][[_using_the_listener_attribute]] === Using the listener Attribute @@ -118,7 +118,7 @@ on the server side in response to an Ajax action on the client. The listener's `javax.faces.event.AjaxBehaviorListener.processAjaxBehavior` method is called once during the Invoke Application phase of the lifecycle. In the following code from the `reservation` example -application (see link:#BABGGIAA[The reservation +application (see xref:jsf-facelets/jsf-facelets.adoc#BABGGIAA[The reservation Example Application]), a `listener` attribute is defined by an `f:ajax` tag, which refers to a method from the bean: diff --git a/src/main/antora/modules/web/pages/jsf-ajax/jsf-ajax005.adoc b/src/main/antora/modules/web/pages/jsf-ajax/jsf-ajax005.adoc index 97119bbd..ac3ca32e 100644 --- a/src/main/antora/modules/web/pages/jsf-ajax/jsf-ajax005.adoc +++ b/src/main/antora/modules/web/pages/jsf-ajax/jsf-ajax005.adoc @@ -1,4 +1,4 @@ -[[GKDDF]][[monitoring-events-on-the-client]] +[[GKDDF]][[_monitoring_events_on_the_client]] == Monitoring Events on the Client @@ -9,7 +9,7 @@ the processing of an Ajax request: begin, complete, and success. When calling the JavaScript function assigned to the `onevent` property, Jakarta Server Faces passes a data object to it. The data object contains -the properties listed in link:#GKGOE[Table 13-3]. +the properties listed in xref:jsf-ajax/jsf-ajax.adoc#GKGOE[Table 13-3]. [[sthref71]][[GKGOE]] diff --git a/src/main/antora/modules/web/pages/jsf-ajax/jsf-ajax006.adoc b/src/main/antora/modules/web/pages/jsf-ajax/jsf-ajax006.adoc index 36040317..86f5e104 100644 --- a/src/main/antora/modules/web/pages/jsf-ajax/jsf-ajax006.adoc +++ b/src/main/antora/modules/web/pages/jsf-ajax/jsf-ajax006.adoc @@ -1,4 +1,4 @@ -[[GKDCB]][[handling-errors]] +[[GKDCB]][[_handling_errors]] == Handling Errors @@ -16,7 +16,7 @@ to it. The data object contains all the properties available for the * `errorMessage` The `type` is `error`. The `status` property of the data object contains -one of the valid error values listed in link:#GKGOU[Table 13-4]. +one of the valid error values listed in xref:jsf-ajax/jsf-ajax.adoc#GKGOU[Table 13-4]. [[sthref72]][[GKGOU]] diff --git a/src/main/antora/modules/web/pages/jsf-ajax/jsf-ajax007.adoc b/src/main/antora/modules/web/pages/jsf-ajax/jsf-ajax007.adoc index f986e755..1014c502 100644 --- a/src/main/antora/modules/web/pages/jsf-ajax/jsf-ajax007.adoc +++ b/src/main/antora/modules/web/pages/jsf-ajax/jsf-ajax007.adoc @@ -1,4 +1,4 @@ -[[GKDBR]][[receiving-an-ajax-response]] +[[GKDBR]][[_receiving_an_ajax_response]] == Receiving an Ajax Response diff --git a/src/main/antora/modules/web/pages/jsf-ajax/jsf-ajax008.adoc b/src/main/antora/modules/web/pages/jsf-ajax/jsf-ajax008.adoc index 9dc25872..43067113 100644 --- a/src/main/antora/modules/web/pages/jsf-ajax/jsf-ajax008.adoc +++ b/src/main/antora/modules/web/pages/jsf-ajax/jsf-ajax008.adoc @@ -1,4 +1,4 @@ -[[GKUAR]][[ajax-request-lifecycle]] +[[GKUAR]][[_ajax_request_lifecycle]] == Ajax Request Lifecycle @@ -6,7 +6,7 @@ An Ajax request varies from other typical Jakarta Server Faces requests, and its processing is also handled differently by the Jakarta Server Faces lifecycle. -As described in link:#GKNOJ[Partial Processing and +As described in xref:jsf-intro/jsf-intro.adoc#GKNOJ[Partial Processing and Partial Rendering], when an Ajax request is received, the state associated with that request is captured by the `javax.faces.context.PartialViewContext`. This object provides access to diff --git a/src/main/antora/modules/web/pages/jsf-ajax/jsf-ajax009.adoc b/src/main/antora/modules/web/pages/jsf-ajax/jsf-ajax009.adoc index d9567cd9..b55dfc7b 100644 --- a/src/main/antora/modules/web/pages/jsf-ajax/jsf-ajax009.adoc +++ b/src/main/antora/modules/web/pages/jsf-ajax/jsf-ajax009.adoc @@ -1,4 +1,4 @@ -[[GKHYH]][[grouping-of-components]] +[[GKHYH]][[_grouping_of_components]] == Grouping of Components diff --git a/src/main/antora/modules/web/pages/jsf-ajax/jsf-ajax010.adoc b/src/main/antora/modules/web/pages/jsf-ajax/jsf-ajax010.adoc index d9b84013..c15f154f 100644 --- a/src/main/antora/modules/web/pages/jsf-ajax/jsf-ajax010.adoc +++ b/src/main/antora/modules/web/pages/jsf-ajax/jsf-ajax010.adoc @@ -1,4 +1,4 @@ -[[GKAAM]][[loading-javascript-as-a-resource]] +[[GKAAM]][[_loading_javascript_as_a_resource]] == Loading JavaScript as a Resource @@ -16,13 +16,13 @@ To use a JavaScript resource directly with a `UIComponent`, you must explicitly load the resource as described in either of the following topics: -* link:#GKAFI[Using JavaScript API in a Facelets Application] – Uses the +* xref:jsf-ajax/jsf-ajax.adoc#GKAFI[Using JavaScript API in a Facelets Application] – Uses the `h:outputScript` tag directly in a Facelets page -* link:#GKIPX[Using the @ResourceDependency Annotation in a Bean Class] +* xref:jsf-ajax/jsf-ajax.adoc#GKIPX[Using the @ResourceDependency Annotation in a Bean Class] – Uses the `javax.faces.application.ResourceDependency` annotation on a `UIComponent` Java class -[[GKAFI]][[using-javascript-api-in-a-facelets-application]] +[[GKAFI]][[_using_javascript_api_in_a_facelets_application]] === Using JavaScript API in a Facelets Application @@ -66,7 +66,7 @@ source, event, and options. The source parameter identifies the DOM element that triggered the Ajax request, typically `this`. The optional event parameter identifies the DOM event that triggered this request. The optional options parameter contains a set of name/value pairs from -link:#GKAIW[Table 13-5]. +xref:jsf-ajax/jsf-ajax.adoc#GKAIW[Table 13-5]. + [[sthref73]][[GKAIW]] @@ -76,12 +76,12 @@ link:#GKAIW[Table 13-5]. |======================================================================= |*Name* |*Value* |`execute` |A space-delimited list of client identifiers or one of the -keywords listed in link:#GKNLK[Table 13-2]. The +keywords listed in xref:jsf-ajax/jsf-ajax.adoc#GKNLK[Table 13-2]. The identifiers reference the components that will be processed during the Execute phase of the lifecycle. |`render` |A space-delimited list of client identifiers or one of the -keywords listed in link:#GKNLK[Table 13-2]. The +keywords listed in xref:jsf-ajax/jsf-ajax.adoc#GKNLK[Table 13-2]. The identifiers reference the components that will be processed during the render phase of the lifecycle. @@ -103,7 +103,7 @@ If no identifier is specified, the default assumed keyword for the You can also place the JavaScript method in a file and include it as a resource. -[[GKIPX]][[using-the-resourcedependency-annotation-in-a-bean-class]] +[[GKIPX]][[_using_the_resourcedependency_annotation_in_a_bean_class]] === Using the @ResourceDependency Annotation in a Bean Class diff --git a/src/main/antora/modules/web/pages/jsf-ajax/jsf-ajax011.adoc b/src/main/antora/modules/web/pages/jsf-ajax/jsf-ajax011.adoc index f71564dd..7e6da83a 100644 --- a/src/main/antora/modules/web/pages/jsf-ajax/jsf-ajax011.adoc +++ b/src/main/antora/modules/web/pages/jsf-ajax/jsf-ajax011.adoc @@ -1,9 +1,9 @@ -[[GKOKB]][[the-ajaxguessnumber-example-application]] +[[GKOKB]][[_the_ajaxguessnumber_example_application]] == The ajaxguessnumber Example Application To demonstrate the advantages of using Ajax, revisit the `guessnumber` -example from link:#GIEPX[Chapter 8, "Introduction to +example from xref:jsf-facelets/jsf-facelets.adoc#GIEPX[Chapter 8, "Introduction to Facelets"]. If you modify this example to use Ajax, the response need not be displayed on the `response.xhtml` page. Instead, an asynchronous call is made to the bean on the server side, and the response is @@ -13,13 +13,13 @@ rather than by form submission. The source code for this application is in the `_tut-install_/examples/web/jsf/ajaxguessnumber/` directory. -[[GKOIJ]][[the-ajaxguessnumber-source-files]] +[[GKOIJ]][[_the_ajaxguessnumber_source_files]] === The ajaxguessnumber Source Files The changes to the `guessnumber` application occur in two source files. -[[GKOFW]][[the-ajaxgreeting.xhtml-facelets-page]] +[[GKOFW]][[_the_ajaxgreeting.xhtml_facelets_page]] ==== The ajaxgreeting.xhtml Facelets Page @@ -82,7 +82,7 @@ validation error occurs, the managed bean is not executed, and the validation error message is displayed in the message pane. Otherwise, the result of the guess is rendered in the `result` component. -[[GKOHN]][[the-usernumberbean-backing-bean]] +[[GKOHN]][[_the_usernumberbean_backing_bean]] ==== The UserNumberBean Backing Bean @@ -105,7 +105,7 @@ public String getResponse() { } ---- -[[CHDGAIGJ]][[the-dukesnumberbean-cdi-managed-bean]] +[[CHDGAIGJ]][[_the_dukesnumberbean_cdi_managed_bean]] ==== The DukesNumberBean CDI Managed Bean @@ -121,22 +121,22 @@ user submitted: DukesNumberBean dukesNumberBean; ---- -You will learn more about CDI in link:#GIWHB[Chapter 25, +You will learn more about CDI in xref:#GIWHB[Chapter 25, "Introduction to Jakarta Contexts and Dependency Injection"]. -[[GKOKE]][[running-the-ajaxguessnumber-example]] +[[GKOKE]][[_running_the_ajaxguessnumber_example]] === Running the ajaxguessnumber Example You can use either NetBeans IDE or Maven to build, package, deploy, and run the `ajaxguessnumber` application. -[[GLHVU]][[to-build-package-and-deploy-the-ajaxguessnumber-example-using-netbeans-ide]] +[[GLHVU]][[_to_build_package_and_deploy_the_ajaxguessnumber_example_using_netbeans_ide]] ==== To Build, Package, and Deploy the ajaxguessnumber Example Using NetBeans IDE 1. Make sure that GlassFish Server has been started (see -link:#BNADI[Starting and Stopping GlassFish +xref:#BNADI[Starting and Stopping GlassFish Server]). 2. From the File menu, choose Open Project. 3. In the Open Project dialog box, navigate to: @@ -152,12 +152,12 @@ select Build. + This command builds and deploys the project. -[[GLHVQ]][[to-build-package-and-deploy-the-ajaxguessnumber-example-using-maven]] +[[GLHVQ]][[_to_build_package_and_deploy_the_ajaxguessnumber_example_using_maven]] ==== To Build, Package, and Deploy the ajaxguessnumber Example Using Maven 1. Make sure that GlassFish Server has been started (see -link:#BNADI[Starting and Stopping GlassFish +xref:#BNADI[Starting and Stopping GlassFish Server]). 2. In a terminal window, go to: + @@ -176,7 +176,7 @@ This command builds and packages the application into a WAR file, `ajaxguessnumber.war`, located in the `target` directory. It then deploys the application. -[[GLHWE]][[to-run-the-ajaxguessnumber-example]] +[[GLHWE]][[_to_run_the_ajaxguessnumber_example]] ==== To Run the ajaxguessnumber Example diff --git a/src/main/antora/modules/web/pages/jsf-ajax/jsf-ajax012.adoc b/src/main/antora/modules/web/pages/jsf-ajax/jsf-ajax012.adoc index adc7284b..00e98213 100644 --- a/src/main/antora/modules/web/pages/jsf-ajax/jsf-ajax012.adoc +++ b/src/main/antora/modules/web/pages/jsf-ajax/jsf-ajax012.adoc @@ -1,4 +1,4 @@ -[[GKSDK]][[further-information-about-ajax-in-javaserver-faces-technology]] +[[GKSDK]][[_further_information_about_ajax_in_javaserver_faces_technology]] == Further Information about Ajax in Jakarta Server Faces Technology @@ -7,5 +7,5 @@ For more information on Ajax in Jakarta Server Faces Technology, see * Jakarta Server Faces project website: + `https://javaserverfaces.github.io/users.html` -* link:../javaserver-faces-2-2/jsdocs/symbols/jsf.ajax.html[Jakarta Server +* xref:../javaserver-faces-2-2/jsdocs/symbols/jsf.ajax.html[Jakarta Server Faces JavaScript Library APIs] diff --git a/src/main/antora/modules/web/pages/jsf-configure/jsf-configure.adoc b/src/main/antora/modules/web/pages/jsf-configure/jsf-configure.adoc index 92b55c70..88691c43 100644 --- a/src/main/antora/modules/web/pages/jsf-configure/jsf-configure.adoc +++ b/src/main/antora/modules/web/pages/jsf-configure/jsf-configure.adoc @@ -1,6 +1,6 @@ = Configuring Jakarta Server Faces Applications -[[BNAWO]][[configuring-javaserver-faces-applications]] +[[BNAWO]][[_configuring_javaserver_faces_applications]] This chapter describes additional configuration tasks required when you create large and complex applications. diff --git a/src/main/antora/modules/web/pages/jsf-configure/jsf-configure001.adoc b/src/main/antora/modules/web/pages/jsf-configure/jsf-configure001.adoc index 54502bbc..e2cdeeea 100644 --- a/src/main/antora/modules/web/pages/jsf-configure/jsf-configure001.adoc +++ b/src/main/antora/modules/web/pages/jsf-configure/jsf-configure001.adoc @@ -1,14 +1,14 @@ -[[A1352824]][[introduction-to-configuring-javaserver-faces-applications]] +[[A1352824]][[_introduction_to_configuring_javaserver_faces_applications]] == Introduction to Configuring Jakarta Server Faces Applications The process of building and deploying simple Jakarta Server Faces applications is described in earlier chapters of this tutorial, -including link:#BNADR[Chapter 6, "Getting Started with Web -Applications,"] link:#GIEPX[Chapter 8, "Introduction to -Facelets,"] link:#GKIOW[Chapter 13, "Using Ajax with +including xref:webapp/webapp.adoc#BNADR[Chapter 6, "Getting Started with Web +Applications,"] xref:jsf-facelets/jsf-facelets.adoc#GIEPX[Chapter 8, "Introduction to +Facelets,"] xref:jsf-ajax/jsf-ajax.adoc#GKIOW[Chapter 13, "Using Ajax with Jakarta Server Faces Technology,"] and -link:#GKHXA[Chapter 14, "Composite Components: +xref:jsf-advanced-cc/jsf-advanced-cc.adoc#GKHXA[Chapter 14, "Composite Components: Advanced Topics and an Example."] When you create large and complex applications, however, various additional configuration tasks are required. These tasks include the following: diff --git a/src/main/antora/modules/web/pages/jsf-configure/jsf-configure002.adoc b/src/main/antora/modules/web/pages/jsf-configure/jsf-configure002.adoc index 29678105..878d59c5 100644 --- a/src/main/antora/modules/web/pages/jsf-configure/jsf-configure002.adoc +++ b/src/main/antora/modules/web/pages/jsf-configure/jsf-configure002.adoc @@ -1,4 +1,4 @@ -[[GIRCH]][[using-annotations-to-configure-managed-beans]] +[[GIRCH]][[_using_annotations_to_configure_managed_beans]] == Using Annotations to Configure Managed Beans @@ -15,7 +15,7 @@ preferred approach. Jakarta Server Faces support for bean annotations is introduced in -link:#BNAPH[Chapter 7, "Jakarta Server Faces Technology"]. Bean +xref:jsf-intro/jsf-intro.adoc#BNAPH[Chapter 7, "Jakarta Server Faces Technology"]. Bean annotations can be used for configuring Jakarta Server Faces applications. The `@Named` (`javax.inject.Named`) annotation in a class, along with a @@ -37,7 +37,7 @@ The above code snippet shows a bean that is managed by the Jakarta Server Faces implementation and is available for the length of the session. You can annotate beans with any of the scopes listed in the next -section, link:#GIRCR[Using Managed Bean Scopes]. +section, xref:jsf-configure/jsf-configure.adoc#GIRCR[Using Managed Bean Scopes]. All classes will be scanned for annotations at startup unless the `faces-config` element in the `faces-config.xml` file has the @@ -47,10 +47,10 @@ Annotations are also available for other artifacts, such as components, converters, validators, and renderers, to be used in place of application configuration resource file entries. These are discussed, along with registration of custom listeners, custom validators, and -custom converters, in link:#BNAVG[Chapter 15, "Creating +custom converters, in xref:jsf-custom/jsf-custom.adoc#BNAVG[Chapter 15, "Creating Custom UI Components and Other Custom Objects"]. -[[GIRCR]][[using-managed-bean-scopes]] +[[GIRCR]][[_using_managed_bean_scopes]] === Using Managed Bean Scopes @@ -64,7 +64,7 @@ application. persists across multiple HTTP requests in a web application. * Flow (`javax.faces.flows.FlowScoped`): Flow scope persists during a user's interaction with a specific flow of a web application. See -link:#CHDGFCJF[Using Faces Flows] for more +xref:jsf-configure/jsf-configure.adoc#CHDGFCJF[Using Faces Flows] for more information. * Request (`javax.enterprise.context.RequestScoped`): Request scope persists during a single HTTP request in a web application. diff --git a/src/main/antora/modules/web/pages/jsf-configure/jsf-configure003.adoc b/src/main/antora/modules/web/pages/jsf-configure/jsf-configure003.adoc index decaf805..41b0d2c3 100644 --- a/src/main/antora/modules/web/pages/jsf-configure/jsf-configure003.adoc +++ b/src/main/antora/modules/web/pages/jsf-configure/jsf-configure003.adoc @@ -1,4 +1,4 @@ -[[BNAWP]][[application-configuration-resource-file]] +[[BNAWP]][[_application_configuration_resource_file]] == Application Configuration Resource File @@ -75,7 +75,7 @@ creates a single instance of the `Application` class and configures it with the information you provided in the application configuration resource file. -[[GIREP]][[configuring-eager-application-scoped-managed-beans]] +[[GIREP]][[_configuring_eager_application_scoped_managed_beans]] === Configuring Eager Application-Scoped Managed Beans @@ -104,7 +104,7 @@ The annotation is as follows: @ApplicationScoped ---- -[[GIQCK]][[ordering-of-application-configuration-resource-files]] +[[GIQCK]][[_ordering_of_application_configuration_resource_files]] === Ordering of Application Configuration Resource Files diff --git a/src/main/antora/modules/web/pages/jsf-configure/jsf-configure004.adoc b/src/main/antora/modules/web/pages/jsf-configure/jsf-configure004.adoc index 3c5c2985..52db7a84 100644 --- a/src/main/antora/modules/web/pages/jsf-configure/jsf-configure004.adoc +++ b/src/main/antora/modules/web/pages/jsf-configure/jsf-configure004.adoc @@ -1,4 +1,4 @@ -[[CHDGFCJF]][[using-faces-flows]] +[[CHDGFCJF]][[_using_faces_flows]] == Using Faces Flows @@ -44,17 +44,13 @@ have many flows in an application. The programmatic configuration places the code closer to the rest of the flow code and enables you to modularize the flows. -link:#CHDIHDCD[Figure 16-1] shows two flows and illustrates how they +xref:jsf-configure/jsf-configure.adoc#CHDIHDCD[Figure 16-1] shows two flows and illustrates how they interact. [[CHDIHDCD]] .*Figure 16-1 Two Faces Flows and Their Interactions* -image:jakartaeett_dt_017.png[ -"This figure shows two Faces flows, Flow A and Flow B. Each has a start -node and two additional pages. Each has an associated managed bean. Each -defines a return node, and each defines two parameters to be passed to -the other flow."] +image::common:jakartaeett_dt_017.png[ "This figure shows two Faces flows, Flow A and Flow B. Each has a start node and two additional pages. Each has an associated managed bean. Each defines a return node, and each defines two parameters to be passed to the other flow."] In this figure, Flow A has a start node named `flow-a` and two additional pages, `next_a1` and `next_a2`. From `next_a2`, a user can @@ -64,7 +60,7 @@ parameters that it can accept from Flow B. Flow B is identical to Flow A except for the names of the flow and files. Each flow also has an associated managed bean; the beans are `Flow_a_Bean` and `Flow_b_Bean`. -[[sthref81]][[packaging-flows-in-an-application]] +[[sthref81]][[_packaging_flows_in_an_application]] === Packaging Flows in an Application @@ -74,7 +70,7 @@ of a Maven project, for example, you would place the Facelets files that are outside the flow at the top level as usual. Then the `webapp` files for each flow would be in a separate directory, and the Java files would be under `src/main/java`. For example, the files for the application -shown in link:#CHDIHDCD[Figure 16-1] might look like this: +shown in xref:jsf-configure/jsf-configure.adoc#CHDIHDCD[Figure 16-1] might look like this: [source,xml] ---- @@ -101,7 +97,7 @@ src/main/java/jakarta/tutorial/flowexample In this example, `flow-a` is defined programmatically in `FlowA.java`, while `flow-b` is defined by the configuration file `flow-b-flow.xml`. -[[sthref82]][[the-simplest-possible-flow-the-simple-flow-example-application]] +[[sthref82]][[_the_simplest_possible_flow_the_simple_flow_example_application]] === The Simplest Possible Flow: The simple-flow Example Application @@ -195,12 +191,12 @@ no value outside of the flow, and provides a link that navigates to the The Facelets pages use only flow-scoped data, so the example does not need a managed bean. -[[sthref83]][[to-build-package-and-deploy-the-simple-flow-example-using-netbeans-ide]] +[[sthref83]][[_to_build_package_and_deploy_the_simple_flow_example_using_netbeans_ide]] ==== To Build, Package, and Deploy the simple-flow Example Using NetBeans IDE 1. Make sure that GlassFish Server has been started (see -link:#BNADI[Starting and Stopping GlassFish +xref:#BNADI[Starting and Stopping GlassFish Server]). 2. From the File menu, choose Open Project. 3. In the Open Project dialog box, navigate to: @@ -218,12 +214,12 @@ This command builds and packages the application into a WAR file, `simple-flow.war`, that is located in the `target` directory. It then deploys the application to the server. -[[sthref84]][[to-build-package-and-deploy-the-simple-flow-example-using-maven]] +[[sthref84]][[_to_build_package_and_deploy_the_simple_flow_example_using_maven]] ==== To Build, Package, and Deploy the simple-flow Example Using Maven 1. Make sure that GlassFish Server has been started (see -link:#BNADI[Starting and Stopping GlassFish +xref:#BNADI[Starting and Stopping GlassFish Server]). 2. In a terminal window, go to: + @@ -242,7 +238,7 @@ This command builds and packages the application into a WAR file, `simple-flow.war`, that is located in the `target` directory. It then deploys the application to the server. -[[sthref85]][[to-run-the-simple-flow-example]] +[[sthref85]][[_to_run_the_simple_flow_example]] ==== To Run the simple-flow Example @@ -261,7 +257,7 @@ Click Return. inaccessible value. Click Back to Start to return to the `index.xhtml` page. -[[sthref86]][[the-checkout-module-example-application]] +[[sthref86]][[_the_checkout_module_example_application]] === The checkout-module Example Application @@ -269,7 +265,7 @@ The `checkout-module` example application is considerably more complex than `simple-flow`. It shows how you might use the Faces Flows feature to implement a checkout module for an online store. -Like the hypothetical example in link:#CHDIHDCD[Figure 16-1], the +Like the hypothetical example in xref:jsf-configure/jsf-configure.adoc#CHDIHDCD[Figure 16-1], the example application contains two flows, each of which can call the other. Both flows have explicit flow definitions. One flow, `checkoutFlow`, is specified programmatically. The other flow, @@ -320,7 +316,7 @@ The managed beans scoped to each flow are `CheckoutFlowBean.java` and `JoinFlowBean.java`, whereas `CheckoutBean.java` is the backing bean for the `index.html` page. -[[sthref87]][[the-facelets-pages-for-the-checkout-module-example]] +[[sthref87]][[_the_facelets_pages_for_the_checkout_module_example]] ==== The Facelets Pages for the checkout-module Example @@ -396,7 +392,7 @@ to call the checkout flow as well as one to return from the join flow: For this flow, the actions `callcheckoutFlow` and `returnFromJoinFlow` are defined in the configuration file `joinFlow-flow.xml`. -[[sthref88]][[using-a-configuration-file-to-configure-a-flow]] +[[sthref88]][[_using_a_configuration_file_to_configure_a_flow]] ==== Using a Configuration File to Configure a Flow @@ -471,7 +467,7 @@ action of calling the flow. Within the `flow-call` element, the to be passed when `checkoutFlow` is called. Here they are just arbitrary strings. -[[sthref89]][[using-a-java-class-to-configure-a-flow]] +[[sthref89]][[_using_a_java_class_to_configure_a_flow]] ==== Using a Java Class to Configure a Flow @@ -553,7 +549,7 @@ are values from the `CheckoutFlowBean` managed bean. Finally, the `defineFlow` method calls the `getFlow` method and returns the result. -[[sthref90]][[the-flow-scoped-managed-beans]] +[[sthref90]][[_the_flow_scoped_managed_beans]] ==== The Flow-Scoped Managed Beans @@ -575,12 +571,12 @@ public String getReturnValue() { For the `JoinFlowBean`, the return node is the `exithome.xhtml` page. -[[sthref91]][[to-build-package-and-deploy-the-checkout-module-example-using-netbeans-ide]] +[[sthref91]][[_to_build_package_and_deploy_the_checkout_module_example_using_netbeans_ide]] ==== To Build, Package, and Deploy the checkout-module Example Using NetBeans IDE 1. Make sure that GlassFish Server has been started (see -link:#BNADI[Starting and Stopping GlassFish +xref:#BNADI[Starting and Stopping GlassFish Server]). 2. From the File menu, choose Open Project. 3. In the Open Project dialog box, navigate to: @@ -598,12 +594,12 @@ This command builds and packages the application into a WAR file, `checkout-module.war`, that is located in the `target` directory. It then deploys the application to the server. -[[sthref92]][[to-build-package-and-deploy-the-checkout-module-example-using-maven]] +[[sthref92]][[_to_build_package_and_deploy_the_checkout_module_example_using_maven]] ==== To Build, Package, and Deploy the checkout-module Example Using Maven 1. Make sure that GlassFish Server has been started (see -link:#BNADI[Starting and Stopping GlassFish +xref:#BNADI[Starting and Stopping GlassFish Server]). 2. In a terminal window, go to: + @@ -622,7 +618,7 @@ This command builds and packages the application into a WAR file, `checkout-module.war`, that is located in the `target` directory. It then deploys the application to the server. -[[sthref93]][[to-run-the-checkout-module-example]] +[[sthref93]][[_to_run_the_checkout_module_example]] ==== To Run the checkout-module Example diff --git a/src/main/antora/modules/web/pages/jsf-configure/jsf-configure005.adoc b/src/main/antora/modules/web/pages/jsf-configure/jsf-configure005.adoc index 44406ada..ff580f2c 100644 --- a/src/main/antora/modules/web/pages/jsf-configure/jsf-configure005.adoc +++ b/src/main/antora/modules/web/pages/jsf-configure/jsf-configure005.adoc @@ -1,4 +1,4 @@ -[[BNAWQ]][[configuring-managed-beans]] +[[BNAWQ]][[_configuring_managed_beans]] == Configuring Managed Beans @@ -7,7 +7,7 @@ Faces implementation initializes it either based on a `@Named` annotation and scope annotation in the bean class or according to its configuration in the application configuration resource file. For information on using annotations to initialize beans, see -link:#GIRCH[Using Annotations to Configure Managed +xref:jsf-configure/jsf-configure.adoc#GIRCH[Using Annotations to Configure Managed Beans]. You can use either annotations or the application configuration resource @@ -16,7 +16,7 @@ application and to store them in scope. The managed bean creation facility is configured in the application configuration resource file using `managed-bean` XML elements to define each bean. This file is processed at application startup time. For information on using this -facility, see link:#BNAWR[Using the managed-bean Element]. +facility, see xref:jsf-configure/jsf-configure.adoc#BNAWR[Using the managed-bean Element]. Managed beans created in the application configuration resource file are Jakarta Server Faces managed beans, not CDI managed beans. @@ -34,11 +34,11 @@ is created result of evaluating another value expression This section shows you how to initialize beans using the managed bean -creation facility. See link:#BNATY[Writing Bean -Properties] and link:#BNAVB[Writing Managed Bean +creation facility. See xref:jsf-develop/jsf-develop.adoc#BNATY[Writing Bean +Properties] and xref:jsf-develop/jsf-develop.adoc#BNAVB[Writing Managed Bean Methods] for information on programming managed beans. -[[BNAWR]][[using-the-managed-bean-element]] +[[BNAWR]][[_using_the_managed_bean_element]] === Using the managed-bean Element @@ -136,18 +136,18 @@ from the database. Note that each of the individual newsletter beans has a `managed-bean-scope` setting of `none` so that they will not themselves be placed into any scope. -See link:#BNAWX[Initializing Array and List Properties] for more +See xref:jsf-configure/jsf-configure.adoc#BNAWX[Initializing Array and List Properties] for more information on configuring collections as beans. To map to a property defined by a `managed-property` element, you must ensure that the part of a component tag's `value` expression after the period matches the `managed-property` element's `property-name` element. -The next section, link:#BNAWS[Initializing Properties Using the +The next section, xref:jsf-configure/jsf-configure.adoc#BNAWS[Initializing Properties Using the managed-property Element], explains in more detail how to use the -`managed-property` element. See link:#BNAWY[Initializing Managed Bean +`managed-property` element. See xref:jsf-configure/jsf-configure.adoc#BNAWY[Initializing Managed Bean Properties] for an example of initializing a managed bean property. -[[BNAWS]][[initializing-properties-using-the-managed-property-element]] +[[BNAWS]][[_initializing_properties_using_the_managed_property_element]] === Initializing Properties Using the managed-property Element @@ -157,7 +157,7 @@ which must match the name of the corresponding property in the bean. A that defines the value of the property. This value must be of the same type as that defined for the property in the corresponding bean. Which element you use to define the value depends on the type of the property -defined in the bean. link:#BNAWT[Table 16-1] lists all the elements that +defined in the bean. xref:jsf-configure/jsf-configure.adoc#BNAWT[Table 16-1] lists all the elements that are used to initialize a value. [[sthref94]][[BNAWT]] @@ -179,7 +179,7 @@ Jakarta Server Faces EL expression |======================================================================= -link:#BNAWR[Using the managed-bean Element] includes an example of +xref:jsf-configure/jsf-configure.adoc#BNAWR[Using the managed-bean Element] includes an example of initializing an `int` property (a primitive type) using the `value` subelement. You also use the `value` subelement to initialize `String` and other reference types. The rest of this section describes how to use @@ -187,7 +187,7 @@ the `value` subelement and other subelements to initialize properties of Java `Enum` types, `Map`, `array`, and `Collection`, as well as initialization parameters. -[[BNAWU]][[referencing-a-java-enum-type]] +[[BNAWU]][[_referencing_a_java_enum_type]] ==== Referencing a Java Enum Type @@ -224,7 +224,7 @@ When the system encounters this property, it iterates over each of the members of the `enum` and calls `toString()` on each member until it finds one that is exactly equal to the value from the `value` element. -[[BNAWV]][[referencing-a-context-initialization-parameter]] +[[BNAWV]][[_referencing_a_context_initialization_parameter]] ==== Referencing a Context Initialization Parameter @@ -271,7 +271,7 @@ property from the `area` component tag's `value` attribute: Values are retrieved from other implicit objects in a similar way. -[[BNAWW]][[initializing-map-properties]] +[[BNAWW]][[_initializing_map_properties]] ==== Initializing Map Properties @@ -345,7 +345,7 @@ Instead of using a `map-entries` element, it is also possible to assign the entire map using a `value` element that specifies a map-typed expression. -[[BNAWX]][[initializing-array-and-list-properties]] +[[BNAWX]][[_initializing_array_and_list_properties]] ==== Initializing Array and List Properties @@ -379,7 +379,7 @@ an argument of `null`. A `null` property cannot be specified for a property whose data type is a Java primitive, such as `int` or `boolean`. -[[BNAWY]][[initializing-managed-bean-properties]] +[[BNAWY]][[_initializing_managed_bean_properties]] ==== Initializing Managed Bean Properties @@ -447,7 +447,7 @@ impossible to recover that scope's resources when it goes away. A session-scoped object, for example, cannot point to a request-scoped object. And objects with `none` scope have no effective life span managed by the framework, so they can point only to other `none`-scoped -objects. link:#BNAWZ[Table 16-2] outlines all of the allowed +objects. xref:jsf-configure/jsf-configure.adoc#BNAWZ[Table 16-2] outlines all of the allowed connections. [[sthref95]][[BNAWZ]] @@ -470,7 +470,7 @@ neither of the `AddressBean` objects in the preceding example should point back to the `CustomerBean` object, because `CustomerBean` already points to the `AddressBean` objects. -[[BNAXA]][[initializing-maps-and-lists]] +[[BNAXA]][[_initializing_maps_and_lists]] === Initializing Maps and Lists diff --git a/src/main/antora/modules/web/pages/jsf-configure/jsf-configure006.adoc b/src/main/antora/modules/web/pages/jsf-configure/jsf-configure006.adoc index b667ea40..59124351 100644 --- a/src/main/antora/modules/web/pages/jsf-configure/jsf-configure006.adoc +++ b/src/main/antora/modules/web/pages/jsf-configure/jsf-configure006.adoc @@ -1,4 +1,4 @@ -[[BNAXB]][[registering-application-messages]] +[[BNAXB]][[_registering_application_messages]] == Registering Application Messages @@ -9,7 +9,7 @@ messages available at application startup time, do one of the following: * Queue an individual message onto the `javax.faces.context.FacesContext` instance programmatically, as -described in link:#GKUHG[Using FacesMessage to Create a Message] +described in xref:jsf-configure/jsf-configure.adoc#GKUHG[Using FacesMessage to Create a Message] * Register all the messages with your application using the application configuration resource file @@ -72,7 +72,7 @@ The `alt` attribute can accept value expressions. In this case, the `alt` attribute refers to localized text that will be included in the alternative text of the image rendered by this tag. -[[GKUHG]][[using-facesmessage-to-create-a-message]] +[[GKUHG]][[_using_facesmessage_to_create_a_message]] === Using FacesMessage to Create a Message @@ -111,12 +111,12 @@ public static String loadErrorMessage(FacesContext context, } ---- -[[BNASS]][[referencing-error-messages]] +[[BNASS]][[_referencing_error_messages]] === Referencing Error Messages A Jakarta Server Faces page uses the `message` or `messages` tags to access -error messages, as explained in link:#BNASO[Displaying +error messages, as explained in xref:jsf-page/jsf-page.adoc#BNASO[Displaying Error Messages with the h:message and h:messages Tags]. The error messages these tags access include diff --git a/src/main/antora/modules/web/pages/jsf-configure/jsf-configure007.adoc b/src/main/antora/modules/web/pages/jsf-configure/jsf-configure007.adoc index e8c49030..4597dfcd 100644 --- a/src/main/antora/modules/web/pages/jsf-configure/jsf-configure007.adoc +++ b/src/main/antora/modules/web/pages/jsf-configure/jsf-configure007.adoc @@ -1,4 +1,4 @@ -[[GIREB]][[using-default-validators]] +[[GIREB]][[_using_default_validators]] == Using Default Validators diff --git a/src/main/antora/modules/web/pages/jsf-configure/jsf-configure008.adoc b/src/main/antora/modules/web/pages/jsf-configure/jsf-configure008.adoc index ce156a33..1c6ed7ae 100644 --- a/src/main/antora/modules/web/pages/jsf-configure/jsf-configure008.adoc +++ b/src/main/antora/modules/web/pages/jsf-configure/jsf-configure008.adoc @@ -1,4 +1,4 @@ -[[BNAXD]][[registering-a-custom-validator]] +[[BNAXD]][[_registering_a_custom_validator]] == Registering a Custom Validator @@ -6,7 +6,7 @@ If the application developer provides an implementation of the `javax.faces.validator.Validator` interface to perform validation, you must register this custom validator either by using the `@FacesValidator` annotation, as described in -link:#BNAUX[Implementing the Validator Interface], or +xref:jsf-custom/jsf-custom.adoc#BNAUX[Implementing the Validator Interface], or by using the `validator` XML element in the application configuration resource file: @@ -44,10 +44,10 @@ the name of the attribute as it appears in the `validator` tag. The `attribute-class` element identifies the Java type of the value associated with the attribute. -link:#BNAUW[Creating and Using a Custom Validator] +xref:jsf-custom/jsf-custom.adoc#BNAUW[Creating and Using a Custom Validator] explains how to implement the `Validator` interface. -link:#BNATV[Using a Custom Validator] explains how to +xref:jsf-custom/jsf-custom.adoc#BNATV[Using a Custom Validator] explains how to reference the validator from the page. diff --git a/src/main/antora/modules/web/pages/jsf-configure/jsf-configure009.adoc b/src/main/antora/modules/web/pages/jsf-configure/jsf-configure009.adoc index 835a83f9..9e2bfa25 100644 --- a/src/main/antora/modules/web/pages/jsf-configure/jsf-configure009.adoc +++ b/src/main/antora/modules/web/pages/jsf-configure/jsf-configure009.adoc @@ -1,11 +1,11 @@ -[[BNAXE]][[registering-a-custom-converter]] +[[BNAXE]][[_registering_a_custom_converter]] == Registering a Custom Converter As is the case with a custom validator, if the application developer creates a custom converter, you must register it with the application either by using the `@FacesConverter` annotation, as described in -link:#GLPHB[Creating a Custom Converter], or by using +xref:jsf-custom/jsf-custom.adoc#GLPHB[Creating a Custom Converter], or by using the `converter` XML element in the application configuration resource file. Here is a hypothetical `converter` configuration for `CreditCardConverter` from the Duke's Bookstore case study: @@ -33,13 +33,13 @@ implementation and contains required `converter-id` and The `converter-id` element identifies an ID that is used by the `converter` attribute of a UI component tag to apply the converter to -the component's data. link:#BNATU[Using a Custom +the component's data. xref:jsf-custom/jsf-custom.adoc#BNATU[Using a Custom Converter] includes an example of referencing the custom converter from a component tag. The `converter-class` element identifies the `Converter` implementation. -link:#BNAUS[Creating and Using a Custom Converter] +xref:jsf-custom/jsf-custom.adoc#BNAUS[Creating and Using a Custom Converter] explains how to create a custom converter. diff --git a/src/main/antora/modules/web/pages/jsf-configure/jsf-configure010.adoc b/src/main/antora/modules/web/pages/jsf-configure/jsf-configure010.adoc index e3f4cdd0..5530dde2 100644 --- a/src/main/antora/modules/web/pages/jsf-configure/jsf-configure010.adoc +++ b/src/main/antora/modules/web/pages/jsf-configure/jsf-configure010.adoc @@ -1,4 +1,4 @@ -[[BNAXF]][[configuring-navigation-rules]] +[[BNAXF]][[_configuring_navigation_rules]] == Configuring Navigation Rules @@ -7,7 +7,7 @@ such as choosing the next page to be displayed after a button or link component is clicked, is defined by a set of rules. Navigation rules can be implicit, or they can be explicitly defined in the application configuration resource file. For more information on implicit navigation -rules, see link:#BNAQL[Navigation Model]. +rules, see xref:jsf-intro/jsf-intro.adoc#BNAQL[Navigation Model]. Each navigation rule specifies how to navigate from one page to another page or set of pages. The Jakarta Server Faces implementation chooses the @@ -20,7 +20,7 @@ to access next from the current page depends on two factors: * The logical outcome referenced by the component's tag or returned from the action method -The outcome can be anything the developer chooses, but link:#BNAXG[Table +The outcome can be anything the developer chooses, but xref:jsf-configure/jsf-configure.adoc#BNAXG[Table 16-3] lists some outcomes commonly used in web applications. [[sthref96]][[BNAXG]] diff --git a/src/main/antora/modules/web/pages/jsf-configure/jsf-configure011.adoc b/src/main/antora/modules/web/pages/jsf-configure/jsf-configure011.adoc index f21c7ec5..226cb174 100644 --- a/src/main/antora/modules/web/pages/jsf-configure/jsf-configure011.adoc +++ b/src/main/antora/modules/web/pages/jsf-configure/jsf-configure011.adoc @@ -1,16 +1,16 @@ -[[BNAXH]][[registering-a-custom-renderer-with-a-render-kit]] +[[BNAXH]][[_registering_a_custom_renderer_with_a_render_kit]] == Registering a Custom Renderer with a Render Kit When the application developer creates a custom renderer, as described -in link:#BNAWA[Delegating Rendering to a Renderer], you +in xref:jsf-custom/jsf-custom.adoc#BNAWA[Delegating Rendering to a Renderer], you must register it using the appropriate render kit. Because the image map application implements an HTML image map, the `AreaRenderer` and `MapRenderer` classes in the Duke's Bookstore case study should be registered using the HTML render kit. You register the renderer either by using the `@FacesRenderer` -annotation, as described in link:#BNAWB[Creating the +annotation, as described in xref:jsf-custom/jsf-custom.adoc#BNAWB[Creating the Renderer Class], or by using the `render-kit` element of the application configuration resource file. Here is a hypothetical configuration of `AreaRenderer`: diff --git a/src/main/antora/modules/web/pages/jsf-configure/jsf-configure012.adoc b/src/main/antora/modules/web/pages/jsf-configure/jsf-configure012.adoc index f1295172..f90f054f 100644 --- a/src/main/antora/modules/web/pages/jsf-configure/jsf-configure012.adoc +++ b/src/main/antora/modules/web/pages/jsf-configure/jsf-configure012.adoc @@ -1,4 +1,4 @@ -[[BNAXI]][[registering-a-custom-component]] +[[BNAXI]][[_registering_a_custom_component]] == Registering a Custom Component @@ -6,7 +6,7 @@ In addition to registering custom renderers (as explained in the preceding section), you also must register the custom components that are usually associated with the custom renderers. You use either a `@FacesComponent` annotation, as described in -link:#BNAVU[Creating Custom Component Classes], or the +xref:jsf-custom/jsf-custom.adoc#BNAVU[Creating Custom Component Classes], or the `component` element of the application configuration resource file. Here is a hypothetical `component` element from the application @@ -51,7 +51,7 @@ properties and their types. If the custom component can include facets, you can configure the facets in the component configuration using `facet` elements, which are allowed after the `component-class` elements. See -link:#BNAXH[Registering a Custom Renderer with a +xref:jsf-configure/jsf-configure.adoc#BNAXH[Registering a Custom Renderer with a Render Kit] for further details on configuring facets. diff --git a/src/main/antora/modules/web/pages/jsf-configure/jsf-configure013.adoc b/src/main/antora/modules/web/pages/jsf-configure/jsf-configure013.adoc index 5fa2eda5..7a4493ba 100644 --- a/src/main/antora/modules/web/pages/jsf-configure/jsf-configure013.adoc +++ b/src/main/antora/modules/web/pages/jsf-configure/jsf-configure013.adoc @@ -1,4 +1,4 @@ -[[BNAXJ]][[basic-requirements-of-a-javaserver-faces-application]] +[[BNAXJ]][[_basic_requirements_of_a_javaserver_faces_application]] == Basic Requirements of a Jakarta Server Faces Application @@ -44,7 +44,7 @@ The `web.xml` file (or web deployment descriptor), the set of JAR files, and the set of application files must be contained in the `WEB-INF` directory of the WAR file. -[[BNAXK]][[configuring-an-application-with-a-web-deployment-descriptor]] +[[BNAXK]][[_configuring_an_application_with_a_web_deployment_descriptor]] === Configuring an Application with a Web Deployment Descriptor @@ -72,7 +72,7 @@ This section gives more details on these configurations. Where appropriate, it also describes how you can make these configurations using NetBeans IDE. -[[GLPOO]][[identifying-the-servlet-for-lifecycle-processing]] +[[GLPOO]][[_identifying_the_servlet_for_lifecycle_processing]] ==== Identifying the Servlet for Lifecycle Processing @@ -86,7 +86,7 @@ technology. Before a Jakarta Server Faces application can launch its first web page, the web container must invoke the `FacesServlet` instance in order for the application lifecycle process to start. See -link:#BNAQQ[The Lifecycle of a Jakarta Server Faces +xref:jsf-intro/jsf-intro.adoc#BNAQQ[The Lifecycle of a Jakarta Server Faces Application] for more information. The following example shows the default configuration of the @@ -159,11 +159,11 @@ deployment descriptor is automatically created for you with default configurations. If you created your application without an IDE, you can create a web deployment descriptor. -[[BNAXM]][[to-specify-a-path-to-an-application-configuration-resource-file]] +[[BNAXM]][[_to_specify_a_path_to_an_application_configuration_resource_file]] ==== To Specify a Path to an Application Configuration Resource File -As explained in link:#BNAWP[Application +As explained in xref:jsf-configure/jsf-configure.adoc#BNAWP[Application Configuration Resource File], an application can have multiple application configuration resource files. If these files are not located in the directories that the implementation searches by default or the @@ -184,7 +184,7 @@ To specify these paths using NetBeans IDE, do the following. .. Click OK. .. Repeat steps 1 through 7 for each configuration file. -[[BNAXN]][[to-specify-where-state-is-saved]] +[[BNAXN]][[_to_specify_where_state_is_saved]] ==== To Specify Where State Is Saved @@ -193,7 +193,7 @@ deployment descriptor where you want the state to be saved, on either client or server. You do this by setting a context parameter in your deployment descriptor. By default, state is saved on the server, so you need to specify this context parameter only if you want to save state on -the client. See link:#BNAVZ[Saving and Restoring State] +the client. See xref:jsf-custom/jsf-custom.adoc#BNAVZ[Saving and Restoring State] for information on the advantages and disadvantages of each location. To specify where state is saved using NetBeans IDE, do the following. @@ -214,7 +214,7 @@ rendered to a hidden field on the page. The Jakarta Server Faces implementation saves the state on the server by default. Duke's Forest saves its state on the client. -[[GIQXL]][[configuring-project-stage]] +[[GIQXL]][[_configuring_project_stage]] === Configuring Project Stage @@ -245,7 +245,7 @@ deployment descriptor file. Here is an example: If no Project Stage is defined, the default stage is `Production`. You can also add custom stages according to your requirements. -[[BNAXT]][[including-the-classes-pages-and-other-resources]] +[[BNAXT]][[_including_the_classes_pages_and_other_resources]] === Including the Classes, Pages, and Other Resources @@ -256,7 +256,7 @@ notice that the scripts package resources in the following ways. * The `faces-config.xml` file and the `web.xml` file are packaged in the `WEB-INF` directory. * All packages are stored in the `WEB-INF/classes/` directory. * All application JAR files are packaged in the `WEB-INF/lib/` directory. -* All resource files are either under the root of the web application `/resources` directory or in the web application's classpath, the `META-INF/resources/`{zwsp}resourceIdentifier directory. For more information on resources, see link:#GIRGM[Web Resources]. +* All resource files are either under the root of the web application `/resources` directory or in the web application's classpath, the `META-INF/resources/`{zwsp}resourceIdentifier directory. For more information on resources, see xref:jsf-facelets/jsf-facelets.adoc#GIRGM[Web Resources]. When packaging your own applications, you can use NetBeans IDE or you can use XML files such as those created for Maven. You can modify the diff --git a/src/main/antora/modules/web/pages/jsf-custom/jsf-custom.adoc b/src/main/antora/modules/web/pages/jsf-custom/jsf-custom.adoc index e3ef2c55..012051c7 100644 --- a/src/main/antora/modules/web/pages/jsf-custom/jsf-custom.adoc +++ b/src/main/antora/modules/web/pages/jsf-custom/jsf-custom.adoc @@ -1,6 +1,6 @@ = Creating Custom UI Components and Other Custom Objects -[[BNAVG]][[creating-custom-ui-components-and-other-custom-objects]] +[[BNAVG]][[_creating_custom_ui_components_and_other_custom_objects]] This chapter describes creating custom components for applications that have additional functionality not provided by standard Jakarta Server Faces diff --git a/src/main/antora/modules/web/pages/jsf-custom/jsf-custom001.adoc b/src/main/antora/modules/web/pages/jsf-custom/jsf-custom001.adoc index 570f55ba..058e14ee 100644 --- a/src/main/antora/modules/web/pages/jsf-custom/jsf-custom001.adoc +++ b/src/main/antora/modules/web/pages/jsf-custom/jsf-custom001.adoc @@ -1,4 +1,4 @@ -[[A1350198]][[introduction-to-creating-custom-components]] +[[A1350198]][[_introduction_to_creating_custom_components]] == Introduction to Creating Custom Components @@ -60,7 +60,7 @@ A `javax.faces.view.facelets.Tag` object is a helper to the instance of a `UIComponent` in a Jakarta Server Faces view. A tag represents a specific combination of `component-type` and `renderer-type`. -See link:#BNAVK[Component, Renderer, and Tag +See xref:jsf-custom/jsf-custom.adoc#BNAVK[Component, Renderer, and Tag Combinations] for information on how components, renderers, and tags interact. @@ -68,7 +68,7 @@ This chapter uses the image map component from the Duke's Bookstore case study example to explain how you can create simple custom components, custom renderers, and associated custom tags, and take care of all the other details associated with using the components and renderers in an -application. See link:#GLNVI[Chapter 60, "Duke's +application. See xref:#GLNVI[Chapter 60, "Duke's Bookstore Case Study Example"] for more information about this example. The chapter also describes how to create other custom objects: custom diff --git a/src/main/antora/modules/web/pages/jsf-custom/jsf-custom002.adoc b/src/main/antora/modules/web/pages/jsf-custom/jsf-custom002.adoc index fad2bb19..5f648ab1 100644 --- a/src/main/antora/modules/web/pages/jsf-custom/jsf-custom002.adoc +++ b/src/main/antora/modules/web/pages/jsf-custom/jsf-custom002.adoc @@ -1,4 +1,4 @@ -[[BNAVH]][[determining-whether-you-need-a-custom-component-or-renderer]] +[[BNAVH]][[_determining_whether_you_need_a_custom_component_or_renderer]] == Determining Whether You Need a Custom Component or Renderer @@ -7,7 +7,7 @@ components and associated renderers. This section helps you to decide whether you can use standard components and renderers in your application or need a custom component or custom renderer. -[[BNAVI]][[when-to-use-a-custom-component]] +[[BNAVI]][[_when_to_use_a_custom_component]] === When to Use a Custom Component @@ -50,34 +50,34 @@ You do not need to create a custom component in the following cases. * You need to aggregate components to create a new component that has its own unique behavior. In this situation, you can use a composite component to combine existing standard components. For more information -on composite components, see link:#GIQZR[Composite -Components] and link:#GKHXA[Chapter 14, "Composite +on composite components, see xref:jsf-facelets/jsf-facelets.adoc#GIQZR[Composite +Components] and xref:jsf-advanced-cc/jsf-advanced-cc.adoc#GKHXA[Chapter 14, "Composite Components: Advanced Topics and an Example"]. * You simply need to manipulate data on the component or add application-specific functionality to it. In this situation, you should create a managed bean for this purpose and bind it to the standard component rather than create a custom component. See -link:#BNAQM[Managed Beans in Jakarta Server Faces +xref:jsf-develop/jsf-develop.adoc#BNAQM[Managed Beans in Jakarta Server Faces Technology] for more information on managed beans. * You need to convert a component's data to a type not supported by its -renderer. See link:#BNAST[Using the Standard +renderer. See xref:jsf-page-core/jsf-page-core.adoc#BNAST[Using the Standard Converters] for more information about converting a component's data. * You need to perform validation on the component data. Standard validators and custom validators can be added to a component by using the validator tags from the page. See -link:#BNATC[Using the Standard Validators] and -link:#BNAUW[Creating and Using a Custom Validator] for +xref:jsf-page-core/jsf-page-core.adoc#BNATC[Using the Standard Validators] and +xref:jsf-custom/jsf-custom.adoc#BNAUW[Creating and Using a Custom Validator] for more information about validating a component's data. * You need to register event listeners on components. You can either register event listeners on components using the `f:valueChangeListener` and `f:actionListener` tags, or you can point at an event-processing method on a managed bean using the component's `actionListener` or `valueChangeListener` attributes. See -link:#BNAUT[Implementing an Event Listener] and -link:#BNAVB[Writing Managed Bean Methods] for more +xref:jsf-custom/jsf-custom.adoc#BNAUT[Implementing an Event Listener] and +xref:jsf-develop/jsf-develop.adoc#BNAVB[Writing Managed Bean Methods] for more information. -[[BNAVJ]][[when-to-use-a-custom-renderer]] +[[BNAVJ]][[_when_to_use_a_custom_renderer]] === When to Use a Custom Renderer @@ -121,7 +121,7 @@ approach, you can actually use both models. Your component class can include some default rendering code, but it can delegate rendering to a renderer if there is one. -[[BNAVK]][[component-renderer-and-tag-combinations]] +[[BNAVK]][[_component_renderer_and_tag_combinations]] === Component, Renderer, and Tag Combinations @@ -156,7 +156,7 @@ validator tag. In this case, the custom tag corresponds to a custom validator and not to a custom component or custom renderer. In any case, you still need to associate the custom tag with a server-side object. -link:#BNAVL[Table 15-1] summarizes what you must or can associate with a +xref:jsf-custom/jsf-custom.adoc#BNAVL[Table 15-1] summarizes what you must or can associate with a custom component, custom renderer, or custom tag. [[sthref76]][[BNAVL]] diff --git a/src/main/antora/modules/web/pages/jsf-custom/jsf-custom003.adoc b/src/main/antora/modules/web/pages/jsf-custom/jsf-custom003.adoc index 29492d18..13e69d01 100644 --- a/src/main/antora/modules/web/pages/jsf-custom/jsf-custom003.adoc +++ b/src/main/antora/modules/web/pages/jsf-custom/jsf-custom003.adoc @@ -1,4 +1,4 @@ -[[GLPCB]][[understanding-the-image-map-example]] +[[GLPCB]][[_understanding_the_image_map_example]] == Understanding the Image Map Example @@ -9,7 +9,7 @@ the application goes to a page that displays the title of the selected book as well as information about a featured book. The page allows the user to add either book (or none) to the shopping cart. -[[GLPBD]][[why-use-javaserver-faces-technology-to-implement-an-image-map]] +[[GLPBD]][[_why_use_javaserver_faces_technology_to_implement_an_image_map]] === Why Use Jakarta Server Faces Technology to Implement an Image Map? @@ -32,7 +32,7 @@ it has the best of both styles of image maps: It can handle the parts of the application that need to be performed on the server while allowing the other parts of the application to be performed on the client side. -[[GLPEM]][[understanding-the-rendered-html]] +[[GLPEM]][[_understanding_the_rendered_html]] === Understanding the Rendered HTML @@ -86,7 +86,7 @@ The server-side objects retrieve the value of `bookMap_current` and set the locale in the `javax.faces.context.FacesContext` instance according to the region that was selected. -[[GLPCD]][[understanding-the-facelets-page]] +[[GLPCD]][[_understanding_the_facelets_page]] === Understanding the Facelets Page @@ -131,13 +131,13 @@ The `f:actionListener` tag within the `bookstore:map` tag points to a listener class for an action event. The `processAction` method of the listener places the book ID for the selected map area into the session map. The way this event is handled is explained more in -link:#BNAWD[Handling Events for Custom Components]. +xref:jsf-custom/jsf-custom.adoc#BNAWD[Handling Events for Custom Components]. The `action` attribute of the `bookstore:map` tag specifies a logical outcome `String`, `"bookstore"`, which by implicit navigation rules sends the application to the page `bookstore.xhtml`. For more information on navigation, see -link:#BNAXF[Configuring Navigation Rules]. +xref:jsf-configure/jsf-configure.adoc#BNAXF[Configuring Navigation Rules]. The `immediate` attribute of the `bookstore:map` tag is set to `true`, which indicates that the default `javax.faces.event.ActionListener` @@ -158,7 +158,7 @@ page. The JavaScript is generated by the `dukesbookstore.renderers.AreaRenderer` class. The `onmouseover` and `onmouseout` attribute values indicate the image to be loaded when these events occur. How the JavaScript is generated is explained more in -link:#BNAVW[Performing Encoding]. +xref:jsf-custom/jsf-custom.adoc#BNAVW[Performing Encoding]. The coordinate, shape, and alternate text data are obtained through the `value` attribute, whose value refers to an attribute in application @@ -166,7 +166,7 @@ scope. The value of this attribute is a bean, which stores the `coords`, `shape`, and `alt` data. How these beans are stored in the application scope is explained more in the next section. -[[GLPBO]][[configuring-model-data]] +[[GLPBO]][[_configuring_model_data]] === Configuring Model Data @@ -181,7 +181,7 @@ both the shape and the coordinates. To solve this problem, the application encapsulates all of this information in a set of `ImageArea` objects. These objects are initialized into application scope by the managed bean creation facility -(see link:#BNAWR[Using the managed-bean Element]). +(see xref:jsf-configure/jsf-configure.adoc#BNAWR[Using the managed-bean Element]). Here is part of the managed bean declaration for the `ImageArea` bean corresponding to the South America hotspot: @@ -214,7 +214,7 @@ corresponding to the South America hotspot: For more information on initializing managed beans with the managed bean creation facility, see the section -link:#BNAWP[Application Configuration Resource +xref:jsf-configure/jsf-configure.adoc#BNAWP[Application Configuration Resource File]. The `value` attributes of the `bookstore:area` tags refer to the beans @@ -246,14 +246,14 @@ ImageArea iarea = (ImageArea) area.getValue(); `ImageArea` is a simple bean, so you can access the shape, coordinates, and alternative text values by calling the appropriate accessor methods -of `ImageArea`. link:#BNAWB[Creating the Renderer +of `ImageArea`. xref:jsf-custom/jsf-custom.adoc#BNAWB[Creating the Renderer Class] explains how to do this in the `AreaRenderer` class. -[[GLPEL]][[summary-of-the-image-map-application-classes]] +[[GLPEL]][[_summary_of_the_image_map_application_classes]] === Summary of the Image Map Application Classes -link:#GLPEK[Table 15-2] summarizes all the classes needed to implement +xref:jsf-custom/jsf-custom.adoc#GLPEK[Table 15-2] summarizes all the classes needed to implement the image map component. [[sthref77]][[GLPEK]] diff --git a/src/main/antora/modules/web/pages/jsf-custom/jsf-custom004.adoc b/src/main/antora/modules/web/pages/jsf-custom/jsf-custom004.adoc index 7f177bfb..5d4a8802 100644 --- a/src/main/antora/modules/web/pages/jsf-custom/jsf-custom004.adoc +++ b/src/main/antora/modules/web/pages/jsf-custom/jsf-custom004.adoc @@ -1,4 +1,4 @@ -[[BNAVT]][[steps-for-creating-a-custom-component]] +[[BNAVT]][[_steps_for_creating_a_custom_component]] == Steps for Creating a Custom Component @@ -7,7 +7,7 @@ component. . Create a custom component class that does the following: . Overrides the `getFamily` method to return the component family, which is used to look up renderers that can render the component -. Includes the rendering code or delegates it to a renderer (explained in Step link:#CDECBJAE[2]) +. Includes the rendering code or delegates it to a renderer (explained in Step xref:jsf-custom/jsf-custom.adoc#CDECBJAE[2]) . Enables component attributes to accept expressions . Queues an event on the component if the component generates events . Saves and restores the component state @@ -21,10 +21,10 @@ component. .. Create a tag library descriptor (TLD) that defines the custom tag. -- -See link:#BNAXI[Registering a Custom Component] and -link:#BNAXH[Registering a Custom Renderer with a +See xref:jsf-configure/jsf-configure.adoc#BNAXI[Registering a Custom Component] and +xref:jsf-configure/jsf-configure.adoc#BNAXH[Registering a Custom Renderer with a Render Kit] for information on registering the custom component and the -renderer. The section link:#BNATT[Using a Custom +renderer. The section xref:jsf-custom/jsf-custom.adoc#BNATT[Using a Custom Component] discusses how to use the custom component in a Jakarta Server Faces page. diff --git a/src/main/antora/modules/web/pages/jsf-custom/jsf-custom005.adoc b/src/main/antora/modules/web/pages/jsf-custom/jsf-custom005.adoc index 544a4c55..aa8b58c0 100644 --- a/src/main/antora/modules/web/pages/jsf-custom/jsf-custom005.adoc +++ b/src/main/antora/modules/web/pages/jsf-custom/jsf-custom005.adoc @@ -1,8 +1,8 @@ -[[BNAVU]][[creating-custom-component-classes]] +[[BNAVU]][[_creating_custom_component_classes]] == Creating Custom Component Classes -As explained in link:#BNAVI[When to Use a Custom +As explained in xref:jsf-custom/jsf-custom.adoc#BNAVI[When to Use a Custom Component], a component class defines the state and behavior of a UI component. The state information includes the component's type, identifier, and local value. The behavior defined by the component class @@ -135,7 +135,7 @@ tags to the `MapRenderer` class. `AreaComponent` is bound to a bean that stores the shape and coordinates of the region of the image map. You will see how all this data is accessed through the value expression in -link:#BNAWB[Creating the Renderer Class]. The behavior +xref:jsf-custom/jsf-custom.adoc#BNAWB[Creating the Renderer Class]. The behavior of `AreaComponent` consists of the following: * Retrieving the shape and coordinate data from the bean @@ -145,15 +145,15 @@ of `AreaComponent` consists of the following: Although these tasks are actually performed by `AreaRenderer`, `AreaComponent` must delegate the tasks to `AreaRenderer`. See -link:#BNAWA[Delegating Rendering to a Renderer] for +xref:jsf-custom/jsf-custom.adoc#BNAWA[Delegating Rendering to a Renderer] for more information. The rest of this section describes the tasks that `MapComponent` performs as well as the encoding and decoding that it delegates to -`MapRenderer`. link:#BNAWD[Handling Events for Custom +`MapRenderer`. xref:jsf-custom/jsf-custom.adoc#BNAWD[Handling Events for Custom Components] details how `MapComponent` handles events. -[[BNAVV]][[specifying-the-component-family]] +[[BNAVV]][[_specifying_the_component_family]] === Specifying the Component Family @@ -174,13 +174,13 @@ public String getFamily() { The component family identifier, `Map`, must match that defined by the `component-family` elements included in the component and renderer configurations in the application configuration resource file. -link:#BNAXH[Registering a Custom Renderer with a +xref:jsf-configure/jsf-configure.adoc#BNAXH[Registering a Custom Renderer with a Render Kit] explains how to define the component family in the renderer -configuration. link:#BNAXI[Registering a Custom +configuration. xref:jsf-configure/jsf-configure.adoc#BNAXI[Registering a Custom Component] explains how to define the component family in the component configuration. -[[BNAVW]][[performing-encoding]] +[[BNAVW]][[_performing_encoding]] === Performing Encoding @@ -296,7 +296,7 @@ might need to implement other methods in addition to `encodeEnd`. For example, if you need to retrieve the component's value from the request parameters, you must also implement the `decode` method. -[[BNAVX]][[performing-decoding]] +[[BNAVX]][[_performing_decoding]] === Performing Decoding @@ -337,7 +337,7 @@ the `input` field. This value represents the currently selected area. Finally, it sets the value of the `MapComponent` class's `current` attribute to the value of the `input` field. -[[BNAVY]][[enabling-component-properties-to-accept-expressions]] +[[BNAVY]][[_enabling_component_properties_to_accept_expressions]] === Enabling Component Properties to Accept Expressions @@ -416,11 +416,11 @@ public void setAction(MethodExpression action) { } ---- -[[BNAVZ]][[saving-and-restoring-state]] +[[BNAVZ]][[_saving_and_restoring_state]] === Saving and Restoring State -As described in link:#BNAVY[Enabling Component Properties to Accept +As described in xref:jsf-custom/jsf-custom.adoc#BNAVY[Enabling Component Properties to Accept Expressions], use of the `StateHelper` interface facilities allows you to save the component's state at the same time you set and retrieve property values. The `StateHelper` implementation allows partial state diff --git a/src/main/antora/modules/web/pages/jsf-custom/jsf-custom006.adoc b/src/main/antora/modules/web/pages/jsf-custom/jsf-custom006.adoc index 02dc84b9..46fa7e05 100644 --- a/src/main/antora/modules/web/pages/jsf-custom/jsf-custom006.adoc +++ b/src/main/antora/modules/web/pages/jsf-custom/jsf-custom006.adoc @@ -1,10 +1,10 @@ -[[BNAWA]][[delegating-rendering-to-a-renderer]] +[[BNAWA]][[_delegating_rendering_to_a_renderer]] == Delegating Rendering to a Renderer Both `MapComponent` and `AreaComponent` delegate all of their rendering to a separate renderer. The section -link:#BNAVW[Performing Encoding] explains how +xref:jsf-custom/jsf-custom.adoc#BNAVW[Performing Encoding] explains how `MapRenderer` performs the encoding for `MapComponent`. This section explains in detail the process of delegating rendering to a renderer using `AreaRenderer`, which performs the rendering for `AreaComponent`. @@ -12,10 +12,10 @@ using `AreaRenderer`, which performs the rendering for `AreaComponent`. To delegate rendering, you perform the tasks described in the following topics: -* link:#BNAWB[Creating the Renderer Class] -* link:#BNAWC[Identifying the Renderer Type] +* xref:jsf-custom/jsf-custom.adoc#BNAWB[Creating the Renderer Class] +* xref:jsf-custom/jsf-custom.adoc#BNAWC[Identifying the Renderer Type] -[[BNAWB]][[creating-the-renderer-class]] +[[BNAWB]][[_creating_the_renderer_class]] === Creating the Renderer Class @@ -51,7 +51,7 @@ ImageArea ia = (ImageArea)area.getValue(); The attribute value is the `ImageArea` bean instance, which contains the `shape`, `coords`, and `alt` values associated with the `book203` -`AreaComponent` instance. link:#GLPBO[Configuring Model +`AreaComponent` instance. xref:jsf-custom/jsf-custom.adoc#GLPBO[Configuring Model Data] describes how the application stores these values. After retrieving the `ImageArea` object, the method renders the values @@ -128,13 +128,13 @@ The `@FacesRenderer` annotation registers the renderer class with the Jakarta Server Faces implementation as a renderer class. The annotation identifies the component family as well as the renderer type. -[[BNAWC]][[identifying-the-renderer-type]] +[[BNAWC]][[_identifying_the_renderer_type]] === Identifying the Renderer Type Register the renderer with a render kit by using the `@FacesRenderer` annotation (or by using the application configuration resource file, as -explained in link:#BNAXH[Registering a Custom +explained in xref:jsf-configure/jsf-configure.adoc#BNAXH[Registering a Custom Renderer with a Render Kit]). During the Render Response phase, the Jakarta Server Faces implementation calls the `getRendererType` method of the component's tag handler to determine which renderer to invoke, if diff --git a/src/main/antora/modules/web/pages/jsf-custom/jsf-custom007.adoc b/src/main/antora/modules/web/pages/jsf-custom/jsf-custom007.adoc index 86965dbe..d25de62e 100644 --- a/src/main/antora/modules/web/pages/jsf-custom/jsf-custom007.adoc +++ b/src/main/antora/modules/web/pages/jsf-custom/jsf-custom007.adoc @@ -1,4 +1,4 @@ -[[BNAUT]][[implementing-an-event-listener]] +[[BNAUT]][[_implementing_an_event_listener]] == Implementing an Event Listener @@ -25,7 +25,7 @@ This section explains how to implement the two listener classes. To handle events generated by custom components, you must implement an event listener and an event handler and manually queue the event on the -component. See link:#BNAWD[Handling Events for Custom +component. See xref:jsf-custom/jsf-custom.adoc#BNAWD[Handling Events for Custom Components] for more information. @@ -37,13 +37,13 @@ Note: You do not need to create an `ActionListener` implementation to handle an event that results solely in navigating to a page and does not perform any other application-specific processing. See -link:#BNAVC[Writing a Method to Handle Navigation] for +xref:jsf-develop/jsf-develop.adoc#BNAVC[Writing a Method to Handle Navigation] for information on how to manage page navigation. |======================================================================= -[[BNAUU]][[implementing-value-change-listeners]] +[[BNAUU]][[_implementing_value_change_listeners]] === Implementing Value-Change Listeners @@ -103,10 +103,10 @@ the ID of the component that fired the event from the `ValueChangeEvent` object, and it puts the value, along with an attribute name, into the session map of the `FacesContext` instance. -link:#BNATA[Registering a Value-Change Listener on a +xref:jsf-page-core/jsf-page-core.adoc#BNATA[Registering a Value-Change Listener on a Component] explains how to register this listener onto a component. -[[BNAUV]][[implementing-action-listeners]] +[[BNAUV]][[_implementing_action_listeners]] === Implementing Action Listeners @@ -118,10 +118,10 @@ implementation invokes the `processAction(ActionEvent)` method when the The Duke's Bookstore case study uses two `ActionListener` implementations, `LinkBookChangeListener` and `MapBookChangeListener`. -See link:#BNAWD[Handling Events for Custom Components] +See xref:jsf-custom/jsf-custom.adoc#BNAWD[Handling Events for Custom Components] for details on `MapBookChangeListener`. -link:#BNATB[Registering an Action Listener on a +xref:jsf-page-core/jsf-page-core.adoc#BNATB[Registering an Action Listener on a Component] explains how to register this listener onto a component. diff --git a/src/main/antora/modules/web/pages/jsf-custom/jsf-custom008.adoc b/src/main/antora/modules/web/pages/jsf-custom/jsf-custom008.adoc index 33437a9b..bd236546 100644 --- a/src/main/antora/modules/web/pages/jsf-custom/jsf-custom008.adoc +++ b/src/main/antora/modules/web/pages/jsf-custom/jsf-custom008.adoc @@ -1,18 +1,18 @@ -[[BNAWD]][[handling-events-for-custom-components]] +[[BNAWD]][[_handling_events_for_custom_components]] == Handling Events for Custom Components -As explained in link:#BNAUT[Implementing an Event +As explained in xref:jsf-custom/jsf-custom.adoc#BNAUT[Implementing an Event Listener], events are automatically queued on standard components that fire events. A custom component, on the other hand, must manually queue events from its `decode` method if it fires events. -link:#BNAVX[Performing Decoding] explains how to queue +xref:jsf-custom/jsf-custom.adoc#BNAVX[Performing Decoding] explains how to queue an event on `MapComponent` using its `decode` method. This section explains how to write the class that represents the event of clicking on the map and how to write the method that processes this event. -As explained in link:#GLPCD[Understanding the Facelets +As explained in xref:jsf-custom/jsf-custom.adoc#GLPCD[Understanding the Facelets Page], the `actionListener` attribute of the `bookstore:map` tag points to the `MapBookChangeListener` class. The listener class's `processAction` method processes the event of clicking the image map. @@ -64,7 +64,7 @@ public class AreaSelectedEvent extends ActionEvent { } ---- -As explained in the section link:#BNAVU[Creating Custom +As explained in the section xref:jsf-custom/jsf-custom.adoc#BNAVU[Creating Custom Component Classes], in order for `MapComponent` to fire events in the first place, it must implement `ActionSource`. Because `MapComponent` extends `UICommand`, it also implements `ActionSource`. diff --git a/src/main/antora/modules/web/pages/jsf-custom/jsf-custom009.adoc b/src/main/antora/modules/web/pages/jsf-custom/jsf-custom009.adoc index b45eda58..48a4e836 100644 --- a/src/main/antora/modules/web/pages/jsf-custom/jsf-custom009.adoc +++ b/src/main/antora/modules/web/pages/jsf-custom/jsf-custom009.adoc @@ -1,4 +1,4 @@ -[[BNAWN]][[defining-the-custom-component-tag-in-a-tag-library-descriptor]] +[[BNAWN]][[_defining_the_custom_component_tag_in_a_tag_library_descriptor]] == Defining the Custom Component Tag in a Tag Library Descriptor @@ -45,7 +45,7 @@ the `rendererType` defined in the `@FacesRenderer` annotation. The `facelet-taglib` element must also include a `namespace` element, which defines the namespace to be specified in pages that use the custom -component. See link:#BNATT[Using a Custom Component] +component. See xref:jsf-custom/jsf-custom.adoc#BNATT[Using a Custom Component] for information on specifying the namespace in pages. The TLD file is located in the `WEB-INF` directory. In addition, an diff --git a/src/main/antora/modules/web/pages/jsf-custom/jsf-custom010.adoc b/src/main/antora/modules/web/pages/jsf-custom/jsf-custom010.adoc index 7dabd2ff..1fe597b4 100644 --- a/src/main/antora/modules/web/pages/jsf-custom/jsf-custom010.adoc +++ b/src/main/antora/modules/web/pages/jsf-custom/jsf-custom010.adoc @@ -1,11 +1,11 @@ -[[BNATT]][[using-a-custom-component]] +[[BNATT]][[_using_a_custom_component]] == Using a Custom Component To use a custom component in a page, you add the custom tag associated with the component to the page. -As explained in link:#BNAWN[Defining the Custom +As explained in xref:jsf-custom/jsf-custom.adoc#BNAWN[Defining the Custom Component Tag in a Tag Library Descriptor], you must ensure that the TLD that defines any custom tags is packaged in the application if you intend to use the tags in your pages. TLD files are stored in the diff --git a/src/main/antora/modules/web/pages/jsf-custom/jsf-custom011.adoc b/src/main/antora/modules/web/pages/jsf-custom/jsf-custom011.adoc index cbadcd53..e9375766 100644 --- a/src/main/antora/modules/web/pages/jsf-custom/jsf-custom011.adoc +++ b/src/main/antora/modules/web/pages/jsf-custom/jsf-custom011.adoc @@ -1,19 +1,19 @@ -[[BNAUS]][[creating-and-using-a-custom-converter]] +[[BNAUS]][[_creating_and_using_a_custom_converter]] == Creating and Using a Custom Converter A Jakarta Server Faces converter class converts strings to objects and objects to strings as required. Several standard converters are provided by Jakarta Server Faces for this purpose. See -link:#BNAST[Using the Standard Converters] for more +xref:jsf-page-core/jsf-page-core.adoc#BNAST[Using the Standard Converters] for more information on these included converters. -As explained in link:#BNAQI[Conversion Model], if the +As explained in xref:jsf-intro/jsf-intro.adoc#BNAQI[Conversion Model], if the standard converters included with Jakarta Server Faces cannot perform the data conversion that you need, you can create a custom converter to perform this specialized conversion. This implementation, at a minimum, must define how to convert data both ways between the two views of the -data described in link:#BNAQI[Conversion Model]. +data described in xref:jsf-intro/jsf-intro.adoc#BNAQI[Conversion Model]. All custom converters must implement the `javax.faces.convert.Converter` interface. This section explains how to implement this interface to @@ -32,7 +32,7 @@ nonstandard object type. In the Duke's Tutoring case study, the `Student` and `Guardian` entities require a custom converter so that they can be converted to and from a `UISelectItems` input component. -[[GLPHB]][[creating-a-custom-converter]] +[[GLPHB]][[_creating_a_custom_converter]] === Creating a Custom Converter @@ -50,7 +50,7 @@ The `@FacesConverter` annotation registers the custom converter class as a converter with the name of `ccno` with the Jakarta Server Faces implementation. Alternatively, you can register the converter with entries in the application configuration resource file, as shown in -link:#BNAXE[Registering a Custom Converter]. +xref:jsf-configure/jsf-configure.adoc#BNAXE[Registering a Custom Converter]. To define how the data is converted from the presentation view to the model view, the `Converter` implementation must implement the @@ -153,7 +153,7 @@ value to a `String`. If the value cannot be converted to a `String`, the method throws an exception, passing an error message from the resource bundle that is registered with the application. -link:#BNAXB[Registering Application Messages] +xref:jsf-configure/jsf-configure.adoc#BNAXB[Registering Application Messages] explains how to register custom error messages with the application. If the value can be converted to a `String`, the method reads the @@ -182,7 +182,7 @@ bean, as in the `address-book` persistence example, in which the converters use an enterprise bean that is injected into the managed bean class. -[[BNATU]][[using-a-custom-converter]] +[[BNATU]][[_using_a_custom_converter]] === Using a Custom Converter @@ -196,7 +196,7 @@ custom converter from one of the `f:converter` tag's attributes. If you are using the component tag's `converter` attribute, this attribute must reference the `Converter` implementation's identifier or -the fully-qualified class name of the converter. link:#BNAUS[Creating +the fully-qualified class name of the converter. xref:jsf-custom/jsf-custom.adoc#BNAUS[Creating and Using a Custom Converter] explains how to implement a custom converter. @@ -255,7 +255,7 @@ in `bookcashier.xhtml`: ---- * Bind the `Converter` implementation to a managed bean property using the `f:converter` tag's `binding` attribute, as described in -link:#BNATM[Binding Converters, Listeners, and +xref:jsf-custom/jsf-custom.adoc#BNATM[Binding Converters, Listeners, and Validators to Managed Bean Properties]. The Jakarta Server Faces implementation calls the converter's `getAsObject` diff --git a/src/main/antora/modules/web/pages/jsf-custom/jsf-custom012.adoc b/src/main/antora/modules/web/pages/jsf-custom/jsf-custom012.adoc index ec873764..495b2900 100644 --- a/src/main/antora/modules/web/pages/jsf-custom/jsf-custom012.adoc +++ b/src/main/antora/modules/web/pages/jsf-custom/jsf-custom012.adoc @@ -1,18 +1,18 @@ -[[BNAUW]][[creating-and-using-a-custom-validator]] +[[BNAUW]][[_creating_and_using_a_custom_validator]] == Creating and Using a Custom Validator If the standard validators or Bean Validation don't perform the validation checking you need, you can create a custom validator to validate user input. As explained in -link:#BNAQK[Validation Model], there are two ways to +xref:jsf-intro/jsf-intro.adoc#BNAQK[Validation Model], there are two ways to implement validation code. * Implement a managed bean method that performs the validation. * Provide an implementation of the `javax.faces.validator.Validator` interface to perform the validation. -link:#BNAVE[Writing a Method to Perform Validation] +xref:jsf-develop/jsf-develop.adoc#BNAVE[Writing a Method to Perform Validation] explains how to implement a managed bean method to perform validation. The rest of this section explains how to implement the `Validator` interface. @@ -25,12 +25,12 @@ on a component. If you prefer to configure the attributes in the `Validator` implementation, you can forgo specifying a custom tag and instead let the page author register the validator on a component using the -`f:validator` tag, as described in link:#BNATV[Using a Custom +`f:validator` tag, as described in xref:jsf-custom/jsf-custom.adoc#BNATV[Using a Custom Validator]. You can also create a managed bean property that accepts and returns the `Validator` implementation you create, as described in -link:#BNAUL[Writing Properties Bound to Converters, +xref:jsf-develop/jsf-develop.adoc#BNAUL[Writing Properties Bound to Converters, Listeners, or Validators]. You can use the `f:validator` tag's binding attribute to bind the `Validator` implementation to the managed bean property. @@ -42,7 +42,7 @@ After creating the resource bundle, you have two ways to make the messages available to the application. You can queue the error messages onto the `FacesContext` programmatically, or you can register the error messages in the application configuration resource file, as explained in -link:#BNAXB[Registering Application Messages]. +xref:jsf-configure/jsf-configure.adoc#BNAXB[Registering Application Messages]. For example, an e-commerce application might use a general-purpose custom validator called `FormatValidator.java` to validate input data @@ -68,7 +68,7 @@ situation. However, the rest of this section describes how this validator would be implemented and how to specify a custom tag so that the page author could register the validator on a component. -[[BNAUX]][[implementing-the-validator-interface]] +[[BNAUX]][[_implementing_the_validator_interface]] === Implementing the Validator Interface @@ -185,10 +185,10 @@ implement the `StateHolder` interface as well as the `Validator` interface. To implement `StateHolder`, you would need to implement its four methods: `saveState(FacesContext)`, `restoreState(FacesContext, Object)`, `isTransient`, and -`setTransient(boolean)`. See link:#BNAVZ[Saving and +`setTransient(boolean)`. See xref:jsf-custom/jsf-custom.adoc#BNAVZ[Saving and Restoring State] for more information. -[[BNAUY]][[specifying-a-custom-tag]] +[[BNAUY]][[_specifying_a_custom_tag]] === Specifying a Custom Tag @@ -198,7 +198,7 @@ the following. * Allow the page author to specify the `Validator` implementation to use with the `f:validator` tag. In this case, the `Validator` implementation -must define its own properties. link:#BNATV[Using a Custom Validator] +must define its own properties. xref:jsf-custom/jsf-custom.adoc#BNATV[Using a Custom Validator] explains how to use the `f:validator` tag. * Specify a custom tag that provides attributes for configuring the properties of the validator from the page. @@ -224,10 +224,10 @@ a Facelets page. The `validator-id` element identifies the custom validator. The `validator-class` element wires the custom tag to its implementation class. -link:#BNATV[Using a Custom Validator] explains how to use the custom +xref:jsf-custom/jsf-custom.adoc#BNATV[Using a Custom Validator] explains how to use the custom validator tag on the page. -[[BNATV]][[using-a-custom-validator]] +[[BNATV]][[_using_a_custom_validator]] === Using a Custom Validator @@ -274,7 +274,7 @@ validator that is defined in the application configuration resource file. * Bind the custom `Validator` implementation to a managed bean property using the `f:validator` tag's `binding` attribute, as described in -link:#BNATM[Binding Converters, Listeners, and +xref:jsf-custom/jsf-custom.adoc#BNATM[Binding Converters, Listeners, and Validators to Managed Bean Properties]. The following tag registers a hypothetical validator on a component diff --git a/src/main/antora/modules/web/pages/jsf-custom/jsf-custom013.adoc b/src/main/antora/modules/web/pages/jsf-custom/jsf-custom013.adoc index fd7664ea..5cf8bcca 100644 --- a/src/main/antora/modules/web/pages/jsf-custom/jsf-custom013.adoc +++ b/src/main/antora/modules/web/pages/jsf-custom/jsf-custom013.adoc @@ -1,4 +1,4 @@ -[[BNATG]][[binding-component-values-and-instances-to-managed-bean-properties]] +[[BNATG]][[_binding_component_values_and_instances_to_managed_bean_properties]] == Binding Component Values and Instances to Managed Bean Properties @@ -68,7 +68,7 @@ In addition to binding a component's value to a bean property, the `value` attribute can specify a literal value or can map the component's data to any primitive (such as `int`), structure (such as an array), or collection (such as a list), independent of a JavaBeans component. -link:#BNATH[Table 15-3] lists some example value-binding expressions +xref:jsf-custom/jsf-custom.adoc#BNATH[Table 15-3] lists some example value-binding expressions that you can use with the `value` attribute. [[sthref78]][[BNATH]] @@ -98,7 +98,7 @@ component's value to a bean property or other data objects and how to use the `binding` attribute to bind a component instance to a bean property. -[[BNATI]][[binding-a-component-value-to-a-property]] +[[BNATI]][[_binding_a_component_value_to_a_property]] === Binding a Component Value to a Property @@ -176,11 +176,11 @@ attribute of the component's tag: ---- -See link:#BNAWQ[Configuring Managed Beans] for +See xref:jsf-configure/jsf-configure.adoc#BNAWQ[Configuring Managed Beans] for information on how to configure beans in the application configuration resource file. -[[BNATJ]][[binding-a-component-value-to-an-implicit-object]] +[[BNATJ]][[_binding_a_component_value_to_an_implicit_object]] === Binding a Component Value to an Implicit Object @@ -209,7 +209,7 @@ Thank you, Gwen Canigetit, for purchasing your books from us. ---- Retrieving values from other implicit objects is done in a similar way -to the example shown in this section. link:#BNATK[Table 15-4] lists the +to the example shown in this section. xref:jsf-custom/jsf-custom.adoc#BNATK[Table 15-4] lists the implicit objects to which a value attribute can refer. All of the implicit objects, except for the scope objects, are read-only and therefore should not be used as values for a `UIInput` component. @@ -256,7 +256,7 @@ the `FacesRequest` for this request |======================================================================= -[[BNATL]][[binding-a-component-instance-to-a-bean-property]] +[[BNATL]][[_binding_a_component_instance_to_a_bean_property]] === Binding a Component Instance to a Bean Property @@ -308,6 +308,6 @@ would therefore require additional code to access the components from the `FacesContext` instance to change the components' `rendered` properties. -link:#BNAUK[Writing Properties Bound to Component +xref:jsf-develop/jsf-develop.adoc#BNAUK[Writing Properties Bound to Component Instances] explains how to write the bean properties bound to the example components. diff --git a/src/main/antora/modules/web/pages/jsf-custom/jsf-custom014.adoc b/src/main/antora/modules/web/pages/jsf-custom/jsf-custom014.adoc index 056e2df5..90a308b1 100644 --- a/src/main/antora/modules/web/pages/jsf-custom/jsf-custom014.adoc +++ b/src/main/antora/modules/web/pages/jsf-custom/jsf-custom014.adoc @@ -1,8 +1,8 @@ -[[BNATM]][[binding-converters-listeners-and-validators-to-managed-bean-properties]] +[[BNATM]][[_binding_converters_listeners_and_validators_to_managed_bean_properties]] == Binding Converters, Listeners, and Validators to Managed Bean Properties -As described in link:#BNARF[Adding Components to a Page +As described in xref:jsf-page/jsf-page.adoc#BNARF[Adding Components to a Page Using HTML Tag Library Tags], a page author can bind converter, listener, and validator implementations to managed bean properties using the `binding` attributes of the tags that are used to register the @@ -10,7 +10,7 @@ implementations on components. This technique has similar advantages to binding component instances to managed bean properties, as described in -link:#BNATG[Binding Component Values and Instances to +xref:jsf-custom/jsf-custom.adoc#BNATG[Binding Component Values and Instances to Managed Bean Properties]. In particular, binding a converter, listener, or validator implementation to a managed bean property yields the following benefits. @@ -64,7 +64,7 @@ public void setConvertDate(DateTimeConverter convertDate) { } ---- -See link:#BNAUL[Writing Properties Bound to +See xref:jsf-develop/jsf-develop.adoc#BNAUL[Writing Properties Bound to Converters, Listeners, or Validators] for more information on writing managed bean properties for converter, listener, and validator implementations. diff --git a/src/main/antora/modules/web/pages/jsf-develop/jsf-develop.adoc b/src/main/antora/modules/web/pages/jsf-develop/jsf-develop.adoc index e8069910..7a197bb4 100644 --- a/src/main/antora/modules/web/pages/jsf-develop/jsf-develop.adoc +++ b/src/main/antora/modules/web/pages/jsf-develop/jsf-develop.adoc @@ -1,6 +1,6 @@ = Developing with Jakarta Server Faces Technology -[[BNATX]][[developing-with-javaserver-faces-technology]] +[[BNATX]][[_developing_with_javaserver_faces_technology]] This chapter provides an overview of managed beans and explains how to write methods and properties of managed beans that are used by a diff --git a/src/main/antora/modules/web/pages/jsf-develop/jsf-develop001.adoc b/src/main/antora/modules/web/pages/jsf-develop/jsf-develop001.adoc index ddd542b8..4cd57c0d 100644 --- a/src/main/antora/modules/web/pages/jsf-develop/jsf-develop001.adoc +++ b/src/main/antora/modules/web/pages/jsf-develop/jsf-develop001.adoc @@ -1,4 +1,4 @@ -[[BNAQM]][[managed-beans-in-javaserver-faces-technology]] +[[BNAQM]][[_managed_beans_in_javaserver_faces_technology]] == Managed Beans in Jakarta Server Faces Technology @@ -13,8 +13,8 @@ configuring, and using managed beans in an application. a| *Note*: -link:#BNAQZ[Chapter 10, "Using Jakarta Server Faces Technology -in Web Pages"] and link:#GJCUT[Chapter 11, "Using +xref:jsf-page/jsf-page.adoc#BNAQZ[Chapter 10, "Using Jakarta Server Faces Technology +in Web Pages"] and xref:jsf-page-core/jsf-page-core.adoc#GJCUT[Chapter 11, "Using Converters, Listeners, and Validators"] show how to add components to a page and connect them to server-side objects by using component tags and core tags. These chapters also show how to provide additional @@ -26,7 +26,7 @@ event handlers, and validators. |======================================================================= -[[BNAQN]][[creating-a-managed-bean]] +[[BNAQN]][[_creating_a_managed_bean]] === Creating a Managed Bean @@ -69,7 +69,7 @@ basic primitive and numeric types or any Java object type for which the application has access to an appropriate converter. For example, a property can be of type `java.util.Date` if the application has access to a converter that can convert the `Date` type to a `String` and back -again. See link:#BNATY[Writing Bean Properties] for +again. See xref:jsf-develop/jsf-develop.adoc#BNATY[Writing Bean Properties] for information on which types are accepted by which component tags. When a bean property is bound to a component instance, the property's @@ -81,16 +81,16 @@ listener instance, the property must be of the appropriate converter, validator, or listener type. For more information on writing beans and their properties, see -link:#BNATY[Writing Bean Properties]. +xref:jsf-develop/jsf-develop.adoc#BNATY[Writing Bean Properties]. -[[BNAQP]][[using-the-el-to-reference-managed-beans]] +[[BNAQP]][[_using_the_el_to_reference_managed_beans]] === Using the EL to Reference Managed Beans To bind component values and objects to managed bean properties or to reference managed bean methods from component tags, page authors use the Expression Language syntax. As explained in -link:#BNAHQ[Overview of the EL], the following are some of +xref:jsf-el/jsf-el.adoc#BNAHQ[Overview of the EL], the following are some of the features that the EL offers: * Deferred evaluation of expressions @@ -157,8 +157,8 @@ can configure your custom component properties to accept expressions by creating `javax.el.ValueExpression` or `javax.el.MethodExpression` instances for them. -For information on the EL, see link:#GJDDD[Chapter 9, +For information on the EL, see xref:jsf-el/jsf-el.adoc#GJDDD[Chapter 9, "Expression Language"]. For information on referencing managed bean methods from component tags, -see link:#BNATN[Referencing a Managed Bean Method]. +see xref:jsf-page-core/jsf-page-core.adoc#BNATN[Referencing a Managed Bean Method]. diff --git a/src/main/antora/modules/web/pages/jsf-develop/jsf-develop002.adoc b/src/main/antora/modules/web/pages/jsf-develop/jsf-develop002.adoc index c73c6ca5..84b13cd2 100644 --- a/src/main/antora/modules/web/pages/jsf-develop/jsf-develop002.adoc +++ b/src/main/antora/modules/web/pages/jsf-develop/jsf-develop002.adoc @@ -1,9 +1,9 @@ -[[BNATY]][[writing-bean-properties]] +[[BNATY]][[_writing_bean_properties]] == Writing Bean Properties -As explained in link:#BNAQM[Managed Beans in +As explained in xref:jsf-develop/jsf-develop.adoc#BNAQM[Managed Beans in Jakarta Server Faces Technology], a managed bean property can be bound to one of the following items: @@ -23,9 +23,9 @@ property by using its `value` attribute and binds the component's instance to a managed bean property by using its `binding` attribute. Likewise, all the converter, listener, and validator tags use their `binding` attributes to bind their associated implementations to managed -bean properties. See link:#BNATG[Binding Component +bean properties. See xref:jsf-custom/jsf-custom.adoc#BNATG[Binding Component Values and Instances to Managed Bean Properties] and -link:#BNATM[Binding Converters, Listeners, and +xref:jsf-custom/jsf-custom.adoc#BNATM[Binding Converters, Listeners, and Validators to Managed Bean Properties] for more information. To bind a component's value to a managed bean property, the type of the @@ -48,18 +48,18 @@ must accept and return a `DateTimeConverter` instance. The rest of this section explains how to write properties that can be bound to component values, to component instances for the component -objects described in link:#BNARF[Adding Components to a +objects described in xref:jsf-page/jsf-page.adoc#BNARF[Adding Components to a Page Using HTML Tag Library Tags], and to converter, listener, and validator implementations. -[[BNATZ]][[writing-properties-bound-to-component-values]] +[[BNATZ]][[_writing_properties_bound_to_component_values]] === Writing Properties Bound to Component Values To write a managed bean property that is bound to a component's value, you must match the property type to the component's value. -link:#BNAUA[Table 12-1] lists the `javax.faces.component` classes and +xref:jsf-develop/jsf-develop.adoc#BNAUA[Table 12-1] lists the `javax.faces.component` classes and the acceptable types of their values. [[sthref67]][[BNAUA]] @@ -91,7 +91,7 @@ When they bind components to properties by using the `value` attributes of the component tags, page authors need to ensure that the corresponding properties match the types of the components' values. -[[BNAUB]][[uiinput-and-uioutput-properties]] +[[BNAUB]][[_uiinput_and_uioutput_properties]] ==== UIInput and UIOutput Properties @@ -126,11 +126,11 @@ public String getName() { } ---- -As described in link:#BNAST[Using the Standard +As described in xref:jsf-page-core/jsf-page-core.adoc#BNAST[Using the Standard Converters], to convert the value of an input or output component you can either apply a converter or create the bean property bound to the component with the matching type. Here is the example tag, from -link:#BNASV[Using DateTimeConverter], that displays +xref:jsf-page-core/jsf-page-core.adoc#BNASV[Using DateTimeConverter], that displays the date on which items will be shipped. [source,java] @@ -157,7 +157,7 @@ public void setShipDate(Date shipDate) { } ---- -[[BNAUC]][[uidata-properties]] +[[BNAUC]][[_uidata_properties]] ==== UIData Properties @@ -165,8 +165,8 @@ The `UIData` component class is represented by the `h:dataTable` component tag. `UIData` components must be bound to one of the managed bean property -types listed in link:#BNAUA[Table 12-1]. Data components are discussed -in link:#BNARZ[Using Data-Bound Table Components]. Here +types listed in xref:jsf-develop/jsf-develop.adoc#BNAUA[Table 12-1]. Data components are discussed +in xref:jsf-page/jsf-page.adoc#BNARZ[Using Data-Bound Table Components]. Here is part of the start tag of `dataTable` from that section: [source,xml] @@ -247,7 +247,7 @@ For UIData and UIRepeat, the supported types are: * `java.util.Map` * `java.lang.Object` (becomes ScalarDataModel) -[[BNAUD]][[uiselectboolean-properties]] +[[BNAUD]][[_uiselectboolean_properties]] ==== UISelectBoolean Properties @@ -257,7 +257,7 @@ tag `h:selectBooleanCheckbox`. Managed bean properties that hold a `UISelectBoolean` component's data must be of `boolean` or `Boolean` type. The example `selectBooleanCheckbox` tag from the section -link:#BNASE[Displaying Components for Selecting One +xref:jsf-page/jsf-page.adoc#BNASE[Displaying Components for Selecting One Value] binds a component to a property. The following example shows a tag that binds a component value to a `boolean` property: @@ -284,7 +284,7 @@ public boolean getReceiveEmails() { } ---- -[[BNAUE]][[uiselectmany-properties]] +[[BNAUE]][[_uiselectmany_properties]] ==== UISelectMany Properties @@ -298,7 +298,7 @@ of type `List` or `array`. This bean property represents the set of currently selected items from the list of available items. The following example of the `selectManyCheckbox` tag comes from -link:#BNASI[Displaying Components for Selecting Multiple +xref:jsf-page/jsf-page.adoc#BNASI[Displaying Components for Selecting Multiple Values]: [source,java] @@ -327,11 +327,11 @@ public String[] getNewsletters() { The `UISelectItem` and `UISelectItems` components are used to represent all the values in a `UISelectMany` component. See -link:#BNAUH[UISelectItems +xref:jsf-develop/jsf-develop.adoc#BNAUH[UISelectItems Properties] for information on writing the bean properties for the `UISelectItem` and `UISelectItems` components. -[[BNAUF]][[uiselectone-properties]] +[[BNAUF]][[_uiselectone_properties]] ==== UISelectOne Properties @@ -345,7 +345,7 @@ single selected item from a set of items. This item can be any of the primitive types and anything else for which you can apply a converter. Here is an example of the `h:selectOneMenu` tag from -link:#BNASH[Displaying a Menu Using the h:selectOneMenu +xref:jsf-page/jsf-page.adoc#BNASH[Displaying a Menu Using the h:selectOneMenu Tag]: [source,java] @@ -381,15 +381,15 @@ the list of items in the `UISelectOne` component. The `UISelectItem` and `UISelectItems` components are used to represent all the values in a `UISelectOne` component. This is explained in -link:#BNASH[Displaying a Menu Using the h:selectOneMenu +xref:jsf-page/jsf-page.adoc#BNASH[Displaying a Menu Using the h:selectOneMenu Tag]. For information on how to write the managed bean properties for the `UISelectItem` and `UISelectItems` components, see -link:#BNAUH[UISelectItems +xref:jsf-develop/jsf-develop.adoc#BNAUH[UISelectItems Properties]. -[[BNAUG]][[uiselectitem-properties]] +[[BNAUG]][[_uiselectitem_properties]] ==== UISelectItem Properties @@ -400,7 +400,7 @@ component must be bound to a managed bean property of type `Object` representing the value along with two `Strings` representing the label and the description of the `UISelectItem` object. -The example `selectOneMenu` tag from link:#BNAUF[UISelectOne Properties] +The example `selectOneMenu` tag from xref:jsf-develop/jsf-develop.adoc#BNAUF[UISelectOne Properties] contains `selectItem` tags that set the values of the list of items in the page. Here is an example of a bean property that can set the values for this list in the bean: @@ -417,7 +417,7 @@ void setItemOne(SelectItem item) { } ---- -[[BNAUH]][[uiselectitems-properties]] +[[BNAUH]][[_uiselectitems_properties]] ==== UISelectItems Properties @@ -460,7 +460,7 @@ value of the item, whereas the second argument is a `String` representing the label that appears in the `UISelectMany` component on the page. -[[BNAUK]][[writing-properties-bound-to-component-instances]]] +[[BNAUK]][[_writing_properties_bound_to_component_instances]]] === Writing Properties Bound to Component Instances @@ -517,19 +517,19 @@ public void setSpecialOffer(UISelectBoolean specialOffer) { ---- For more general information on component binding, see -link:#BNAQM[Managed Beans in Jakarta Server Faces +xref:jsf-develop/jsf-develop.adoc#BNAQM[Managed Beans in Jakarta Server Faces Technology]. For information on how to reference a managed bean method that performs navigation when a button is clicked, see -link:#BNATP[Referencing a Method That Performs +xref:jsf-page-core/jsf-page-core.adoc#BNATP[Referencing a Method That Performs Navigation]. For more information on writing managed bean methods that handle -navigation, see link:#BNAVC[Writing a Method to Handle +navigation, see xref:jsf-develop/jsf-develop.adoc#BNAVC[Writing a Method to Handle Navigation]. -[[BNAUL]][[writing-properties-bound-to-converters-listeners-or-validators]] +[[BNAUL]][[_writing_properties_bound_to_converters_listeners_or_validators]] === Writing Properties Bound to Converters, Listeners, or Validators diff --git a/src/main/antora/modules/web/pages/jsf-develop/jsf-develop003.adoc b/src/main/antora/modules/web/pages/jsf-develop/jsf-develop003.adoc index ee64be2c..e40933c7 100644 --- a/src/main/antora/modules/web/pages/jsf-develop/jsf-develop003.adoc +++ b/src/main/antora/modules/web/pages/jsf-develop/jsf-develop003.adoc @@ -1,4 +1,4 @@ -[[BNAVB]][[writing-managed-bean-methods]] +[[BNAVB]][[_writing_managed_bean_methods]] == Writing Managed Bean Methods @@ -10,7 +10,7 @@ functions for components on the page. These functions include * Performing validation on the component's value * Handling value-change events -[[sthref68]][[why-use-managed-beans]] +[[sthref68]][[_why_use_managed_beans]] === Why Use Managed Beans @@ -30,7 +30,7 @@ perform the validation associated with the component. The following sections explain how to write various types of managed bean methods. -[[BNAVC]][[writing-a-method-to-handle-navigation]] +[[BNAVC]][[_writing_a_method_to_handle_navigation]] === Writing a Method to Handle Navigation @@ -108,13 +108,13 @@ public Object submit(){ } ---- -The section link:#BNATP[Referencing a Method That +The section xref:jsf-page-core/jsf-page-core.adoc#BNATP[Referencing a Method That Performs Navigation] explains how a component tag references this -method. The section link:#BNAUK[Writing Properties +method. The section xref:jsf-develop/jsf-develop.adoc#BNAUK[Writing Properties Bound to Component Instances] explains how to write the bean properties to which the components are bound. -[[BNAVD]][[writing-a-method-to-handle-an-action-event]] +[[BNAVD]][[_writing_a_method_to_handle_an_action_event]] === Writing a Method to Handle an Action Event @@ -144,10 +144,10 @@ The method matches the code against a `HashMap` object that contains the book codes and corresponding book ID values. Finally, the method sets the book ID by using the selected value from the `HashMap` object. -link:#BNATQ[Referencing a Method That Handles an +xref:jsf-page-core/jsf-page-core.adoc#BNATQ[Referencing a Method That Handles an Action Event] explains how a component tag references this method. -[[BNAVE]][[writing-a-method-to-perform-validation]] +[[BNAVE]][[_writing_a_method_to_perform_validation]] === Writing a Method to Perform Validation @@ -163,7 +163,7 @@ components or values of components that extend `UIInput` can be validated. Here is an example of a managed bean method that validates user input, -from link:#GJCXV[The guessnumber-cdi CDI +from xref:#GJCXV[The guessnumber-cdi CDI Example]: [source,java] @@ -200,11 +200,11 @@ allowable range, the method again sets the `valid` property of the `UIInput` component to `false`, queues a different message on the `FacesContext` instance, and returns. -See link:#BNATR[Referencing a Method That Performs +See xref:jsf-page-core/jsf-page-core.adoc#BNATR[Referencing a Method That Performs Validation] for information on how a component tag references this method. -[[BNAVF]][[writing-a-method-to-handle-a-value-change-event]] +[[BNAVF]][[_writing_a_method_to_handle_a_value_change_event]] === Writing a Method to Handle a Value-Change Event @@ -215,7 +215,7 @@ This section explains how to write a managed bean method to replace the `javax.faces.event.ValueChangeListener` implementation. The following example tag comes from -link:#BNATA[Registering a Value-Change Listener on a +xref:jsf-page-core/jsf-page-core.adoc#BNATA[Registering a Value-Change Listener on a Component], where the `h:inputText` tag with the `id` of `name` has a `ValueChangeListener` instance registered on it. This `ValueChangeListener` instance handles the event of entering a value in @@ -258,7 +258,7 @@ public void processValueChange(ValueChangeEvent event) To make this method handle the `ValueChangeEvent` generated by an input component, reference this method from the component tag's `valueChangeListener` attribute. See -link:#BNATS[Referencing a Method That Handles a +xref:jsf-page-core/jsf-page-core.adoc#BNATS[Referencing a Method That Handles a Value-Change Event] for more information. diff --git a/src/main/antora/modules/web/pages/jsf-el/jsf-el.adoc b/src/main/antora/modules/web/pages/jsf-el/jsf-el.adoc index 449ab928..91cb9176 100644 --- a/src/main/antora/modules/web/pages/jsf-el/jsf-el.adoc +++ b/src/main/antora/modules/web/pages/jsf-el/jsf-el.adoc @@ -1,6 +1,6 @@ = Expression Language -[[GJDDD]][[expression-language]] +[[GJDDD]][[_expression_language]] This chapter introduces the Expression Language (also referred to as the diff --git a/src/main/antora/modules/web/pages/jsf-el/jsf-el001.adoc b/src/main/antora/modules/web/pages/jsf-el/jsf-el001.adoc index 78b5f673..37a3b970 100644 --- a/src/main/antora/modules/web/pages/jsf-el/jsf-el001.adoc +++ b/src/main/antora/modules/web/pages/jsf-el/jsf-el001.adoc @@ -1,4 +1,4 @@ -[[BNAHQ]][[overview-of-the-el]] +[[BNAHQ]][[_overview_of_the_el]] == Overview of the EL @@ -15,7 +15,7 @@ compares 0 with the number of items in the session-scoped bean named ---- -See link:#BNAQP[Using the EL to Reference Managed +See xref:jsf-develop/jsf-develop.adoc#BNAQP[Using the EL to Reference Managed Beans] for more information on how to use the EL in Jakarta Server Faces applications. diff --git a/src/main/antora/modules/web/pages/jsf-el/jsf-el002.adoc b/src/main/antora/modules/web/pages/jsf-el/jsf-el002.adoc index c53c7a55..4253749b 100644 --- a/src/main/antora/modules/web/pages/jsf-el/jsf-el002.adoc +++ b/src/main/antora/modules/web/pages/jsf-el/jsf-el002.adoc @@ -1,4 +1,4 @@ -[[BNAHR]][[immediate-and-deferred-evaluation-syntax]] +[[BNAHR]][[_immediate_and_deferred_evaluation_syntax]] == Immediate and Deferred Evaluation Syntax @@ -22,7 +22,7 @@ lifecycle. Other technologies using the EL might have different reasons for using deferred expressions. -[[BNAHS]][[immediate-evaluation]] +[[BNAHS]][[_immediate_evaluation]] === Immediate Evaluation @@ -43,7 +43,7 @@ The Jakarta Server Faces implementation evaluates the expression `${catalog.bookQuantity}`, converts it, and passes the returned value to the tag handler. The value is updated on the page. -[[BNAHT]][[deferred-evaluation]] +[[BNAHT]][[_deferred_evaluation]] === Deferred Evaluation diff --git a/src/main/antora/modules/web/pages/jsf-el/jsf-el003.adoc b/src/main/antora/modules/web/pages/jsf-el/jsf-el003.adoc index 1cf0177c..cfef5a7f 100644 --- a/src/main/antora/modules/web/pages/jsf-el/jsf-el003.adoc +++ b/src/main/antora/modules/web/pages/jsf-el/jsf-el003.adoc @@ -1,4 +1,4 @@ -[[BNAHU]][[value-and-method-expressions]] +[[BNAHU]][[_value_and_method_expressions]] == Value and Method Expressions @@ -6,7 +6,7 @@ The EL defines two kinds of expressions: value expressions and method expressions. Value expressions can be evaluated to yield a value, and method expressions are used to reference a method. -[[BNAHV]][[value-expressions]] +[[BNAHV]][[_value_expressions]] === Value Expressions @@ -41,7 +41,7 @@ is evaluated immediately during an initial request for the page. During a postback request, this expression can be used to set the value of the `name` property with user input. -[[BNAHW]][[referencing-objects]] +[[BNAHW]][[_referencing_objects]] ==== Referencing Objects @@ -86,7 +86,7 @@ you can compare `suit.hearts` to the instance: ${mySuit == suit.hearts} ---- -[[BNAHX]][[referencing-object-properties-or-collection-elements]] +[[BNAHX]][[_referencing_object_properties_or_collection_elements]] ==== Referencing Object Properties or Collection Elements @@ -145,7 +145,7 @@ ${customer.orders["socks"]} ${customer.orders.socks} ---- -[[sthref38]][[referencing-literals]] +[[sthref38]][[_referencing_literals]] ==== Referencing Literals @@ -164,7 +164,7 @@ Here are some examples: * `${true}` * `${57}` -[[GJHBZ]][[parameterized-method-calls]] +[[GJHBZ]][[_parameterized_method_calls]] ==== Parameterized Method Calls @@ -217,7 +217,7 @@ in which a parameter is passed: In the preceding example, you are passing the string `'SOMESTOCK'` (a stock symbol) as a parameter to the `buy` method. -[[BNAHY]][[where-value-expressions-can-be-used]] +[[BNAHY]][[_where_value_expressions_can_be_used]] ==== Where Value Expressions Can Be Used @@ -301,7 +301,7 @@ of an attribute of type `float` will result in the following conversion: Float.valueOf("1.2E4").floatValue() ---- -[[BNAHZ]][[method-expressions]] +[[BNAHZ]][[_method_expressions]] === Method Expressions @@ -366,7 +366,7 @@ this method expression is invoked, the method returns the `String` literal, which is then converted to the expected return type, as defined in the tag's tag library descriptor. -[[BEIHCBAH]][[lambda-expressions]] +[[BEIHCBAH]][[_lambda_expressions]] === Lambda Expressions diff --git a/src/main/antora/modules/web/pages/jsf-el/jsf-el004.adoc b/src/main/antora/modules/web/pages/jsf-el/jsf-el004.adoc index a463634a..d8670d67 100644 --- a/src/main/antora/modules/web/pages/jsf-el/jsf-el004.adoc +++ b/src/main/antora/modules/web/pages/jsf-el/jsf-el004.adoc @@ -1,4 +1,4 @@ -[[CIHGABHD]][[operations-on-collection-objects]] +[[CIHGABHD]][[_operations_on_collection_objects]] == Operations on Collection Objects diff --git a/src/main/antora/modules/web/pages/jsf-el/jsf-el005.adoc b/src/main/antora/modules/web/pages/jsf-el/jsf-el005.adoc index 91fb3174..45e634e5 100644 --- a/src/main/antora/modules/web/pages/jsf-el/jsf-el005.adoc +++ b/src/main/antora/modules/web/pages/jsf-el/jsf-el005.adoc @@ -3,7 +3,7 @@ == Operators In addition to the `.` and `[]` operators discussed in -link:#BNAHU[Value and Method Expressions], the EL provides +xref:jsf-el/jsf-el.adoc#BNAHU[Value and Method Expressions], the EL provides the following operators, which can be used in rvalue expressions only. * Arithmetic: `+`, `-` (binary), `*`, `/` and `div`, `%` and `mod`, `-` diff --git a/src/main/antora/modules/web/pages/jsf-el/jsf-el006.adoc b/src/main/antora/modules/web/pages/jsf-el/jsf-el006.adoc index bc68282e..2a017934 100644 --- a/src/main/antora/modules/web/pages/jsf-el/jsf-el006.adoc +++ b/src/main/antora/modules/web/pages/jsf-el/jsf-el006.adoc @@ -1,4 +1,4 @@ -[[BNAIL]][[reserved-words]] +[[BNAIL]][[_reserved_words]] == Reserved Words diff --git a/src/main/antora/modules/web/pages/jsf-el/jsf-el007.adoc b/src/main/antora/modules/web/pages/jsf-el/jsf-el007.adoc index 1b34624d..3abfa51c 100644 --- a/src/main/antora/modules/web/pages/jsf-el/jsf-el007.adoc +++ b/src/main/antora/modules/web/pages/jsf-el/jsf-el007.adoc @@ -1,8 +1,8 @@ -[[BNAIM]][[examples-of-el-expressions]] +[[BNAIM]][[_examples_of_el_expressions]] == Examples of EL Expressions -link:#BNAIN[Table 9-1] contains example EL expressions and the result of +xref:jsf-el/jsf-el.adoc#BNAIN[Table 9-1] contains example EL expressions and the result of evaluating them. [[sthref39]][[BNAIN]] diff --git a/src/main/antora/modules/web/pages/jsf-el/jsf-el008.adoc b/src/main/antora/modules/web/pages/jsf-el/jsf-el008.adoc index 26f86664..e99f73aa 100644 --- a/src/main/antora/modules/web/pages/jsf-el/jsf-el008.adoc +++ b/src/main/antora/modules/web/pages/jsf-el/jsf-el008.adoc @@ -1,4 +1,4 @@ -[[CIHGBBHA]][[further-information-about-the-expression-language]] +[[CIHGBBHA]][[_further_information_about_the_expression_language]] == Further Information about the Expression Language diff --git a/src/main/antora/modules/web/pages/jsf-facelets/jsf-facelets.adoc b/src/main/antora/modules/web/pages/jsf-facelets/jsf-facelets.adoc index 07997e00..79ae0e0f 100644 --- a/src/main/antora/modules/web/pages/jsf-facelets/jsf-facelets.adoc +++ b/src/main/antora/modules/web/pages/jsf-facelets/jsf-facelets.adoc @@ -1,6 +1,6 @@ = Introduction to Facelets -[[GIEPX]][[introduction-to-facelets]] +[[GIEPX]][[_introduction_to_facelets]] The term Facelets refers to the view declaration language for Jakarta Server diff --git a/src/main/antora/modules/web/pages/jsf-facelets/jsf-facelets001.adoc b/src/main/antora/modules/web/pages/jsf-facelets/jsf-facelets001.adoc index 62a09119..c8cbf6c9 100644 --- a/src/main/antora/modules/web/pages/jsf-facelets/jsf-facelets001.adoc +++ b/src/main/antora/modules/web/pages/jsf-facelets/jsf-facelets001.adoc @@ -1,4 +1,4 @@ -[[GIJTU]][[what-is-facelets]] +[[GIJTU]][[_what_is_facelets]] == What Is Facelets? @@ -33,7 +33,7 @@ convention, web pages built with XHTML have an `.xhtml` extension. Jakarta Server Faces technology supports various tag libraries to add components to a web page. To support the Jakarta Server Faces tag library -mechanism, Facelets uses XML namespace declarations. link:#GJBOX[Table +mechanism, Facelets uses XML namespace declarations. xref:jsf-facelets/jsf-facelets.adoc#GJBOX[Table 8-1] lists the tag libraries supported by Facelets. [[sthref29]][[GJBOX]] @@ -100,11 +100,11 @@ HTML5-friendly markup Facelets provides two namespaces to support HTML5-friendly markup. For -details, see link:#BABGECCJ[HTML5-Friendly Markup]. +details, see xref:jsf-facelets/jsf-facelets.adoc#BABGECCJ[HTML5-Friendly Markup]. Facelets supports tags for composite components, for which you can declare custom prefixes. For more information on composite components, -see link:#GIQZR[Composite Components]. +see xref:jsf-facelets/jsf-facelets.adoc#GIQZR[Composite Components]. The namespace prefixes shown in the table are conventional, not mandatory. As is always the case when you declare an XML namespace, you @@ -128,4 +128,4 @@ syntax, Facelets uses EL expressions to reference properties and methods of managed beans. EL expressions can be used to bind component objects or values to methods or properties of managed beans that are used as backing beans. For more information on using EL expressions, see -link:#BNAQP[Using the EL to Reference Managed Beans]. +xref:jsf-develop/jsf-develop.adoc#BNAQP[Using the EL to Reference Managed Beans]. diff --git a/src/main/antora/modules/web/pages/jsf-facelets/jsf-facelets002.adoc b/src/main/antora/modules/web/pages/jsf-facelets/jsf-facelets002.adoc index 5f98bf60..7226c644 100644 --- a/src/main/antora/modules/web/pages/jsf-facelets/jsf-facelets002.adoc +++ b/src/main/antora/modules/web/pages/jsf-facelets/jsf-facelets002.adoc @@ -1,10 +1,10 @@ -[[GIPRR]][[the-lifecycle-of-a-facelets-application]] +[[GIPRR]][[_the_lifecycle_of_a_facelets_application]] == The Lifecycle of a Facelets Application The Jakarta Server Faces specification defines the lifecycle of a Jakarta Server Faces application. For more information on this lifecycle, see -link:#BNAQQ[The Lifecycle of a Jakarta Server Faces +xref:jsf-intro/jsf-intro.adoc#BNAQQ[The Lifecycle of a Jakarta Server Faces Application]. The following steps describe that process as applied to a Facelets-based application. @@ -29,7 +29,7 @@ triggered. 7. If the same view is requested, the stored view is rendered once again. 8. If a new view is requested, then the process described in Step -link:#BABGCBAJ[2] is continued. +xref:jsf-facelets/jsf-facelets.adoc#BABGCBAJ[2] is continued. 9. The new view is then rendered back as a response to the client. diff --git a/src/main/antora/modules/web/pages/jsf-facelets/jsf-facelets003.adoc b/src/main/antora/modules/web/pages/jsf-facelets/jsf-facelets003.adoc index 28e7f16b..7959af59 100644 --- a/src/main/antora/modules/web/pages/jsf-facelets/jsf-facelets003.adoc +++ b/src/main/antora/modules/web/pages/jsf-facelets/jsf-facelets003.adoc @@ -1,4 +1,4 @@ -[[GIPOB]][[developing-a-simple-facelets-application-the-guessnumber-jsf-example-application]] +[[GIPOB]][[_developing_a_simple_facelets_application_the_guessnumber_jsf_example_application]] == Developing a Simple Facelets Application: The guessnumber-jsf Example Application @@ -11,7 +11,7 @@ Jakarta Server Faces application. The following tasks are usually required: * Mapping the `FacesServlet` instance * Adding managed bean declarations -[[GIQTE]][[creating-a-facelets-application]] +[[GIQTE]][[_creating_a_facelets_application]] === Creating a Facelets Application @@ -24,7 +24,7 @@ correctly or incorrectly. The source code for this application is in the `_tut-install_/examples/web/jsf/guessnumber-jsf/` directory. -[[GIQQZ]][[developing-a-managed-bean]] +[[GIQQZ]][[_developing_a_managed_bean]] ==== Developing a Managed Bean @@ -102,7 +102,7 @@ accessible through the EL. The `@SessionScoped` annotation registers the bean scope as `session` to enable you to make multiple guesses as you run the application. -[[GJZPV]][[creating-facelets-views]] +[[GJZPV]][[_creating_facelets_views]] ==== Creating Facelets Views @@ -187,7 +187,7 @@ range by the Jakarta Server Faces standard validator tag The image file, `wave.med.gif`, is added to the page as a resource, as is the style sheet. For more details about the resources facility, see -link:#GIRGM[Web Resources]. +xref:jsf-facelets/jsf-facelets.adoc#GIRGM[Web Resources]. An `h:commandButton` tag with the ID `submit` starts validation of the input data when a user clicks the button. Using implicit navigation, the @@ -227,7 +227,7 @@ content: This page also uses implicit navigation, setting the `action` attribute for the Back button to send the user to the `greeting.xhtml` page. -[[GJJKC]][[configuring-the-application]] +[[GJJKC]][[_configuring_the_application]] === Configuring the Application @@ -283,19 +283,19 @@ For example, if the project stage is defined as `Development`, debugging information is automatically generated for the user. If not defined by the user, the default project stage is `Production`. -[[GIRGF]][[running-the-guessnumber-jsf-facelets-example]] +[[GIRGF]][[_running_the_guessnumber_jsf_facelets_example]] === Running the guessnumber-jsf Facelets Example You can use either NetBeans IDE or Maven to build, package, deploy, and run the `guessnumber-jsf` example. -[[GJQZL]][[to-build-package-and-deploy-the-guessnumber-jsf-example-using-netbeans-ide]] +[[GJQZL]][[_to_build_package_and_deploy_the_guessnumber_jsf_example_using_netbeans_ide]] ==== To Build, Package, and Deploy the guessnumber-jsf Example Using NetBeans IDE 1. Make sure that GlassFish Server has been started (see -link:#BNADI[Starting and Stopping GlassFish +xref:#BNADI[Starting and Stopping GlassFish Server]). 2. From the File menu, choose Open Project. 3. In the Open Project dialog box, navigate to: @@ -312,12 +312,12 @@ select Build. This option builds the example application and deploys it to your GlassFish Server instance. -[[GJQYU]][[to-build-package-and-deploy-the-guessnumber-jsf-example-using-maven]] +[[GJQYU]][[_to_build_package_and_deploy_the_guessnumber_jsf_example_using_maven]] ==== To Build, Package, and Deploy the guessnumber-jsf Example Using Maven 1. Make sure that GlassFish Server has been started (see -link:#BNADI[Starting and Stopping GlassFish +xref:#BNADI[Starting and Stopping GlassFish Server]). 2. In a terminal window, go to: + @@ -336,7 +336,7 @@ This command builds and packages the application into a WAR file, `guessnumber-jsf.war`, that is located in the `target` directory. It then deploys it to the server. -[[GJQYX]][[to-run-the-guessnumber-jsf-example]] +[[GJQYX]][[_to_run_the_guessnumber_jsf_example]] ==== To Run the guessnumber-jsf Example diff --git a/src/main/antora/modules/web/pages/jsf-facelets/jsf-facelets004.adoc b/src/main/antora/modules/web/pages/jsf-facelets/jsf-facelets004.adoc index 6eed3ee9..9e98d26d 100644 --- a/src/main/antora/modules/web/pages/jsf-facelets/jsf-facelets004.adoc +++ b/src/main/antora/modules/web/pages/jsf-facelets/jsf-facelets004.adoc @@ -1,4 +1,4 @@ -[[GIQXP]][[using-facelets-templates]] +[[GIQXP]][[_using_facelets_templates]] == Using Facelets Templates @@ -10,7 +10,7 @@ templates, you can reuse code and avoid recreating similarly constructed pages. Templating also helps in maintaining a standard look and feel in an application with a large number of pages. -link:#GJBFP[Table 8-2] lists Facelets tags that are used for templating +xref:jsf-facelets/jsf-facelets.adoc#GJBFP[Table 8-2] lists Facelets tags that are used for templating and their respective functionality. [[sthref30]][[GJBFP]] diff --git a/src/main/antora/modules/web/pages/jsf-facelets/jsf-facelets005.adoc b/src/main/antora/modules/web/pages/jsf-facelets/jsf-facelets005.adoc index 95eef4c7..ee9ed7f3 100644 --- a/src/main/antora/modules/web/pages/jsf-facelets/jsf-facelets005.adoc +++ b/src/main/antora/modules/web/pages/jsf-facelets/jsf-facelets005.adoc @@ -1,4 +1,4 @@ -[[GIQZR]][[composite-components]] +[[GIQZR]][[_composite_components]] == Composite Components @@ -22,7 +22,7 @@ resources facility, the composite component can be stored in a library that is available to the application from the defined resources location. -link:#GJCWC[Table 8-3] lists the most commonly used composite tags and +xref:jsf-facelets/jsf-facelets.adoc#GJCWC[Table 8-3] lists the most commonly used composite tags and their functions. [[sthref31]][[GJCWC]] @@ -106,7 +106,7 @@ The preceding example content is stored as a file named `email.xhtml` in a folder named `resources/emcomp`, under the application web root directory. This directory is considered a library by Jakarta Server Faces, and a component can be accessed from such a library. For more -information on resources, see link:#GIRGM[Web +information on resources, see xref:jsf-facelets/jsf-facelets.adoc#GIRGM[Web Resources]. The web page that uses this composite component is generally called a @@ -146,5 +146,5 @@ accessed with the following URL: http://localhost:8080/application-name/emuserpage.xhtml ---- -See link:#GKHXA[Chapter 14, "Composite Components: +See xref:jsf-advanced-cc/jsf-advanced-cc.adoc#GKHXA[Chapter 14, "Composite Components: Advanced Topics and an Example,"] for more information and an example. diff --git a/src/main/antora/modules/web/pages/jsf-facelets/jsf-facelets006.adoc b/src/main/antora/modules/web/pages/jsf-facelets/jsf-facelets006.adoc index 4b384269..f17bc940 100644 --- a/src/main/antora/modules/web/pages/jsf-facelets/jsf-facelets006.adoc +++ b/src/main/antora/modules/web/pages/jsf-facelets/jsf-facelets006.adoc @@ -1,4 +1,4 @@ -[[GIRGM]][[web-resources]] +[[GIRGM]][[_web_resources]] == Web Resources diff --git a/src/main/antora/modules/web/pages/jsf-facelets/jsf-facelets007.adoc b/src/main/antora/modules/web/pages/jsf-facelets/jsf-facelets007.adoc index fde81f4d..98deb1b2 100644 --- a/src/main/antora/modules/web/pages/jsf-facelets/jsf-facelets007.adoc +++ b/src/main/antora/modules/web/pages/jsf-facelets/jsf-facelets007.adoc @@ -1,4 +1,4 @@ -[[BABHGBJI]][[relocatable-resources]] +[[BABHGBJI]][[_relocatable_resources]] == Relocatable Resources @@ -26,7 +26,7 @@ similar way. Relocatable resources are essential for composite components that use stylesheets and can also be useful for composite components that use -JavaScript. See link:#GKHVN[The +JavaScript. See xref:jsf-advanced-cc/jsf-advanced-cc.adoc#GKHVN[The compositecomponentexample Example Application] for an example. diff --git a/src/main/antora/modules/web/pages/jsf-facelets/jsf-facelets008.adoc b/src/main/antora/modules/web/pages/jsf-facelets/jsf-facelets008.adoc index a3a7fc4c..2c1f5d7c 100644 --- a/src/main/antora/modules/web/pages/jsf-facelets/jsf-facelets008.adoc +++ b/src/main/antora/modules/web/pages/jsf-facelets/jsf-facelets008.adoc @@ -1,4 +1,4 @@ -[[BABHAHDF]][[resource-library-contracts]] +[[BABHAHDF]][[_resource_library_contracts]] == Resource Library Contracts @@ -70,12 +70,12 @@ You can specify the contract usage within an application's You need to use this element only if your application uses more than one contract, however. -[[sthref32]][[the-hello1-rlc-example-application]] +[[sthref32]][[_the_hello1_rlc_example_application]] === The hello1-rlc Example Application The `hello1-rlc` example modifies the simple `hello1` example from -link:#BNADX[A Web Module That Uses Jakarta Server Faces +xref:webapp/webapp.adoc#BNADX[A Web Module That Uses Jakarta Server Faces Technology: The hello1 Example] to use two resource library contracts. Each of the two pages in the application uses a different contract. @@ -86,7 +86,7 @@ annotations with `@Model`). The source code for this application is in the `_tut-install_/examples/web/jsf/hello1-rlc/` directory. -[[BABGEDEB]][[configuring-the-hello1-rlc-example]] +[[BABGEDEB]][[_configuring_the_hello1_rlc_example]] ==== Configuring the hello1-rlc Example @@ -143,7 +143,7 @@ Because it is not located under `src/main/webapp/reply`, this Facelets page uses the `hello` contract, whereas `src/main/webapp/reply/response.xhtml` uses the `reply` contract. -[[BABDHCFG]][[the-facelets-pages-for-the-hello1-rlc-example]] +[[BABDHCFG]][[_the_facelets_pages_for_the_hello1_rlc_example]] ==== The Facelets Pages for the hello1-rlc Example @@ -163,12 +163,12 @@ specifies. The `default.css` stylesheets in the two contracts differ in only one respect: the background color specified for the `body` element. -[[BABBGFFF]][[to-build-package-and-deploy-the-hello1-rlc-example-using-netbeans-ide]] +[[BABBGFFF]][[_to_build_package_and_deploy_the_hello1_rlc_example_using_netbeans_ide]] ==== To Build, Package, and Deploy the hello1-rlc Example Using NetBeans IDE 1. Make sure that GlassFish Server has been started (see -link:#BNADI[Starting and Stopping GlassFish +xref:#BNADI[Starting and Stopping GlassFish Server]). 2. From the File menu, choose Open Project. 3. In the Open Project dialog box, navigate to: @@ -185,12 +185,12 @@ Build. This option builds the example application and deploys it to your GlassFish Server instance. -[[BABJAGFB]][[to-build-package-and-deploy-the-hello1-rlc-example-using-maven]] +[[BABJAGFB]][[_to_build_package_and_deploy_the_hello1_rlc_example_using_maven]] ==== To Build, Package, and Deploy the hello1-rlc Example Using Maven 1. Make sure that GlassFish Server has been started (see -link:#BNADI[Starting and Stopping GlassFish +xref:#BNADI[Starting and Stopping GlassFish Server]). 2. In a terminal window, go to: + @@ -209,7 +209,7 @@ This command builds and packages the application into a WAR file, `hello1-rlc.war`, that is located in the `target` directory. It then deploys it to your GlassFish Server instance. -[[BABFCHEB]][[to-run-the-hello1-rlc-example]] +[[BABFCHEB]][[_to_run_the_hello1_rlc_example]] ==== To Run the hello1-rlc Example diff --git a/src/main/antora/modules/web/pages/jsf-facelets/jsf-facelets009.adoc b/src/main/antora/modules/web/pages/jsf-facelets/jsf-facelets009.adoc index cc380973..4029ed0d 100644 --- a/src/main/antora/modules/web/pages/jsf-facelets/jsf-facelets009.adoc +++ b/src/main/antora/modules/web/pages/jsf-facelets/jsf-facelets009.adoc @@ -1,4 +1,4 @@ -[[BABGECCJ]][[html5-friendly-markup]] +[[BABGECCJ]][[_html5_friendly_markup]] == HTML5-Friendly Markup @@ -6,7 +6,7 @@ When you want to produce user interface features for which HTML does not have its own elements, you can create a custom Jakarta Server Faces component and insert it in your Facelets page. This mechanism can cause a simple element to create complex web code. However, creating such a -component is a significant task (see link:#BNAVG[Chapter +component is a significant task (see xref:jsf-custom/jsf-custom.adoc#BNAVG[Chapter 15, "Creating Custom UI Components and Other Custom Objects"]). HTML5 offers new elements and attributes that can make it unnecessary to @@ -26,7 +26,7 @@ rather than having to pass this control off to component authors. You can mix and match Jakarta Server Faces and HTML5 components and elements as you see fit. -[[sthref33]][[using-pass-through-elements]] +[[sthref33]][[_using_pass_through_elements]] === Using Pass-Through Elements @@ -52,7 +52,7 @@ input tag's attributes are treated as part of the Facelets page. This means that, for example, you can use EL expressions to retrieve managed bean properties. -link:#BABJADGH[Table 8-4] shows how pass-through elements are rendered +xref:jsf-facelets/jsf-facelets.adoc#BABJADGH[Table 8-4] shows how pass-through elements are rendered as Facelets tags. The server faces implementation uses the element name and the identifying attribute to determine the corresponding Facelets tag that will be used in the server-side processing. The browser, however, @@ -104,7 +104,7 @@ interprets the markup that the page author has written. |======================================================= -[[sthref35]][[using-pass-through-attributes]] +[[sthref35]][[_using_pass_through_attributes]] === Using Pass-Through Attributes @@ -189,7 +189,7 @@ public Bean() { } ---- -[[BABGGIAA]][[the-reservation-example-application]] +[[BABGGIAA]][[_the_reservation_example_application]] === The reservation Example Application @@ -202,7 +202,7 @@ The pages use both pass-through attributes and pass-through elements. The source code for this application is in the `_tut-install_/examples/web/jsf/reservation/` directory. -[[BABGCAHH]][[the-facelets-pages-for-the-reservation-application]] +[[BABGCAHH]][[_the_facelets_pages_for_the_reservation_application]] ==== The Facelets Pages for the reservation Application @@ -233,7 +233,7 @@ namespaces: Next, an empty `h:head` tag followed by an `h:outputStylesheet` tag within the `h:body` tag illustrates the use of a relocatable resource -(as described in link:#BABHGBJI[Relocatable +(as described in xref:jsf-facelets/jsf-facelets.adoc#BABHGBJI[Relocatable Resources]): [source,xml] @@ -291,7 +291,7 @@ to the browser uninterpreted by the Jakarta Server Faces input component: The output of the `calculateTotal` method that is specified as the listener for the Ajax event is rendered in the output element whose `id` -and `name` value is `total`. See link:#GKIOW[Chapter 13, +and `name` value is `total`. See xref:jsf-ajax/jsf-ajax.adoc#GKIOW[Chapter 13, "Using Ajax with Jakarta Server Faces Technology"], for more information. The second Facelets page, `confirmation.xhtml`, uses a pass-through @@ -299,7 +299,7 @@ The second Facelets page, `confirmation.xhtml`, uses a pass-through a Facelets `h:commandButton` tag to allow the user to return to the `reservation.xhtml` page. -[[BABHFCCG]][[the-managed-bean-for-the-reservation-application]] +[[BABHFCCG]][[_the_managed_bean_for_the_reservation_application]] ==== The Managed Bean for the reservation Application @@ -309,12 +309,12 @@ Facelets pages. It also contains two methods, `calculateTotal` and `clear`, that act as listeners for Ajax events on the `reservation.xhtml` page. -[[BABIHHGC]][[to-build-package-and-deploy-the-reservation-example-using-netbeans-ide]] +[[BABIHHGC]][[_to_build_package_and_deploy_the_reservation_example_using_netbeans_ide]] ==== To Build, Package, and Deploy the reservation Example Using NetBeans IDE 1. Make sure that GlassFish Server has been started (see -link:#BNADI[Starting and Stopping GlassFish +xref:#BNADI[Starting and Stopping GlassFish Server]). 2. From the File menu, choose Open Project. 3. In the Open Project dialog box, navigate to: @@ -331,12 +331,12 @@ select Build. This option builds the example application and deploys it to your GlassFish Server instance. -[[sthref36]][[to-build-package-and-deploy-the-reservation-example-using-maven]] +[[sthref36]][[_to_build_package_and_deploy_the_reservation_example_using_maven]] ==== To Build, Package, and Deploy the reservation Example Using Maven 1. Make sure that GlassFish Server has been started (see -link:#BNADI[Starting and Stopping GlassFish +xref:#BNADI[Starting and Stopping GlassFish Server]). 2. In a terminal window, go to: + @@ -355,7 +355,7 @@ This command builds and packages the application into a WAR file, `reservation.war`, that is located in the `target` directory. It then deploys the WAR file to your GlassFish Server instance. -[[sthref37]][[to-run-the-reservation-example]] +[[sthref37]][[_to_run_the_reservation_example]] ==== To Run the reservation Example diff --git a/src/main/antora/modules/web/pages/jsf-intro/jsf-intro.adoc b/src/main/antora/modules/web/pages/jsf-intro/jsf-intro.adoc index d11735c8..4f58baa1 100644 --- a/src/main/antora/modules/web/pages/jsf-intro/jsf-intro.adoc +++ b/src/main/antora/modules/web/pages/jsf-intro/jsf-intro.adoc @@ -1,6 +1,6 @@ = Jakarta Server Faces Technology -[[BNAPH]][[javaserver-faces-technology]] +[[BNAPH]][[_javaserver_faces_technology]] Jakarta Server Faces technology is a server-side component framework for building Java technology–based web applications. diff --git a/src/main/antora/modules/web/pages/jsf-intro/jsf-intro001.adoc b/src/main/antora/modules/web/pages/jsf-intro/jsf-intro001.adoc index 575cd744..b582f1ad 100644 --- a/src/main/antora/modules/web/pages/jsf-intro/jsf-intro001.adoc +++ b/src/main/antora/modules/web/pages/jsf-intro/jsf-intro001.adoc @@ -1,4 +1,4 @@ -[[A1073698]][[introduction-to-javaserver-faces-technology]] +[[A1073698]][[_introduction_to_javaserver_faces_technology]] == Introduction to Jakarta Server Faces Technology diff --git a/src/main/antora/modules/web/pages/jsf-intro/jsf-intro002.adoc b/src/main/antora/modules/web/pages/jsf-intro/jsf-intro002.adoc index b6e21f1a..f63b82c6 100644 --- a/src/main/antora/modules/web/pages/jsf-intro/jsf-intro002.adoc +++ b/src/main/antora/modules/web/pages/jsf-intro/jsf-intro002.adoc @@ -1,4 +1,4 @@ -[[BNAPK]][[what-is-a-javaserver-faces-application]] +[[BNAPK]][[_what_is_a_javaserver_faces_application]] == What Is a Jakarta Server Faces Application? @@ -23,7 +23,7 @@ application developer. * Optionally, a set of custom tags for representing custom objects on the page. -link:#BNAPI[Figure 7-1] shows the interaction between client and server +xref:jsf-intro/jsf-intro.adoc#BNAPI[Figure 7-1] shows the interaction between client and server in a typical Jakarta Server Faces application. In response to a client request, a web page is rendered by the web container that implements Jakarta Server Faces technology. @@ -31,10 +31,7 @@ Jakarta Server Faces technology. [[BNAPI]] .*Figure 7-1 Responding to a Client Request for a Jakarta Server Faces Page* -image:jakartaeett_dt_014.png[ -"Diagram that shows a browser accessing the myfacelet.xhtml page using an -HTTP Request and the server sending the rendered HTML page using an HTTP -Response."] +image::common:jakartaeett_dt_014.png[ "Diagram that shows a browser accessing the myfacelet.xhtml page using an HTTP Request and the server sending the rendered HTML page using an HTTP Response."] The web page, `myfacelet.xhtml`, is built using Jakarta Server Faces component tags. Component tags are used to add components to the `view` diff --git a/src/main/antora/modules/web/pages/jsf-intro/jsf-intro003.adoc b/src/main/antora/modules/web/pages/jsf-intro/jsf-intro003.adoc index 14847ca2..1dc50c02 100644 --- a/src/main/antora/modules/web/pages/jsf-intro/jsf-intro003.adoc +++ b/src/main/antora/modules/web/pages/jsf-intro/jsf-intro003.adoc @@ -1,4 +1,4 @@ -[[BNAPJ]][[javaserver-faces-technology-benefits]] +[[BNAPJ]][[_javaserver_faces_technology_benefits]] == Jakarta Server Faces Technology Benefits @@ -22,15 +22,12 @@ Another important goal of Jakarta Server Faces technology is to leverage familiar component and web-tier concepts without limiting you to a particular scripting technology or markup language. Jakarta Server Faces technology APIs are layered directly on top of the Servlet API, as shown -in link:#GJEPW[Figure 7-2]. +in xref:jsf-intro/jsf-intro.adoc#GJEPW[Figure 7-2]. [[GJEPW]] .*Figure 7-2 Java Web Application Technologies* -image:jakartaeett_dt_015.png[ -"Diagram of web application technologies. Jakarta Server Pages, the server pages -Standard Tag Library, and Jakarta Server Faces rest on Java Servlet -technology."] +image::common:jakartaeett_dt_015.png[ "Diagram of web application technologies. Jakarta Server Pages, the server pages Standard Tag Library, and Jakarta Server Faces rest on Java Servlet technology."] This layering of APIs enables several important application use cases, such as using different presentation technologies, creating your own @@ -40,7 +37,7 @@ output for various client devices. Facelets technology, available as part of Jakarta Server Faces technology, is the preferred presentation technology for building Jakarta Server Faces technology–based web applications. For more information on Facelets -technology features, see link:#GIEPX[Chapter 8, +technology features, see xref:jsf-facelets/jsf-facelets.adoc#GIEPX[Chapter 8, "Introduction to Facelets"]. Facelets technology offers several advantages. @@ -50,7 +47,7 @@ and composite component features. * You can use annotations to automatically register the managed bean as a resource available for Jakarta Server Faces applications. In addition, implicit navigation rules allow developers to quickly configure page -navigation (see link:#BNAQL[Navigation Model] for +navigation (see xref:jsf-intro/jsf-intro.adoc#BNAQL[Navigation Model] for details). These features reduce the manual configuration process for applications. * Most important, Jakarta Server Faces technology provides a rich diff --git a/src/main/antora/modules/web/pages/jsf-intro/jsf-intro004.adoc b/src/main/antora/modules/web/pages/jsf-intro/jsf-intro004.adoc index 4126d69d..67f49c91 100644 --- a/src/main/antora/modules/web/pages/jsf-intro/jsf-intro004.adoc +++ b/src/main/antora/modules/web/pages/jsf-intro/jsf-intro004.adoc @@ -1,11 +1,11 @@ -[[GJAAM]][[a-simple-javaserver-faces-application]] +[[GJAAM]][[_a_simple_javaserver_faces_application]] == A Simple Jakarta Server Faces Application Jakarta Server Faces technology provides an easy and user-friendly process for creating web applications. Developing a simple Jakarta Server Faces application typically requires the following tasks, which have already -been described in link:#BNADX[A Web Module That Uses +been described in xref:webapp/webapp.adoc#BNADX[A Web Module That Uses Jakarta Server Faces Technology: The hello1 Example]: * Creating web pages using component tags @@ -17,11 +17,11 @@ When accessed by a client, the first web page asks the user for his or her name, and the second page responds by providing a greeting. For details on Facelets technology, see -link:#GIEPX[Chapter 8, "Introduction to Facelets"]. For -details on using EL expressions, see link:#GJDDD[Chapter 9, +xref:jsf-facelets/jsf-facelets.adoc#GIEPX[Chapter 8, "Introduction to Facelets"]. For +details on using EL expressions, see xref:jsf-el/jsf-el.adoc#GJDDD[Chapter 9, "Expression Language"]. For details on the Jakarta Server Faces programming model and building web pages using Jakarta Server Faces technology, see -link:#BNAQZ[Chapter 10, "Using Jakarta Server Faces Technology +xref:jsf-page/jsf-page.adoc#BNAQZ[Chapter 10, "Using Jakarta Server Faces Technology in Web Pages"]. Every web application has a lifecycle. Common tasks, such as handling @@ -79,7 +79,7 @@ bean property associated with it, represented by the EL expression 8. On subsequent (postback) requests, the component tree is rebuilt, and the saved state is applied. -For full details on the lifecycle, see link:#BNAQQ[The +For full details on the lifecycle, see xref:jsf-intro/jsf-intro.adoc#BNAQQ[The Lifecycle of a Jakarta Server Faces Application]. diff --git a/src/main/antora/modules/web/pages/jsf-intro/jsf-intro005.adoc b/src/main/antora/modules/web/pages/jsf-intro/jsf-intro005.adoc index a5e51cd5..3b2e8a48 100644 --- a/src/main/antora/modules/web/pages/jsf-intro/jsf-intro005.adoc +++ b/src/main/antora/modules/web/pages/jsf-intro/jsf-intro005.adoc @@ -1,4 +1,4 @@ -[[BNAQD]][[user-interface-component-model]] +[[BNAQD]][[_user_interface_component_model]] == User Interface Component Model @@ -31,7 +31,7 @@ component This section briefly describes each of these pieces of the component architecture. -[[BNAQE]][[user-interface-component-classes]] +[[BNAQE]][[_user_interface_component_classes]] === User Interface Component Classes @@ -43,7 +43,7 @@ standard components. The component classes are completely extensible, allowing component writers to create their own custom components. See -link:#BNAVG[Chapter 15, "Creating Custom UI Components and +xref:jsf-custom/jsf-custom.adoc#BNAVG[Chapter 15, "Creating Custom UI Components and Other Custom Objects"] for more information. The abstract base class for all components is @@ -133,7 +133,7 @@ The next section explains how the rendering model works and how page authors can choose to render the components by selecting the appropriate tags. -[[BNAQF]][[component-rendering-model]] +[[BNAQF]][[_component_rendering_model]] === Component Rendering Model @@ -172,14 +172,14 @@ Each custom tag defined in the standard HTML render kit is composed of the component functionality (defined in the `UIComponent` class) and the rendering attributes (defined by the `Renderer` class). -The section link:#BNARF[Adding Components to a Page Using +The section xref:jsf-page/jsf-page.adoc#BNARF[Adding Components to a Page Using HTML Tag Library Tags] lists all supported component tags and illustrates how to use the tags in an example. The Jakarta Server Faces implementation provides a custom tag library for rendering components in HTML. -[[BNAQI]][[conversion-model]] +[[BNAQI]][[_conversion_model]] === Conversion Model @@ -220,10 +220,10 @@ implementation converts the component's data between the two views. You can either use the standard converters supplied with the Jakarta Server Faces implementation or create your own custom converter. Custom -converter creation is covered in link:#BNAVG[Chapter 15, +converter creation is covered in xref:jsf-custom/jsf-custom.adoc#BNAVG[Chapter 15, "Creating Custom UI Components and Other Custom Objects"]. -[[GIREH]][[event-and-listener-model]] +[[GIREH]][[_event_and_listener_model]] === Event and Listener Model @@ -263,7 +263,7 @@ types that can generate these types of events are the `UIInput`, Value-change events are fired only if no validation errors are detected. Depending on the value of the `immediate` property (see -link:#BNARI[The immediate Attribute]) of the component +xref:jsf-page/jsf-page.adoc#BNARI[The immediate Attribute]) of the component emitting the event, action events can be processed during the Invoke Application phase or the Apply Request Values phase, and value-change events can be processed during the Process Validations phase or the @@ -288,27 +288,27 @@ component tag. the method with a method expression from the appropriate attribute of the component's tag. -See link:#BNAUT[Implementing an Event Listener] for +See xref:jsf-custom/jsf-custom.adoc#BNAUT[Implementing an Event Listener] for information on how to implement an event listener. See -link:#BNASZ[Registering Listeners on Components] for +xref:jsf-page-core/jsf-page-core.adoc#BNASZ[Registering Listeners on Components] for information on how to register the listener on a component. -See link:#BNAVD[Writing a Method to Handle an Action -Event] and link:#BNAVF[Writing a Method to Handle a +See xref:jsf-develop/jsf-develop.adoc#BNAVD[Writing a Method to Handle an Action +Event] and xref:jsf-develop/jsf-develop.adoc#BNAVF[Writing a Method to Handle a Value-Change Event] for information on how to implement managed bean methods that handle these events. -See link:#BNATN[Referencing a Managed Bean Method] +See xref:jsf-page-core/jsf-page-core.adoc#BNATN[Referencing a Managed Bean Method] for information on how to refer to the managed bean method from the component tag. When emitting events from custom components, you must implement the appropriate event class and manually queue the event on the component in addition to implementing an event listener class or a managed bean -method that handles the event. link:#BNAWD[Handling +method that handles the event. xref:jsf-custom/jsf-custom.adoc#BNAWD[Handling Events for Custom Components] explains how to do this. -[[BNAQK]][[validation-model]] +[[BNAQK]][[_validation_model]] === Validation Model @@ -321,7 +321,7 @@ Like the conversion model, the validation model defines a set of standard classes for performing common data validation checks. The Jakarta Server Faces core tag library also defines a set of tags that correspond to the standard `javax.faces.validator.Validator` -implementations. See link:#BNATC[Using the Standard +implementations. See xref:jsf-page-core/jsf-page-core.adoc#BNATC[Using the Standard Validators] for a list of all the standard validation classes and corresponding tags. @@ -333,7 +333,7 @@ component by nesting the validator's tag within the component's tag. In addition to validators that are registered on the component, you can declare a default validator that is registered on all `UIInput` components in the application. For more information on default -validators, see link:#GIREB[Using Default +validators, see xref:jsf-configure/jsf-configure.adoc#GIREB[Using Default Validators]. The validation model also allows you to create your own custom validator @@ -353,7 +353,7 @@ validator on the component. In the previously described standard validation model, the validator is defined for each input component on a page. The Bean Validation model allows the validator to be applied to all fields in a page. See -link:#CHDGJIIA[Chapter 23, "Introduction to Bean -Validation"] and link:#GKAHP[Chapter 24, +xref:#CHDGJIIA[Chapter 23, "Introduction to Bean +Validation"] and xref:#GKAHP[Chapter 24, "Bean Validation: Advanced Topics"] for more information on Bean Validation. diff --git a/src/main/antora/modules/web/pages/jsf-intro/jsf-intro006.adoc b/src/main/antora/modules/web/pages/jsf-intro/jsf-intro006.adoc index 1369e718..e904a18d 100644 --- a/src/main/antora/modules/web/pages/jsf-intro/jsf-intro006.adoc +++ b/src/main/antora/modules/web/pages/jsf-intro/jsf-intro006.adoc @@ -1,4 +1,4 @@ -[[BNAQL]][[navigation-model]] +[[BNAQL]][[_navigation_model]] == Navigation Model @@ -173,14 +173,14 @@ After the student is created, the user is returned to the Administration index page. For more information on how to define navigation rules, see -link:#BNAXF[Configuring Navigation Rules]. +xref:jsf-configure/jsf-configure.adoc#BNAXF[Configuring Navigation Rules]. For more information on how to implement action methods to handle -navigation, see link:#BNAVD[Writing a Method to Handle +navigation, see xref:jsf-develop/jsf-develop.adoc#BNAVD[Writing a Method to Handle an Action Event]. For more information on how to reference outcomes or action methods from -component tags, see link:#BNATP[Referencing a Method +component tags, see xref:jsf-page-core/jsf-page-core.adoc#BNATP[Referencing a Method That Performs Navigation]. diff --git a/src/main/antora/modules/web/pages/jsf-intro/jsf-intro007.adoc b/src/main/antora/modules/web/pages/jsf-intro/jsf-intro007.adoc index 117dca78..e19d076d 100644 --- a/src/main/antora/modules/web/pages/jsf-intro/jsf-intro007.adoc +++ b/src/main/antora/modules/web/pages/jsf-intro/jsf-intro007.adoc @@ -1,4 +1,4 @@ -[[BNAQQ]][[the-lifecycle-of-a-javaserver-faces-application]] +[[BNAQQ]][[_the_lifecycle_of_a_javaserver_faces_application]] == The Lifecycle of a Jakarta Server Faces Application @@ -19,16 +19,16 @@ manually for more complex applications as required. Jakarta Server Faces applications that use advanced features may require interaction with the lifecycle at certain phases. For example, Ajax applications use partial processing features of the lifecycle (see -link:#GKNOJ[Partial Processing and Partial Rendering]). +xref:jsf-intro/jsf-intro.adoc#GKNOJ[Partial Processing and Partial Rendering]). A clearer understanding of the lifecycle phases is key to creating well-designed components. A simplified view of the Jakarta Server faces lifecycle, consisting of the two main phases of a Jakarta Server Faces web application, is introduced in -link:#GJAAM[A Simple Jakarta Server Faces Application]. This +xref:jsf-intro/jsf-intro.adoc#GJAAM[A Simple Jakarta Server Faces Application]. This section examines the Jakarta Server Faces lifecycle in more detail. -[[GLPRC]][[overview-of-the-javaserver-faces-lifecycle]] +[[GLPRC]][[_overview_of_the_javaserver_faces_lifecycle]] === Overview of the Jakarta Server Faces Lifecycle @@ -52,15 +52,12 @@ specified on the server side. The Jakarta Server Faces implementation performs all these tasks as a series of steps in the Jakarta Server Faces request-response lifecycle. -link:#BNAQR[Figure 7-3] illustrates these steps. +xref:jsf-intro/jsf-intro.adoc#BNAQR[Figure 7-3] illustrates these steps. [[BNAQR]] .*Figure 7-3 Jakarta Server Faces Standard Request-Response Lifecycle* -image:jakartaeett_dt_016.png[ -"Flow diagram of Faces request and Faces response, including event and -validation processing, error handling, model updating, application -invocation."] +image::common:jakartaeett_dt_016.png[ "Flow diagram of Faces request and Faces response, including event and validation processing, error handling, model updating, application invocation."] The request-response lifecycle handles two kinds of requests: initial requests and postbacks. An initial request occurs when a user makes a @@ -82,8 +79,8 @@ information associated with processing an incoming request and creating a response. The application then acquires object references needed by the view and calls the `FacesContext.renderResponse` method, which forces immediate rendering of the view by skipping to the -link:#BNAQX[Render Response Phase] of the lifecycle, as is shown by the -arrows labelled Render Response in link:#BNAQR[Figure 7-3]. +xref:jsf-intro/jsf-intro.adoc#BNAQX[Render Response Phase] of the lifecycle, as is shown by the +arrows labelled Render Response in xref:jsf-intro/jsf-intro.adoc#BNAQR[Figure 7-3]. Sometimes, an application might need to redirect to a different web application resource, such as a web service, or generate a response that @@ -101,7 +98,7 @@ validations, and model updates and to generate the response. There is one exception to the lifecycle described in this section. When a component's `immediate` attribute is set to `true`, the validation, conversion, and events associated with these components are processed -during the link:#BNAQT[Apply Request Values Phase] rather than in a +during the xref:jsf-intro/jsf-intro.adoc#BNAQT[Apply Request Values Phase] rather than in a later phase. The details of the lifecycle explained in the following sections are @@ -114,14 +111,14 @@ documentation from `https://jakarta.ee/specifications/faces/`. The Jakarta Server Faces application lifecycle Execute phase contains the following subphases: -* link:#BNAQS[Restore View Phase] -* link:#BNAQT[Apply Request Values Phase] -* link:#GJSBP[Process Validations Phase] -* link:#BNAQV[Update Model Values Phase] -* link:#BNAQW[Invoke Application Phase] -* link:#BNAQX[Render Response Phase] +* xref:jsf-intro/jsf-intro.adoc#BNAQS[Restore View Phase] +* xref:jsf-intro/jsf-intro.adoc#BNAQT[Apply Request Values Phase] +* xref:jsf-intro/jsf-intro.adoc#GJSBP[Process Validations Phase] +* xref:jsf-intro/jsf-intro.adoc#BNAQV[Update Model Values Phase] +* xref:jsf-intro/jsf-intro.adoc#BNAQW[Invoke Application Phase] +* xref:jsf-intro/jsf-intro.adoc#BNAQX[Render Response Phase] -[[BNAQS]][[restore-view-phase]] +[[BNAQS]][[_restore_view_phase]] === Restore View Phase @@ -146,7 +143,7 @@ page already exists in the `FacesContext` instance. During this phase, the Jakarta Server Faces implementation restores the view by using the state information saved on the client or the server. -[[BNAQT]][[apply-request-values-phase]] +[[BNAQT]][[_apply_request_values_phase]] === Apply Request Values Phase @@ -163,7 +160,7 @@ If any events have been queued during this phase, the Jakarta Server Faces implementation broadcasts the events to interested listeners. If some components on the page have their `immediate` attributes (see -link:#BNARI[The immediate Attribute]) set to `true`, then +xref:jsf-page/jsf-page.adoc#BNARI[The immediate Attribute]) set to `true`, then the validations, conversions, and events associated with these components will be processed during this phase. If any conversion fails, an error message associated with the component is generated and queued @@ -183,7 +180,7 @@ If the current request is identified as a partial request, the partial context is retrieved from the `FacesContext`, and the partial processing method is applied. -[[GJSBP]][[process-validations-phase]] +[[GJSBP]][[_process_validations_phase]] === Process Validations Phase @@ -218,7 +215,7 @@ If the current request is identified as a partial request, the partial context is retrieved from the `FacesContext`, and the partial processing method is applied. -[[BNAQV]][[update-model-values-phase]] +[[BNAQV]][[_update_model_values_phase]] === Update Model Values Phase @@ -248,7 +245,7 @@ If the current request is identified as a partial request, the partial context is retrieved from the `FacesContext`, and the partial processing method is applied. -[[BNAQW]][[invoke-application-phase]] +[[BNAQW]][[_invoke_application_phase]] === Invoke Application Phase @@ -268,7 +265,7 @@ events are broadcast to interested listeners. Finally, the Jakarta Server Faces implementation transfers control to the Render Response phase. -[[BNAQX]][[render-response-phase]] +[[BNAQX]][[_render_response_phase]] === Render Response Phase diff --git a/src/main/antora/modules/web/pages/jsf-intro/jsf-intro008.adoc b/src/main/antora/modules/web/pages/jsf-intro/jsf-intro008.adoc index 9e32baee..2dfa2458 100644 --- a/src/main/antora/modules/web/pages/jsf-intro/jsf-intro008.adoc +++ b/src/main/antora/modules/web/pages/jsf-intro/jsf-intro008.adoc @@ -1,4 +1,4 @@ -[[GKNOJ]][[partial-processing-and-partial-rendering]] +[[GKNOJ]][[_partial_processing_and_partial_rendering]] == Partial Processing and Partial Rendering @@ -17,7 +17,7 @@ component tree accordingly. The `execute` and `render` attributes of the `f:ajax` tag are used to identify which components may be executed and rendered. For more -information on these attributes, see link:#GKIOW[Chapter 13, +information on these attributes, see xref:jsf-ajax/jsf-ajax.adoc#GKIOW[Chapter 13, "Using Ajax with Jakarta Server Faces Technology"]. diff --git a/src/main/antora/modules/web/pages/jsf-intro/jsf-intro009.adoc b/src/main/antora/modules/web/pages/jsf-intro/jsf-intro009.adoc index 40bec6f2..cbf567d1 100644 --- a/src/main/antora/modules/web/pages/jsf-intro/jsf-intro009.adoc +++ b/src/main/antora/modules/web/pages/jsf-intro/jsf-intro009.adoc @@ -1,4 +1,4 @@ -[[BNAQY]][[further-information-about-javaserver-faces-technology]] +[[BNAQY]][[_further_information_about_javaserver_faces_technology]] == Further Information about Jakarta Server Faces Technology diff --git a/src/main/antora/modules/web/pages/jsf-page-core/jsf-page-core.adoc b/src/main/antora/modules/web/pages/jsf-page-core/jsf-page-core.adoc index d67ffde1..bab8ae1a 100644 --- a/src/main/antora/modules/web/pages/jsf-page-core/jsf-page-core.adoc +++ b/src/main/antora/modules/web/pages/jsf-page-core/jsf-page-core.adoc @@ -1,6 +1,6 @@ = Using Converters, Listeners, and Validators -[[GJCUT]][[using-converters-listeners-and-validators]] +[[GJCUT]][[_using_converters_listeners_and_validators]] The previous chapter described components and explained how to add them to a web page. This chapter provides information on adding more diff --git a/src/main/antora/modules/web/pages/jsf-page-core/jsf-page-core001.adoc b/src/main/antora/modules/web/pages/jsf-page-core/jsf-page-core001.adoc index a57df148..af6dc152 100644 --- a/src/main/antora/modules/web/pages/jsf-page-core/jsf-page-core001.adoc +++ b/src/main/antora/modules/web/pages/jsf-page-core/jsf-page-core001.adoc @@ -1,4 +1,4 @@ -[[BNAST]][[using-the-standard-converters]] +[[BNAST]][[_using_the_standard_converters]] == Using the Standard Converters @@ -8,13 +8,13 @@ implementations that you can use to convert component data. The purpose of conversion is to take the String-based data coming in from the Servlet API and convert it to strongly typed Java objects suitable for the business domain. For more information on the conceptual details of -the conversion model, see link:#BNAQI[Conversion Model]. +the conversion model, see xref:jsf-intro/jsf-intro.adoc#BNAQI[Conversion Model]. The standard `Converter` implementations are located in the `javax.faces.convert` package. Normally, converters are implicitly assigned based on the type of the EL expression pointed to by the value of the component. However, these converters can also be accessed by a -converter ID. link:#CHDIHIIC[Table 11-1] shows the converter classes and +converter ID. xref:jsf-page-core/jsf-page-core.adoc#CHDIHIIC[Table 11-1] shows the converter classes and their associated converter IDs. [[sthref60]][[CHDIHIIC]] @@ -58,13 +58,13 @@ name of the input component on which the converter is registered. Two of the standard converters (`DateTimeConverter` and `NumberConverter`) have their own tags, which allow you to configure the format of the component data using the tag attributes. For more -information about using `DateTimeConverter`, see link:#BNASV[Using +information about using `DateTimeConverter`, see xref:jsf-page-core/jsf-page-core.adoc#BNASV[Using DateTimeConverter]. For more information about using `NumberConverter`, -see link:#BNASX[Using NumberConverter]. The following section explains +see xref:jsf-page-core/jsf-page-core.adoc#BNASX[Using NumberConverter]. The following section explains how to convert a component's value, including how to register other standard converters with a component. -[[BNASU]][[converting-a-components-value]] +[[BNASU]][[_converting_a_components_value]] === Converting a Component's Value @@ -74,7 +74,7 @@ the standard converters in one of the following ways. * Nest one of the standard converter tags inside the component's tag. These tags are `f:convertDateTime` and `f:convertNumber`, which are -described in link:#BNASX[Using +described in xref:jsf-page-core/jsf-page-core.adoc#BNASX[Using NumberConverter], respectively. * Bind the value of the component to a managed bean property of the same type as the converter. This is the most common technique. @@ -108,7 +108,7 @@ attribute to reference the converter. The `converterId` attribute must reference the converter's ID. Here is an example that uses one of the converter IDs listed in -link:#CHDIHIIC[Table 11-1]: +xref:jsf-page-core/jsf-page-core.adoc#CHDIHIIC[Table 11-1]: [source,xml] ---- @@ -124,16 +124,16 @@ instance. You can also create custom converters and register them on components using the `f:converter` tag. For details, see -link:#BNAUS[Creating and Using a Custom Converter]. +xref:jsf-custom/jsf-custom.adoc#BNAUS[Creating and Using a Custom Converter]. -[[BNASV]][[using-datetimeconverter]] +[[BNASV]][[_using_datetimeconverter]] === Using DateTimeConverter You can convert a component's data to a `java.util.Date` by nesting the `convertDateTime` tag inside the component tag. The `convertDateTime` tag has several attributes that allow you to specify the format and type -of the data. link:#BNASW[Table 11-2] lists the attributes. +of the data. xref:jsf-page-core/jsf-page-core.adoc#BNASW[Table 11-2] lists the attributes. Here is a simple example of a `convertDateTime` tag: @@ -218,7 +218,7 @@ Custom formatting pattern that determines how the date/time string should be formatted and parsed. If this attribute is specified, `dateStyle` and `timeStyle` attributes are ignored. -See link:#CFHEABEI[Table 11-3] for the default values when `pattern` is +See xref:jsf-page-core/jsf-page-core.adoc#CFHEABEI[Table 11-3] for the default values when `pattern` is not specified. |`timeStyle` |`String` |Defines the format, as specified by @@ -236,7 +236,7 @@ Valid values are: `date`, `time`, `both`, `LocalDate`, `LocalTime`, `LocalDateTime`, `OffsetTime`, `OffsetDateTime`, or `ZonedDateTime`. If no value is specified, `date` is used. -See link:#CFHEABEI[Table 11-3] for additional information. +See xref:jsf-page-core/jsf-page-core.adoc#CFHEABEI[Table 11-3] for additional information. |======================================================================= @@ -275,14 +275,14 @@ See link:#CFHEABEI[Table 11-3] for additional information. |======================================================================= -[[BNASX]][[using-numberconverter]] +[[BNASX]][[_using_numberconverter]] === Using NumberConverter You can convert a component's data to a `java.lang.Number` by nesting the `convertNumber` tag inside the component tag. The `convertNumber` tag has several attributes that allow you to specify the format and type -of the data. link:#BNASY[Table 11-4] lists the attributes. +of the data. xref:jsf-page-core/jsf-page-core.adoc#BNASY[Table 11-4] lists the attributes. The following example uses a `convertNumber` tag to display the total prices of the contents of a shopping cart: diff --git a/src/main/antora/modules/web/pages/jsf-page-core/jsf-page-core002.adoc b/src/main/antora/modules/web/pages/jsf-page-core/jsf-page-core002.adoc index dfbd24f2..d023c900 100644 --- a/src/main/antora/modules/web/pages/jsf-page-core/jsf-page-core002.adoc +++ b/src/main/antora/modules/web/pages/jsf-page-core/jsf-page-core002.adoc @@ -1,4 +1,4 @@ -[[BNASZ]][[registering-listeners-on-components]] +[[BNASZ]][[_registering_listeners_on_components]] == Registering Listeners on Components @@ -11,8 +11,8 @@ either an `f:valueChangeListener` tag or an `f:actionListener` tag and nest the tag inside the component tag to register the listener on the component. -link:#BNATQ[Referencing a Method That Handles an -Action Event] and link:#BNATS[Referencing a Method +xref:jsf-page-core/jsf-page-core.adoc#BNATQ[Referencing a Method That Handles an +Action Event] and xref:jsf-page-core/jsf-page-core.adoc#BNATS[Referencing a Method That Handles a Value-Change Event] explain how a page author uses the `valueChangeListener` and `actionListener` attributes to reference managed bean methods that handle events. @@ -22,7 +22,7 @@ listener and a `BookChange` action listener implementation on components. The Duke's Bookstore case study includes both of these listeners. -[[BNATA]][[registering-a-value-change-listener-on-a-component]] +[[BNATA]][[_registering_a_value_change_listener_on_a_component]] === Registering a Value-Change Listener on a Component @@ -30,7 +30,7 @@ A page author can register a `ValueChangeListener` implementation on a component that implements `EditableValueHolder` by nesting an `f:valueChangeListener` tag within the component's tag on the page. The `f:valueChangeListener` tag supports the attributes shown in -link:#GKCLY[Table 11-5], one of which must be used. +xref:jsf-page-core/jsf-page-core.adoc#GKCLY[Table 11-5], one of which must be used. [[sthref64]][[GKCLY]] @@ -77,10 +77,10 @@ to the component. The `binding` attribute is used to bind a `ValueChangeListener` implementation to a managed bean property. This attribute works in a similar way to the `binding` attribute supported by the standard -converter tags. See link:#BNATG[Binding Component +converter tags. See xref:jsf-custom/jsf-custom.adoc#BNATG[Binding Component Values and Instances to Managed Bean Properties] for more information. -[[BNATB]][[registering-an-action-listener-on-a-component]] +[[BNATB]][[_registering_an_action_listener_on_a_component]] === Registering an Action Listener on a Component @@ -107,7 +107,7 @@ The `type` attribute of the `f:actionListener` tag specifies the fully qualified class name of the `ActionListener` implementation. Similarly to the `f:valueChangeListener` tag, the `f:actionListener` tag also supports the `binding` attribute. See -link:#BNATM[Binding Converters, Listeners, and +xref:jsf-custom/jsf-custom.adoc#BNATM[Binding Converters, Listeners, and Validators to Managed Bean Properties] for more information about binding listeners to managed bean properties. diff --git a/src/main/antora/modules/web/pages/jsf-page-core/jsf-page-core003.adoc b/src/main/antora/modules/web/pages/jsf-page-core/jsf-page-core003.adoc index 7d023581..e6af2a59 100644 --- a/src/main/antora/modules/web/pages/jsf-page-core/jsf-page-core003.adoc +++ b/src/main/antora/modules/web/pages/jsf-page-core/jsf-page-core003.adoc @@ -1,11 +1,11 @@ -[[BNATC]][[using-the-standard-validators]] +[[BNATC]][[_using_the_standard_validators]] == Using the Standard Validators Jakarta Server Faces technology provides a set of standard classes and associated tags that page authors and application developers can use to -validate a component's data. link:#BNATD[Table 11-6] lists all the +validate a component's data. xref:jsf-page-core/jsf-page-core.adoc#BNATD[Table 11-6] lists all the standard validator classes and the tags that allow you to use the validators from the page. @@ -65,7 +65,7 @@ In this case, the `{1}` substitution parameter is replaced by the component's label or `id`, and the `{0}` substitution parameter is replaced with the maximum value allowed by the validator. -See link:#BNASO[Displaying Error Messages with the +See xref:jsf-page/jsf-page.adoc#BNASO[Displaying Error Messages with the h:message and h:messages Tags] for information on how to display validation error messages on the page when validation fails. @@ -73,7 +73,7 @@ Instead of using the standard validators, you can use Bean Validation to validate data. If you specify bean validation constraints on your managed bean properties, the constraints are automatically placed on the corresponding fields on your applications web pages. See -link:#CHDGJIIA[Chapter 23, "Introduction to Bean +xref:#CHDGJIIA[Chapter 23, "Introduction to Bean Validation"] for more information. You do not need to specify the `validateBean` tag to use Bean Validation, but the tag allows you to use more advanced Bean Validation features. For example, you can use the @@ -81,9 +81,9 @@ more advanced Bean Validation features. For example, you can use the You can also create and register custom validators, although Bean Validation has made this feature less useful. For details, see -link:#BNAUW[Creating and Using a Custom Validator]. +xref:jsf-custom/jsf-custom.adoc#BNAUW[Creating and Using a Custom Validator]. -[[BNATE]][[validating-a-components-value]] +[[BNATE]][[_validating_a_components_value]] === Validating a Component's Value @@ -91,8 +91,8 @@ To validate a component's value using a particular validator, you need to register that validator on the component. You can do this in one of the following ways. -* Nest the validator's corresponding tag (shown in link:#BNATD[Table -11-6]) inside the component's tag. link:#BNATF[Using Validator Tags] +* Nest the validator's corresponding tag (shown in xref:jsf-page-core/jsf-page-core.adoc#BNATD[Table +11-6]) inside the component's tag. xref:jsf-page-core/jsf-page-core.adoc#BNATF[Using Validator Tags] explains how to use the `validateLongRange` tag. You can use the other standard tags in the same way. * Refer to a method that performs the validation from the component @@ -101,18 +101,18 @@ tag's `validator` attribute. validator tag's `validatorId` attribute or its `binding` attribute to refer to the validator. -See link:#BNATR[Referencing a Method That Performs +See xref:jsf-page-core/jsf-page-core.adoc#BNATR[Referencing a Method That Performs Validation] for more information on using the `validator` attribute. The `validatorId` attribute works similarly to the `converterId` attribute of the `converter` tag, as described in -link:#BNASU[Converting a Component's Value]. +xref:jsf-page-core/jsf-page-core.adoc#BNASU[Converting a Component's Value]. Keep in mind that validation can be performed only on components that implement `EditableValueHolder`, because these components accept values that can be validated. -[[BNATF]][[using-validator-tags]] +[[BNATF]][[_using_validator_tags]] === Using Validator Tags diff --git a/src/main/antora/modules/web/pages/jsf-page-core/jsf-page-core004.adoc b/src/main/antora/modules/web/pages/jsf-page-core/jsf-page-core004.adoc index 4091eee6..1c819f62 100644 --- a/src/main/antora/modules/web/pages/jsf-page-core/jsf-page-core004.adoc +++ b/src/main/antora/modules/web/pages/jsf-page-core/jsf-page-core004.adoc @@ -1,10 +1,10 @@ -[[BNATN]][[referencing-a-managed-bean-method]] +[[BNATN]][[_referencing_a_managed_bean_method]] == Referencing a Managed Bean Method A component tag has a set of attributes for referencing managed bean methods that can perform certain functions for the component associated -with the tag. These attributes are summarized in link:#BNATO[Table +with the tag. These attributes are summarized in xref:jsf-page-core/jsf-page-core.adoc#BNATO[Table 11-7]. [[sthref66]][[BNATO]] @@ -48,7 +48,7 @@ void validate(javax.faces.context.FacesContext, The following sections give examples of how to use the attributes. -[[BNATP]][[referencing-a-method-that-performs-navigation]] +[[BNATP]][[_referencing_a_method_that_performs_navigation]] === Referencing a Method That Performs Navigation @@ -70,10 +70,10 @@ The following example shows how to reference a navigation method: action="#{cashierBean.submit}" /> ---- -See link:#BNAVC[Writing a Method to Handle Navigation] +See xref:jsf-develop/jsf-develop.adoc#BNAVC[Writing a Method to Handle Navigation] for information on how to write such a method. -[[BNATQ]][[referencing-a-method-that-handles-an-action-event]] +[[BNATQ]][[_referencing_a_method_that_handles_an_action_event]] === Referencing a Method That Handles an Action Event @@ -93,10 +93,10 @@ The `actionListener` attribute of this component tag references the `chooseBookFromLink` method using a method expression. The `chooseBookFromLink` method handles the event when the user clicks the link rendered by this component. See -link:#BNAVD[Writing a Method to Handle an Action +xref:jsf-develop/jsf-develop.adoc#BNAVD[Writing a Method to Handle an Action Event] for information on how to write such a method. -[[BNATR]][[referencing-a-method-that-performs-validation]] +[[BNATR]][[_referencing_a_method_that_performs_validation]] === Referencing a Method That Performs Validation @@ -105,7 +105,7 @@ managed bean method, refer to the method from the component's tag by using the `validator` attribute. The following simplified example from -link:#GJCXV[The guessnumber-cdi CDI Example] +xref:#GJCXV[The guessnumber-cdi CDI Example] shows how to reference a method that performs validation on `inputGuess`, an input component: @@ -121,10 +121,10 @@ shows how to reference a method that performs validation on The managed bean method `validateNumberRange` verifies that the input value is within the valid range, which changes each time another guess -is made. See link:#BNAVE[Writing a Method to Perform +is made. See xref:jsf-develop/jsf-develop.adoc#BNAVE[Writing a Method to Perform Validation] for information on how to write such a method. -[[BNATS]][[referencing-a-method-that-handles-a-value-change-event]] +[[BNATS]][[_referencing_a_method_that_handles_a_value_change_event]] === Referencing a Method That Handles a Value-Change Event @@ -148,6 +148,6 @@ The `valueChangeListener` attribute of this component tag references the expression. The `processValueChange` method handles the event of a user entering a name in the input field rendered by this component. -link:#BNAVF[Writing a Method to Handle a Value-Change +xref:jsf-develop/jsf-develop.adoc#BNAVF[Writing a Method to Handle a Value-Change Event] describes how to implement a method that handles a `ValueChangeEvent`. diff --git a/src/main/antora/modules/web/pages/jsf-page/jsf-page.adoc b/src/main/antora/modules/web/pages/jsf-page/jsf-page.adoc index f9a31335..1f999ac9 100644 --- a/src/main/antora/modules/web/pages/jsf-page/jsf-page.adoc +++ b/src/main/antora/modules/web/pages/jsf-page/jsf-page.adoc @@ -1,6 +1,6 @@ = Using Jakarta Server Faces Technology in Web Pages -[[BNAQZ]][[using-javaserver-faces-technology-in-web-pages]] +[[BNAQZ]][[_using_javaserver_faces_technology_in_web_pages]] Web pages (Facelets pages, in most cases) represent the presentation layer for web applications. The process of creating web pages for a @@ -15,7 +15,7 @@ adding converters, validators, and listeners to component tags to provide additional functionality to components. Many of the examples in this chapter are taken from -link:#GLNVI[Chapter 60, "Duke's Bookstore Case Study +xref:#GLNVI[Chapter 60, "Duke's Bookstore Case Study Example."] include::jsf-page001.adoc[] diff --git a/src/main/antora/modules/web/pages/jsf-page/jsf-page001.adoc b/src/main/antora/modules/web/pages/jsf-page/jsf-page001.adoc index 8f8dc51b..cd613563 100644 --- a/src/main/antora/modules/web/pages/jsf-page/jsf-page001.adoc +++ b/src/main/antora/modules/web/pages/jsf-page/jsf-page001.adoc @@ -1,4 +1,4 @@ -[[BNARB]][[setting-up-a-page]] +[[BNARB]][[_setting_up_a_page]] == Setting Up a Page @@ -51,8 +51,8 @@ to distinguish the tags defined in the HTML tag library: ---- -The sections link:#BNARF[Adding Components to a Page -Using HTML Tag Library Tags] and link:#BNARC[Using Core +The sections xref:jsf-page/jsf-page.adoc#BNARF[Adding Components to a Page +Using HTML Tag Library Tags] and xref:jsf-page/jsf-page.adoc#BNARC[Using Core Tags] describe how to use the component tags from the Jakarta Server Faces standard HTML tag library and the core tags from the Jakarta Server Faces core tag library. diff --git a/src/main/antora/modules/web/pages/jsf-page/jsf-page002.adoc b/src/main/antora/modules/web/pages/jsf-page/jsf-page002.adoc index d7ebbae5..f0050173 100644 --- a/src/main/antora/modules/web/pages/jsf-page/jsf-page002.adoc +++ b/src/main/antora/modules/web/pages/jsf-page/jsf-page002.adoc @@ -1,4 +1,4 @@ -[[BNARF]][[adding-components-to-a-page-using-html-tag-library-tags]] +[[BNARF]][[_adding_components_to_a_page_using_html_tag_library_tags]] == Adding Components to a Page Using HTML Tag Library Tags @@ -7,7 +7,7 @@ represent HTML form components and other basic HTML elements. These components display data or accept data from the user. This data is collected as part of a form and is submitted to the server, usually when the user clicks a button. This section explains how to use each of the -component tags shown in link:#BNAQH[Table 10-1]. +component tags shown in xref:jsf-page/jsf-page.adoc#BNAQH[Table 10-1]. [[sthref40]][[BNAQH]] @@ -104,24 +104,24 @@ For a standalone radio button, use the `group` attribute. The tags correspond to components in the `javax.faces.component` package. The components are discussed in more detail in -link:#BNATX[Chapter 12, "Developing with Jakarta Server Faces +xref:jsf-develop/jsf-develop.adoc#BNATX[Chapter 12, "Developing with Jakarta Server Faces Technology."] The next section explains the important attributes that are common to most component tags. For each of the components discussed in the -following sections, link:#BNATY[Writing Bean +following sections, xref:jsf-develop/jsf-develop.adoc#BNATY[Writing Bean Properties] explains how to write a bean property bound to that particular component or its value. For reference information about the tags and their attributes, see the https://jakarta.ee/specifications/faces/2.3/vdldoc/[Jakarta Server Faces Facelets Tag Library documentation]. -[[BNARG]][[common-component-tag-attributes]] +[[BNARG]][[_common_component_tag_attributes]] === Common Component Tag Attributes Most of the component tags support the attributes shown in -link:#GKCKS[Table 10-2]. +xref:jsf-page/jsf-page.adoc#GKCKS[Table 10-2]. [[sthref41]][[GKCKS]] @@ -154,12 +154,12 @@ expression. All the tag attributes except `id` can accept expressions, as defined by -the EL, described in link:#GJDDD[Expression Language]. +the EL, described in xref:jsf-el/jsf-el.adoc#GJDDD[Expression Language]. An attribute such as `rendered` or `value` can be set on the page and then modified in the backing bean for the page. -[[BNARH]][[the-id-attribute]] +[[BNARH]][[_the_id_attribute]] ==== The id Attribute @@ -169,11 +169,11 @@ component. If you don't include an `id` attribute, the Jakarta Server Faces implementation automatically generates a component ID. Unlike most other Jakarta Server Faces tag attributes, the `id` attribute takes expressions using only the evaluation syntax described in -link:#BNAHS[Immediate Evaluation], which uses the `${}` +xref:jsf-el/jsf-el.adoc#BNAHS[Immediate Evaluation], which uses the `${}` delimiters. For more information on expression syntax, see -link:#BNAHV[Value Expressions]. +xref:jsf-el/jsf-el.adoc#BNAHV[Value Expressions]. -[[BNARI]][[the-immediate-attribute]] +[[BNARI]][[_the_immediate_attribute]] ==== The immediate Attribute @@ -243,7 +243,7 @@ entered into the `quantity` input fields will be processed. If you click the Update Quantities hyperlink, the values in the `quantity` fields will be updated in the shopping cart. -[[BNARJ]][[the-rendered-attribute]] +[[BNARJ]][[_the_rendered_attribute]] ==== The rendered Attribute @@ -261,7 +261,7 @@ is not rendered if the cart contains no items: Unlike nearly every other Jakarta Server Faces tag attribute, the `rendered` attribute is restricted to using rvalue expressions. As explained in -link:#BNAHU[Value and Method Expressions], these rvalue +xref:jsf-el/jsf-el.adoc#BNAHU[Value and Method Expressions], these rvalue expressions can only read data; they cannot write the data back to the data source. Therefore, expressions used with `rendered` attributes can use the arithmetic operators and literals that rvalue expressions can @@ -277,18 +277,18 @@ a| In this example and others, `bundle` refers to a `java.util.ResourceBundle` file that contains locale-specific strings to be displayed. Resource bundles are discussed in -link:#BNAXU[Chapter 22, "Internationalizing and Localizing +xref:webi18n/webi18n.adoc#BNAXU[Chapter 22, "Internationalizing and Localizing Web Applications"]. |======================================================================= -[[BNARK]][[the-style-and-styleclass-attributes]] +[[BNARK]][[_the_style_and_styleclass_attributes]] ==== The style and styleClass Attributes The `style` and `styleClass` attributes allow you to specify CSS styles -for the rendered output of your tags. link:#BNASO[Displaying Error +for the rendered output of your tags. xref:jsf-page/jsf-page.adoc#BNASO[Displaying Error Messages with the h:message and h:messages Tags] describes an example of using the `style` attribute to specify styles directly in the attribute. A component tag can instead refer to a CSS class. @@ -310,7 +310,7 @@ be included in the application. For more information on defining styles, see the Cascading Style Sheets specifications and drafts at `http://www.w3.org/Style/CSS/`. -[[BNARL]][[the-value-and-binding-attributes]] +[[BNARL]][[_the_value_and_binding_attributes]] ==== The value and binding Attributes @@ -319,12 +319,12 @@ attributes to bind its component's value or instance, respectively, to a data object. The `value` attribute is used more commonly than the `binding` attribute, and examples appear throughout this chapter. For more information on these attributes, see -link:#BNAQN[Creating a Managed Bean], -link:#BNATZ[Writing Properties Bound to Component -Values], and link:#BNAUK[Writing Properties Bound to +xref:jsf-develop/jsf-develop.adoc#BNAQN[Creating a Managed Bean], +xref:jsf-develop/jsf-develop.adoc#BNATZ[Writing Properties Bound to Component +Values], and xref:jsf-develop/jsf-develop.adoc#BNAUK[Writing Properties Bound to Component Instances]. -[[GJDGQ]][[adding-html-head-and-body-tags]] +[[GJDGQ]][[_adding_html_head_and_body_tags]] === Adding HTML Head and Body Tags @@ -372,10 +372,10 @@ tags: Both of the preceding example code segments render the same HTML elements. The head and body tags are useful mainly for resource relocation. For more information on resource relocation, see -link:#GJGEP[Resource Relocation Using h:outputScript and +xref:jsf-page/jsf-page.adoc#GJGEP[Resource Relocation Using h:outputScript and h:outputStylesheet Tags]. -[[BNARM]][[adding-a-form-component]] +[[BNARM]][[_adding_a_form_component]] === Adding a Form Component @@ -383,15 +383,14 @@ An `h:form` tag represents an input form, which includes child components that can contain data that is either presented to the user or submitted with the form. -link:#BNARN[Figure 10-1] shows a typical login form in which a user +xref:jsf-page/jsf-page.adoc#BNARN[Figure 10-1] shows a typical login form in which a user enters a user name and password, then submits the form by clicking the Login button. [[BNARN]] .*Figure 10-1 A Typical Form* -image:jakartaeett_dt_065_frmcmpnt.png[ -"Form with User Name and Password text fields and a Login button."] +image::common:jakartaeett_dt_065_frmcmpnt.png[ "Form with User Name and Password text fields and a Login button."] The `h:form` tag represents the form on the page and encloses all the components that display or collect data from the user, as shown here: @@ -411,7 +410,7 @@ can be used by other components in the form. A page can include multiple `h:form` tags, but only the values from the form submitted by the user will be included in the postback request. -[[BNARO]][[using-text-components]] +[[BNARO]][[_using_text_components]] === Using Text Components @@ -425,14 +424,12 @@ to be submitted as part of a form characters, such as asterisks, instead of the password text that the user enters -link:#BNARP[Figure 10-2] shows examples of these text components. +xref:jsf-page/jsf-page.adoc#BNARP[Figure 10-2] shows examples of these text components. [[BNARP]] .*Figure 10-2 Example Text Components* -image:jakartaeett_dt_068_txtcmpnts.png[ -"A form. "User Name" labels a field. "Password" labels a password field. -"Comments" labels a multi-line field."] +image::common:jakartaeett_dt_068_txtcmpnts.png[ "A form. "User Name" labels a field. "Password" labels a password field. "Comments" labels a multi-line field."] Text components can be categorized as either input or output. A Jakarta Server Faces output component, such as a label, is rendered as @@ -442,7 +439,7 @@ rendered as editable text. The input and output components can each be rendered in various ways to display more specialized text. -link:#BNARQ[Table 10-3] lists the tags that represent the input +xref:jsf-page/jsf-page.adoc#BNARQ[Table 10-3] lists the tags that represent the input components. [[sthref44]][[BNARQ]] @@ -465,8 +462,8 @@ of text |======================================================================= -The input tags support the tag attributes shown in link:#GKCNH[Table -10-4] in addition to those described in link:#BNARG[Common Component Tag +The input tags support the tag attributes shown in xref:jsf-page/jsf-page.adoc#GKCNH[Table +10-4] in addition to those described in xref:jsf-page/jsf-page.adoc#BNARG[Common Component Tag Attributes]. Note that this table does not include all the attributes supported by the input tags but just those that are used most often. For the complete list of attributes, refer to the https://jakarta.ee/specifications/faces/2.3/vdldoc/[Jakarta Server @@ -480,7 +477,7 @@ Faces Facelets Tag Library documentation]. |======================================================================= |*Attribute* |*Description* |`converter` |Identifies a converter that will be used to convert the -component's local data. See link:#BNAST[Using the +component's local data. See xref:jsf-page-core/jsf-page-core.adoc#BNAST[Using the Standard Converters] for more information on how to use this attribute. |`converterMessage` |Specifies an error message to display when the @@ -504,7 +501,7 @@ does not enter a value into the component. |`validator` |Identifies a method expression pointing to a managed bean method that performs validation on the component's data. See -link:#BNATR[Referencing a Method That Performs +xref:jsf-page-core/jsf-page-core.adoc#BNATR[Referencing a Method That Performs Validation] for an example of using the `f:validator` tag. |`validatorMessage` |Specifies an error message to display when the @@ -513,13 +510,13 @@ local value. |`valueChangeListener` |Identifies a method expression that points to a managed bean method that handles the event of entering a value in this -component. See link:#BNATS[Referencing a Method That +component. See xref:jsf-page-core/jsf-page-core.adoc#BNATS[Referencing a Method That Handles a Value-Change Event] for an example of using `valueChangeListener`. |======================================================================= -link:#GJFWE[Table 10-5] lists the tags that represent the output +xref:jsf-page/jsf-page.adoc#GJFWE[Table 10-5] lists the tags that represent the output components. [[sthref46]][[GJFWE]] @@ -542,13 +539,13 @@ without generating an action event The output tags support the `converter` tag attribute in addition to -those listed in link:#BNARG[Common Component Tag Attributes]. +those listed in xref:jsf-page/jsf-page.adoc#BNARG[Common Component Tag Attributes]. The rest of this section explains how to use some of the tags listed in -link:#GJFWE[Output Tags]. The other tags are +xref:jsf-page/jsf-page.adoc#GJFWE[Output Tags]. The other tags are written in a similar way. -[[BNARR]][[rendering-a-field-with-the-hinputtext-tag]] +[[BNARR]][[_rendering_a_field_with_the_hinputtext_tag]] ==== Rendering a Field with the h:inputText Tag @@ -595,10 +592,10 @@ string, no other validators that are registered on the tag are called. If your tag does not have a `required` attribute set to `true`, other validators that are registered on the tag are called, but those validators must handle the possibility of a null or zero-length string. -See link:#GKCRG[Validating Null and Empty Strings] +See xref:#GKCRG[Validating Null and Empty Strings] for more information. -[[BNARV]][[rendering-a-password-field-with-the-hinputsecret-tag]] +[[BNARV]][[_rendering_a_password_field_with_the_hinputsecret_tag]] ==== Rendering a Password Field with the h:inputSecret Tag @@ -615,7 +612,7 @@ In this example, the `redisplay` attribute is set to `false`. This will prevent the password from being displayed in a query string or in the source file of the resulting HTML page. -[[BNARS]][[rendering-a-label-with-the-houtputlabel-tag]] +[[BNARS]][[_rendering_a_label_with_the_houtputlabel_tag]] ==== Rendering a Label with the h:outputLabel Tag @@ -665,7 +662,7 @@ specify the text of the label: ... ---- -[[BNART]][[rendering-a-link-with-the-houtputlink-tag]] +[[BNART]][[_rendering_a_link_with_the_houtputlink_tag]] ==== Rendering a Link with the h:outputLink Tag @@ -686,7 +683,7 @@ Here is an example: The text in the body of the `h:outputLink` tag identifies the text that the user clicks to get to the next page. -[[BNARU]][[displaying-a-formatted-message-with-the-houtputformat-tag]] +[[BNARU]][[_displaying_a_formatted_message_with_the_houtputformat_tag]] ==== Displaying a Formatted Message with the h:outputFormat Tag @@ -739,7 +736,7 @@ expression. The message displayed in the page is now as follows: Hello, Bill! You are visitor number 10 to the page. ---- -[[BNARW]][[using-command-component-tags-for-performing-actions-and-navigation]] +[[BNARW]][[_using_command_component_tags_for_performing_actions_and_navigation]] === Using Command Component Tags for Performing Actions and Navigation @@ -751,7 +748,7 @@ they perform an action when activated. The `h:commandButton` tag is rendered as a button. The `h:commandLink` tag is rendered as a link. -In addition to the tag attributes listed in link:#BNARG[Common Component +In addition to the tag attributes listed in xref:jsf-page/jsf-page.adoc#BNARG[Common Component Tag Attributes], the `h:commandButton` and `h:commandLink` tags can use the following attributes. @@ -764,12 +761,12 @@ activated. method that processes an action event fired by the command component tag. -See link:#BNATP[Referencing a Method That Performs +See xref:jsf-page-core/jsf-page-core.adoc#BNATP[Referencing a Method That Performs Navigation] for more information on using the `action` attribute. See -link:#BNATQ[Referencing a Method That Handles an +xref:jsf-page-core/jsf-page-core.adoc#BNATQ[Referencing a Method That Handles an Action Event] for details on using the `actionListener` attribute. -[[BNARX]][[rendering-a-button-with-the-hcommandbutton-tag]] +[[BNARX]][[_rendering_a_button_with_the_hcommandbutton_tag]] ==== Rendering a Button with the h:commandButton Tag @@ -789,10 +786,10 @@ be invoked because the `action` attribute references this method. The The `value` attribute of the example `h:commandButton` tag references the button's label. For information on how to use the `action` -attribute, see link:#BNATP[Referencing a Method That +attribute, see xref:jsf-page-core/jsf-page-core.adoc#BNATP[Referencing a Method That Performs Navigation]. -[[GKBUJ]][[rendering-a-link-with-the-hcommandlink-tag]] +[[GKBUJ]][[_rendering_a_link_with_the_hcommandlink_tag]] ==== Rendering a Link with the h:commandLink Tag @@ -835,7 +832,7 @@ technology. |======================================================================= -[[BNASB]][[adding-graphics-and-images-with-the-hgraphicimage-tag]] +[[BNASB]][[_adding_graphics_and_images_with_the_hgraphicimage_tag]] === Adding Graphics and Images with the h:graphicImage Tag @@ -853,7 +850,7 @@ relative context path of the web application to the beginning of the path to the image. Alternatively, you can use the facility described in -link:#GIRGM[Web Resources] to point to the image +xref:jsf-facelets/jsf-facelets.adoc#GIRGM[Web Resources] to point to the image location. Here are two examples: [source,xml] @@ -880,13 +877,13 @@ header { ... ---- -[[BNASC]][[laying-out-components-with-the-hpanelgrid-and-hpanelgroup-tags]] +[[BNASC]][[_laying_out_components_with_the_hpanelgrid_and_hpanelgroup_tags]] === Laying Out Components with the h:panelGrid and h:panelGroup Tags In a Jakarta Server Faces application, you use a panel as a layout container for a set of other components. A panel is rendered as an HTML table. -link:#BNASD[Table 10-6] lists the tags used to create panels. +xref:jsf-page/jsf-page.adoc#BNASD[Table 10-6] lists the tags used to create panels. [[sthref47]][[BNASD]] @@ -979,11 +976,11 @@ uses an `f:facet` tag for the header. Facets can have only one child, so an `h:panelGroup` tag is needed if you want to group more than one component within an `f:facet`. The example `h:panelGrid` tag has only one cell of data, so an `h:panelGroup` tag is not needed. (For more -information about facets, see link:#BNARZ[Using Data-Bound Table +information about facets, see xref:jsf-page/jsf-page.adoc#BNARZ[Using Data-Bound Table Components]. The `h:panelGroup` tag has an attribute, `layout`, in addition to those -listed in link:#BNARG[Common Component Tag Attributes]. If the `layout` +listed in xref:jsf-page/jsf-page.adoc#BNARG[Common Component Tag Attributes]. If the `layout` attribute has the value `block`, an HTML `div` element is rendered to enclose the row; otherwise, an HTML `span` element is rendered to enclose the row. If you are specifying styles for the `h:panelGroup` @@ -1006,7 +1003,7 @@ the page modulo 2. So, if a component is the fifth one in the list of components, that component will be in the 5 modulo 2 column, or column 1. -[[BNASE]][[displaying-components-for-selecting-one-value]] +[[BNASE]][[_displaying_components_for_selecting_one_value]] === Displaying Components for Selecting One Value @@ -1020,15 +1017,14 @@ represents a Boolean state * An `h:selectOneMenu` tag, displayed as a scrollable list * An `h:selectOneListbox` tag, displayed as an unscrollable list -link:#BNASF[Figure 10-3] shows examples of these components. +xref:jsf-page/jsf-page.adoc#BNASF[Figure 10-3] shows examples of these components. [[BNASF]] .*Figure 10-3 Example Components for Selecting One Item* -image:jakartaeett_dt_067_slctn.png[ -"Options, check box, and lists."] +image::common:jakartaeett_dt_067_slctn.png[ "Options, check box, and lists."] -[[BNASG]][[displaying-a-check-box-using-the-hselectbooleancheckbox-tag]] +[[BNASG]][[_displaying_a_check_box_using_the_hselectbooleancheckbox_tag]] ==== Displaying a Check Box Using the h:selectBooleanCheckbox Tag @@ -1057,7 +1053,7 @@ allow users to indicate whether they want to join the Duke Fan Club. When the `h:outputLabel` tag is rendered, it displays the label for the check box. The label text is represented by the `value` attribute. -[[BNASH]][[displaying-a-menu-using-the-hselectonemenu-tag]] +[[BNASH]][[_displaying_a_menu_using_the_hselectonemenu_tag]] ==== Displaying a Menu Using the h:selectOneMenu Tag @@ -1092,10 +1088,10 @@ determines which one is selected. Like the `h:selectOneRadio` tag, the `h:selectOneMenu` tag must contain either an `f:selectItems` tag or a set of `f:selectItem` tags for -representing the items in the list. link:#BNASK[Using the f:selectItem +representing the items in the list. xref:jsf-page/jsf-page.adoc#BNASK[Using the f:selectItem and f:selectItems Tags] describes these tags. -[[BNASI]][[displaying-components-for-selecting-multiple-values]] +[[BNASI]][[_displaying_components_for_selecting_multiple_values]] === Displaying Components for Selecting Multiple Values @@ -1107,13 +1103,12 @@ one of the following component tags: * An `h:selectManyMenu` tag, displayed as a menu * An `h:selectManyListbox` tag, displayed as a box -link:#BNASJ[Figure 10-4] shows examples of these components. +xref:jsf-page/jsf-page.adoc#BNASJ[Figure 10-4] shows examples of these components. [[BNASJ]] .*Figure 10-4 Example Components for Selecting Multiple Values* -image:jakartaeett_dt_066_slctmny.png[ -"Check box group, scrollable box, and unscrollable box."] +image::common:jakartaeett_dt_066_slctmny.png[ "Check box group, scrollable box, and unscrollable box."] These tags allow the user to select zero or more values from a set of values. This section explains the `h:selectManyCheckbox` tag. The @@ -1157,7 +1152,7 @@ use the `f:selectItems` tag. To represent each item individually, you use the `f:selectItem` tag. The following section explains these tags in more detail. -[[BNASK]][[using-the-fselectitem-and-fselectitems-tags]] +[[BNASK]][[_using_the_fselectitem_and_fselectitems_tags]] === Using the f:selectItem and f:selectItems Tags @@ -1188,11 +1183,11 @@ properties. The rest of this section shows you how to use the `f:selectItems` and `f:selectItem` tags. -[[BNASM]][[using-the-fselectitems-tag]] +[[BNASM]][[_using_the_fselectitems_tag]] ==== Using the f:selectItems Tag -The following example from link:#BNASI[Displaying Components for +The following example from xref:jsf-page/jsf-page.adoc#BNASI[Displaying Components for Selecting Multiple Values] shows how to use the `h:selectManyCheckbox` tag: @@ -1209,16 +1204,16 @@ The `value` attribute of the `f:selectItems` tag is bound to the managed bean property `cashierBean.newsletterItems`. The individual `SelectItem` objects are created programmatically in the managed bean. -See link:#BNAUH[UISelectItems Properties] for +See xref:jsf-develop/jsf-develop.adoc#BNAUH[UISelectItems Properties] for information on how to write a managed bean property for one of these tags. -[[BNASN]][[using-the-fselectitem-tag]] +[[BNASN]][[_using_the_fselectitem_tag]] ==== Using the f:selectItem Tag The `f:selectItem` tag represents a single item in a list of items. Here -is the example from link:#BNASH[Displaying a Menu Using the +is the example from xref:jsf-page/jsf-page.adoc#BNASH[Displaying a Menu Using the h:selectOneMenu Tag] once again: [source,xml] @@ -1244,7 +1239,7 @@ meaning that they can use value-binding expressions to refer to values in external objects. These attributes can also define literal values, as shown in the example `h:selectOneMenu` tag. -[[sthref50]][[displaying-the-results-from-selection-components]] +[[sthref50]][[_displaying_the_results_from_selection_components]] === Displaying the Results from Selection Components @@ -1252,7 +1247,7 @@ If you display components that allow a user to select values, you may also want to display the result of the selection. For example, you might want to thank a user who selected the checkbox to -join the Duke Fan Club, as described in link:#BNASG[Displaying a Check +join the Duke Fan Club, as described in xref:jsf-page/jsf-page.adoc#BNASG[Displaying a Check Box Using the h:selectBooleanCheckbox Tag]. Because the checkbox is bound to the `specialOffer` property of `CashierBean`, a `UISelectBoolean` value, you can call the `isSelected` method of the @@ -1266,7 +1261,7 @@ property to determine whether to render a thank-you message: Similarly, you might want to acknowledge that a user subscribed to newsletters using the `h:selectManyCheckbox` tag, as described in -link:#BNASI[Displaying Components for Selecting Multiple Values]. To do +xref:jsf-page/jsf-page.adoc#BNASI[Displaying Components for Selecting Multiple Values]. To do so, you can retrieve the value of the `newsletters` property, the `String` array that holds the selected items: @@ -1284,9 +1279,9 @@ so, you can retrieve the value of the `newsletters` property, the An introductory thank-you message is displayed only if the `newsletters` array is not empty. Then a `ui:repeat` tag, a simple way to show values in a loop, displays the contents of the selected items in an itemized -list. (This tag is listed in link:#GJBFP[Table 8-2].) +list. (This tag is listed in xref:jsf-facelets/jsf-facelets.adoc#GJBFP[Table 8-2].) -[[BNARZ]][[using-data-bound-table-components]] +[[BNARZ]][[_using_data_bound_table_components]] === Using Data-Bound Table Components @@ -1404,7 +1399,7 @@ following: All data sources for data components have a `DataModel` wrapper. Unless you explicitly construct a `DataModel` wrapper, the Jakarta Server Faces implementation will create one around data of any of the other -acceptable types. See link:#BNATY[Writing Bean +acceptable types. See xref:jsf-develop/jsf-develop.adoc#BNATY[Writing Bean Properties] for more information on how to write properties for use with a data component. @@ -1431,7 +1426,7 @@ want to consider including a link or button that causes subsequent rows to display when clicked. By default, both `first` and `rows` are set to zero, and this causes all the rows of the underlying data to display. -link:#GKBUK[Table 10-7] shows the optional attributes for the +xref:jsf-page/jsf-page.adoc#GKBUK[Table 10-7] shows the optional attributes for the `h:dataTable` tag. [[sthref51]][[GKBUK]] @@ -1450,7 +1445,7 @@ link:#GKBUK[Table 10-7] shows the optional attributes for the |================================ -Each of the attributes in link:#GKBUK[Table 10-7] can specify more than +Each of the attributes in xref:jsf-page/jsf-page.adoc#GKBUK[Table 10-7] can specify more than one style. If `columnClasses` or `rowClasses` specifies more than one style, the styles are applied to the columns or rows in the order that the styles are listed in the attribute. For example, if `columnClasses` @@ -1465,7 +1460,7 @@ from the first column or row. Similarly, if the style attribute specifies fewer styles than there are columns or rows, the remaining columns or rows will be assigned styles starting from the first style. -[[BNASO]][[displaying-error-messages-with-the-hmessage-and-hmessages-tags]] +[[BNASO]][[_displaying_error_messages_with_the_hmessage_and_hmessages_tags]] === Displaying Error Messages with the h:message and h:messages Tags @@ -1532,7 +1527,7 @@ standard validators. An application architect can override these standard messages and supply error messages for custom converters and validators by registering custom error messages with the application. -[[GIQZD]][[creating-bookmarkable-urls-with-the-hbutton-and-hlink-tags]] +[[GIQZD]][[_creating_bookmarkable_urls_with_the_hbutton_and_hlink_tags]] === Creating Bookmarkable URLs with the h:button and h:link Tags @@ -1575,7 +1570,7 @@ This is a simple GET request that cannot pass any data from page to page. To create more complex GET requests and utilize the complete functionality of the `h:link` tag, use view parameters. -[[GIQWQ]][[using-view-parameters-to-configure-bookmarkable-urls]] +[[GIQWQ]][[_using_view_parameters_to_configure_bookmarkable_urls]] === Using View Parameters to Configure Bookmarkable URLs @@ -1642,12 +1637,12 @@ parameter values are read is as follows: 2. Navigation-case parameters 3. View parameters -[[sthref52]][[the-bookmarks-example-application]] +[[sthref52]][[_the_bookmarks_example_application]] === The bookmarks Example Application The `bookmarks` example application modifies the `hello1` application -described in link:#BNADX[A Web Module That Uses Jakarta Server +described in xref:webapp/webapp.adoc#BNADX[A Web Module That Uses Jakarta Server Faces Technology: The hello1 Example] to use a bookmarkable URL that uses view parameters. @@ -1655,18 +1650,18 @@ Like `hello1`, the application includes the `Hello.java` managed bean, an `index.xhtml` page, and a `response.xhtml` page. In addition, it includes a `personal.xhtml page`, to which a bookmarkable URL and view parameters are passed from the `response.xhtml` page, as described in -link:#GIQWQ[Using View Parameters to Configure Bookmarkable URLs]. +xref:jsf-page/jsf-page.adoc#GIQWQ[Using View Parameters to Configure Bookmarkable URLs]. You can use either NetBeans IDE or Maven to build, package, deploy, and run the `bookmarks` example. The source code for this example is in the `_tut-install_/examples/web/jsf/bookmarks/` directory. -[[CHDIEHEB]][[to-build-package-and-deploy-the-bookmarks-example-using-netbeans-ide]] +[[CHDIEHEB]][[_to_build_package_and_deploy_the_bookmarks_example_using_netbeans_ide]] ==== To Build, Package, and Deploy the bookmarks Example Using NetBeans IDE 1. Make sure that GlassFish Server has been started (see -link:#BNADI[Starting and Stopping GlassFish +xref:#BNADI[Starting and Stopping GlassFish Server]). 2. From the File menu, choose Open Project. 3. In the Open Project dialog box, navigate to: @@ -1683,12 +1678,12 @@ Build. This option builds the example application and deploys it to your GlassFish Server instance. -[[CHDEFJEF]][[to-build-package-and-deploy-the-bookmarks-example-using-maven]] +[[CHDEFJEF]][[_to_build_package_and_deploy_the_bookmarks_example_using_maven]] ==== To Build, Package, and Deploy the bookmarks Example Using Maven 1. Make sure that GlassFish Server has been started (see -link:#BNADI[Starting and Stopping GlassFish +xref:#BNADI[Starting and Stopping GlassFish Server]). 2. In a terminal window, go to: + @@ -1707,7 +1702,7 @@ This command builds and packages the application into a WAR file, `bookmarks.war`, that is located in the `target` directory. It then deploys the WAR file to your GlassFish Server instance. -[[CHDGEBCB]][[to-run-the-bookmarks-example]] +[[CHDGEBCB]][[_to_run_the_bookmarks_example]] ==== To Run the bookmarks Example @@ -1728,7 +1723,7 @@ Return. + The name in the greeting changes to what you typed. -[[GJGEP]][[resource-relocation-using-houtputscript-and-houtputstylesheet-tags]] +[[GJGEP]][[_resource_relocation_using_houtputscript_and_houtputstylesheet_tags]] === Resource Relocation Using h:outputScript and h:outputStylesheet Tags diff --git a/src/main/antora/modules/web/pages/jsf-page/jsf-page003.adoc b/src/main/antora/modules/web/pages/jsf-page/jsf-page003.adoc index 52abf66e..553cb57a 100644 --- a/src/main/antora/modules/web/pages/jsf-page/jsf-page003.adoc +++ b/src/main/antora/modules/web/pages/jsf-page/jsf-page003.adoc @@ -1,11 +1,11 @@ -[[BNARC]][[using-core-tags]] +[[BNARC]][[_using_core_tags]] == Using Core Tags The tags included in the Jakarta Server Faces core tag library are used to perform core actions that are not performed by HTML tags. -link:#GKVYB[Table 10-8] lists the event-handling core tags. +xref:jsf-page/jsf-page.adoc#GKVYB[Table 10-8] lists the event-handling core tags. [[sthref53]][[GKVYB]] @@ -27,7 +27,7 @@ component |======================================================================= -link:#GKVYY[Table 10-9] lists the data-conversion core tags. +xref:jsf-page/jsf-page.adoc#GKVYY[Table 10-9] lists the data-conversion core tags. [[sthref54]][[GKVYY]] @@ -46,7 +46,7 @@ component |======================================================================= -link:#GKVZG[Table 10-10] lists the facet core tags. +xref:jsf-page/jsf-page.adoc#GKVZG[Table 10-10] lists the facet core tags. [[sthref55]][[GKVZG]] @@ -62,7 +62,7 @@ its enclosing tag |======================================================================= -link:#GKVZA[Table 10-11] lists the core tags that represent items in a +xref:jsf-page/jsf-page.adoc#GKVZA[Table 10-11] lists the core tags that represent items in a list. [[sthref56]][[GKVZA]] @@ -77,7 +77,7 @@ list. |====================================================== -link:#GKVYV[Table 10-12] lists the validator core tags. +xref:jsf-page/jsf-page.adoc#GKVYV[Table 10-12] lists the validator core tags. [[sthref57]][[GKVYV]] @@ -103,7 +103,7 @@ link:#GKVYV[Table 10-12] lists the validator core tags. |======================================================================= -link:#GKVYU[Table 10-13] lists the core tags that fall into other +xref:jsf-page/jsf-page.adoc#GKVYU[Table 10-13] lists the core tags that fall into other categories. [[sthref58]][[GKVYU]] @@ -136,7 +136,7 @@ pushed to all instances of a socket containing the same channel name. These tags, which are used in conjunction with component tags, are explained in other sections of this tutorial. -link:#BNARE[Table 10-14] lists the sections that explain how to use +xref:jsf-page/jsf-page.adoc#BNARE[Table 10-14] lists the sections that explain how to use specific core tags. [[sthref59]][[BNARE]] @@ -147,45 +147,45 @@ specific core tags. |======================================================================= |*Tags* |*Where Explained* |Event-handling tags a| -link:#BNASZ[Registering Listeners on Components] +xref:jsf-page-core/jsf-page-core.adoc#BNASZ[Registering Listeners on Components] |Data-conversion tags a| -link:#BNAST[Using the Standard Converters] +xref:jsf-page-core/jsf-page-core.adoc#BNAST[Using the Standard Converters] -|`f:facet` |link:#BNARZ[Using Data-Bound Table -Components] and link:#BNASC[Laying Out Components with +|`f:facet` |xref:jsf-page/jsf-page.adoc#BNARZ[Using Data-Bound Table +Components] and xref:jsf-page/jsf-page.adoc#BNASC[Laying Out Components with the h:panelGrid and h:panelGroup Tags] |`f:loadBundle` a| -link:#BNAXY[Setting the Resource Bundle] +xref:webi18n/webi18n.adoc#BNAXY[Setting the Resource Bundle] |`f:metadata` a| -link:#GIQWQ[Using View Parameters to Configure +xref:jsf-page/jsf-page.adoc#GIQWQ[Using View Parameters to Configure Bookmarkable URLs] |`f:param` a| -link:#BNARU[Displaying a Formatted Message with the +xref:jsf-page/jsf-page.adoc#BNARU[Displaying a Formatted Message with the h:outputFormat Tag] |`f:selectItem` and `f:selectItems` a| -link:#BNASK[Using the f:selectItem and f:selectItems +xref:jsf-page/jsf-page.adoc#BNASK[Using the f:selectItem and f:selectItems Tags] -|Validator tags |link:#BNATC[Using the Standard +|Validator tags |xref:jsf-page-core/jsf-page-core.adoc#BNATC[Using the Standard Validators] |`f:ajax` a| -link:#GKIOW[Chapter 13, "Using Ajax with Jakarta Server Faces +xref:jsf-ajax/jsf-ajax.adoc#GKIOW[Chapter 13, "Using Ajax with Jakarta Server Faces Technology"] |`f:websocket` a| -link:#using-websockets-with-javaserver-faces-technology[Chapter 17, "Using WebSockets with Jakarta Server Faces Technology"] +xref:jsf-ws/jsf-ws.adoc#_using_websockets_with_javaserver_faces_technology[Chapter 17, "Using WebSockets with Jakarta Server Faces Technology"] |======================================================================= diff --git a/src/main/antora/modules/web/pages/jsf-ws/jsf-ws.adoc b/src/main/antora/modules/web/pages/jsf-ws/jsf-ws.adoc index c92d2a1c..c8c3994d 100644 --- a/src/main/antora/modules/web/pages/jsf-ws/jsf-ws.adoc +++ b/src/main/antora/modules/web/pages/jsf-ws/jsf-ws.adoc @@ -1,6 +1,6 @@ = Using WebSockets with Jakarta Server Faces Technology -[[using-websockets-with-javaserver-faces-technology]] +[[_using_websockets_with_javaserver_faces_technology]] This chapter describes using WebSockets in Jakarta Server Faces web applications. diff --git a/src/main/antora/modules/web/pages/jsf-ws/jsf-ws001.adoc b/src/main/antora/modules/web/pages/jsf-ws/jsf-ws001.adoc index f69cc650..3cf22a0f 100644 --- a/src/main/antora/modules/web/pages/jsf-ws/jsf-ws001.adoc +++ b/src/main/antora/modules/web/pages/jsf-ws/jsf-ws001.adoc @@ -1,4 +1,4 @@ -[[about-websockets-in-jsf]] +[[_about_websockets_in_jsf]] == About WebSockets in JSF You use the `f:websocket tag` in a view to allow server-side communications diff --git a/src/main/antora/modules/web/pages/jsf-ws/jsf-ws002.adoc b/src/main/antora/modules/web/pages/jsf-ws/jsf-ws002.adoc index 74c827bc..2724470c 100644 --- a/src/main/antora/modules/web/pages/jsf-ws/jsf-ws002.adoc +++ b/src/main/antora/modules/web/pages/jsf-ws/jsf-ws002.adoc @@ -1,4 +1,4 @@ -[[configuring-websockets]] +[[_configuring_websockets]] == Configuring WebSockets To configure WebSockets for use in server faces web applications, first enable the @@ -25,7 +25,7 @@ to explicitly specify the port: ---- -[[websocket-usage-client-side]] +[[_websocket_usage_client_side]] === WebSocket Usage: Client Side Declare the `f:websocket tag` in the server faces view with a channel name and @@ -62,7 +62,7 @@ network error or server restart. It will not auto-reconnect when the very first connection attempt fails. The WebSocket will be implicitly closed after the document is unloaded. -[[websocket-usage-server-side]] +[[_websocket_usage_server_side]] === WebSocket Usage: Server Side On the Java programming side, inject a `PushContext` using the `@Push` annotation diff --git a/src/main/antora/modules/web/pages/jsf-ws/jsf-ws003.adoc b/src/main/antora/modules/web/pages/jsf-ws/jsf-ws003.adoc index 4c2bba29..5b1fc546 100644 --- a/src/main/antora/modules/web/pages/jsf-ws/jsf-ws003.adoc +++ b/src/main/antora/modules/web/pages/jsf-ws/jsf-ws003.adoc @@ -1,10 +1,10 @@ -[[using-the-fwebsocket-tag]] +[[_using_the_fwebsocket_tag]] == Using the f:websocket Tag -link:#attributes-of-the-f:websocket-tag[Table 17-1] describes the attributes of +xref:jsf-ws/jsf-ws.adoc#_attributes_of_the_f:websocket_tag[Table 17-1] describes the attributes of the `f:websocket` tag. -[[attributes-of-the-f:websocket-tag]] +[[_attributes_of_the_f:websocket_tag]] *Table 17-1 Attributes of the `f:websocket` Tag* [width="85%",cols="15%,15%,55%"] diff --git a/src/main/antora/modules/web/pages/jsf-ws/jsf-ws004.adoc b/src/main/antora/modules/web/pages/jsf-ws/jsf-ws004.adoc index c3995f46..b8775bd0 100644 --- a/src/main/antora/modules/web/pages/jsf-ws/jsf-ws004.adoc +++ b/src/main/antora/modules/web/pages/jsf-ws/jsf-ws004.adoc @@ -1,4 +1,4 @@ -[[websocket-scopes-and-users]] +[[_websocket_scopes_and_users]] == WebSocket Scopes and Users By default, the WebSocket is application-scoped. For example, any view or diff --git a/src/main/antora/modules/web/pages/jsf-ws/jsf-ws005.adoc b/src/main/antora/modules/web/pages/jsf-ws/jsf-ws005.adoc index a15829ae..c6c1b7a2 100644 --- a/src/main/antora/modules/web/pages/jsf-ws/jsf-ws005.adoc +++ b/src/main/antora/modules/web/pages/jsf-ws/jsf-ws005.adoc @@ -1,4 +1,4 @@ -[[conditionally-connecting-websockets]] +[[_conditionally_connecting_websockets]] == Conditionally Connecting WebSockets You can use the optional connected attribute to control whether to @@ -35,7 +35,7 @@ function someWebsocketListener(message) { } ---- -[[websocket-events-server]] +[[_websocket_events_server]] === WebSocket Events: Server When a session or view-scoped socket is automatically closed with close reason @@ -63,7 +63,7 @@ public class WebsocketObserver { } ---- -[[websocket-events-clients]] +[[_websocket_events_clients]] === WebSocket Events: Clients You can use the optional `onopen` JavaScript listener function to listen for diff --git a/src/main/antora/modules/web/pages/jsf-ws/jsf-ws006.adoc b/src/main/antora/modules/web/pages/jsf-ws/jsf-ws006.adoc index 92cb37d7..6cdba3ba 100644 --- a/src/main/antora/modules/web/pages/jsf-ws/jsf-ws006.adoc +++ b/src/main/antora/modules/web/pages/jsf-ws/jsf-ws006.adoc @@ -1,4 +1,4 @@ -[[websocket-security-considerations]] +[[_websocket_security_considerations]] == WebSocket Security Considerations If the WebSocket is declared in a page which is restricted to logged-in users diff --git a/src/main/antora/modules/web/pages/jsf-ws/jsf-ws007.adoc b/src/main/antora/modules/web/pages/jsf-ws/jsf-ws007.adoc index 1c05c620..705b23a3 100644 --- a/src/main/antora/modules/web/pages/jsf-ws/jsf-ws007.adoc +++ b/src/main/antora/modules/web/pages/jsf-ws/jsf-ws007.adoc @@ -1,4 +1,4 @@ -[[using-ajax-with-websockets]] +[[_using_ajax_with_websockets]] == Using Ajax With WebSockets If you want to perform complex UI updates depending on the received push diff --git a/src/main/antora/modules/web/pages/jsonb/jsonb.adoc b/src/main/antora/modules/web/pages/jsonb/jsonb.adoc index dd0c1729..b50e8b4b 100644 --- a/src/main/antora/modules/web/pages/jsonb/jsonb.adoc +++ b/src/main/antora/modules/web/pages/jsonb/jsonb.adoc @@ -1,12 +1,12 @@ -[[json-binding]] +[[_json_binding]] = JSON Binding This chapter describes the Jakarta JSON Binding. JSON is a data exchange format widely used in web services and other connected applications. For a brief overview of JSON, see -link:#introduction-to-json[Introduction to JSON]. +xref:jsonp/jsonp.adoc#_introduction_to_json[Introduction to JSON]. -The link:https://jakarta.ee/specifications/json-binding/[Jakarta JSON Binding] specification provides a standard +The httpss://jakarta.ee/specifications/json-binding/[Jakarta JSON Binding] specification provides a standard binding layer (metadata and runtime) between Java classes and JSON documents. One Jakarta JSON Binding reference implementation is Yasson, which is developed through Eclipse.org and is included as part of GlassFish Server. You can learn more about Yasson at https://projects.eclipse.org/projects/ee4j.yasson. diff --git a/src/main/antora/modules/web/pages/jsonb/jsonb001.adoc b/src/main/antora/modules/web/pages/jsonb/jsonb001.adoc index 447b9d7d..d6bf7d6b 100644 --- a/src/main/antora/modules/web/pages/jsonb/jsonb001.adoc +++ b/src/main/antora/modules/web/pages/jsonb/jsonb001.adoc @@ -1,4 +1,4 @@ -[[json-binding-in-the-jakarta-ee-platform]] +[[_json_binding_in_the_jakarta_ee_platform]] == JSON Binding in the Jakarta EE Platform Jakarta EE includes support for the Jakarta JSON Binding spec, which provides an API that can serialize @@ -6,7 +6,7 @@ Java objects to JSON documents and deserialize JSON documents to Java objects. Jakarta JSON Binding contains the following packages: * The `javax.json.bind` package contains the binding interface, the builder interface, and -a configuration class. link:#main-classes-and-interfaces-in-bind[Table 21-1] lists the main classes +a configuration class. xref:jsonb/jsonb.adoc#_main_classes_and_interfaces_in_bind[Table 21-1] lists the main classes and interfaces in this package. * The `javax.json.bind.adapter` package contains the `JsonbAdapter` interface, which provides @@ -17,19 +17,19 @@ binding behavior. Annotations can be used for field, JavaBean property, type, or elements. * The `javax.json.bind.config` package interfaces and classes for customizing default binding behavior. -link:#main-classes-and-interfaces-in-config[Table 21-2] lists the main classes +xref:jsonb/jsonb.adoc#_main_classes_and_interfaces_in_config[Table 21-2] lists the main classes and interfaces in this package. * The `javax.json.bind.serializer` package contains interfaces that are used to create serialization and deserialization routines for custom types that cannot be easily mapped using the `JsonbAdapter` methods. - link:#main-classes-and-interfaces-in-serializer[Table 21-3] lists the main interfaces in this package. + xref:jsonb/jsonb.adoc#_main_classes_and_interfaces_in_serializer[Table 21-3] lists the main interfaces in this package. * The `javax.json.bind.spi` package contains a Service Provider Interface (SPI) for creating JSON Binding implementations. This package contains the `JsonbProvider` class, which contains the methods that a service provider implements. -[[main-classes-and-interfaces-in-bind]] +[[_main_classes_and_interfaces_in_bind]] *Table 21-1 Main Classes and Interfaces in javax.json.bind* @@ -47,7 +47,7 @@ binding strategies and properties for configuring custom serializers and deseria |`JsonbException` | Indicates that a problem occurred during JSON binding. |======================================================================= -[[main-classes-and-interfaces-in-config]] +[[_main_classes_and_interfaces_in_config]] *Table 21-2 Main Classes and Interfaces in javax.json.bind.config* [width="99%",cols="25%,75%"] @@ -64,7 +64,7 @@ overriding the default scope and field access behavior. |======================================================================= -[[main-classes-and-interfaces-in-serializer]] +[[_main_classes_and_interfaces_in_serializer]] *Table 21-3 Main Classes and Interfaces in javax.json.bind.serializer* [width="99%",cols="25%,75%"] diff --git a/src/main/antora/modules/web/pages/jsonb/jsonb002.adoc b/src/main/antora/modules/web/pages/jsonb/jsonb002.adoc index 69791479..5e49ebc6 100644 --- a/src/main/antora/modules/web/pages/jsonb/jsonb002.adoc +++ b/src/main/antora/modules/web/pages/jsonb/jsonb002.adoc @@ -1,12 +1,12 @@ -[[overview-of-the-json-binding-api]] +[[_overview_of_the_json_binding_api]] == Overview of the JSON Binding API This section provides basic instructions for using the Jakarta JSON Binding client API. The instructions provide a -basis for understanding the link:jsonb003.html[jsonbbasics Example Application]. -Refer to the link:http://json-b.net/index.html[Jakarta JSON Binding] project page for API documentation and a more detailed +basis for understanding the xref:jsonb003.html[jsonbbasics Example Application]. +Refer to the https://json-b.net/index.html[Jakarta JSON Binding] project page for API documentation and a more detailed User Guide. -[[creating-a-jasonb-instance]] +[[_creating_a_jasonb_instance]] === Creating a jasonb Instance A `jsonb` instance provides access to methods for binding objects to JSON. @@ -20,7 +20,7 @@ Jsonb jsonb = JsonbBuilder.create(); ---- -[[using-the-default-mapping]] +[[_using_the_default_mapping]] === Using the Default Mapping Jakarta JSON Binding provides default mappings for serializing and deserializing basic Java and Java SE types as well @@ -45,7 +45,7 @@ person = jsonb.fromJson("{name:\"joe"\"}", Person.class); ---- -[[using-customizations]] +[[_using_customizations]] === Using Customizations Jakarta JSON Binding supports many ways to customize the default mapping behavior. For runtime customizations, a `JsonbConfig` configuration object is used when creating the `jsonbinstance`. The `JsonbConfig` @@ -64,7 +64,7 @@ JsonbConfig config = new JsonbConfig() Jsonb jsonb = JsonbBuilder.create(config); ---- -[[using-annotations]] +[[_using_annotations]] === Using Annotations Jakarta JSON Binding includes many annotations that can be used at compile time to customize the default mapping behavior. The following example uses the `@JsonbProperty` annotation to change the `name` field to `person-name` when diff --git a/src/main/antora/modules/web/pages/jsonb/jsonb003.adoc b/src/main/antora/modules/web/pages/jsonb/jsonb003.adoc index 73ccdf36..b4f9b534 100644 --- a/src/main/antora/modules/web/pages/jsonb/jsonb003.adoc +++ b/src/main/antora/modules/web/pages/jsonb/jsonb003.adoc @@ -1,4 +1,4 @@ -[[running-the-jsonbbasics-example-application]] +[[_running_the_jsonbbasics_example_application]] == Running the jsonbbasics Example Application This section describes how to build and run the `jsonbbasics` example @@ -9,7 +9,7 @@ object. The `jsonbbasics` example application is in the `_tut-install_/examples/web/jsonb/jsonbbasics` directory. -[[components-of-the-jsonbbasics-example-application]] +[[_components_of_the_jsonbbasics_example_application]] === Components of the jsonbbasics Example Application The `jsonbbasics` example application contains the following files. @@ -19,7 +19,7 @@ The `jsonbbasics` example application contains the following files. ** The `jsongenerated.xhtml` page contains a text area that displays the data in JSON format. * The `jsonbBean.java` managed bean, which is a session-scoped managed bean that stores the data from the form and directs the navigation between the Facelets pages. This file contains code that uses the JSON Binding API. -[[running-the-jsonbbasics-example-application-2]] +[[_running_the_jsonbbasics_example_application_2]] === Running the jsonbbasics Example Application This section describes how to run the `jsonbbasics` example application @@ -27,7 +27,7 @@ from the command line using Maven. To run the jsonbbasics example application using Maven: -. Make sure that GlassFish Server has been started (see link:#BNADI[Starting and Stopping GlassFish Server]). +. Make sure that GlassFish Server has been started (see xref:#BNADI[Starting and Stopping GlassFish Server]). . In a terminal window, go to: + [source,java] diff --git a/src/main/antora/modules/web/pages/jsonb/jsonb004.adoc b/src/main/antora/modules/web/pages/jsonb/jsonb004.adoc index c9660255..8d1df669 100644 --- a/src/main/antora/modules/web/pages/jsonb/jsonb004.adoc +++ b/src/main/antora/modules/web/pages/jsonb/jsonb004.adoc @@ -1,4 +1,4 @@ -[[further-information-about-the-java-api-for-json-binding]] +[[_further_information_about_the_java_api_for_json_binding]] == Further Information about the Jakarta JSON Binding For more information on Jakarta JSON Binding, see: diff --git a/src/main/antora/modules/web/pages/jsonp/jsonp.adoc b/src/main/antora/modules/web/pages/jsonp/jsonp.adoc index 8bb3e942..a1d9c968 100644 --- a/src/main/antora/modules/web/pages/jsonp/jsonp.adoc +++ b/src/main/antora/modules/web/pages/jsonp/jsonp.adoc @@ -1,4 +1,4 @@ -[[json-processing]] +[[_json_processing]] = JSON Processing diff --git a/src/main/antora/modules/web/pages/jsonp/jsonp001.adoc b/src/main/antora/modules/web/pages/jsonp/jsonp001.adoc index 68405b1f..b0831232 100644 --- a/src/main/antora/modules/web/pages/jsonp/jsonp001.adoc +++ b/src/main/antora/modules/web/pages/jsonp/jsonp001.adoc @@ -1,4 +1,4 @@ -[[introduction-to-json]] +[[_introduction_to_json]] == Introduction to JSON JSON is a text-based data exchange format derived from JavaScript that @@ -7,7 +7,7 @@ sections provide an introduction to JSON syntax, an overview of JSON uses, and a description of the most common approaches to generate and parse JSON. -[[json-syntax]] +[[_json_syntax]] === JSON Syntax JSON defines only two data structures: objects and arrays. An object is @@ -49,7 +49,7 @@ including another array or an object. * When objects and arrays contain other objects or arrays, the data has a tree-like structure. -[[uses-of-json]] +[[_uses_of_json]] === Uses of JSON JSON is often used as a common format to serialize and deserialize data @@ -73,7 +73,7 @@ because JSON does not have closing tags. Unlike XML, JSON does not have a widely accepted schema for defining and validating the structure of JSON data. -[[generating-and-parsing-json-data]] +[[_generating_and_parsing_json_data]] === Generating and Parsing JSON Data For generating and parsing JSON data, there are two programming models, @@ -96,7 +96,7 @@ the data. The streaming model generates JSON output to a given stream by making a function call with one element at a time. There are many JSON generators and parsers available for different -programming languages and environments. link:#BABDFHHD[JSON +programming languages and environments. xref:#BABDFHHD[JSON Processing in the Jakarta EE Platform] describes the functionality provided by Jakarta JSON Processing. diff --git a/src/main/antora/modules/web/pages/jsonp/jsonp002.adoc b/src/main/antora/modules/web/pages/jsonp/jsonp002.adoc index 3d49853b..4d23bb40 100644 --- a/src/main/antora/modules/web/pages/jsonp/jsonp002.adoc +++ b/src/main/antora/modules/web/pages/jsonp/jsonp002.adoc @@ -1,22 +1,22 @@ -[[json-processing-in-the-jakarta-ee-platform]] +[[_json_processing_in_the_jakarta_ee_platform]] == JSON Processing in the Jakarta EE Platform Jakarta EE includes support for the Jakarta JSON Processing spec, which provides an API to parse, transform, and query JSON data using the object model or the streaming -model described in link:#BABJJACI[Generating and Parsing +model described in xref:#BABJJACI[Generating and Parsing JSON Data]. Jakarta JSON Processing contains the following packages: * The `javax.json` package contains a reader interface, a writer interface, a model builder interface for the object model, and utility classes and Java types for JSON elements. This package also includes -several classes that implement other JSON-related standards: link:http://tools.ietf.org/html/rfc6901[JSON Pointer], -link:http://tools.ietf.org/html/rfc6902[JSON Patch], and link:http://tools.ietf.org/html/rfc7396[JSON Merge Patch]. +several classes that implement other JSON-related standards: https://tools.ietf.org/html/rfc6901[JSON Pointer], +https://tools.ietf.org/html/rfc6902[JSON Patch], and https://tools.ietf.org/html/rfc7396[JSON Merge Patch]. These standards are used to retrieve, transform or manipulate values -in an object model. link:#CHDJJCBE[Table 20-1] lists the main classes +in an object model. xref:jsonp/jsonp.adoc#CHDJJCBE[Table 20-1] lists the main classes and interfaces in this package. * The `javax.json.stream` package contains a parser interface and a -generator interface for the streaming model. link:#CHDIHCEG[Table 20-2] +generator interface for the streaming model. xref:jsonp/jsonp.adoc#CHDIHCEG[Table 20-2] lists the main classes and interfaces in this package. * The `javax.json.spi` package contains a Service Provider Interface (SPI) to plug in implementations for JSON processing objects. This package diff --git a/src/main/antora/modules/web/pages/jsonp/jsonp003.adoc b/src/main/antora/modules/web/pages/jsonp/jsonp003.adoc index 4a5b1d42..43330940 100644 --- a/src/main/antora/modules/web/pages/jsonp/jsonp003.adoc +++ b/src/main/antora/modules/web/pages/jsonp/jsonp003.adoc @@ -1,4 +1,4 @@ -[[using-the-object-model-api]] +[[_using_the_object_model_api]] == Using the Object Model API This section describes four use cases of the object model API: creating @@ -6,7 +6,7 @@ an object model from JSON data, creating an object model from application code, navigating an object model, and writing an object model to a stream. -[[creating-an-object-model-from-json-data]] +[[_creating_an_object_model_from_json_data]] === Creating an Object Model from JSON Data The following code demonstrates how to create an object model from JSON @@ -30,7 +30,7 @@ represents the top of the tree and can be used to navigate the tree or to write it to a stream as JSON data. -[[creating-an-object-model-from-application-code]] +[[_creating_an_object_model_from_application_code]] === Creating an Object Model from Application Code The following code demonstrates how to create an object model from @@ -85,10 +85,10 @@ a new `JsonArrayBuilder` object or a new `JsonObjectBuilder` object to the corresponding `add` method, as shown in this example. The resulting tree represents the JSON data from -link:#BABGHEHG[JSON Syntax]. +xref:#BABGHEHG[JSON Syntax]. -[[navigating-an-object-model]] +[[_navigating_an_object_model]] === Navigating an Object Model The following code demonstrates a simple approach to navigating an @@ -136,8 +136,8 @@ public static void navigateTree(JsonValue tree, String key) { ---- The method `navigateTree` can be used with the models built in -link:#BABBHEBA[Creating an Object Model from JSON Data] and -link:#BABIGIAF[Creating an Object Model from Application Code] as +xref:#BABBHEBA[Creating an Object Model from JSON Data] and +xref:#BABIGIAF[Creating an Object Model from Application Code] as follows: [source,java] @@ -161,7 +161,7 @@ whose key is `name`. For arrays, `JsonArray` implements the `Set` instance returned by `JsonObject.keySet` and with instances of `JsonArray`, as shown in this example. -The `navigateTree` method for the model built in link:#BABIGIAF[Creating +The `navigateTree` method for the model built in xref:#BABIGIAF[Creating an Object Model from Application Code] produces the following output: [source,java] @@ -183,11 +183,11 @@ Key type: STRING home Key number: STRING 222-222-2222 ---- -[[writing-an-object-model-to-a-stream]] +[[_writing_an_object_model_to_a_stream]] === Writing an Object Model to a Stream -The object models created in link:#BABBHEBA[Creating an Object Model -from JSON Data] and link:#BABIGIAF[Creating an Object Model from +The object models created in xref:#BABBHEBA[Creating an Object Model +from JSON Data] and xref:#BABIGIAF[Creating an Object Model from Application Code] can be written to a stream using the `JsonWriter` class as follows: diff --git a/src/main/antora/modules/web/pages/jsonp/jsonp004.adoc b/src/main/antora/modules/web/pages/jsonp/jsonp004.adoc index 02b90e65..c9920971 100644 --- a/src/main/antora/modules/web/pages/jsonp/jsonp004.adoc +++ b/src/main/antora/modules/web/pages/jsonp/jsonp004.adoc @@ -1,9 +1,9 @@ -[[using-the-streaming-api]] +[[_using_the_streaming_api]] == Using the Streaming API This section describes two use cases of the streaming API. -[[reading-json-data-using-a-parser]] +[[_reading_json_data_using_a_parser]] === Reading JSON Data Using a Parser The streaming API is the most efficient approach for parsing JSON text. @@ -89,7 +89,7 @@ END_OBJECT ---- -[[writing-json-data-using-a-generator]] +[[_writing_json_data_using_a_generator]] === Writing JSON Data Using a Generator The following code demonstrates how to write JSON data to a file using diff --git a/src/main/antora/modules/web/pages/jsonp/jsonp005.adoc b/src/main/antora/modules/web/pages/jsonp/jsonp005.adoc index a0b54775..36cb7bbe 100644 --- a/src/main/antora/modules/web/pages/jsonp/jsonp005.adoc +++ b/src/main/antora/modules/web/pages/jsonp/jsonp005.adoc @@ -1,16 +1,16 @@ -[[json-in-jakarta-ee-restful-web-services]] +[[_json_in_jakarta_ee_restful_web_services]] == JSON in Jakarta EE RESTful Web Services This section explains how the Jakarta JSON Processing is related to other Jakarta EE packages that provide JSON support for RESTful web -services. See link:#GIEPU[Chapter 32, "Building RESTful Web +services. See xref:#GIEPU[Chapter 32, "Building RESTful Web Services with Jakarta RESTful Web Services,"] for more information on RESTful web services. Jersey, the Jakarta RESTful Web Services implementation included in GlassFish Server, provides support for binding JSON data from RESTful resource methods to Java objects using Jakarta XML Binding, as described in -link:#GKKNJ[Using Jakarta RESTful Web Services with JAXB] in -link:#GJJXE[Chapter 34, "Jakarta RESTful Web Services: Advanced Topics and +xref:#GKKNJ[Using Jakarta RESTful Web Services with JAXB] in +xref:#GJJXE[Chapter 34, "Jakarta RESTful Web Services: Advanced Topics and an Example"]. However, JSON support is not part of Jakarta RESTful Web Services or Jakarta XML Binding, so that procedure may not work for Jakarta EE implementations other than GlassFish Server. diff --git a/src/main/antora/modules/web/pages/jsonp/jsonp006.adoc b/src/main/antora/modules/web/pages/jsonp/jsonp006.adoc index ad6e919e..0e16615b 100644 --- a/src/main/antora/modules/web/pages/jsonp/jsonp006.adoc +++ b/src/main/antora/modules/web/pages/jsonp/jsonp006.adoc @@ -1,4 +1,4 @@ -[[the-jsonpmodel-example-application]] +[[_the_jsonpmodel_example_application]] == The jsonpmodel Example Application This section describes how to build and run the `jsonpmodel` example @@ -9,7 +9,7 @@ write JSON data using the object model API. The `jsonpmodel` example application is in the `_tut-install_/examples/web/jsonp/jsonpmodel` directory. -[[components-of-the-jsonpmodel-example-application]] +[[_components_of_the_jsonpmodel_example_application]] === Components of the jsonpmodel Example Application The `jsonpmodel` example application contains the following files. @@ -30,24 +30,24 @@ uses the JSON object model API. The code used in `ObjectModelBean.java` to create an object model from the data in the form is similar to the example in -link:#BABIGIAF[Creating an Object Model from Application +xref:#BABIGIAF[Creating an Object Model from Application Code]. The code to write JSON output from the model is similar to the -example in link:#BABHEJFF[Writing an Object Model to a +example in xref:#BABHEJFF[Writing an Object Model to a Stream]. The code to navigate the object model tree is similar to the -example in link:#BABJHEHG[Navigating an Object Model]. +example in xref:#BABJHEHG[Navigating an Object Model]. -[[running-the-jsonpmodel-example-application]] +[[_running_the_jsonpmodel_example_application]] === Running the jsonpmodel Example Application This section describes how to run the `jsonpmodel` example application using NetBeans IDE and from the command line. -[[to-run-the-jsonpmodel-example-application-using-netbeans-ide]] +[[_to_run_the_jsonpmodel_example_application_using_netbeans_ide]] ==== To Run the jsonpmodel Example Application Using NetBeans IDE 1. Make sure that GlassFish Server has been started (see -link:#BNADI[Starting and Stopping GlassFish +xref:#BNADI[Starting and Stopping GlassFish Server]). 2. From the File menu, choose Open Project. 3. In the Open Project dialog box, navigate to: @@ -76,11 +76,11 @@ from the form. nodes of the object model tree. -[[to-run-the-jsonpmodel-example-application-using-maven]] +[[_to_run_the_jsonpmodel_example_application_using_maven]] ==== To Run the jsonpmodel Example Application Using Maven 1. Make sure that GlassFish Server has been started (see -link:#BNADI[Starting and Stopping GlassFish +xref:#BNADI[Starting and Stopping GlassFish Server]). 2. In a terminal window, go to: + diff --git a/src/main/antora/modules/web/pages/jsonp/jsonp007.adoc b/src/main/antora/modules/web/pages/jsonp/jsonp007.adoc index c90f3549..eb65922c 100644 --- a/src/main/antora/modules/web/pages/jsonp/jsonp007.adoc +++ b/src/main/antora/modules/web/pages/jsonp/jsonp007.adoc @@ -1,4 +1,4 @@ -[[the-jsonpstreaming-example-application]] +[[_the_jsonpstreaming_example_application]] == The jsonpstreaming Example Application This section describes how to build and run the `jsonpstreaming` example @@ -9,7 +9,7 @@ write JSON output using the streaming API. The `jsonpstreaming` example application is in the `_tut-install_/examples/web/jsonp/jsonpstreaming` directory. -[[components-of-the-jsonpstreaming-example-application]] +[[_components_of_the_jsonpstreaming_example_application]] === Components of the jsonpstreaming Example Application The `jsonpstreaming` example application contains the following files. @@ -29,23 +29,23 @@ the Facelets pages. This file also contains code that uses the JSON streaming API. The code used in `StreamingBean.java` to write JSON data to a file is -similar to the example in link:#BABGJEEF[Writing JSON Data +similar to the example in xref:#BABGJEEF[Writing JSON Data Using a Generator]. The code to parse JSON data from a file is similar -to the example in link:#BABGCHIG[Reading JSON Data Using a +to the example in xref:#BABGCHIG[Reading JSON Data Using a Parser]. -[[running-the-jsonpstreaming-example-application]] +[[_running_the_jsonpstreaming_example_application]] === Running the jsonpstreaming Example Application This section describes how to run the `jsonpstreaming` example application using NetBeans IDE and from the command line. -[[to-run-the-jsonpstreaming-example-application-using-netbeans-ide]] +[[_to_run_the_jsonpstreaming_example_application_using_netbeans_ide]] ==== To Run the jsonpstreaming Example Application Using NetBeans IDE 1. Make sure that GlassFish Server has been started (see -link:#BNADI[Starting and Stopping GlassFish +xref:#BNADI[Starting and Stopping GlassFish Server]). 2. From the File menu, choose Open Project. 3. In the Open Project dialog box, navigate to: @@ -74,11 +74,11 @@ page shows the contents of the text file. lists the parser events for the JSON data in the text file. -[[to-run-the-jsonpstreaming-example-application-using-maven]] +[[_to_run_the_jsonpstreaming_example_application_using_maven]] ==== To Run the jsonpstreaming Example Application Using Maven 1. Make sure that GlassFish Server has been started (see -link:#BNADI[Starting and Stopping GlassFish +xref:#BNADI[Starting and Stopping GlassFish Server]). 2. In a terminal window, go to: + diff --git a/src/main/antora/modules/web/pages/jsonp/jsonp008.adoc b/src/main/antora/modules/web/pages/jsonp/jsonp008.adoc index 0abe0025..e9e01954 100644 --- a/src/main/antora/modules/web/pages/jsonp/jsonp008.adoc +++ b/src/main/antora/modules/web/pages/jsonp/jsonp008.adoc @@ -1,4 +1,4 @@ -[[further-information-about-the-java-api-for-json-processing]] +[[_further_information_about_the_java_api_for_json_processing]] == Further Information about the Jakarta JSON Processing For more information on JSON processing in Jakarta EE, see the Jakarta JSON Processing specification: diff --git a/src/main/antora/modules/web/pages/servlets/servlets.adoc b/src/main/antora/modules/web/pages/servlets/servlets.adoc index 397dce36..f41afc6b 100644 --- a/src/main/antora/modules/web/pages/servlets/servlets.adoc +++ b/src/main/antora/modules/web/pages/servlets/servlets.adoc @@ -1,7 +1,7 @@ = Jakarta Servlet Technology -[[BNAFD]][[java-servlet-technology]] +[[BNAFD]][[_java_servlet_technology]] Jakarta Servlet technology provides dynamic, user-oriented content in web applications using a request-response programming model. diff --git a/src/main/antora/modules/web/pages/servlets/servlets001.adoc b/src/main/antora/modules/web/pages/servlets/servlets001.adoc index f95ec77c..0c2aa2f1 100644 --- a/src/main/antora/modules/web/pages/servlets/servlets001.adoc +++ b/src/main/antora/modules/web/pages/servlets/servlets001.adoc @@ -1,4 +1,4 @@ -[[BNAFE]][[what-is-a-servlet]] +[[BNAFE]][[_what_is_a_servlet]] == What Is a Servlet? diff --git a/src/main/antora/modules/web/pages/servlets/servlets002.adoc b/src/main/antora/modules/web/pages/servlets/servlets002.adoc index 7b1812da..79635d4c 100644 --- a/src/main/antora/modules/web/pages/servlets/servlets002.adoc +++ b/src/main/antora/modules/web/pages/servlets/servlets002.adoc @@ -1,4 +1,4 @@ -[[BNAFI]][[servlet-lifecycle]] +[[BNAFI]][[_servlet_lifecycle]] == Servlet Lifecycle @@ -9,14 +9,14 @@ container performs the following steps. . If an instance of the servlet does not exist, the web container: . Loads the servlet class . Creates an instance of the servlet class -. Initializes the servlet instance by calling the `init` method (initialization is covered in link:#BNAFU[Creating and Initializing a Servlet]) -. The container invokes the `service` method, passing request and response objects. Service methods are discussed in link:#BNAFV[Writing Service Methods]. +. Initializes the servlet instance by calling the `init` method (initialization is covered in xref:servlets/servlets.adoc#BNAFU[Creating and Initializing a Servlet]) +. The container invokes the `service` method, passing request and response objects. Service methods are discussed in xref:servlets/servlets.adoc#BNAFV[Writing Service Methods]. If it needs to remove the servlet, the container finalizes the servlet by calling the servlet's `destroy` method. For more information, see -link:#BNAGS[Finalizing a Servlet]. +xref:servlets/servlets.adoc#BNAGS[Finalizing a Servlet]. -[[BNAFJ]][[handling-servlet-lifecycle-events]] +[[BNAFJ]][[_handling_servlet_lifecycle_events]] === Handling Servlet Lifecycle Events @@ -25,12 +25,12 @@ listener objects whose methods get invoked when lifecycle events occur. To use these listener objects, you must define and specify the listener class. -[[BNAFK]][[defining-the-listener-class]] +[[BNAFK]][[_defining_the_listener_class]] ==== Defining the Listener Class You define a listener class as an implementation of a listener -interface. link:#BNAFL[Table 18-1] lists the events that can be +interface. xref:servlets/servlets.adoc#BNAFL[Table 18-1] lists the events that can be monitored and the corresponding interface that must be implemented. When a listener method is invoked, it is passed an event that contains information appropriate to the event. For example, the methods in the @@ -100,7 +100,7 @@ public class SimpleServletListener implements ServletContextListener, ... ---- -[[BNAFN]][[handling-servlet-errors]] +[[BNAFN]][[_handling_servlet_errors]] === Handling Servlet Errors diff --git a/src/main/antora/modules/web/pages/servlets/servlets003.adoc b/src/main/antora/modules/web/pages/servlets/servlets003.adoc index 42561fbc..9c354d23 100644 --- a/src/main/antora/modules/web/pages/servlets/servlets003.adoc +++ b/src/main/antora/modules/web/pages/servlets/servlets003.adoc @@ -1,4 +1,4 @@ -[[BNAFO]][[sharing-information]] +[[BNAFO]][[_sharing_information]] == Sharing Information @@ -10,16 +10,16 @@ accomplish their tasks. Web components can do so by doing the following. * Using a database. * Invoking other web resources. The Jakarta Servlet technology mechanisms that allow a web component to invoke other web resources are described -in link:#BNAGI[Invoking Other Web Resources]. +in xref:servlets/servlets.adoc#BNAGI[Invoking Other Web Resources]. -[[BNAFP]][[using-scope-objects]] +[[BNAFP]][[_using_scope_objects]] === Using Scope Objects Collaborating web components share information by means of objects that are maintained as attributes of four scope objects. You access these attributes by using the `getAttribute` and `setAttribute` methods of the -class representing the scope. link:#BNAFQ[Table 18-2] lists the scope +class representing the scope. xref:servlets/servlets.adoc#BNAFQ[Table 18-2] lists the scope objects. [[sthref98]][[BNAFQ]] @@ -30,11 +30,11 @@ objects. |======================================================================= |*Scope Object* |*Class* |*Accessible From* |Web context |`javax.servlet.ServletContext` |Web components within a -web context. See link:#BNAGL[Accessing the Web Context]. +web context. See xref:servlets/servlets.adoc#BNAGL[Accessing the Web Context]. |Session |`javax.servlet.http.HttpSession` |Web components handling a request that belongs to the session. See -link:#BNAGM[Maintaining Client State]. +xref:servlets/servlets.adoc#BNAGM[Maintaining Client State]. |Request |Subtype of `javax.servlet.ServletRequest` |Web components handling the request. @@ -44,7 +44,7 @@ object. |======================================================================= -[[BNAFS]][[controlling-concurrent-access-to-shared-resources]] +[[BNAFS]][[_controlling_concurrent_access_to_shared_resources]] === Controlling Concurrent Access to Shared Resources diff --git a/src/main/antora/modules/web/pages/servlets/servlets004.adoc b/src/main/antora/modules/web/pages/servlets/servlets004.adoc index 46c7f152..0143cef7 100644 --- a/src/main/antora/modules/web/pages/servlets/servlets004.adoc +++ b/src/main/antora/modules/web/pages/servlets/servlets004.adoc @@ -1,4 +1,4 @@ -[[BNAFU]][[creating-and-initializing-a-servlet]] +[[BNAFU]][[_creating_and_initializing_a_servlet]] == Creating and Initializing a Servlet diff --git a/src/main/antora/modules/web/pages/servlets/servlets005.adoc b/src/main/antora/modules/web/pages/servlets/servlets005.adoc index c60d5d6d..fd54a1a8 100644 --- a/src/main/antora/modules/web/pages/servlets/servlets005.adoc +++ b/src/main/antora/modules/web/pages/servlets/servlets005.adoc @@ -1,4 +1,4 @@ -[[BNAFV]][[writing-service-methods]] +[[BNAFV]][[_writing_service_methods]] == Writing Service Methods @@ -24,7 +24,7 @@ committed. The web container will ignore any attempt to set or add headers after the response has been committed. The next two sections describe how to get information from requests and generate responses. -[[BNAFW]][[getting-information-from-requests]] +[[BNAFW]][[_getting_information_from_requests]] === Getting Information from Requests @@ -79,7 +79,7 @@ method. There are two ways to generate query strings. * A query string is appended to a URL when a form with a `GET` HTTP method is submitted. -[[BNAFZ]][[constructing-responses]] +[[BNAFZ]][[_constructing_responses]] === Constructing Responses @@ -107,7 +107,7 @@ with more time to set appropriate status codes and headers or forward to another web resource. The method must be called before any content is written or before the response is committed. * Set localization information, such as locale and character encoding. -See link:#BNAXU[Chapter 22, "Internationalizing and +See xref:webi18n/webi18n.adoc#BNAXU[Chapter 22, "Internationalizing and Localizing Web Applications"] for details. HTTP response objects, `javax.servlet.http.HttpServletResponse`, have @@ -117,5 +117,5 @@ fields representing HTTP headers, such as the following. satisfied or that a request has been redirected. * Cookies, which are used to store application-specific information at the client. Sometimes, cookies are used to maintain an identifier for -tracking a user's session (see link:#BNAGR[Session +tracking a user's session (see xref:servlets/servlets.adoc#BNAGR[Session Tracking]). diff --git a/src/main/antora/modules/web/pages/servlets/servlets006.adoc b/src/main/antora/modules/web/pages/servlets/servlets006.adoc index 8f57e350..6a6f5346 100644 --- a/src/main/antora/modules/web/pages/servlets/servlets006.adoc +++ b/src/main/antora/modules/web/pages/servlets/servlets006.adoc @@ -1,4 +1,4 @@ -[[BNAGB]][[filtering-requests-and-responses]] +[[BNAGB]][[_filtering_requests_and_responses]] == Filtering Requests and Responses @@ -27,7 +27,7 @@ or more filters in a specific order. This chain is specified when the web application containing the component is deployed and is instantiated when a web container loads the component. -[[BNAGC]][[programming-filters]] +[[BNAGC]][[_programming_filters]] === Programming Filters @@ -83,7 +83,7 @@ instantiated. If you wish to pass initialization parameters to the filter, you retrieve them from the `FilterConfig` object passed to `init`. -[[BNAGD]][[programming-customized-requests-and-responses]] +[[BNAGD]][[_programming_customized_requests_and_responses]] === Programming Customized Requests and Responses @@ -108,7 +108,7 @@ extends either `ServletRequestWrapper` or `HttpServletRequestWrapper`. To override response methods, you wrap the response in an object that extends either `ServletResponseWrapper` or `HttpServletResponseWrapper`. -[[BNAGF]][[specifying-filter-mappings]] +[[BNAGF]][[_specifying_filter_mappings]] === Specifying Filter Mappings @@ -125,16 +125,14 @@ counter filter to the URL pattern `/*`. You can map a filter to one or more web resources, and you can map more than one filter to a web resource. This is illustrated in -link:#BNAGH[Figure 18-1], in which filter F1 is mapped to servlets S1, +xref:servlets/servlets.adoc#BNAGH[Figure 18-1], in which filter F1 is mapped to servlets S1, S2, and S3; filter F2 is mapped to servlet S2; and filter F3 is mapped to servlets S1 and S2. [[BNAGH]] .*Figure 18-1 Filter-to-Servlet Mapping* -image:jakartaeett_dt_018.png[ -"Diagram of filter-to-servlet mapping with filters F1-F3 and servlets -S1-S3. F1 filters S1-S3, then F2 filters S2, then F3 filters S1 and S2."] +image::common:jakartaeett_dt_018.png[ "Diagram of filter-to-servlet mapping with filters F1-F3 and servlets S1-S3. F1 filters S1-S3, then F2 filters S2, then F3 filters S1 and S2."] Recall that a filter chain is one of the objects passed to the `doFilter` method of a filter. This chain is formed indirectly by means @@ -150,7 +148,7 @@ F1 and F3, F1's call to `chain.doFilter` invokes the `doFilter` method of filter F3. When F3's `doFilter` method completes, control returns to F1's `doFilter` method. -[[GJSLC]][[to-specify-filter-mappings-using-netbeans-ide]] +[[GJSLC]][[_to_specify_filter_mappings_using_netbeans_ide]] ==== To Specify Filter Mappings Using NetBeans IDE @@ -176,9 +174,9 @@ You can include wildcard characters so that you can apply the filter to more tha .. In the Add Filter Mapping dialog box, select one of the following dispatcher types: ... REQUEST: Only when the request comes directly from the client ... ASYNC: Only when the asynchronous request comes from the client -... FORWARD: Only when the request has been forwarded to a component (see link:#BNAGK[Transferring Control to Another Web Component]) -... INCLUDE: Only when the request is being processed by a component that has been included (see link:#BNAGJ[Including Other Resources in the Response]) -... ERROR: Only when the request is being processed with the error page mechanism (see link:#BNAFN[Handling Servlet Errors]) +... FORWARD: Only when the request has been forwarded to a component (see xref:servlets/servlets.adoc#BNAGK[Transferring Control to Another Web Component]) +... INCLUDE: Only when the request is being processed by a component that has been included (see xref:servlets/servlets.adoc#BNAGJ[Including Other Resources in the Response]) +... ERROR: Only when the request is being processed with the error page mechanism (see xref:servlets/servlets.adoc#BNAFN[Handling Servlet Errors]) You can direct the filter to be applied to any combination of the preceding situations by selecting multiple dispatcher types. If no types are specified, the default option is REQUEST. -- diff --git a/src/main/antora/modules/web/pages/servlets/servlets007.adoc b/src/main/antora/modules/web/pages/servlets/servlets007.adoc index a3093c20..45ce2581 100644 --- a/src/main/antora/modules/web/pages/servlets/servlets007.adoc +++ b/src/main/antora/modules/web/pages/servlets/servlets007.adoc @@ -1,4 +1,4 @@ -[[BNAGI]][[invoking-other-web-resources]] +[[BNAGI]][[_invoking_other_web_resources]] == Invoking Other Web Resources @@ -21,7 +21,7 @@ available or if the server has not implemented a `RequestDispatcher` object for that type of resource, `getRequestDispatcher` will return null. Your servlet should be prepared to deal with this condition. -[[BNAGJ]][[including-other-resources-in-the-response]] +[[BNAGJ]][[_including_other_resources_in_the_response]] === Including Other Resources in the Response @@ -47,7 +47,7 @@ response object. * It cannot set headers or call any method, such as `setCookie`, that affects the headers of the response. -[[BNAGK]][[transferring-control-to-another-web-component]] +[[BNAGK]][[_transferring_control_to_another_web_component]] === Transferring Control to Another Web Component diff --git a/src/main/antora/modules/web/pages/servlets/servlets008.adoc b/src/main/antora/modules/web/pages/servlets/servlets008.adoc index 2fabdcf4..c982e187 100644 --- a/src/main/antora/modules/web/pages/servlets/servlets008.adoc +++ b/src/main/antora/modules/web/pages/servlets/servlets008.adoc @@ -1,4 +1,4 @@ -[[BNAGL]][[accessing-the-web-context]] +[[BNAGL]][[_accessing_the_web_context]] == Accessing the Web Context diff --git a/src/main/antora/modules/web/pages/servlets/servlets009.adoc b/src/main/antora/modules/web/pages/servlets/servlets009.adoc index 2847acfb..c2fb9410 100644 --- a/src/main/antora/modules/web/pages/servlets/servlets009.adoc +++ b/src/main/antora/modules/web/pages/servlets/servlets009.adoc @@ -1,4 +1,4 @@ -[[BNAGM]][[maintaining-client-state]] +[[BNAGM]][[_maintaining_client_state]] == Maintaining Client State @@ -10,7 +10,7 @@ HTTP is stateless. To support applications that need to maintain state, Jakarta Servlet technology provides an API for managing sessions and allows several mechanisms for implementing sessions. -[[BNAGN]][[accessing-a-session]] +[[BNAGN]][[_accessing_a_session]] === Accessing a Session @@ -19,7 +19,7 @@ session by calling the `getSession` method of a request object. This method returns the current session associated with this request; or, if the request does not have a session, this method creates one. -[[BNAGO]][[associating-objects-with-a-session]] +[[BNAGO]][[_associating_objects_with_a_session]] === Associating Objects with a Session @@ -28,7 +28,7 @@ attributes are accessible by any web component that belongs to the same web context and is handling a request that is part of the same session. Recall that your application can notify web context and session listener -objects of servlet lifecycle events (link:#BNAFJ[Handling +objects of servlet lifecycle events (xref:servlets/servlets.adoc#BNAFJ[Handling Servlet Lifecycle Events]). You can also notify objects of certain events related to their association with a session, such as the following. @@ -42,7 +42,7 @@ between virtual machines or saved to and restored from persistent storage. To receive this notification, your object must implement the `javax.servlet.http.HttpSessionActivationListener` interface. -[[BNAGQ]][[session-management]] +[[BNAGQ]][[_session_management]] === Session Management @@ -58,7 +58,7 @@ resets the session's time-to-live counter. session's `invalidate` method to invalidate a session on the server side and remove any session data. -[[sthref100]][[to-set-the-timeout-period-using-netbeans-ide]] +[[sthref100]][[_to_set_the_timeout_period_using_netbeans_ide]] ==== To Set the Timeout Period Using NetBeans IDE @@ -76,7 +76,7 @@ node. The integer value represents the number of minutes of inactivity that must pass before the session times out. -[[BNAGR]][[session-tracking]] +[[BNAGR]][[_session_tracking]] === Session Tracking diff --git a/src/main/antora/modules/web/pages/servlets/servlets010.adoc b/src/main/antora/modules/web/pages/servlets/servlets010.adoc index 6f073066..ff9cbf07 100644 --- a/src/main/antora/modules/web/pages/servlets/servlets010.adoc +++ b/src/main/antora/modules/web/pages/servlets/servlets010.adoc @@ -1,4 +1,4 @@ -[[BNAGS]][[finalizing-a-servlet]] +[[BNAGS]][[_finalizing_a_servlet]] == Finalizing a Servlet @@ -27,7 +27,7 @@ long-running threads of the shutdown and wait for them to complete. * Have the long-running methods poll periodically to check for shutdown and, if necessary, stop working, clean up, and return. -[[BNAGT]][[tracking-service-requests]] +[[BNAGT]][[_tracking_service_requests]] === Tracking Service Requests @@ -78,7 +78,7 @@ protected void service(HttpServletRequest req, } ---- -[[BNAGU]][[notifying-methods-to-shut-down]] +[[BNAGU]][[_notifying_methods_to_shut_down]] === Notifying Methods to Shut Down @@ -128,7 +128,7 @@ public void destroy() { } ---- -[[BNAGV]][[creating-polite-long-running-methods]] +[[BNAGV]][[_creating_polite_long_running_methods]] === Creating Polite Long-Running Methods diff --git a/src/main/antora/modules/web/pages/servlets/servlets011.adoc b/src/main/antora/modules/web/pages/servlets/servlets011.adoc index 0c9817ae..7277397d 100644 --- a/src/main/antora/modules/web/pages/servlets/servlets011.adoc +++ b/src/main/antora/modules/web/pages/servlets/servlets011.adoc @@ -1,4 +1,4 @@ -[[BABFGCHB]][[uploading-files-with-java-servlet-technology]] +[[BABFGCHB]][[_uploading_files_with_java_servlet_technology]] == Uploading Files with Jakarta Servlet Technology @@ -19,7 +19,7 @@ annotated with `@MultipartConfig` can retrieve the `Part` components of a given `multipart/form-data` request by calling the `request.getPart(String name)` or `request.getParts()` method. -[[sthref101]][[the-multipartconfig-annotation]] +[[sthref101]][[_the_multipartconfig_annotation]] === The @MultipartConfig Annotation @@ -66,7 +66,7 @@ file: ---- -[[sthref102]][[the-getparts-and-getpart-methods]] +[[sthref102]][[_the_getparts_and_getpart_methods]] === The getParts and getPart Methods diff --git a/src/main/antora/modules/web/pages/servlets/servlets012.adoc b/src/main/antora/modules/web/pages/servlets/servlets012.adoc index 335ddb52..fb28825b 100644 --- a/src/main/antora/modules/web/pages/servlets/servlets012.adoc +++ b/src/main/antora/modules/web/pages/servlets/servlets012.adoc @@ -1,4 +1,4 @@ -[[BEIGCFDF]][[asynchronous-processing]] +[[BEIGCFDF]][[_asynchronous_processing]] == Asynchronous Processing @@ -27,7 +27,7 @@ of web applications. Asynchronous processing refers to assigning these blocking operations to a new thread and retuning the thread associated with the request immediately to the container. -[[sthref103]][[asynchronous-processing-in-servlets]] +[[sthref103]][[_asynchronous_processing_in_servlets]] === Asynchronous Processing in Servlets @@ -68,7 +68,7 @@ response is not committed after exiting the service method. You have to generate the response in the asynchronous context after the blocking operation completes or dispatch the request to another servlet. -link:#BEICFIEC[Table 18-3] describes the basic functionality provided by +xref:servlets/servlets.adoc#BEICFIEC[Table 18-3] describes the basic functionality provided by the `AsyncContext` class. [[sthref104]][[BEICFIEC]] @@ -117,7 +117,7 @@ the blocking operation completes. |======================================================================= -[[sthref105]][[waiting-for-a-resource]] +[[sthref105]][[_waiting_for_a_resource]] === Waiting for a Resource diff --git a/src/main/antora/modules/web/pages/servlets/servlets013.adoc b/src/main/antora/modules/web/pages/servlets/servlets013.adoc index 29d71bab..2864371b 100644 --- a/src/main/antora/modules/web/pages/servlets/servlets013.adoc +++ b/src/main/antora/modules/web/pages/servlets/servlets013.adoc @@ -1,4 +1,4 @@ -[[BEIHICDH]][[nonblocking-io]] +[[BEIHICDH]][[_nonblocking_io]] == Nonblocking I/O @@ -6,7 +6,7 @@ Web containers in application servers normally use a server thread per client request. To develop scalable web applications, you must ensure that threads associated with client requests are never sitting idle waiting for a blocking operation to complete. -link:#BEIGCFDF[Asynchronous Processing] provides a +xref:servlets/servlets.adoc#BEIGCFDF[Asynchronous Processing] provides a mechanism to execute application-specific blocking operations in a new thread, returning the thread associated with the request immediately to the container. Even if you use asynchronous processing for all the @@ -26,7 +26,7 @@ how to use nonblocking I/O to process requests and write responses inside service methods. 1. Put the request in asynchronous mode as described in -link:#BEIGCFDF[Asynchronous Processing]. +xref:servlets/servlets.adoc#BEIGCFDF[Asynchronous Processing]. 2. Obtain an input stream and/or an output stream from the request and response objects in the service method. 3. Assign a read listener to the input stream and/or a write listener @@ -34,9 +34,9 @@ to the output stream. 4. Process the request and the response inside the listener's callback methods. -link:#BEIFIIIH[Table 18-5] describe the +xref:servlets/servlets.adoc#BEIFIIIH[Table 18-5] describe the methods available in the servlet input and output streams for -nonblocking I/O support. link:#BEIFGJCG[Table 18-6] describes the +nonblocking I/O support. xref:servlets/servlets.adoc#BEIFGJCG[Table 18-6] describes the interfaces for read listeners and write listeners. [[sthref106]][[BEIFDICJ]] @@ -105,15 +105,15 @@ error. |======================================================================= -[[sthref109]][[reading-a-large-http-post-request-using-nonblocking-io]] +[[sthref109]][[_reading_a_large_http_post_request_using_nonblocking_io]] === Reading a Large HTTP POST Request Using Nonblocking I/O The code in this section shows how to read a large HTTP POST request inside a servlet by putting the request in asynchronous mode (as -described in link:#BEIGCFDF[Asynchronous Processing]) and -using the nonblocking I/O functionality from link:#BEIFDICJ[Table 18-4] -and link:#BEIFGJCG[Table 18-6]. +described in xref:servlets/servlets.adoc#BEIGCFDF[Asynchronous Processing]) and +using the nonblocking I/O functionality from xref:servlets/servlets.adoc#BEIFDICJ[Table 18-4] +and xref:servlets/servlets.adoc#BEIFGJCG[Table 18-6]. [source,java] ---- diff --git a/src/main/antora/modules/web/pages/servlets/servlets014.adoc b/src/main/antora/modules/web/pages/servlets/servlets014.adoc index 337f4e38..afbe33ad 100644 --- a/src/main/antora/modules/web/pages/servlets/servlets014.adoc +++ b/src/main/antora/modules/web/pages/servlets/servlets014.adoc @@ -1,4 +1,4 @@ -[[BEIJHCDJ]][[protocol-upgrade-processing]] +[[BEIJHCDJ]][[_protocol_upgrade_processing]] == Protocol Upgrade Processing @@ -37,7 +37,7 @@ OtherHeaderB: Value ---- Jakarta EE supports the HTTP protocol upgrade functionality in servlets, as -described in link:#BEIBDHAG[Table 18-7]. +described in xref:servlets/servlets.adoc#BEIBDHAG[Table 18-7]. [[sthref110]][[BEIBDHAG]] @@ -74,14 +74,14 @@ the new protocol. `ServletInputStream getInputStream()` The `getInputStream` method provides access to the input stream of the -connection. You can use link:#BEIHICDH[Nonblocking I/O] +connection. You can use xref:servlets/servlets.adoc#BEIHICDH[Nonblocking I/O] with the returned stream to implement the new protocol. |`WebConnection` a| `ServletOutputStream getOutputStream()` The `getOutputStream` method provides access to the output stream of the -connection. You can use link:#BEIHICDH[Nonblocking I/O] +connection. You can use xref:servlets/servlets.adoc#BEIHICDH[Nonblocking I/O] with the returned stream to implement the new protocol. |======================================================================= diff --git a/src/main/antora/modules/web/pages/servlets/servlets014a.adoc b/src/main/antora/modules/web/pages/servlets/servlets014a.adoc index 4da9c801..94345a8f 100644 --- a/src/main/antora/modules/web/pages/servlets/servlets014a.adoc +++ b/src/main/antora/modules/web/pages/servlets/servlets014a.adoc @@ -1,4 +1,4 @@ -[[server-push]] +[[_server_push]] == Server Push Server push is the ability of the server to anticipate what will be diff --git a/src/main/antora/modules/web/pages/servlets/servlets014b.adoc b/src/main/antora/modules/web/pages/servlets/servlets014b.adoc index 338809f3..67b8fdf9 100644 --- a/src/main/antora/modules/web/pages/servlets/servlets014b.adoc +++ b/src/main/antora/modules/web/pages/servlets/servlets014b.adoc @@ -1,4 +1,4 @@ -[[http-trailer]] +[[_http_trailer]] == HTTP Trailer HTTP trailer is a collection of a special type of HTTP headers that comes diff --git a/src/main/antora/modules/web/pages/servlets/servlets015.adoc b/src/main/antora/modules/web/pages/servlets/servlets015.adoc index 06a07aa1..1dc0781a 100644 --- a/src/main/antora/modules/web/pages/servlets/servlets015.adoc +++ b/src/main/antora/modules/web/pages/servlets/servlets015.adoc @@ -1,4 +1,4 @@ -[[GKCPG]][[the-mood-example-application]] +[[GKCPG]][[_the_mood_example_application]] == The mood Example Application @@ -9,7 +9,7 @@ example shows how to develop a simple application by using the `@WebServlet`, `@WebFilter`, and `@WebListener` annotations to create a servlet, a listener, and a filter. -[[CHDEBFCB]][[components-of-the-mood-example-application]] +[[CHDEBFCB]][[_components_of_the_mood_example_application]] === Components of the mood Example Application @@ -47,19 +47,19 @@ statement that sets Duke's mood based on the current time. `SimpleServletListener` logs changes in the servlet's lifecycle. The log entries appear in the server log. -[[GKCOJ]][[running-the-mood-example]] +[[GKCOJ]][[_running_the_mood_example]] === Running the mood Example You can use either NetBeans IDE or Maven to build, package, deploy, and run the `mood` example. -[[GKCOB]][[to-run-the-mood-example-using-netbeans-ide]] +[[GKCOB]][[_to_run_the_mood_example_using_netbeans_ide]] ==== To Run the mood Example Using NetBeans IDE 1. Make sure that GlassFish Server has been started (see -link:#BNADI[Starting and Stopping GlassFish +xref:#BNADI[Starting and Stopping GlassFish Server]). 2. From the File menu, choose Open Project. 3. In the Open Project dialog box, navigate to: @@ -84,12 +84,12 @@ The URL specifies the context root, followed by the URL pattern. A web page appears with the title "Servlet MoodServlet at /mood", a text string describing Duke's mood, and an illustrative graphic. -[[GKCPJ]][[to-run-the-mood-example-using-maven]] +[[GKCPJ]][[_to_run_the_mood_example_using_maven]] ==== To Run the mood Example Using Maven 1. Make sure that GlassFish Server has been started (see -link:#BNADI[Starting and Stopping GlassFish +xref:#BNADI[Starting and Stopping GlassFish Server]). 2. In a terminal window, go to: + diff --git a/src/main/antora/modules/web/pages/servlets/servlets016.adoc b/src/main/antora/modules/web/pages/servlets/servlets016.adoc index 68500c65..abad3a2a 100644 --- a/src/main/antora/modules/web/pages/servlets/servlets016.adoc +++ b/src/main/antora/modules/web/pages/servlets/servlets016.adoc @@ -1,4 +1,4 @@ -[[BABDGFJJ]][[the-fileupload-example-application]] +[[BABDGFJJ]][[_the_fileupload_example_application]] == The fileupload Example Application @@ -37,7 +37,7 @@ data that results from the download or use of content. |======================================================================= -[[CHDFGBGI]][[architecture-of-the-fileupload-example-application]] +[[CHDFGBGI]][[_architecture_of_the_fileupload_example_application]] === Architecture of the fileupload Example Application @@ -210,19 +210,19 @@ private String getFileName(final Part part) { } ---- -[[CHDIHJCI]][[running-the-fileupload-example]] +[[CHDIHJCI]][[_running_the_fileupload_example]] === Running the fileupload Example You can use either NetBeans IDE or Maven to build, package, deploy, and run the `fileupload` example. -[[CHDGDJCI]][[to-build-package-and-deploy-the-fileupload-example-using-netbeans-ide]] +[[CHDGDJCI]][[_to_build_package_and_deploy_the_fileupload_example_using_netbeans_ide]] ==== To Build, Package, and Deploy the fileupload Example Using NetBeans IDE 1. Make sure that GlassFish Server has been started (see -link:#BNADI[Starting and Stopping GlassFish +xref:#BNADI[Starting and Stopping GlassFish Server]). 2. From the File menu, choose Open Project. 3. In the Open Project dialog box, navigate to: @@ -236,12 +236,12 @@ tut-install/examples/web/servlet 6. In the Projects tab, right-click the `fileupload` project and select Build. -[[CHDCFADG]][[to-build-package-and-deploy-the-fileupload-example-using-maven]] +[[CHDCFADG]][[_to_build_package_and_deploy_the_fileupload_example_using_maven]] ==== To Build, Package, and Deploy the fileupload Example Using Maven 1. Make sure that GlassFish Server has been started (see -link:#BNADI[Starting and Stopping GlassFish +xref:#BNADI[Starting and Stopping GlassFish Server]). 2. In a terminal window, go to: + @@ -256,7 +256,7 @@ tut-install/examples/web/servlet/fileupload/ mvn install ---- -[[CHDDDAAJ]][[to-run-the-fileupload-example]] +[[CHDDDAAJ]][[_to_run_the_fileupload_example]] ==== To Run the fileupload Example diff --git a/src/main/antora/modules/web/pages/servlets/servlets017.adoc b/src/main/antora/modules/web/pages/servlets/servlets017.adoc index 3ff398eb..7303fb92 100644 --- a/src/main/antora/modules/web/pages/servlets/servlets017.adoc +++ b/src/main/antora/modules/web/pages/servlets/servlets017.adoc @@ -1,4 +1,4 @@ -[[BEIFAIFF]][[the-dukeetf-example-application]] +[[BEIFAIFF]][[_the_dukeetf_example_application]] == The dukeetf Example Application @@ -8,7 +8,7 @@ asynchronous processing in a servlet to provide data updates to web clients. The example resembles a service that provides periodic updates on the price and trading volume of an electronically traded fund (ETF). -[[CHDBBEDA]][[architecture-of-the-dukeetf-example-application]] +[[CHDBBEDA]][[_architecture_of_the_dukeetf_example_application]] === Architecture of the dukeetf Example Application @@ -35,7 +35,7 @@ uses JavaScript to make new connections. In this model, clients make a new request immediately after receiving new data, and the server keeps the connection open until new data becomes available. -[[sthref111]][[the-servlet]] +[[sthref111]][[_the_servlet]] ==== The Servlet @@ -117,7 +117,7 @@ public void doGet(HttpServletRequest request, } ---- -[[sthref112]][[the-enterprise-bean]] +[[sthref112]][[_the_enterprise_bean]] ==== The Enterprise Bean @@ -159,11 +159,11 @@ public class PriceVolumeBean { } ---- -See link:#BNBOY[Using the Timer Service] in -link:#GIJRB[Chapter 37, "Running the Enterprise +See xref:#BNBOY[Using the Timer Service] in +xref:#GIJRB[Chapter 37, "Running the Enterprise Bean Examples"] for more information on the timer service. -[[sthref113]][[the-html-page]] +[[sthref113]][[_the_html_page]] ==== The HTML Page @@ -218,24 +218,24 @@ The `XMLHttpRequest` API is supported by most modern browsers, and it is widely used in Ajax web client development (Asynchronous JavaScript and XML). -See link:#BABGCEHE[The dukeetf2 Example Application] in -link:#GKJIQ5[Chapter 19, "Jakarta WebSocket"] for an +See xref:websocket/websocket.adoc#BABGCEHE[The dukeetf2 Example Application] in +xref:websocket/websocket.adoc#GKJIQ5[Chapter 19, "Jakarta WebSocket"] for an equivalent version of this example implemented using a WebSocket endpoint. -[[CHDHBBBI]][[running-the-dukeetf-example-application]] +[[CHDHBBBI]][[_running_the_dukeetf_example_application]] === Running the dukeetf Example Application This section describes how to run the `dukeetf` example application using NetBeans IDE and from the command line. -[[CHDCGCJD]][[to-run-the-dukeetf-example-application-using-netbeans-ide]] +[[CHDCGCJD]][[_to_run_the_dukeetf_example_application_using_netbeans_ide]] ==== To Run the dukeetf Example Application Using NetBeans IDE 1. Make sure that GlassFish Server has been started (see -link:#BNADI[Starting and Stopping GlassFish +xref:#BNADI[Starting and Stopping GlassFish Server]). 2. From the File menu, choose Open Project. 3. In the Open Project dialog box, navigate to: @@ -261,12 +261,12 @@ http://localhost:8080/dukeetf/ Open the same URL in a different web browser to see how both pages get price and volume updates simultaneously. -[[CHDHHAFG]][[to-run-the-dukeetf-example-application-using-maven]] +[[CHDHHAFG]][[_to_run_the_dukeetf_example_application_using_maven]] ==== To Run the dukeetf Example Application Using Maven 1. Make sure that GlassFish Server has been started (see -link:#BNADI[Starting and Stopping GlassFish +xref:#BNADI[Starting and Stopping GlassFish Server]). 2. In a terminal window, go to: + diff --git a/src/main/antora/modules/web/pages/servlets/servlets018.adoc b/src/main/antora/modules/web/pages/servlets/servlets018.adoc index 93dd3272..ae978b82 100644 --- a/src/main/antora/modules/web/pages/servlets/servlets018.adoc +++ b/src/main/antora/modules/web/pages/servlets/servlets018.adoc @@ -1,4 +1,4 @@ -[[BNAGW]][[further-information-about-java-servlet-technology]] +[[BNAGW]][[_further_information_about_java_servlet_technology]] == Further Information about Jakarta Servlet Technology diff --git a/src/main/antora/modules/web/pages/webapp/webapp.adoc b/src/main/antora/modules/web/pages/webapp/webapp.adoc index 34bb755c..fad9d0ce 100644 --- a/src/main/antora/modules/web/pages/webapp/webapp.adoc +++ b/src/main/antora/modules/web/pages/webapp/webapp.adoc @@ -1,6 +1,6 @@ = Getting Started with Web Applications -[[BNADR]][[getting-started-with-web-applications]] +[[BNADR]][[_getting_started_with_web_applications]] This chapter introduces web applications, which typically use JavaServer Faces technology and/or Java Servlet technology. diff --git a/src/main/antora/modules/web/pages/webapp/webapp001.adoc b/src/main/antora/modules/web/pages/webapp/webapp001.adoc index a13c1c52..2df1e60f 100644 --- a/src/main/antora/modules/web/pages/webapp/webapp001.adoc +++ b/src/main/antora/modules/web/pages/webapp/webapp001.adoc @@ -1,4 +1,4 @@ -[[GEYSJ]][[web-applications]] +[[GEYSJ]][[_web_applications]] == Web Applications @@ -9,21 +9,21 @@ Web applications are of the following types: generates interactive web pages containing various types of markup language (HTML, XHTML, XML, and so on) and dynamic content in response to requests. Development of presentation-oriented web applications is -covered in link:#BNAPH[Chapter 7, "Jakarta Server Faces -Technology,"] through link:#BNAFD[Chapter 18, "Jakarta Servlet +covered in xref:jsf-intro/jsf-intro.adoc#BNAPH[Chapter 7, "Jakarta Server Faces +Technology,"] through xref:servlets/servlets.adoc#BNAFD[Chapter 18, "Jakarta Servlet Technology."] * Service-oriented: A service-oriented web application implements the endpoint of a web service. Presentation-oriented applications are often clients of service-oriented web applications. Development of service-oriented web applications is covered in -link:#BNAYL[Chapter 31, "Building Web Services with JAX-WS,"] -and link:#GIEPU[Chapter 32, "Building RESTful Web Services with -Jakarta RESTful Web Services,"] in link:#BNAYK[Part III, "Web Services."] +xref:#BNAYL[Chapter 31, "Building Web Services with JAX-WS,"] +and xref:#GIEPU[Chapter 32, "Building RESTful Web Services with +Jakarta RESTful Web Services,"] in xref:#BNAYK[Part III, "Web Services."] In the Jakarta EE platform, web components provide the dynamic extension capabilities for a web server. Web components can be Jakarta servlets, web pages implemented with Jakarta Server Faces technology, web service -endpoints, or Jakarta Server pages. link:#BNADS[Figure 6-1] illustrates the +endpoints, or Jakarta Server pages. xref:webapp/webapp.adoc#BNADS[Figure 6-1] illustrates the interaction between a web client and a web application that uses a servlet. The client sends an HTTP request to the web server. A web server that implements Jakarta Servlet and Jakarta Server Pages technology @@ -38,9 +38,7 @@ HTTP response and returns it to the client. [[BNADS]] .*Figure 6-1 Jakarta Web Application Request Handling* -image:jakartaeett_dt_013.png[ -"Diagram of web application request handling. Clients and servlets -communicate using HttpServletRequest and HttpServletResponse."] +image::common:jakartaeett_dt_013.png[ "Diagram of web application request handling. Clients and servlets communicate using HttpServletRequest and HttpServletResponse."] Servlets are Java programming language classes that dynamically process requests and construct responses. Java technologies, such as Jakarta Server diff --git a/src/main/antora/modules/web/pages/webapp/webapp002.adoc b/src/main/antora/modules/web/pages/webapp/webapp002.adoc index 281fa8da..1c098474 100644 --- a/src/main/antora/modules/web/pages/webapp/webapp002.adoc +++ b/src/main/antora/modules/web/pages/webapp/webapp002.adoc @@ -1,4 +1,4 @@ -[[BNADU]][[web-application-lifecycle]] +[[BNADU]][[_web_application_lifecycle]] == Web Application Lifecycle diff --git a/src/main/antora/modules/web/pages/webapp/webapp003.adoc b/src/main/antora/modules/web/pages/webapp/webapp003.adoc index ef34065f..a5cb9e8d 100644 --- a/src/main/antora/modules/web/pages/webapp/webapp003.adoc +++ b/src/main/antora/modules/web/pages/webapp/webapp003.adoc @@ -1,4 +1,4 @@ -[[BNADX]][[a-web-module-that-uses-javaserver-faces-technology-the-hello1-example]] +[[BNADX]][[_a_web_module_that_uses_javaserver_faces_technology_the_hello1_example]] == A Web Module That Uses Jakarta Server Faces Technology: The hello1 Example @@ -9,7 +9,7 @@ to view the application files, or you can use NetBeans IDE. The source code for this application is in the `_tut-install_/examples/web/jsf/hello1/` directory. -[[GJWTV]][[to-view-the-hello1-web-module-using-netbeans-ide]] +[[GJWTV]][[_to_view_the_hello1_web_module_using_netbeans_ide]] === To View the hello1 Web Module Using NetBeans IDE @@ -151,7 +151,7 @@ If you use the default name for the bean class, you can specify `@Model` as the annotation instead of having to specify both `@Named` and `@RequestScoped`. The `@Model` annotation is called a stereotype, a term for an annotation that encapsulates other annotations. It is described -later in link:#GKHQC[Using Stereotypes in CDI +later in xref:#GKHQC[Using Stereotypes in CDI Applications]. Some examples will use `@Model` where it is appropriate. 8. Under the Web Pages node, expand the WEB-INF node and double-click the `web.xml` file to view it. @@ -199,7 +199,7 @@ page: ---- -[[GLQLK]][[introduction-to-scopes]] +[[GLQLK]][[_introduction_to_scopes]] ==== Introduction to Scopes @@ -223,9 +223,9 @@ use session scope. all users' interactions with a web application. For more information on scopes in Jakarta Server Faces technology, see -link:#GIRCR[Using Managed Bean Scopes]. +xref:jsf-configure/jsf-configure.adoc#GIRCR[Using Managed Bean Scopes]. -[[BNADZ]][[packaging-and-deploying-the-hello1-web-module]] +[[BNADZ]][[_packaging_and_deploying_the_hello1_web_module]] === Packaging and Deploying the hello1 Web Module @@ -245,14 +245,14 @@ You can deploy a WAR file to GlassFish Server by: Throughout the tutorial, you will use NetBeans IDE or Maven for packaging and deploying. -[[GJRGN]][[to-build-and-package-the-hello1-web-module-using-netbeans-ide]] +[[GJRGN]][[_to_build_and_package_the_hello1_web_module_using_netbeans_ide]] ==== To Build and Package the hello1 Web Module Using NetBeans IDE To build and package the `hello1` web module using NetBeans IDE: 1. Start GlassFish Server as described in -link:#CHDCACDI[To Start GlassFish Server Using +xref:#CHDCACDI[To Start GlassFish Server Using NetBeans IDE], if you have not already done so. 2. From the File menu, choose Open Project. 3. In the Open Project dialog box, navigate to: @@ -266,14 +266,14 @@ tut-install/examples/web/jsf 6. In the Projects tab, right-click the `hello1` project and select Build. This command deploys the project to the server. -[[GJRKN]][[to-build-and-package-the-hello1-web-module-using-maven]] +[[GJRKN]][[_to_build_and_package_the_hello1_web_module_using_maven]] ==== To Build and Package the hello1 Web Module Using Maven To build and package the `hello1` web module using Maven: 1. Start GlassFish Server as described in -link:#CHDBDDAF[To Start GlassFish Server Using the +xref:#CHDBDDAF[To Start GlassFish Server Using the Command Line], if you have not already done so. 2. In a terminal window, go to: + @@ -292,7 +292,7 @@ This command spawns any necessary compilations and creates the WAR file in `_tut-install_/examples/web/jsf/hello1/target/`. It then deploys the project to the server. -[[BNAEI]][[viewing-deployed-web-modules]] +[[BNAEI]][[_viewing_deployed_web_modules]] === Viewing Deployed Web Modules @@ -300,7 +300,7 @@ GlassFish Server provides two ways to view the deployed web modules: the Administration Console and the `asadmin` command. You can also use NetBeans IDE to view deployed modules. -[[GJSGR]][[to-view-deployed-web-modules-using-the-administration-console]] +[[GJSGR]][[_to_view_deployed_web_modules_using_the_administration_console]] ==== To View Deployed Web Modules Using the Administration Console @@ -311,7 +311,7 @@ To view deployed web modules using the Administration Console: + The deployed web modules appear in the Deployed Applications table. -[[GJSEW]][[to-view-deployed-web-modules-using-the-asadmin-command]] +[[GJSEW]][[_to_view_deployed_web_modules_using_the_asadmin_command]] ==== To View Deployed Web Modules Using the asadmin Command @@ -322,7 +322,7 @@ Enter the following command: asadmin list-applications ---- -[[sthref24]][[to-view-deployed-web-modules-using-netbeans-ide]] +[[sthref24]][[_to_view_deployed_web_modules_using_netbeans_ide]] ==== To View Deployed Web Modules Using NetBeans IDE @@ -332,7 +332,7 @@ To view deployed web modules using NetBeans IDE: GlassFish Server node. 2. Expand the Applications node to view the deployed modules. -[[BCEBEGED]][[running-the-deployed-hello1-web-module]] +[[BCEBEGED]][[_running_the_deployed_hello1_web_module]] === Running the Deployed hello1 Web Module @@ -355,7 +355,7 @@ http://localhost:8080/hello1/ The response page displays the name you submitted. Click Back to try again. -[[BNAEM]][[dynamic-reloading-of-deployed-modules]] +[[BNAEM]][[_dynamic_reloading_of_deployed_modules]] ==== Dynamic Reloading of Deployed Modules @@ -376,14 +376,14 @@ that time become invalid, and the client must restart the session. In GlassFish Server, dynamic reloading is enabled by default. -[[BNAEN]][[undeploying-the-hello1-web-module]] +[[BNAEN]][[_undeploying_the_hello1_web_module]] === Undeploying the hello1 Web Module You can undeploy web modules and other types of enterprise applications by using either NetBeans IDE or Maven. -[[GJSEJ]][[to-undeploy-the-hello1-web-module-using-netbeans-ide]] +[[GJSEJ]][[_to_undeploy_the_hello1_web_module_using_netbeans_ide]] ==== To Undeploy the hello1 Web Module Using NetBeans IDE @@ -396,7 +396,7 @@ GlassFish Server node. 4. To delete the class files and other build artifacts, go back to the Projects tab, right-click the project, and select Clean. -[[GJSHH]][[to-undeploy-the-hello1-web-module-using-maven]] +[[GJSHH]][[_to_undeploy_the_hello1_web_module_using_maven]] ==== To Undeploy the hello1 Web Module Using Maven diff --git a/src/main/antora/modules/web/pages/webapp/webapp004.adoc b/src/main/antora/modules/web/pages/webapp/webapp004.adoc index e7b7c59d..f559d688 100644 --- a/src/main/antora/modules/web/pages/webapp/webapp004.adoc +++ b/src/main/antora/modules/web/pages/webapp/webapp004.adoc @@ -1,4 +1,4 @@ -[[BNAEO]][[a-web-module-that-uses-java-servlet-technology-the-hello2-example]] +[[BNAEO]][[_a_web_module_that_uses_java_servlet_technology_the_hello2_example]] == A Web Module That Uses Jakarta Servlet Technology: The hello2 Example @@ -9,7 +9,7 @@ to view the application files, or you can use NetBeans IDE. The source code for this application is in the `_tut-install_/examples/web/servlet/hello2/` directory. -[[BNAEP]][[mapping-urls-to-web-components]] +[[BNAEP]][[_mapping_urls_to_web_components]] === Mapping URLs to Web Components @@ -48,7 +48,7 @@ http://localhost:8080/hello2/greeting To access the servlet by using only the context root, specify `"/"` as the URL pattern. -[[GJWWG]][[examining-the-hello2-web-module]] +[[GJWWG]][[_examining_the_hello2_web_module]] === Examining the hello2 Web Module @@ -57,7 +57,7 @@ application, but it is implemented using Jakarta Servlet technology instead of Jakarta Server Faces technology. You can use a text editor to view the application files, or you can use NetBeans IDE. -[[GJWWA]][[to-view-the-hello2-web-module-using-netbeans-ide]] +[[GJWWA]][[_to_view_the_hello2_web_module_using_netbeans_ide]] ==== To View the hello2 Web Module Using NetBeans IDE @@ -152,21 +152,21 @@ public class ResponseServlet extends HttpServlet { ... ---- -[[GKBLH]][[running-the-hello2-example]] +[[GKBLH]][[_running_the_hello2_example]] === Running the hello2 Example You can use either NetBeans IDE or Maven to build, package, deploy, and run the `hello2` example. -[[GJSED]][[to-run-the-hello2-example-using-netbeans-ide]] +[[GJSED]][[_to_run_the_hello2_example_using_netbeans_ide]] ==== To Run the hello2 Example Using NetBeans IDE To run the `hello2` example using NetBeans IDE: 1. Start GlassFish Server as described in -link:#CHDCACDI[To Start GlassFish Server Using +xref:#CHDCACDI[To Start GlassFish Server Using NetBeans IDE], if you have not already done so. 2. From the File menu, choose Open Project. 3. In the Open Project dialog box, navigate to: @@ -192,14 +192,14 @@ The application looks much like the `hello1` application. The major difference is that after you click Submit the response appears below the greeting, not on a separate page. -[[GJSHX]][[to-run-the-hello2-example-using-maven]] +[[GJSHX]][[_to_run_the_hello2_example_using_maven]] ==== To Run the hello2 Example Using Maven To run the `hello2` example using Maven: 1. Start GlassFish Server as described in -link:#CHDBDDAF[To Start GlassFish Server Using the +xref:#CHDBDDAF[To Start GlassFish Server Using the Command Line], if you have not already done so. 2. In a terminal window, go to: + diff --git a/src/main/antora/modules/web/pages/webapp/webapp005.adoc b/src/main/antora/modules/web/pages/webapp/webapp005.adoc index e960d339..0f4c2485 100644 --- a/src/main/antora/modules/web/pages/webapp/webapp005.adoc +++ b/src/main/antora/modules/web/pages/webapp/webapp005.adoc @@ -1,4 +1,4 @@ -[[CHDHGJIA]][[configuring-web-applications]] +[[CHDHGJIA]][[_configuring_web_applications]] == Configuring Web Applications @@ -10,7 +10,7 @@ applications: * Mapping errors to error screens * Declaring resource references -[[BNAES]][[setting-context-parameters]] +[[BNAES]][[_setting_context_parameters]] === Setting Context Parameters @@ -18,10 +18,10 @@ The web components in a web module share an object that represents their application context. You can pass context parameters to the context, or you can pass initialization parameters to a servlet. Context parameters are available to the entire application. For information on -initialization parameters, see link:#BNAFU[Creating and +initialization parameters, see xref:servlets/servlets.adoc#BNAFU[Creating and Initializing a Servlet]. -[[GJSFJ]][[to-add-a-context-parameter-using-netbeans-ide]] +[[GJSFJ]][[_to_add_a_context_parameter_using_netbeans_ide]] ==== To Add a Context Parameter Using NetBeans IDE @@ -36,7 +36,7 @@ To add a context parameter using NetBeans IDE: 4. Double-click `web.xml`. + If the project does not have a `web.xml` file, create one by following -the steps in link:#GKIHH[To Create a web.xml File Using NetBeans IDE]. +the steps in xref:webapp/webapp.adoc#GKIHH[To Create a web.xml File Using NetBeans IDE]. 5. Click General at the top of the editor window. 6. Expand the Context Parameters node. 7. Click Add. @@ -46,7 +46,7 @@ field, enter the name that specifies the context object. context object. 10. Click OK. -[[GKIHH]][[to-create-a-web.xml-file-using-netbeans-ide]] +[[GKIHH]][[_to_create_a_web.xml_file_using_netbeans_ide]] ==== To Create a web.xml File Using NetBeans IDE @@ -60,7 +60,7 @@ Standard Deployment Descriptor under File Types. + A basic `web.xml` file appears in `web/WEB-INF/`. -[[BNAER]][[declaring-welcome-files]] +[[BNAER]][[_declaring_welcome_files]] === Declaring Welcome Files @@ -102,7 +102,7 @@ The `hello2` example does not specify a welcome file, because the URL request is mapped to the `GreetingServlet` web component through the URL pattern `/greeting`. -[[GKBKW]][[mapping-errors-to-error-screens]] +[[GKBKW]][[_mapping_errors_to_error_screens]] === Mapping Errors to Error Screens @@ -117,7 +117,7 @@ descriptor. Each element identifies a different error that causes an error page to open. This error page can be the same for any number of `error-page` elements. -[[BNAET]][[to-set-up-error-mapping-using-netbeans-ide]] +[[BNAET]][[_to_set_up_error_mapping_using_netbeans_ide]] ==== To Set Up Error Mapping Using NetBeans IDE @@ -132,7 +132,7 @@ To set up error mapping using NetBeans IDE: 4. Double-click `web.xml`. + If the project does not have a `web.xml` file, create one by following -the steps in link:#GKIHH[To Create a web.xml File Using NetBeans IDE]. +the steps in xref:webapp/webapp.adoc#GKIHH[To Create a web.xml File Using NetBeans IDE]. 5. Click Pages at the top of the editor window. 6. Expand the Error Pages node. 7. Click Add. @@ -147,7 +147,7 @@ exception that will cause the error page to load. To specify all throwable errors and exceptions, enter `java.lang.Throwable`. 10. Click OK. -[[BNAEU]][[declaring-resource-references]] +[[BNAEU]][[_declaring_resource_references]] === Declaring Resource References @@ -167,17 +167,17 @@ simple JavaBeans components. However, managed beans are managed by the container; therefore, they can accept resource injections. Components that can accept resource injections are listed in -link:#BNAEV[Table 6-1]. +xref:webapp/webapp.adoc#BNAEV[Table 6-1]. This section explains how to use a couple of the annotations supported by a web container to inject resources. -link:#GIJST[Chapter 41, "Running the +xref:#GIJST[Chapter 41, "Running the Persistence Examples"], explains how web applications use annotations supported by Jakarta Persistence. -link:#BNCAS[Chapter 51, "Getting Started Securing +xref:#BNCAS[Chapter 51, "Getting Started Securing Web Applications"], explains how to use annotations to specify information about securing web applications. See -link:#BNCJH[Chapter 55, "Resource Adapters and Contracts"], +xref:#BNCJH[Chapter 55, "Resource Adapters and Contracts"], for more information on resources. [[sthref25]][[BNAEV]] @@ -208,7 +208,7 @@ for more information on resources. |================================================ -[[BNAEW]][[declaring-a-reference-to-a-resource]] +[[BNAEW]][[_declaring_a_reference_to_a_resource]] ==== Declaring a Reference to a Resource @@ -259,11 +259,11 @@ do not use the `@Resource` annotation to inject a data source. However, this API supports the `@PersistenceUnit` and `@PersistenceContext` annotations for injecting `EntityManagerFactory` and `EntityManager` instances, respectively. -link:#GIJST[Chapter 41, "Running the +xref:#GIJST[Chapter 41, "Running the Persistence Examples"] describes these annotations and the use of the Jakarta Persistence in web applications. -[[BNAEX]][[declaring-a-reference-to-a-web-service]] +[[BNAEX]][[_declaring_a_reference_to_a_web_service]] ==== Declaring a Reference to a Web Service diff --git a/src/main/antora/modules/web/pages/webapp/webapp006.adoc b/src/main/antora/modules/web/pages/webapp/webapp006.adoc index fed336f7..4cf6127e 100644 --- a/src/main/antora/modules/web/pages/webapp/webapp006.adoc +++ b/src/main/antora/modules/web/pages/webapp/webapp006.adoc @@ -1,4 +1,4 @@ -[[BNAFC]][[further-information-about-web-applications]] +[[BNAFC]][[_further_information_about_web_applications]] == Further Information about Web Applications diff --git a/src/main/antora/modules/web/pages/webi18n/webi18n.adoc b/src/main/antora/modules/web/pages/webi18n/webi18n.adoc index 74c45352..3227051c 100644 --- a/src/main/antora/modules/web/pages/webi18n/webi18n.adoc +++ b/src/main/antora/modules/web/pages/webi18n/webi18n.adoc @@ -1,7 +1,7 @@ = Internationalizing and Localizing Web Applications -[[BNAXU]][[internationalizing-and-localizing-web-applications]] +[[BNAXU]][[_internationalizing_and_localizing_web_applications]] The process of preparing an application to support more than one language and data format is called internationalization. Localization is diff --git a/src/main/antora/modules/web/pages/webi18n/webi18n001.adoc b/src/main/antora/modules/web/pages/webi18n/webi18n001.adoc index 278b2f85..cabdb38d 100644 --- a/src/main/antora/modules/web/pages/webi18n/webi18n001.adoc +++ b/src/main/antora/modules/web/pages/webi18n/webi18n001.adoc @@ -1,4 +1,4 @@ -[[BNAXV]][[java-platform-localization-classes]] +[[BNAXV]][[_java_platform_localization_classes]] == Java Platform Localization Classes @@ -20,7 +20,7 @@ resource bundle) containing the pairs. You construct a resource bundle instance by appending a locale string representation to a base name. The Duke's Bookstore application (see -link:#GLNVI[Chapter 60, "Duke's Bookstore Case Study +xref:#GLNVI[Chapter 60, "Duke's Bookstore Case Study Example"]) contains resource bundles with the base name `messages.properties` for the locales `de` (German), `es` (Spanish), and `fr` (French). The default locale, `en` (English), which is specified in diff --git a/src/main/antora/modules/web/pages/webi18n/webi18n002.adoc b/src/main/antora/modules/web/pages/webi18n/webi18n002.adoc index 2bf9412c..aa76d432 100644 --- a/src/main/antora/modules/web/pages/webi18n/webi18n002.adoc +++ b/src/main/antora/modules/web/pages/webi18n/webi18n002.adoc @@ -1,4 +1,4 @@ -[[BNAXW]][[providing-localized-messages-and-labels]] +[[BNAXW]][[_providing_localized_messages_and_labels]] == Providing Localized Messages and Labels @@ -32,7 +32,7 @@ Visitor=You are visitor number What=What We\'re Reading ---- -[[GKUIA]][[establishing-the-locale]] +[[GKUIA]][[_establishing_the_locale]] === Establishing the Locale @@ -74,7 +74,7 @@ public class LocaleBean { } ---- -[[BNAXY]][[setting-the-resource-bundle]] +[[BNAXY]][[_setting_the_resource_bundle]] === Setting the Resource Bundle @@ -93,7 +93,7 @@ configuration file. The setting for Duke's Bookstore looks like this: After the locale is set, the controller of a web application could retrieve the resource bundle for that locale and save it as a session -attribute (see link:#BNAGO[Associating Objects with a +attribute (see xref:servlets/servlets.adoc#BNAGO[Associating Objects with a Session]) for use by other components or simply be used to return a text string appropriate for the selected locale: @@ -123,9 +123,9 @@ registered using the `resource-bundle` element of the configuration file. For more information on using this element, see -link:#BNAXB[Registering Application Messages]. +xref:jsf-configure/jsf-configure.adoc#BNAXB[Registering Application Messages]. -[[GKUFC]][[retrieving-localized-messages]] +[[GKUFC]][[_retrieving_localized_messages]] === Retrieving Localized Messages @@ -163,7 +163,7 @@ validate the value the user enters into the component. ---- For more information on using the `message` or `messages` tags, see -link:#BNASO[Displaying Error Messages with the h:message +xref:jsf-page/jsf-page.adoc#BNASO[Displaying Error Messages with the h:message and h:messages Tags]. Messages that are not queued on a component and are therefore not loaded diff --git a/src/main/antora/modules/web/pages/webi18n/webi18n003.adoc b/src/main/antora/modules/web/pages/webi18n/webi18n003.adoc index 0d3b1525..85d956d5 100644 --- a/src/main/antora/modules/web/pages/webi18n/webi18n003.adoc +++ b/src/main/antora/modules/web/pages/webi18n/webi18n003.adoc @@ -1,4 +1,4 @@ -[[BNAYA]][[date-and-number-formatting]] +[[BNAYA]][[_date_and_number_formatting]] == Date and Number Formatting @@ -20,6 +20,6 @@ could be converted as follows: ---- For information on Jakarta Server Faces converters, see -link:#BNAST[Using the Standard Converters]. +xref:jsf-page-core/jsf-page-core.adoc#BNAST[Using the Standard Converters]. diff --git a/src/main/antora/modules/web/pages/webi18n/webi18n004.adoc b/src/main/antora/modules/web/pages/webi18n/webi18n004.adoc index 81f0c09c..e1a3bb6d 100644 --- a/src/main/antora/modules/web/pages/webi18n/webi18n004.adoc +++ b/src/main/antora/modules/web/pages/webi18n/webi18n004.adoc @@ -1,10 +1,10 @@ -[[BNAYB]][[character-sets-and-encodings]] +[[BNAYB]][[_character_sets_and_encodings]] == Character Sets and Encodings The following sections describe character sets and character encodings. -[[BNAYC]][[character-sets]] +[[BNAYC]][[_character_sets]] === Character Sets @@ -29,7 +29,7 @@ characters, as follows: admin.nav.main=P\u00e1gina principal de administraci\u00f3n ---- -[[BNAYD]][[character-encoding]] +[[BNAYD]][[_character_encoding]] === Character Encoding diff --git a/src/main/antora/modules/web/pages/websocket/websocket.adoc b/src/main/antora/modules/web/pages/websocket/websocket.adoc index cca75a64..8acc5d38 100644 --- a/src/main/antora/modules/web/pages/websocket/websocket.adoc +++ b/src/main/antora/modules/web/pages/websocket/websocket.adoc @@ -1,6 +1,6 @@ = Jakarta WebSocket -[[GKJIQ5]][[java-api-for-websocket]] +[[GKJIQ5]][[_java_api_for_websocket]] This chapter describes Jakarta WebSocket, which provides support for creating WebSocket applications. WebSocket is an diff --git a/src/main/antora/modules/web/pages/websocket/websocket001.adoc b/src/main/antora/modules/web/pages/websocket/websocket001.adoc index b380c105..0985d60b 100644 --- a/src/main/antora/modules/web/pages/websocket/websocket001.adoc +++ b/src/main/antora/modules/web/pages/websocket/websocket001.adoc @@ -1,4 +1,4 @@ -[[BABDABHF]][[introduction-to-websocket]] +[[BABDABHF]][[_introduction_to_websocket]] == Introduction to WebSocket diff --git a/src/main/antora/modules/web/pages/websocket/websocket002.adoc b/src/main/antora/modules/web/pages/websocket/websocket002.adoc index b110471c..d46346c9 100644 --- a/src/main/antora/modules/web/pages/websocket/websocket002.adoc +++ b/src/main/antora/modules/web/pages/websocket/websocket002.adoc @@ -1,4 +1,4 @@ -[[BABEAEFC]][[creating-websocket-applications-in-the-jakarta-ee-platform]] +[[BABEAEFC]][[_creating_websocket_applications_in_the_jakarta_ee_platform]] == Creating WebSocket Applications in the Jakarta EE Platform @@ -39,7 +39,7 @@ a programmatic endpoint, but it focuses on annotated endpoints. |======================================================================= -[[sthref114]][[creating-and-deploying-a-websocket-endpoint]] +[[sthref114]][[_creating_and_deploying_a_websocket_endpoint]] === Creating and Deploying a WebSocket Endpoint diff --git a/src/main/antora/modules/web/pages/websocket/websocket003.adoc b/src/main/antora/modules/web/pages/websocket/websocket003.adoc index 444640c9..428de54a 100644 --- a/src/main/antora/modules/web/pages/websocket/websocket003.adoc +++ b/src/main/antora/modules/web/pages/websocket/websocket003.adoc @@ -1,4 +1,4 @@ -[[BABGJEIG]][[programmatic-endpoints]] +[[BABGJEIG]][[_programmatic_endpoints]] == Programmatic Endpoints diff --git a/src/main/antora/modules/web/pages/websocket/websocket004.adoc b/src/main/antora/modules/web/pages/websocket/websocket004.adoc index 760d47ea..797bd051 100644 --- a/src/main/antora/modules/web/pages/websocket/websocket004.adoc +++ b/src/main/antora/modules/web/pages/websocket/websocket004.adoc @@ -1,9 +1,9 @@ -[[BABFEBGA]][[annotated-endpoints]] +[[BABFEBGA]][[_annotated_endpoints]] == Annotated Endpoints The following example shows how to create the same endpoint from -link:#BABGJEIG[Programmatic Endpoints] using annotations +xref:websocket/websocket.adoc#BABGJEIG[Programmatic Endpoints] using annotations instead: [source,java] @@ -26,7 +26,7 @@ having to create an additional class for the message handler, this example uses the `OnMessage` annotation to designate the method invoked to handle messages. -link:#BABDGEJH[Table 19-1] lists the annotations available in the +xref:websocket/websocket.adoc#BABDGEJH[Table 19-1] lists the annotations available in the `javax.websocket` package to designate the methods that handle lifecycle events. The examples in the table show the most common parameters for these methods. See the API reference for details on what combinations of diff --git a/src/main/antora/modules/web/pages/websocket/websocket005.adoc b/src/main/antora/modules/web/pages/websocket/websocket005.adoc index 19000400..a65cc12a 100644 --- a/src/main/antora/modules/web/pages/websocket/websocket005.adoc +++ b/src/main/antora/modules/web/pages/websocket/websocket005.adoc @@ -1,4 +1,4 @@ -[[BABFCGBJ]][[sending-and-receiving-messages]] +[[BABFCGBJ]][[_sending_and_receiving_messages]] == Sending and Receiving Messages @@ -8,7 +8,7 @@ section describes how to use the `Session` and `RemoteEndpoint` interfaces to send messages to the connected peer and how to use the `OnMessage` annotation to receive messages from it. -[[CIHEHFCB]][[sending-messages]] +[[CIHEHFCB]][[_sending_messages]] === Sending Messages @@ -18,7 +18,7 @@ Follow these steps to send messages in an endpoint. + The `Session` object is available as a parameter in the annotated lifecycle methods of the endpoint, like those in -link:#BABDGEJH[Table 19-1]. When your message is a +xref:websocket/websocket.adoc#BABDGEJH[Table 19-1]. When your message is a response to a message from the peer, you have the `Session` object available inside the method that received the message (the method annotated with `@OnMessage`). If you have to send messages that are not @@ -51,11 +51,11 @@ Send a ping frame to the peer. + Send a pong frame to the peer. -The example in link:#BABFEBGA[Annotated Endpoints] +The example in xref:websocket/websocket.adoc#BABFEBGA[Annotated Endpoints] demonstrates how to use this procedure to reply to every incoming text message. -[[BABIFBCG]][[sending-messages-to-all-peers-connected-to-an-endpoint]] +[[BABIFBCG]][[_sending_messages_to_all_peers_connected_to_an_endpoint]] ==== Sending Messages to All Peers Connected to an Endpoint @@ -83,7 +83,7 @@ public class EchoAllEndpoint { } ---- -[[CIHIDFHD]][[receiving-messages]] +[[CIHIDFHD]][[_receiving_messages]] === Receiving Messages diff --git a/src/main/antora/modules/web/pages/websocket/websocket006.adoc b/src/main/antora/modules/web/pages/websocket/websocket006.adoc index d1e9ffd6..68b9ce59 100644 --- a/src/main/antora/modules/web/pages/websocket/websocket006.adoc +++ b/src/main/antora/modules/web/pages/websocket/websocket006.adoc @@ -1,4 +1,4 @@ -[[BABGJCAD]][[maintaining-client-state]] +[[BABGJCAD]][[_maintaining_client_state]] == Maintaining Client State diff --git a/src/main/antora/modules/web/pages/websocket/websocket007.adoc b/src/main/antora/modules/web/pages/websocket/websocket007.adoc index fae79870..b31fa438 100644 --- a/src/main/antora/modules/web/pages/websocket/websocket007.adoc +++ b/src/main/antora/modules/web/pages/websocket/websocket007.adoc @@ -1,4 +1,4 @@ -[[BABGADFG]][[using-encoders-and-decoders]] +[[BABGADFG]][[_using_encoders_and_decoders]] == Using Encoders and Decoders @@ -14,7 +14,7 @@ This mechanism simplifies WebSocket applications, because it decouples the business logic from the serialization and deserialization of objects. -[[CIHBIGBI]][[implementing-encoders-to-convert-java-objects-into-websocket-messages]] +[[CIHBIGBI]][[_implementing_encoders_to_convert_java_objects_into_websocket_messages]] === Implementing Encoders to Convert Java Objects into WebSocket Messages @@ -82,7 +82,7 @@ instances are associated with one and only one WebSocket connection and peer, so there is only one thread executing the code of an encoder instance at any given time. -[[CIHGDJFG]][[implementing-decoders-to-convert-websocket-messages-into-java-objects]] +[[CIHGDJFG]][[_implementing_decoders_to_convert_websocket_messages_into_java_objects]] === Implementing Decoders to Convert WebSocket Messages into Java Objects diff --git a/src/main/antora/modules/web/pages/websocket/websocket008.adoc b/src/main/antora/modules/web/pages/websocket/websocket008.adoc index da29e42d..e595fc09 100644 --- a/src/main/antora/modules/web/pages/websocket/websocket008.adoc +++ b/src/main/antora/modules/web/pages/websocket/websocket008.adoc @@ -1,4 +1,4 @@ -[[BABEJIJI]][[path-parameters]] +[[BABEJIJI]][[_path_parameters]] == Path Parameters diff --git a/src/main/antora/modules/web/pages/websocket/websocket009.adoc b/src/main/antora/modules/web/pages/websocket/websocket009.adoc index a084fa88..af40ceee 100644 --- a/src/main/antora/modules/web/pages/websocket/websocket009.adoc +++ b/src/main/antora/modules/web/pages/websocket/websocket009.adoc @@ -1,4 +1,4 @@ -[[BABDEJHB]][[handling-errors]] +[[BABDEJHB]][[_handling_errors]] == Handling Errors diff --git a/src/main/antora/modules/web/pages/websocket/websocket010.adoc b/src/main/antora/modules/web/pages/websocket/websocket010.adoc index c3022670..f37d4e35 100644 --- a/src/main/antora/modules/web/pages/websocket/websocket010.adoc +++ b/src/main/antora/modules/web/pages/websocket/websocket010.adoc @@ -1,4 +1,4 @@ -[[BABJAIGH]][[specifying-an-endpoint-configurator-class]] +[[BABJAIGH]][[_specifying_an_endpoint_configurator_class]] == Specifying an Endpoint Configurator Class diff --git a/src/main/antora/modules/web/pages/websocket/websocket011.adoc b/src/main/antora/modules/web/pages/websocket/websocket011.adoc index cdcb449b..a8b739ba 100644 --- a/src/main/antora/modules/web/pages/websocket/websocket011.adoc +++ b/src/main/antora/modules/web/pages/websocket/websocket011.adoc @@ -1,4 +1,4 @@ -[[BABGCEHE]][[the-dukeetf2-example-application]] +[[BABGCEHE]][[_the_dukeetf2_example_application]] == The dukeetf2 Example Application @@ -8,7 +8,7 @@ how to use a WebSocket endpoint to provide data updates to web clients. The example resembles a service that provides periodic updates on the price and trading volume of an electronically traded fund (ETF). -[[CIHJHJCD]][[architecture-of-the-dukeetf2-sample-application]] +[[CIHJHJCD]][[_architecture_of_the_dukeetf2_sample_application]] === Architecture of the dukeetf2 Sample Application @@ -23,7 +23,7 @@ every second. endpoint, parse incoming messages, and update the price and volume information without reloading the page. -[[sthref116]][[the-endpoint]] +[[sthref116]][[_the_endpoint]] ==== The Endpoint @@ -88,7 +88,7 @@ public class ETFEndpoint { } ---- -[[sthref117]][[the-enterprise-bean]] +[[sthref117]][[_the_enterprise_bean]] ==== The Enterprise Bean @@ -126,12 +126,12 @@ public class PriceVolumeBean { ---- The enterprise bean calls the `send` method of the `ETFEndpoint` class -in the timeout method. See link:#BNBOY[Using the -Timer Service] in link:#GIJRB[Chapter 37, "Running +in the timeout method. See xref:#BNBOY[Using the +Timer Service] in xref:#GIJRB[Chapter 37, "Running the Enterprise Bean Examples"] for more information on the timer service. -[[CIHHIEFH]][[the-html-page]] +[[CIHHIEFH]][[_the_html_page]] ==== The HTML Page @@ -178,19 +178,19 @@ window.addEventListener("load", connect, false); The WebSocket API is supported by most modern browsers, and it is widely used in HTML5 web client development. -[[CIHHBAIC]][[running-the-dukeetf2-example-application]] +[[CIHHBAIC]][[_running_the_dukeetf2_example_application]] === Running the dukeetf2 Example Application This section describes how to run the `dukeetf2` example application using NetBeans IDE and from the command line. -[[CIHEBIAH]][[to-run-the-dukeetf2-example-application-using-netbeans-ide]] +[[CIHEBIAH]][[_to_run_the_dukeetf2_example_application_using_netbeans_ide]] ==== To Run the dukeetf2 Example Application Using NetBeans IDE 1. Make sure that GlassFish Server has been started (see -link:#BNADI[Starting and Stopping GlassFish +xref:#BNADI[Starting and Stopping GlassFish Server]). 2. From the File menu, choose Open Project. 3. In the Open Project dialog box, navigate to: @@ -216,12 +216,12 @@ http://localhost:8080/dukeetf2/ Open the same URL on a different web browser tab or window to see how both pages get price and volume updates simultaneously. -[[CIHDJCGJ]][[to-run-the-dukeetf2-example-application-using-maven]] +[[CIHDJCGJ]][[_to_run_the_dukeetf2_example_application_using_maven]] ==== To Run the dukeetf2 Example Application Using Maven 1. Make sure that GlassFish Server has been started (see -link:#BNADI[Starting and Stopping GlassFish +xref:#BNADI[Starting and Stopping GlassFish Server]). 2. In a terminal window, go to: + diff --git a/src/main/antora/modules/web/pages/websocket/websocket012.adoc b/src/main/antora/modules/web/pages/websocket/websocket012.adoc index c1ad7777..4952c860 100644 --- a/src/main/antora/modules/web/pages/websocket/websocket012.adoc +++ b/src/main/antora/modules/web/pages/websocket/websocket012.adoc @@ -1,4 +1,4 @@ -[[BABCDBBC]][[the-websocketbot-example-application]] +[[BABCDBBC]][[_the_websocketbot_example_application]] == The websocketbot Example Application @@ -9,32 +9,32 @@ example resembles a chat room in which many users can join and have a conversation. Users can ask simple questions to a bot agent that is always available in the chat room. -[[CIHICIDE]][[architecture-of-the-websocketbot-example-application]] +[[CIHICIDE]][[_architecture_of_the_websocketbot_example_application]] === Architecture of the websocketbot Example Application The `websocketbot` example application consists of the following elements: -* link:#CIHDAEHF[The CDI Bean] – A CDI bean (`BotBean`) that contains +* xref:websocket/websocket.adoc#CIHDAEHF[The CDI Bean] – A CDI bean (`BotBean`) that contains the logic for the bot agent to reply to messages -* link:#CIHJJJHG[The WebSocket Endpoint] – A WebSocket endpoint +* xref:websocket/websocket.adoc#CIHJJJHG[The WebSocket Endpoint] – A WebSocket endpoint (`BotEndpoint`) that implements the chat room -* link:#CIHFDGHG[The Application Messages] – A set of classes +* xref:websocket/websocket.adoc#CIHFDGHG[The Application Messages] – A set of classes (`Message`, `ChatMessage`, `InfoMessage`, `JoinMessage`, and `UsersMessage`) that represent application messages -* link:#CIHGHHBD[The Encoder Classes] – A set of classes +* xref:websocket/websocket.adoc#CIHGHHBD[The Encoder Classes] – A set of classes (`ChatMessageEncoder`, `InfoMessageEncoder`, `JoinMessageEncoder`, and `UsersMessageEncoder`) that encode application messages into WebSocket text messages as JSON data -* link:#CIHHFICG[The Message Decoder] – A class (`MessageDecoder`) the +* xref:websocket/websocket.adoc#CIHHFICG[The Message Decoder] – A class (`MessageDecoder`) the parses WebSocket text messages as JSON data and decodes them into `JoinMessage` or `ChatMessage` objects -* link:#CIHHIEFH[The HTML Page] – An HTML page +* xref:websocket/websocket.adoc#CIHHIEFH[The HTML Page] – An HTML page (`index.html`) that uses JavaScript code to implement the client for the chat room -[[CIHDAEHF]][[the-cdi-bean]] +[[CIHDAEHF]][[_the_cdi_bean]] ==== The CDI Bean @@ -50,7 +50,7 @@ public class BotBean { } ---- -[[CIHJJJHG]][[the-websocket-endpoint]] +[[CIHJJJHG]][[_the_websocket_endpoint]] ==== The WebSocket Endpoint @@ -142,7 +142,7 @@ message, the endpoint forwards it to all connected clients. If a chat message is for the bot agent, the endpoint obtains a response using the `BotBean` instance and sends it to all connected clients. The `sendAll` method is similar to the example in -link:#BABIFBCG[Sending Messages to All Peers Connected +xref:websocket/websocket.adoc#BABIFBCG[Sending Messages to All Peers Connected to an Endpoint]. Asynchronous Processing and Concurrency Considerations @@ -166,11 +166,11 @@ accessed by more than one thread are thread safe. In this example, the code in `BotBean` is thread safe, and the `BotEndpoint.sendAll` method has been declared `synchronized`. -Refer to link:#GKJIQ8[Chapter 59, "Concurrency +Refer to xref:#GKJIQ8[Chapter 59, "Concurrency Utilities for Jakarta EE"] for more information on the managed executor service and Concurrency Utilities for Jakarta EE. -[[CIHFDGHG]][[the-application-messages]] +[[CIHFDGHG]][[_the_application_messages]] ==== The Application Messages @@ -189,7 +189,7 @@ public class ChatMessage extends Message { } ---- -[[CIHGHHBD]][[the-encoder-classes]] +[[CIHGHHBD]][[_the_encoder_classes]] ==== The Encoder Classes @@ -216,10 +216,10 @@ public class ChatMessageEncoder implements Encoder.Text { } ---- -See link:#GLRBB[JSON +See xref:#GLRBB[JSON Processing] for more information on the Java API for JSON Processing. -[[CIHHFICG]][[the-message-decoder]] +[[CIHHFICG]][[_the_message_decoder]] ==== The Message Decoder @@ -273,7 +273,7 @@ public class MessageDecoder implements Decoder.Text { } ---- -[[CIHGDBGF]][[the-html-page]] +[[CIHGDBGF]][[_the_html_page]] ==== The HTML Page @@ -288,19 +288,19 @@ endpoint, send messages, and designate callback methods. The WebSocket API is supported by most modern browsers and is widely used for web client development with HTML5. -[[CIHHJHDB]][[running-the-websocketbot-example-application]] +[[CIHHJHDB]][[_running_the_websocketbot_example_application]] === Running the websocketbot Example Application This section describes how to run the `websocketbot` example application using NetBeans IDE and from the command line. -[[CIHFDDGE]][[to-run-the-websocketbot-example-application-using-netbeans-ide]] +[[CIHFDDGE]][[_to_run_the_websocketbot_example_application_using_netbeans_ide]] ==== To Run the websocketbot Example Application Using NetBeans IDE 1. Make sure that GlassFish Server has been started (see -link:#BNADI[Starting and Stopping GlassFish +xref:#BNADI[Starting and Stopping GlassFish Server]). 2. From the File menu, choose Open Project. 3. In the Open Project dialog box, navigate to: @@ -323,15 +323,15 @@ the server; and launches a web browser window with the following URL: http://localhost:8080/websocketbot/ ---- + -See link:#BABDDAAG[To Test the websocketbot Example Application] for +See xref:websocket/websocket.adoc#BABDDAAG[To Test the websocketbot Example Application] for more information. -[[CIHEDEHB]][[to-run-the-websocketbot-example-application-using-maven]] +[[CIHEDEHB]][[_to_run_the_websocketbot_example_application_using_maven]] ==== To Run the websocketbot Example Application Using Maven 1. Make sure that GlassFish Server has been started (see -link:#BNADI[Starting and Stopping GlassFish +xref:#BNADI[Starting and Stopping GlassFish Server]). 2. In a terminal window, go to: + @@ -352,10 +352,10 @@ mvn install http://localhost:8080/websocketbot/ ---- + -See link:#BABDDAAG[To Test the websocketbot Example Application] for +See xref:websocket/websocket.adoc#BABDDAAG[To Test the websocketbot Example Application] for more information. -[[BABDDAAG]][[to-test-the-websocketbot-example-application]] +[[BABDDAAG]][[_to_test_the_websocketbot_example_application]] ==== To Test the websocketbot Example Application diff --git a/src/main/antora/modules/web/pages/websocket/websocket013.adoc b/src/main/antora/modules/web/pages/websocket/websocket013.adoc index e4403cca..89e48da6 100644 --- a/src/main/antora/modules/web/pages/websocket/websocket013.adoc +++ b/src/main/antora/modules/web/pages/websocket/websocket013.adoc @@ -1,4 +1,4 @@ -[[BABDFIFD]][[further-information-about-websocket]] +[[BABDFIFD]][[_further_information_about_websocket]] == Further Information about WebSocket From 474de12f27d51b9cffa0df6524f5b9a7d45cec57 Mon Sep 17 00:00:00 2001 From: "Kito D. Mann" Date: Thu, 1 Jun 2023 13:35:39 -0400 Subject: [PATCH 051/247] JETUT-120 Added updates for link: when it's referencing an external document --- antora-conversion/AntoraConverter.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/antora-conversion/AntoraConverter.java b/antora-conversion/AntoraConverter.java index 4c1bebce..e12b44d8 100755 --- a/antora-conversion/AntoraConverter.java +++ b/antora-conversion/AntoraConverter.java @@ -130,6 +130,14 @@ private static void process(ArrayList files, boolean dryRun) throws IOExce } changeCount++; } + if (content.contains(("link:http"))) { + System.out.println("=> Updating external links"); + content = content.replace("link:http", "https"); + if (!dryRun) { + Files.write(file.toPath(), content.getBytes()); + } + changeCount++; + } if (content.contains(("link:#"))) { System.out.println("=> Updating external anchor references"); content = replaceBetween(content, "link:", "[", "_", "-", "_", (originalLink, newLink) -> { From b15d937f770ea8e4542c104000307b0564358446 Mon Sep 17 00:00:00 2001 From: "Kito D. Mann" Date: Thu, 1 Jun 2023 13:36:53 -0400 Subject: [PATCH 052/247] JETUT-120 Minor antora conversion documentation updates. --- antora-conversion/CONVERTING_TO_ANTORA.adoc | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/antora-conversion/CONVERTING_TO_ANTORA.adoc b/antora-conversion/CONVERTING_TO_ANTORA.adoc index 00cdc5e8..48cffed1 100644 --- a/antora-conversion/CONVERTING_TO_ANTORA.adoc +++ b/antora-conversion/CONVERTING_TO_ANTORA.adoc @@ -55,7 +55,8 @@ include::security-advanced/security-advanced.adoc[] After copying these into `nav.adoc`, replace "include::" with "* xref:" and add a header with the module name: -```asciidoc +[source,asciidoc] +---- .Security * xref:security-intro/security-intro.adoc[] @@ -66,13 +67,22 @@ After copying these into `nav.adoc`, replace "include::" with "* xref:" and add * xref:security-api/security-api.adoc[] * xref:security-advanced/security-advanced.adoc[] -``` +---- . Add this module to the `src/main/antora/antora.yml`. For example, for the Security module, you would add this line to the end of `src/main/antora/antora.yml` file: -```yaml +[source,yaml] +---- - modules/security/nav.adoc -``` +---- + +. Test out your changes by building the playbook from the `jakartaee-tutorial-playbook repo`. In your `local-antora-playbook.yaml` change `release/XX` to the name of your feature branch, so you can test locally. + +. If there are any changes the script didn't make, either make them manually or update the script to handle them. +If you're updating the script, usually your best bet is to revert the changes from the previous and run it again. + +> TIP: If you're using the Antora IDE plugin, it helps to review its errors and updating before committing. With IntellJ, +these are run automatically before pushing. . Commit your changes, push, and raise a PR to merge into the `release/8` branch. You're done with the first part of the migration! @@ -92,6 +102,8 @@ jbang antora-conversion/AntoraConverter.java jakartaee-tutorial/src/main/antora/ > NOTE: References to chapters that haven't yet been converted will not work until they have been converted. +. Test out your changes by building the playbook from the `jakartaee-tutorial-playbook repo` in author mode. In your `local-antora-playbook.yaml` change `release/XX` or `main` to the name of your feature branch, so you can test locally. + . If there are any changes the script didn't make, either make them manually or update the script to handle them. > TIP: If you're using the Antora IDE plugin, it helps to review its errors and updating before committing. With IntellJ, From 177bd1c821cd580ae319dcef5a93cea0477369f4 Mon Sep 17 00:00:00 2001 From: "Kito D. Mann" Date: Thu, 1 Jun 2023 13:37:18 -0400 Subject: [PATCH 053/247] JETUT-120 Minor antora conversion documentation updates. --- antora-conversion/CONVERTING_TO_ANTORA.adoc | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/antora-conversion/CONVERTING_TO_ANTORA.adoc b/antora-conversion/CONVERTING_TO_ANTORA.adoc index 48cffed1..09e5c1a2 100644 --- a/antora-conversion/CONVERTING_TO_ANTORA.adoc +++ b/antora-conversion/CONVERTING_TO_ANTORA.adoc @@ -94,9 +94,10 @@ these are run automatically before pushing. . Run the migration script from the root project folder. For example, for the Security module, you would run: -```shell +[source,shell] +---- jbang antora-conversion/AntoraConverter.java jakartaee-tutorial/src/main/antora/modules/security -``` +---- > TIP: You can use the "dryrun" parameter to see what changes will be made without actually making them. From 9e17d936d7ee39696521f6fe41a17c85244cac51 Mon Sep 17 00:00:00 2001 From: Bauke Scholtz Date: Thu, 1 Jun 2023 14:01:13 -0400 Subject: [PATCH 054/247] JETUT-72: improvements after self-review --- src/main/asciidoc/webapp/webapp001.adoc | 10 +++++----- src/main/asciidoc/webapp/webapp002.adoc | 10 ++++------ 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/src/main/asciidoc/webapp/webapp001.adoc b/src/main/asciidoc/webapp/webapp001.adoc index eafb3dd9..497a7b48 100644 --- a/src/main/asciidoc/webapp/webapp001.adoc +++ b/src/main/asciidoc/webapp/webapp001.adoc @@ -30,7 +30,8 @@ image::jakartaeett_dt_013.svg["Diagram of web application request handling. Clie . The web component can then fill the `HttpServletResponse` object with the generated dynamic content or can pass the object to another web component to fill it. . The servlet container ultimately converts the `HttpServletResponse` object to an HTTP response and the web server returns it to the client. -Jakarta Servlet is a barebones web framework that can act as a presentation-oriented as well as a service-oriented web application. +Jakarta Servlet is a corner stone web framework that can act as a presentation-oriented as well as a service-oriented web application. +Jakarta Servlet intends to reduce the boilerplate code needed to convert the HTTP request into a Java object and to offer a Java object as a HTTP response, and to manage all the lifecycle around them. Jakarta Faces is a component based MVC framework that can be executed on a servlet container and act as a presentation-oriented web application. Jakarta Faces intends to reduce the boilerplate code needed to apply the request values, convert and validate them, update the JavaBean properties, invoke the JavaBean methods and generate HTML output. Jakarta Faces is designed as such that it can be exuected on a non-servlet container such as a portlet container. @@ -40,11 +41,10 @@ Jakarta REST is designed as such that it can be exuected on a non-servlet contai A servlet container is a kind of a web container that can be part of an application server. The application server gives web components access to such APIs as naming, validation, security, web sockets, persistence transactions, concurrency, and email. - -Certain aspects of web application behavior can be configured when the application is installed, or deployed, to a web container. +Certain aspects of web component behavior can be configured when the web application is installed, or deployed, to a servlet container. The configuration information can be specified using annotations or can be maintained in a XML file called a deployment descriptor (DD). -A DD must conform to the schema described in the associated specification. -When the same configuration is specified using annotations and in a XML file, then the configuration in the XML file will always have precedence. +A DD file must conform to the schema described in the associated specification. +When the same configuration is specified using annotations and in a DD file, then the configuration in the DD file will always have precedence. This chapter gives a brief overview of the activities involved in developing Jakarta Servlet based web applications. It explains how to compile, develop, package, deploy, and run Jakarta Servlet based web applications in a servlet container. diff --git a/src/main/asciidoc/webapp/webapp002.adoc b/src/main/asciidoc/webapp/webapp002.adoc index ae8c58b2..b301841e 100644 --- a/src/main/asciidoc/webapp/webapp002.adoc +++ b/src/main/asciidoc/webapp/webapp002.adoc @@ -18,13 +18,11 @@ It can be summarized as follows: . Run the web application by accessing a URL that references the web component. Developing the web component code and DD files is covered in the later chapters. -Steps 3 through 6 are expanded on in the following sections and illustrated with a Hello World–style, web application. -This application allows a user to enter a name into an HTML form and then displays a greeting after the name is submitted. - -The Hello World application contains two web components that generate the greeting and the response. -This chapter discusses the following simple applications: +Steps 3 through 6 are expanded on in the following sections and illustrated with two web applications, in Hello World–style. +The web applications take a name as an HTTP request parameter, generate the greeting and return it as an HTTP response. +This chapter discusses the following simple web applications: * `helloFaces`, a Jakarta Faces based presentation-oriented web application * `helloServlet`, a Jakarta Servlet based service-oriented web application -The applications are used to illustrate tasks involved in compiling, packaging, deploying, and running a Jakarta Servlet based web application that contains web components. +The web applications are used to illustrate tasks involved in compiling, packaging, deploying, and running a Jakarta Servlet based web application that contains web component code. From 9344e47241af9bad1149b6a8a608c48a62c047a1 Mon Sep 17 00:00:00 2001 From: "Kito D. Mann" Date: Thu, 1 Jun 2023 14:29:45 -0400 Subject: [PATCH 055/247] JETUT-120 Fixed config indent and turned figure captions back on --- src/main/antora/antora.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/antora/antora.yml b/src/main/antora/antora.yml index 374418b3..6a9e2ee4 100644 --- a/src/main/antora/antora.yml +++ b/src/main/antora/antora.yml @@ -5,8 +5,7 @@ asciidoc: attributes: source-language: asciidoc@ table-caption: false - figure-caption: false - xrefstyle: full + xrefstyle: full nav: - modules/ROOT/nav.adoc - modules/security/nav.adoc From eaf93292651de8bbb601a0b0c1f0c4ec2c046f08 Mon Sep 17 00:00:00 2001 From: "Kito D. Mann" Date: Thu, 1 Jun 2023 14:35:59 -0400 Subject: [PATCH 056/247] JETUT-120 Ran web tier through conversion script --- .../jsf-advanced-cc/jsf-advanced-cc001.adoc | 6 +- .../jsf-advanced-cc/jsf-advanced-cc002.adoc | 2 +- .../jsf-advanced-cc/jsf-advanced-cc003.adoc | 6 +- .../jsf-advanced-cc/jsf-advanced-cc004.adoc | 2 +- .../web/pages/jsf-ajax/jsf-ajax001.adoc | 2 +- .../web/pages/jsf-ajax/jsf-ajax002.adoc | 2 +- .../web/pages/jsf-ajax/jsf-ajax003.adoc | 10 +- .../web/pages/jsf-ajax/jsf-ajax004.adoc | 4 +- .../web/pages/jsf-ajax/jsf-ajax005.adoc | 4 +- .../web/pages/jsf-ajax/jsf-ajax006.adoc | 4 +- .../web/pages/jsf-ajax/jsf-ajax008.adoc | 2 +- .../web/pages/jsf-ajax/jsf-ajax010.adoc | 10 +- .../web/pages/jsf-ajax/jsf-ajax011.adoc | 4 +- .../pages/jsf-configure/jsf-configure001.adoc | 2 +- .../pages/jsf-configure/jsf-configure002.adoc | 8 +- .../pages/jsf-configure/jsf-configure004.adoc | 10 +- .../pages/jsf-configure/jsf-configure005.adoc | 22 ++-- .../pages/jsf-configure/jsf-configure006.adoc | 4 +- .../pages/jsf-configure/jsf-configure008.adoc | 6 +- .../pages/jsf-configure/jsf-configure009.adoc | 6 +- .../pages/jsf-configure/jsf-configure010.adoc | 6 +- .../pages/jsf-configure/jsf-configure011.adoc | 4 +- .../pages/jsf-configure/jsf-configure012.adoc | 4 +- .../pages/jsf-configure/jsf-configure013.adoc | 8 +- .../web/pages/jsf-custom/jsf-custom001.adoc | 4 +- .../web/pages/jsf-custom/jsf-custom002.adoc | 14 +-- .../web/pages/jsf-custom/jsf-custom003.adoc | 16 +-- .../web/pages/jsf-custom/jsf-custom004.adoc | 6 +- .../web/pages/jsf-custom/jsf-custom005.adoc | 14 +-- .../web/pages/jsf-custom/jsf-custom006.adoc | 10 +- .../web/pages/jsf-custom/jsf-custom007.adoc | 10 +- .../web/pages/jsf-custom/jsf-custom008.adoc | 8 +- .../web/pages/jsf-custom/jsf-custom009.adoc | 2 +- .../web/pages/jsf-custom/jsf-custom010.adoc | 2 +- .../web/pages/jsf-custom/jsf-custom011.adoc | 14 +-- .../web/pages/jsf-custom/jsf-custom012.adoc | 18 +-- .../web/pages/jsf-custom/jsf-custom013.adoc | 12 +- .../web/pages/jsf-custom/jsf-custom014.adoc | 6 +- .../web/pages/jsf-develop/jsf-develop001.adoc | 12 +- .../web/pages/jsf-develop/jsf-develop002.adoc | 38 +++--- .../web/pages/jsf-develop/jsf-develop003.adoc | 12 +- .../modules/web/pages/jsf-el/jsf-el001.adoc | 2 +- .../modules/web/pages/jsf-el/jsf-el005.adoc | 2 +- .../modules/web/pages/jsf-el/jsf-el007.adoc | 4 +- .../pages/jsf-facelets/jsf-facelets001.adoc | 10 +- .../pages/jsf-facelets/jsf-facelets002.adoc | 4 +- .../pages/jsf-facelets/jsf-facelets003.adoc | 2 +- .../pages/jsf-facelets/jsf-facelets004.adoc | 4 +- .../pages/jsf-facelets/jsf-facelets005.adoc | 8 +- .../pages/jsf-facelets/jsf-facelets007.adoc | 2 +- .../pages/jsf-facelets/jsf-facelets008.adoc | 2 +- .../pages/jsf-facelets/jsf-facelets009.adoc | 10 +- .../web/pages/jsf-intro/jsf-intro002.adoc | 6 +- .../web/pages/jsf-intro/jsf-intro003.adoc | 10 +- .../web/pages/jsf-intro/jsf-intro004.adoc | 10 +- .../web/pages/jsf-intro/jsf-intro005.adoc | 24 ++-- .../web/pages/jsf-intro/jsf-intro006.adoc | 6 +- .../web/pages/jsf-intro/jsf-intro007.adoc | 28 ++--- .../web/pages/jsf-intro/jsf-intro008.adoc | 2 +- .../pages/jsf-page-core/jsf-page-core001.adoc | 30 ++--- .../pages/jsf-page-core/jsf-page-core002.adoc | 10 +- .../pages/jsf-page-core/jsf-page-core003.adoc | 16 +-- .../pages/jsf-page-core/jsf-page-core004.adoc | 12 +- .../modules/web/pages/jsf-page/jsf-page.adoc | 2 +- .../web/pages/jsf-page/jsf-page001.adoc | 2 +- .../web/pages/jsf-page/jsf-page002.adoc | 118 +++++++++--------- .../web/pages/jsf-page/jsf-page003.adoc | 48 +++---- .../modules/web/pages/jsf-ws/jsf-ws003.adoc | 4 +- .../antora/modules/web/pages/jsonb/jsonb.adoc | 2 +- .../modules/web/pages/jsonb/jsonb001.adoc | 12 +- .../modules/web/pages/jsonb/jsonb002.adoc | 2 +- .../modules/web/pages/jsonp/jsonp001.adoc | 2 +- .../modules/web/pages/jsonp/jsonp002.adoc | 10 +- .../modules/web/pages/jsonp/jsonp003.adoc | 8 +- .../modules/web/pages/jsonp/jsonp005.adoc | 4 +- .../modules/web/pages/jsonp/jsonp006.adoc | 6 +- .../modules/web/pages/jsonp/jsonp007.adoc | 4 +- .../web/pages/servlets/servlets002.adoc | 10 +- .../web/pages/servlets/servlets003.adoc | 10 +- .../web/pages/servlets/servlets005.adoc | 4 +- .../web/pages/servlets/servlets006.adoc | 12 +- .../web/pages/servlets/servlets009.adoc | 2 +- .../web/pages/servlets/servlets012.adoc | 4 +- .../web/pages/servlets/servlets013.adoc | 16 +-- .../web/pages/servlets/servlets014.adoc | 4 +- .../web/pages/servlets/servlets017.adoc | 4 +- .../modules/web/pages/webapp/webapp001.adoc | 8 +- .../modules/web/pages/webapp/webapp003.adoc | 4 +- .../modules/web/pages/webapp/webapp005.adoc | 10 +- .../modules/web/pages/webi18n/webi18n001.adoc | 2 +- .../modules/web/pages/webi18n/webi18n002.adoc | 6 +- .../modules/web/pages/webi18n/webi18n003.adoc | 2 +- .../web/pages/websocket/websocket004.adoc | 6 +- .../web/pages/websocket/websocket005.adoc | 4 +- .../web/pages/websocket/websocket012.adoc | 20 +-- 95 files changed, 446 insertions(+), 446 deletions(-) diff --git a/src/main/antora/modules/web/pages/jsf-advanced-cc/jsf-advanced-cc001.adoc b/src/main/antora/modules/web/pages/jsf-advanced-cc/jsf-advanced-cc001.adoc index c3376c93..f076b3a8 100644 --- a/src/main/antora/modules/web/pages/jsf-advanced-cc/jsf-advanced-cc001.adoc +++ b/src/main/antora/modules/web/pages/jsf-advanced-cc/jsf-advanced-cc001.adoc @@ -1,12 +1,12 @@ == Attributes of a Composite Component A composite component is a special type of Jakarta Faces template that acts as a component. -If you are new to composite components, see <> before you proceed with this chapter. +If you are new to composite components, see xref:jsf-facelets/jsf-facelets.adoc#_composite_components[Composite Components] before you proceed with this chapter. You define an attribute of a composite component by using the `composite:attribute` tag. -<> lists the commonly used attributes of this tag. +<<_commonly_used_attributes_of_the_compositeattribute_tag>> lists the commonly used attributes of this tag. -[[commonly-used-attributes-of-the-compositeattribute-tag]] +[[_commonly_used_attributes_of_the_compositeattribute_tag]] .Commonly Used Attributes of the composite:attribute Tag [width="70%",cols="15%,55%"] |=== diff --git a/src/main/antora/modules/web/pages/jsf-advanced-cc/jsf-advanced-cc002.adoc b/src/main/antora/modules/web/pages/jsf-advanced-cc/jsf-advanced-cc002.adoc index c0c966e2..2c94d646 100644 --- a/src/main/antora/modules/web/pages/jsf-advanced-cc/jsf-advanced-cc002.adoc +++ b/src/main/antora/modules/web/pages/jsf-advanced-cc/jsf-advanced-cc002.adoc @@ -8,4 +8,4 @@ To enable a composite component to handle server-side data * Directly use the properties of the managed bean. + -The example application described in <> shows how to use a managed bean with a composite component by passing the reference of the managed bean to the component. +The example application described in <<_the_compositecomponentexample_example_application>> shows how to use a managed bean with a composite component by passing the reference of the managed bean to the component. diff --git a/src/main/antora/modules/web/pages/jsf-advanced-cc/jsf-advanced-cc003.adoc b/src/main/antora/modules/web/pages/jsf-advanced-cc/jsf-advanced-cc003.adoc index 9d29c75a..c0d1db6b 100644 --- a/src/main/antora/modules/web/pages/jsf-advanced-cc/jsf-advanced-cc003.adoc +++ b/src/main/antora/modules/web/pages/jsf-advanced-cc/jsf-advanced-cc003.adoc @@ -3,10 +3,10 @@ Jakarta Faces provides the following tags for validating values of input components. These tags can be used with the `composite:valueHolder` or the `composite:editableValueHolder` tag. -<> lists commonly used validator tags. -See <> for details and a complete list. +<<_validator_tags>> lists commonly used validator tags. +See xref:jsf-page-core/jsf-page-core.adoc#_using_the_standard_validators[Using the Standard Validators] for details and a complete list. -[[validator-tags]] +[[_validator_tags]] .Validator Tags [width="70%",cols="15%,55%"] |=== diff --git a/src/main/antora/modules/web/pages/jsf-advanced-cc/jsf-advanced-cc004.adoc b/src/main/antora/modules/web/pages/jsf-advanced-cc/jsf-advanced-cc004.adoc index 8ee7777e..126073f7 100644 --- a/src/main/antora/modules/web/pages/jsf-advanced-cc/jsf-advanced-cc004.adoc +++ b/src/main/antora/modules/web/pages/jsf-advanced-cc/jsf-advanced-cc004.adoc @@ -99,7 +99,7 @@ It calculates the sum of the letters in the string, with `'a'` equal to 1 and `' An uppercase letter in the input string has the same value as its lowercase equivalent. The bean specifies the minimum and maximum size of the `name` string, which is enforced by the Bean Validation `@Size` constraint. -The bean uses the `@Model` annotation, a shortcut for `@Named` and `@RequestScoped`, as described in <> of <>. +The bean uses the `@Model` annotation, a shortcut for `@Named` and `@RequestScoped`, as described in <> of xref:webapp/webapp.adoc#_to_view_the_hello1_web_module_using_netbeans_ide[To View the hello1 Web Module Using NetBeans IDE]. [source,java] ---- diff --git a/src/main/antora/modules/web/pages/jsf-ajax/jsf-ajax001.adoc b/src/main/antora/modules/web/pages/jsf-ajax/jsf-ajax001.adoc index df570795..79597b00 100644 --- a/src/main/antora/modules/web/pages/jsf-ajax/jsf-ajax001.adoc +++ b/src/main/antora/modules/web/pages/jsf-ajax/jsf-ajax001.adoc @@ -18,7 +18,7 @@ When a JavaScript function sends an asynchronous request from the client to the This response is often in the format of an XML document. The term Ajax refers to this interaction between the client and server. -The server response need not be in XML only; it can also be in other formats, such as JSON (see <> and https://www.json.org/[^]). +The server response need not be in XML only; it can also be in other formats, such as JSON (see xref:jsonp/jsonp.adoc#_introduction_to_json[Introduction to JSON] and https://www.json.org/[^]). This tutorial does not focus on the response formats. Ajax enables asynchronous and partial updating of web applications. diff --git a/src/main/antora/modules/web/pages/jsf-ajax/jsf-ajax002.adoc b/src/main/antora/modules/web/pages/jsf-ajax/jsf-ajax002.adoc index e3166ef0..96a86cee 100644 --- a/src/main/antora/modules/web/pages/jsf-ajax/jsf-ajax002.adoc +++ b/src/main/antora/modules/web/pages/jsf-ajax/jsf-ajax002.adoc @@ -16,6 +16,6 @@ The next sections of the tutorial describe the use of the built-in Ajax resource In addition, because the Jakarta Faces technology component model can be extended, custom components can be created with Ajax functionality. The tutorial examples include an Ajax version of the `guessnumber` application, `ajaxguessnumber`. -See <> for more information. +See <<_the_ajaxguessnumber_example_application>> for more information. The Ajax specific `f:ajax` tag and its attributes are explained in the next sections. diff --git a/src/main/antora/modules/web/pages/jsf-ajax/jsf-ajax003.adoc b/src/main/antora/modules/web/pages/jsf-ajax/jsf-ajax003.adoc index 403b8183..c87b5100 100644 --- a/src/main/antora/modules/web/pages/jsf-ajax/jsf-ajax003.adoc +++ b/src/main/antora/modules/web/pages/jsf-ajax/jsf-ajax003.adoc @@ -27,9 +27,9 @@ In the following example, Ajax behavior is added to an input component by includ In this example, although Ajax is enabled, the other attributes of the `f:ajax` tag are not defined. If an event is not defined, the default action for the component is performed. For the `inputText` component, when no `event` attribute is specified, the default event is `valueChange`. -<> lists the attributes of the `f:ajax` tag and their default actions. +<<_attributes_of_the_fajax_tag>> lists the attributes of the `f:ajax` tag and their default actions. -[[attributes-of-the-fajax-tag]] +[[_attributes_of_the_fajax_tag]] .Attributes of the f:ajax Tag [width="99%",cols="15%,25%,60%"] |=== @@ -66,9 +66,9 @@ If a `ValueExpression` is specified, it must refer to a property that returns a If not specified, the default value is `@none`. |=== -The keywords listed in <> can be used with the `execute` and `render` attributes of the `f:ajax` tag. +The keywords listed in <<_execute_and_render_keywords>> can be used with the `execute` and `render` attributes of the `f:ajax` tag. -[[execute-and-render-keywords]] +[[_execute_and_render_keywords]] .Execute and Render Keywords [width="60%",cols="15%,45%"] |=== @@ -84,4 +84,4 @@ The keywords listed in <> can be used with the `exe |=== Note that when you use the `f:ajax` tag in a Facelets page, the JavaScript resource library is loaded implicitly. -This resource library can also be loaded explicitly as described in <>. +This resource library can also be loaded explicitly as described in <<_loading_javascript_as_a_resource>>. diff --git a/src/main/antora/modules/web/pages/jsf-ajax/jsf-ajax004.adoc b/src/main/antora/modules/web/pages/jsf-ajax/jsf-ajax004.adoc index 81dfc037..19eb4a30 100644 --- a/src/main/antora/modules/web/pages/jsf-ajax/jsf-ajax004.adoc +++ b/src/main/antora/modules/web/pages/jsf-ajax/jsf-ajax004.adoc @@ -3,7 +3,7 @@ To activate Ajax functionality, the web application must create an Ajax request and send it to the server. The server then processes the request. -The application uses the attributes of the `f:ajax` tag listed in <> to create the Ajax request. +The application uses the attributes of the `f:ajax` tag listed in <<_attributes_of_the_fajax_tag>> to create the Ajax request. The following sections explain the process of creating and sending an Ajax request using some of these attributes. [NOTE] @@ -70,7 +70,7 @@ If not defined, the default value of this attribute is `false`. The `listener` attribute refers to a method expression that is executed on the server side in response to an Ajax action on the client. The listener's `jakarta.faces.event.AjaxBehaviorListener.processAjaxBehavior` method is called once during the Invoke Application phase of the lifecycle. -In the following code from the `reservation` example application (see <>), a `listener` attribute is defined by an `f:ajax` tag, which refers to a method from the bean: +In the following code from the `reservation` example application (see xref:jsf-facelets/jsf-facelets.adoc#_the_reservation_example_application[The reservation Example Application]), a `listener` attribute is defined by an `f:ajax` tag, which refers to a method from the bean: [source,xml] ---- diff --git a/src/main/antora/modules/web/pages/jsf-ajax/jsf-ajax005.adoc b/src/main/antora/modules/web/pages/jsf-ajax/jsf-ajax005.adoc index bf4a8f9a..9007a491 100644 --- a/src/main/antora/modules/web/pages/jsf-ajax/jsf-ajax005.adoc +++ b/src/main/antora/modules/web/pages/jsf-ajax/jsf-ajax005.adoc @@ -5,9 +5,9 @@ The value of this attribute is the name of a JavaScript function. Jakarta Faces calls the `onevent` function at each stage of the processing of an Ajax request: begin, complete, and success. When calling the JavaScript function assigned to the `onevent` property, Jakarta Faces passes a data object to it. -The data object contains the properties listed in <>. +The data object contains the properties listed in <<_properties_of_the_onevent_data_object>>. -[[properties-of-the-onevent-data-object]] +[[_properties_of_the_onevent_data_object]] .Properties of the onevent Data Object [width="60%",cols="15%,45%"] |=== diff --git a/src/main/antora/modules/web/pages/jsf-ajax/jsf-ajax006.adoc b/src/main/antora/modules/web/pages/jsf-ajax/jsf-ajax006.adoc index 329e3dce..757ccad0 100644 --- a/src/main/antora/modules/web/pages/jsf-ajax/jsf-ajax006.adoc +++ b/src/main/antora/modules/web/pages/jsf-ajax/jsf-ajax006.adoc @@ -13,9 +13,9 @@ The data object contains all the properties available for the `onevent` attribut * `errorMessage` The `type` is `error`. -The `status` property of the data object contains one of the valid error values listed in <>. +The `status` property of the data object contains one of the valid error values listed in <<_valid_error_values_for_the_data_object_status_property>>. -[[valid-error-values-for-the-data-object-status-property]] +[[_valid_error_values_for_the_data_object_status_property]] .Valid Error Values for the Data Object status Property [width="60%",cols="15%,45%"] |=== diff --git a/src/main/antora/modules/web/pages/jsf-ajax/jsf-ajax008.adoc b/src/main/antora/modules/web/pages/jsf-ajax/jsf-ajax008.adoc index 4cdaf006..9b7c2518 100644 --- a/src/main/antora/modules/web/pages/jsf-ajax/jsf-ajax008.adoc +++ b/src/main/antora/modules/web/pages/jsf-ajax/jsf-ajax008.adoc @@ -2,7 +2,7 @@ An Ajax request varies from other typical Jakarta Faces requests, and its processing is also handled differently by the Jakarta Faces lifecycle. -As described in <>, when an Ajax request is received, the state associated with that request is captured by the `jakarta.faces.context.PartialViewContext`. +As described in xref:jsf-intro/jsf-intro.adoc#_partial_processing_and_partial_rendering[Partial Processing and Partial Rendering], when an Ajax request is received, the state associated with that request is captured by the `jakarta.faces.context.PartialViewContext`. This object provides access to information such as which components are targeted for processing/rendering. The `processPartial` method of `PartialViewContext` uses this information to perform partial component tree processing and rendering. diff --git a/src/main/antora/modules/web/pages/jsf-ajax/jsf-ajax010.adoc b/src/main/antora/modules/web/pages/jsf-ajax/jsf-ajax010.adoc index 2a02449e..85648ab6 100644 --- a/src/main/antora/modules/web/pages/jsf-ajax/jsf-ajax010.adoc +++ b/src/main/antora/modules/web/pages/jsf-ajax/jsf-ajax010.adoc @@ -9,7 +9,7 @@ You may want to use the `h:outputScript` tag to specify other JavaScript librari To use a JavaScript resource directly with a `UIComponent`, you must explicitly load the resource as described in either of the following topics: -* <> – Uses the `h:outputScript` tag directly in a Facelets page +* <<_using_javascript_api_in_a_facelets_application>> – Uses the `h:outputScript` tag directly in a Facelets page * <> – Uses the `jakarta.faces.application.ResourceDependency` annotation on a `UIComponent` Java class @@ -51,17 +51,17 @@ For example, consider the following: The `jsf.ajax.request` method takes up to three parameters that specify source, event, and options. The source parameter identifies the DOM element that triggered the Ajax request, typically `this`. The optional event parameter identifies the DOM event that triggered this request. -The optional options parameter contains a set of name/value pairs from <>. +The optional options parameter contains a set of name/value pairs from <<_possible_values_for_the_options_parameter>>. + -[[possible-values-for-the-options-parameter]] +[[_possible_values_for_the_options_parameter]] .Possible Values for the Options Parameter [width="70%",cols="15%,55%"] |=== |Name |Value -|`execute` |A space-delimited list of client identifiers or one of the keywords listed in <>. The identifiers reference the components that will be processed during the Execute phase of the lifecycle. +|`execute` |A space-delimited list of client identifiers or one of the keywords listed in <<_execute_and_render_keywords>>. The identifiers reference the components that will be processed during the Execute phase of the lifecycle. -|`render` |A space-delimited list of client identifiers or one of the keywords listed in <>. The identifiers reference the components that will be processed during the render phase of the lifecycle. +|`render` |A space-delimited list of client identifiers or one of the keywords listed in <<_execute_and_render_keywords>>. The identifiers reference the components that will be processed during the render phase of the lifecycle. |`onevent` |A `String` that is the name of the JavaScript function to call when an event occurs. diff --git a/src/main/antora/modules/web/pages/jsf-ajax/jsf-ajax011.adoc b/src/main/antora/modules/web/pages/jsf-ajax/jsf-ajax011.adoc index 95a66137..2b9fe504 100644 --- a/src/main/antora/modules/web/pages/jsf-ajax/jsf-ajax011.adoc +++ b/src/main/antora/modules/web/pages/jsf-ajax/jsf-ajax011.adoc @@ -1,6 +1,6 @@ == The ajaxguessnumber Example Application -To demonstrate the advantages of using Ajax, revisit the `guessnumber` example from xref:introduction-to-facelets[xrefstyle=full]. +To demonstrate the advantages of using Ajax, revisit the `guessnumber` example from xref:jsf-facelets/jsf-facelets.adoc#_introduction_to_facelets[Introduction to Facelets]. If you modify this example to use Ajax, the response need not be displayed on the `response.xhtml` page. Instead, an asynchronous call is made to the bean on the server side, and the response is displayed on the originating page by executing just the input component rather than by form submission. @@ -99,7 +99,7 @@ It is injected into `UserNumberBean` with the CDI `@Inject` annotation so that t DukesNumberBean dukesNumberBean; ---- -You will learn more about CDI in xref:introduction-to-jakarta-contexts-and-dependency-injection[xrefstyle=full]. +You will learn more about CDI in xref:introduction-to-jakarta-contexts-and-dependency-injection[]. === Running the ajaxguessnumber Example diff --git a/src/main/antora/modules/web/pages/jsf-configure/jsf-configure001.adoc b/src/main/antora/modules/web/pages/jsf-configure/jsf-configure001.adoc index a33f9699..2fee01f3 100644 --- a/src/main/antora/modules/web/pages/jsf-configure/jsf-configure001.adoc +++ b/src/main/antora/modules/web/pages/jsf-configure/jsf-configure001.adoc @@ -1,6 +1,6 @@ == Introduction to Configuring Jakarta Faces Applications -The process of building and deploying simple Jakarta Faces applications is described in earlier chapters of this tutorial, including xref:getting-started-with-web-applications[xrefstyle=full], xref:introduction-to-facelets[xrefstyle=full], xref:using-ajax-with-jakarta-faces-technology[xrefstyle=full] and xref:composite-components-advanced-topics-and-an-example[xrefstyle=full] When you create large and complex applications, however, various additional configuration tasks are required. +The process of building and deploying simple Jakarta Faces applications is described in earlier chapters of this tutorial, including xref:webapp/webapp.adoc#_getting_started_with_web_applications[Getting Started with Web Applications], xref:jsf-facelets/jsf-facelets.adoc#_introduction_to_facelets[Introduction to Facelets], xref:jsf-ajax/jsf-ajax.adoc#_using_ajax_with_jakarta_faces_technology[Using Ajax with Jakarta Faces Technology] and xref:jsf-advanced-cc/jsf-advanced-cc.adoc#_composite_components_advanced_topics_and_an_example[Composite Components: Advanced Topics and an Example] When you create large and complex applications, however, various additional configuration tasks are required. These tasks include the following: * Registering managed beans with the application so that all parts of the application have access to them diff --git a/src/main/antora/modules/web/pages/jsf-configure/jsf-configure002.adoc b/src/main/antora/modules/web/pages/jsf-configure/jsf-configure002.adoc index 706c06d8..5992c92a 100644 --- a/src/main/antora/modules/web/pages/jsf-configure/jsf-configure002.adoc +++ b/src/main/antora/modules/web/pages/jsf-configure/jsf-configure002.adoc @@ -3,7 +3,7 @@ [NOTE] In Jakarta Faces 2.3, managed bean annotations are deprecated; CDI is now the preferred approach. -Jakarta Faces support for bean annotations is introduced in xref:jakarta-faces-technology-2[xrefstyle=full]. +Jakarta Faces support for bean annotations is introduced in xref:jakarta-faces-technology-2[]. Bean annotations can be used for configuring Jakarta Faces applications. The `@Named` (`jakarta.inject.Named`) annotation in a class, along with a scope annotation, automatically registers that class as a resource with the Jakarta Faces implementation. @@ -20,12 +20,12 @@ public class ShoppingCart ... { ... } The above code snippet shows a bean that is managed by the Jakarta Faces implementation and is available for the length of the session. -You can annotate beans with any of the scopes listed in the next section, <>. +You can annotate beans with any of the scopes listed in the next section, <<_using_managed_bean_scopes>>. All classes will be scanned for annotations at startup unless the `faces-config` element in the `faces-config.xml` file has the `metadata-complete` attribute set to `true`. Annotations are also available for other artifacts, such as components, converters, validators, and renderers, to be used in place of application configuration resource file entries. -These are discussed, along with registration of custom listeners, custom validators, and custom converters, in xref:creating-custom-ui-components-and-other-custom-objects[xrefstyle=full]. +These are discussed, along with registration of custom listeners, custom validators, and custom converters, in xref:jsf-custom/jsf-custom.adoc#_creating_custom_ui_components_and_other_custom_objects[Creating Custom UI Components and Other Custom Objects]. === Using Managed Bean Scopes @@ -37,7 +37,7 @@ You can specify one of the following scopes for a bean class. * Session (`jakarta.enterprise.context.SessionScoped`): Session scope persists across multiple HTTP requests in a web application. * Flow (`jakarta.faces.flows.FlowScoped`): Flow scope persists during a user's interaction with a specific flow of a web application. -See <> for more information. +See <<_using_faces_flows>> for more information. * Request (`jakarta.enterprise.context.RequestScoped`): Request scope persists during a single HTTP request in a web application. diff --git a/src/main/antora/modules/web/pages/jsf-configure/jsf-configure004.adoc b/src/main/antora/modules/web/pages/jsf-configure/jsf-configure004.adoc index 5919c734..1276c3f1 100644 --- a/src/main/antora/modules/web/pages/jsf-configure/jsf-configure004.adoc +++ b/src/main/antora/modules/web/pages/jsf-configure/jsf-configure004.adoc @@ -27,11 +27,11 @@ You can configure a flow programmatically, by creating a class annotated `@FlowD The configuration file can be limited to one flow, or you can use the `faces-config.xml` file to put all the flows in one place, if you have many flows in an application. The programmatic configuration places the code closer to the rest of the flow code and enables you to modularize the flows. -<> shows two flows and illustrates how they interact. +<<_two_faces_flows_and_their_interactions>> shows two flows and illustrates how they interact. -[[two-faces-flows-and-their-interactions]] +[[_two_faces_flows_and_their_interactions]] .Two Faces Flows and Their Interactions -image::jakartaeett_dt_017.svg["This figure shows two Faces flows, Flow A and Flow B. Each has a start node and two additional pages. Each has an associated managed bean. Each defines a return node, and each defines two parameters to be passed to the other flow."] +image::common:jakartaeett_dt_017.svg["This figure shows two Faces flows, Flow A and Flow B. Each has a start node and two additional pages. Each has an associated managed bean. Each defines a return node, and each defines two parameters to be passed to the other flow."] In this figure, Flow A has a start node named `flow-a` and two additional pages, `next_a1` and `next_a2`. From `next_a2`, a user can either exit the flow using the defined return node, `taskFlowReturn1`, or call Flow B, passing two parameters. @@ -44,7 +44,7 @@ Each flow also has an associated managed bean; the beans are `Flow_a_Bean` and ` Typically, you package flows in a web application using a directory structure that modularizes the flows. In the `src/main/webapp` directory of a Maven project, for example, you would place the Facelets files that are outside the flow at the top level as usual. Then the `webapp` files for each flow would be in a separate directory, and the Java files would be under `src/main/java`. -For example, the files for the application shown in <> might look like this: +For example, the files for the application shown in <<_two_faces_flows_and_their_interactions>> might look like this: ---- src/main/webapp/ @@ -211,7 +211,7 @@ Click Back to Start to return to the `index.xhtml` page. The `checkout-module` example application is considerably more complex than `simple-flow`. It shows how you might use the Faces Flows feature to implement a checkout module for an online store. -Like the hypothetical example in <>, the example application contains two flows, each of which can call the other. +Like the hypothetical example in <<_two_faces_flows_and_their_interactions>>, the example application contains two flows, each of which can call the other. Both flows have explicit flow definitions. One flow, `checkoutFlow`, is specified programmatically. The other flow, `joinFlow`, is specified in a configuration file. diff --git a/src/main/antora/modules/web/pages/jsf-configure/jsf-configure005.adoc b/src/main/antora/modules/web/pages/jsf-configure/jsf-configure005.adoc index f38af35c..e5b4b79f 100644 --- a/src/main/antora/modules/web/pages/jsf-configure/jsf-configure005.adoc +++ b/src/main/antora/modules/web/pages/jsf-configure/jsf-configure005.adoc @@ -1,11 +1,11 @@ == Configuring Managed Beans When a page references a managed bean for the first time, the Jakarta Faces implementation initializes it either based on a `@Named` annotation and scope annotation in the bean class or according to its configuration in the application configuration resource file. -For information on using annotations to initialize beans, see <>. +For information on using annotations to initialize beans, see <<_using_annotations_to_configure_managed_beans>>. You can use either annotations or the application configuration resource file to instantiate managed beans that are used in a Jakarta Faces application and to store them in scope. The managed bean creation facility is configured in the application configuration resource file using `managed-bean` XML elements to define each bean. This file is processed at application startup time. -For information on using this facility, see <>. +For information on using this facility, see <<_using_the_managed_bean_element>>. Managed beans created in the application configuration resource file are Jakarta Faces managed beans, not CDI managed beans. @@ -20,7 +20,7 @@ With the managed bean creation facility, you can * Using `value` elements, set a property of one managed bean to be the result of evaluating another value expression This section shows you how to initialize beans using the managed bean creation facility. -See <> and <> for information on programming managed beans. +See xref:jsf-develop/jsf-develop.adoc#_writing_bean_properties[Writing Bean Properties] and xref:jsf-develop/jsf-develop.adoc#_writing_managed_bean_methods[Writing Managed Bean Methods] for information on programming managed beans. === Using the managed-bean Element @@ -100,11 +100,11 @@ Each `SelectItem` object is in turn configured as a managed bean with properties This approach may be useful for quick-and-dirty creation of selection item lists before a development team has had time to create such lists from the database. Note that each of the individual newsletter beans has a `managed-bean-scope` setting of `none` so that they will not themselves be placed into any scope. -See <> for more information on configuring collections as beans. +See <<_initializing_array_and_list_properties>> for more information on configuring collections as beans. To map to a property defined by a `managed-property` element, you must ensure that the part of a component tag's `value` expression after the period matches the `managed-property` element's `property-name` element. -The next section, <>, explains in more detail how to use the `managed-property` element. -See <> for an example of initializing a managed bean property. +The next section, <<_initializing_properties_using_the_managed_property_element>>, explains in more detail how to use the `managed-property` element. +See <<_initializing_managed_bean_properties>> for an example of initializing a managed bean property. === Initializing Properties Using the managed-property Element @@ -112,9 +112,9 @@ A `managed-property` element must contain a `property-name` element, which must A `managed-property` element must also contain one of a set of elements that defines the value of the property. This value must be of the same type as that defined for the property in the corresponding bean. Which element you use to define the value depends on the type of the property defined in the bean. -<> lists all the elements that are used to initialize a value. +<<_subelements_of_managed_property_elements_that_define_property_values>> lists all the elements that are used to initialize a value. -[[subelements-of-managed-property-elements-that-define-property-values]] +[[_subelements_of_managed_property_elements_that_define_property_values]] .Subelements of managed-property Elements That Define Property Values [width="75%",cols="25%,50%"] |=== @@ -129,7 +129,7 @@ Which element you use to define the value depends on the type of the property de |`value` |Defines a single value, such as a `String`, `int`, or Jakarta Faces EL expression |=== -<> includes an example of initializing an `int` property (a primitive type) using the `value` subelement. +<<_using_the_managed_bean_element>> includes an example of initializing an `int` property (a primitive type) using the `value` subelement. You also use the `value` subelement to initialize `String` and other reference types. The rest of this section describes how to use the `value` subelement and other subelements to initialize properties of Java `Enum` types, `Map`, `array`, and `Collection`, as well as initialization parameters. @@ -339,9 +339,9 @@ Because both the `mailingAddress` and the `streetAddress` properties reference ` When you create an object that points to other objects, do not try to point to an object with a shorter life span, because it might be impossible to recover that scope's resources when it goes away. A session-scoped object, for example, cannot point to a request-scoped object. And objects with `none` scope have no effective life span managed by the framework, so they can point only to other `none`-scoped objects. -<> outlines all of the allowed connections. +<<_allowable_connections_between_scoped_objects>> outlines all of the allowed connections. -[[allowable-connections-between-scoped-objects]] +[[_allowable_connections_between_scoped_objects]] .Allowable Connections between Scoped Objects [width="60%",cols="20%,40%"] |=== diff --git a/src/main/antora/modules/web/pages/jsf-configure/jsf-configure006.adoc b/src/main/antora/modules/web/pages/jsf-configure/jsf-configure006.adoc index 5062b103..80b018cb 100644 --- a/src/main/antora/modules/web/pages/jsf-configure/jsf-configure006.adoc +++ b/src/main/antora/modules/web/pages/jsf-configure/jsf-configure006.adoc @@ -3,7 +3,7 @@ Application messages can include any strings displayed to the user as well as custom error messages (which are displayed by the `message` and `messages` tags) for your custom converters or validators. To make messages available at application startup time, do one of the following: -* Queue an individual message onto the `jakarta.faces.context.FacesContext` instance programmatically, as described in <> +* Queue an individual message onto the `jakarta.faces.context.FacesContext` instance programmatically, as described in <<_using_facesmessage_to_create_a_message>> * Register all the messages with your application using the application configuration resource file @@ -92,7 +92,7 @@ public static String loadErrorMessage(FacesContext context, === Referencing Error Messages -A Jakarta Faces page uses the `message` or `messages` tags to access error messages, as explained in <>. +A Jakarta Faces page uses the `message` or `messages` tags to access error messages, as explained in xref:jsf-page/jsf-page.adoc#_displaying_error_messages_with_the_hmessage_and_hmessages_tags[Displaying Error Messages with the h:message and h:messages Tags]. The error messages these tags access include diff --git a/src/main/antora/modules/web/pages/jsf-configure/jsf-configure008.adoc b/src/main/antora/modules/web/pages/jsf-configure/jsf-configure008.adoc index b5c2912e..0b1a7b82 100644 --- a/src/main/antora/modules/web/pages/jsf-configure/jsf-configure008.adoc +++ b/src/main/antora/modules/web/pages/jsf-configure/jsf-configure008.adoc @@ -1,6 +1,6 @@ == Registering a Custom Validator -If the application developer provides an implementation of the `jakarta.faces.validator.Validator` interface to perform validation, you must register this custom validator either by using the `@FacesValidator` annotation, as described in <>, or by using the `validator` XML element in the application configuration resource file: +If the application developer provides an implementation of the `jakarta.faces.validator.Validator` interface to perform validation, you must register this custom validator either by using the `@FacesValidator` annotation, as described in xref:jsf-custom/jsf-custom.adoc#_implementing_the_validator_interface[Implementing the Validator Interface], or by using the `validator` XML element in the application configuration resource file: [source,xml] ---- @@ -31,6 +31,6 @@ It has required `attribute-name` and `attribute-class` subelements. The `attribute-name` element refers to the name of the attribute as it appears in the `validator` tag. The `attribute-class` element identifies the Java type of the value associated with the attribute. -<> explains how to implement the `Validator` interface. +xref:jsf-custom/jsf-custom.adoc#_creating_and_using_a_custom_validator[Creating and Using a Custom Validator] explains how to implement the `Validator` interface. -<> explains how to reference the validator from the page. +xref:jsf-custom/jsf-custom.adoc#_using_a_custom_validator[Using a Custom Validator] explains how to reference the validator from the page. diff --git a/src/main/antora/modules/web/pages/jsf-configure/jsf-configure009.adoc b/src/main/antora/modules/web/pages/jsf-configure/jsf-configure009.adoc index 8904345c..ce70832e 100644 --- a/src/main/antora/modules/web/pages/jsf-configure/jsf-configure009.adoc +++ b/src/main/antora/modules/web/pages/jsf-configure/jsf-configure009.adoc @@ -1,6 +1,6 @@ == Registering a Custom Converter -As is the case with a custom validator, if the application developer creates a custom converter, you must register it with the application either by using the `@FacesConverter` annotation, as described in <>, or by using the `converter` XML element in the application configuration resource file. +As is the case with a custom validator, if the application developer creates a custom converter, you must register it with the application either by using the `@FacesConverter` annotation, as described in xref:jsf-custom/jsf-custom.adoc#_creating_a_custom_converter[Creating a Custom Converter], or by using the `converter` XML element in the application configuration resource file. Here is a hypothetical `converter` configuration for `CreditCardConverter` from the Duke's Bookstore case study: [source,xml] @@ -22,8 +22,8 @@ Attributes specified in a `converter` tag override any settings in the `@FacesCo The `converter` element represents a `jakarta.faces.convert.Converter` implementation and contains required `converter-id` and `converter-class` elements. The `converter-id` element identifies an ID that is used by the `converter` attribute of a UI component tag to apply the converter to the component's data. -<> includes an example of referencing the custom converter from a component tag. +xref:jsf-custom/jsf-custom.adoc#_using_a_custom_converter[Using a Custom Converter] includes an example of referencing the custom converter from a component tag. The `converter-class` element identifies the `Converter` implementation. -<> explains how to create a custom converter. +xref:jsf-custom/jsf-custom.adoc#_creating_and_using_a_custom_converter[Creating and Using a Custom Converter] explains how to create a custom converter. diff --git a/src/main/antora/modules/web/pages/jsf-configure/jsf-configure010.adoc b/src/main/antora/modules/web/pages/jsf-configure/jsf-configure010.adoc index 600153d4..10be1763 100644 --- a/src/main/antora/modules/web/pages/jsf-configure/jsf-configure010.adoc +++ b/src/main/antora/modules/web/pages/jsf-configure/jsf-configure010.adoc @@ -2,7 +2,7 @@ Navigation between different pages of a Jakarta Faces application, such as choosing the next page to be displayed after a button or link component is clicked, is defined by a set of rules. Navigation rules can be implicit, or they can be explicitly defined in the application configuration resource file. -For more information on implicit navigation rules, see <>. +For more information on implicit navigation rules, see xref:jsf-intro/jsf-intro.adoc#_navigation_model[Navigation Model]. Each navigation rule specifies how to navigate from one page to another page or set of pages. The Jakarta Faces implementation chooses the proper navigation rule according to which page is currently displayed. @@ -13,9 +13,9 @@ After the proper navigation rule is selected, the choice of which page to access * The logical outcome referenced by the component's tag or returned from the action method -The outcome can be anything the developer chooses, but <> lists some outcomes commonly used in web applications. +The outcome can be anything the developer chooses, but <<_common_outcome_strings>> lists some outcomes commonly used in web applications. -[[common-outcome-strings]] +[[_common_outcome_strings]] .Common Outcome Strings [width="60%",cols="15%,45%"] |=== diff --git a/src/main/antora/modules/web/pages/jsf-configure/jsf-configure011.adoc b/src/main/antora/modules/web/pages/jsf-configure/jsf-configure011.adoc index 9c768fb9..42abab2e 100644 --- a/src/main/antora/modules/web/pages/jsf-configure/jsf-configure011.adoc +++ b/src/main/antora/modules/web/pages/jsf-configure/jsf-configure011.adoc @@ -1,9 +1,9 @@ == Registering a Custom Renderer with a Render Kit -When the application developer creates a custom renderer, as described in <>, you must register it using the appropriate render kit. +When the application developer creates a custom renderer, as described in xref:jsf-custom/jsf-custom.adoc#_delegating_rendering_to_a_renderer[Delegating Rendering to a Renderer], you must register it using the appropriate render kit. Because the image map application implements an HTML image map, the `AreaRenderer` and `MapRenderer` classes in the Duke's Bookstore case study should be registered using the HTML render kit. -You register the renderer either by using the `@FacesRenderer` annotation, as described in <>, or by using the `render-kit` element of the application configuration resource file. +You register the renderer either by using the `@FacesRenderer` annotation, as described in xref:jsf-custom/jsf-custom.adoc#_creating_the_renderer_class[Creating the Renderer Class], or by using the `render-kit` element of the application configuration resource file. Here is a hypothetical configuration of `AreaRenderer`: [source,xml] diff --git a/src/main/antora/modules/web/pages/jsf-configure/jsf-configure012.adoc b/src/main/antora/modules/web/pages/jsf-configure/jsf-configure012.adoc index 3e4747da..a9bfab75 100644 --- a/src/main/antora/modules/web/pages/jsf-configure/jsf-configure012.adoc +++ b/src/main/antora/modules/web/pages/jsf-configure/jsf-configure012.adoc @@ -1,7 +1,7 @@ == Registering a Custom Component In addition to registering custom renderers (as explained in the preceding section), you also must register the custom components that are usually associated with the custom renderers. -You use either a `@FacesComponent` annotation, as described in <>, or the `component` element of the application configuration resource file. +You use either a `@FacesComponent` annotation, as described in xref:jsf-custom/jsf-custom.adoc#_creating_custom_component_classes[Creating Custom Component Classes], or the `component` element of the application configuration resource file. Here is a hypothetical `component` element from the application configuration resource file that registers `AreaComponent`: @@ -37,4 +37,4 @@ The `component-class` element indicates the fully qualified class name of the co The `property` elements specify the component properties and their types. If the custom component can include facets, you can configure the facets in the component configuration using `facet` elements, which are allowed after the `component-class` elements. -See <> for further details on configuring facets. +See <<_registering_a_custom_renderer_with_a_render_kit>> for further details on configuring facets. diff --git a/src/main/antora/modules/web/pages/jsf-configure/jsf-configure013.adoc b/src/main/antora/modules/web/pages/jsf-configure/jsf-configure013.adoc index 6e00c4e4..2b38d6ac 100644 --- a/src/main/antora/modules/web/pages/jsf-configure/jsf-configure013.adoc +++ b/src/main/antora/modules/web/pages/jsf-configure/jsf-configure013.adoc @@ -73,7 +73,7 @@ A requirement of a Jakarta Faces application is that all requests to the applica A `FacesServlet` instance manages the request-processing lifecycle for web applications and initializes the resources required by Jakarta Faces technology. Before a Jakarta Faces application can launch its first web page, the web container must invoke the `FacesServlet` instance in order for the application lifecycle process to start. -See <> for more information. +See xref:jsf-intro/jsf-intro.adoc#_the_lifecycle_of_a_jakarta_faces_application[The Lifecycle of a Jakarta Faces Application] for more information. The following example shows the default configuration of the `FacesServlet`: @@ -133,7 +133,7 @@ If you created your application without an IDE, you can create a web deployment ==== To Specify a Path to an Application Configuration Resource File -As explained in <>, an application can have multiple application configuration resource files. +As explained in <<_application_configuration_resource_file>>, an application can have multiple application configuration resource files. If these files are not located in the directories that the implementation searches by default or the files are not named `faces-config.xml`, you need to specify paths to these files. To specify these paths using NetBeans IDE, do the following. @@ -165,7 +165,7 @@ To specify these paths using NetBeans IDE, do the following. For all the components in a web application, you can specify in your deployment descriptor where you want the state to be saved, on either client or server. You do this by setting a context parameter in your deployment descriptor. By default, state is saved on the server, so you need to specify this context parameter only if you want to save state on the client. -See <> for information on the advantages and disadvantages of each location. +See xref:jsf-custom/jsf-custom.adoc#_saving_and_restoring_state[Saving and Restoring State] for information on the advantages and disadvantages of each location. To specify where state is saved using NetBeans IDE, do the following. @@ -236,7 +236,7 @@ When packaging web applications using the included build scripts, you'll notice * All application JAR files are packaged in the `WEB-INF/lib/` directory. * All resource files are either under the root of the web application `/resources` directory or in the web application's classpath, the `META-INF/resources/_resourceIdentifier_` directory. -For more information on resources, see <>. +For more information on resources, see xref:jsf-facelets/jsf-facelets.adoc#_web_resources[Web Resources]. When packaging your own applications, you can use NetBeans IDE or you can use XML files such as those created for Maven. You can modify the XML files to fit your situation. diff --git a/src/main/antora/modules/web/pages/jsf-custom/jsf-custom001.adoc b/src/main/antora/modules/web/pages/jsf-custom/jsf-custom001.adoc index 5f440584..06d6bbee 100644 --- a/src/main/antora/modules/web/pages/jsf-custom/jsf-custom001.adoc +++ b/src/main/antora/modules/web/pages/jsf-custom/jsf-custom001.adoc @@ -28,10 +28,10 @@ Most Jakarta Faces component libraries provide their own render kits. A `jakarta.faces.view.facelets.Tag` object is a helper to the `UIComponent` and `Renderer` that allows the page author to include an instance of a `UIComponent` in a Jakarta Faces view. A tag represents a specific combination of `component-type` and `renderer-type`. -See <> for information on how components, renderers, and tags interact. +See <<_component_renderer_and_tag_combinations>> for information on how components, renderers, and tags interact. This chapter uses the image map component from the Duke's Bookstore case study example to explain how you can create simple custom components, custom renderers, and associated custom tags, and take care of all the other details associated with using the components and renderers in an application. -See xref:dukes-bookstore-case-study-example[xrefstyle=full] for more information about this example. +See xref:dukes-bookstore-case-study-example[] for more information about this example. The chapter also describes how to create other custom objects: custom converters, custom listeners, and custom validators. It also describes how to bind component values and instances to data objects and how to bind custom objects to managed bean properties. diff --git a/src/main/antora/modules/web/pages/jsf-custom/jsf-custom002.adoc b/src/main/antora/modules/web/pages/jsf-custom/jsf-custom002.adoc index 14efd7db..11d76754 100644 --- a/src/main/antora/modules/web/pages/jsf-custom/jsf-custom002.adoc +++ b/src/main/antora/modules/web/pages/jsf-custom/jsf-custom002.adoc @@ -28,22 +28,22 @@ You do not need to create a custom component in the following cases. * You need to aggregate components to create a new component that has its own unique behavior. In this situation, you can use a composite component to combine existing standard components. -For more information on composite components, see <> and xref:composite-components-advanced-topics-and-an-example[xrefstyle=full]. +For more information on composite components, see xref:jsf-facelets/jsf-facelets.adoc#_composite_components[Composite Components] and xref:jsf-advanced-cc/jsf-advanced-cc.adoc#_composite_components_advanced_topics_and_an_example[Composite Components: Advanced Topics and an Example]. * You simply need to manipulate data on the component or add application-specific functionality to it. In this situation, you should create a managed bean for this purpose and bind it to the standard component rather than create a custom component. -See <> for more information on managed beans. +See xref:jsf-develop/jsf-develop.adoc#_managed_beans_in_jakarta_faces_technology[Managed Beans in Jakarta Faces Technology] for more information on managed beans. * You need to convert a component's data to a type not supported by its renderer. -See <> for more information about converting a component's data. +See xref:jsf-page-core/jsf-page-core.adoc#_using_the_standard_converters[Using the Standard Converters] for more information about converting a component's data. * You need to perform validation on the component data. Standard validators and custom validators can be added to a component by using the validator tags from the page. -See <> and <> for more information about validating a component's data. +See xref:jsf-page-core/jsf-page-core.adoc#_using_the_standard_validators[Using the Standard Validators] and <<_creating_and_using_a_custom_validator>> for more information about validating a component's data. * You need to register event listeners on components. You can either register event listeners on components using the `f:valueChangeListener` and `f:actionListener` tags, or you can point at an event-processing method on a managed bean using the component's `actionListener` or `valueChangeListener` attributes. -See <> and <> for more information. +See <<_implementing_an_event_listener>> and xref:jsf-develop/jsf-develop.adoc#_writing_managed_bean_methods[Writing Managed Bean Methods] for more information. === When to Use a Custom Renderer @@ -93,9 +93,9 @@ For example, suppose that you need to create a custom validator that requires ex In this case, the custom tag corresponds to a custom validator and not to a custom component or custom renderer. In any case, you still need to associate the custom tag with a server-side object. -<> summarizes what you must or can associate with a custom component, custom renderer, or custom tag. +<<_requirements_for_custom_components_custom_renderers_and_custom_tags>> summarizes what you must or can associate with a custom component, custom renderer, or custom tag. -[[requirements-for-custom-components-custom-renderers-and-custom-tags]] +[[_requirements_for_custom_components_custom_renderers_and_custom_tags]] .Requirements for Custom Components, Custom Renderers and Custom Tags [width="90%",cols="34%,30%,36%"] |=== diff --git a/src/main/antora/modules/web/pages/jsf-custom/jsf-custom003.adoc b/src/main/antora/modules/web/pages/jsf-custom/jsf-custom003.adoc index 0b8be7c3..687335aa 100644 --- a/src/main/antora/modules/web/pages/jsf-custom/jsf-custom003.adoc +++ b/src/main/antora/modules/web/pages/jsf-custom/jsf-custom003.adoc @@ -97,10 +97,10 @@ The `alt` attribute of the `h:graphicImage` tag maps to the localized string `"C The `f:actionListener` tag within the `bookstore:map` tag points to a listener class for an action event. The `processAction` method of the listener places the book ID for the selected map area into the session map. -The way this event is handled is explained more in <>. +The way this event is handled is explained more in <<_handling_events_for_custom_components>>. The `action` attribute of the `bookstore:map` tag specifies a logical outcome `String`, `"bookstore"`, which by implicit navigation rules sends the application to the page `bookstore.xhtml`. -For more information on navigation, see <>. +For more information on navigation, see xref:jsf-configure/jsf-configure.adoc#_configuring_navigation_rules[Configuring Navigation Rules]. The `immediate` attribute of the `bookstore:map` tag is set to `true`, which indicates that the default `jakarta.faces.event.ActionListener` implementation should execute during the Apply Request Values phase of the request-processing lifecycle, instead of waiting for the Invoke Application phase. Because the request resulting from clicking the map does not require any validation, data conversion, or server-side object updates, it makes sense to skip directly to the Invoke Application phase. @@ -110,7 +110,7 @@ The `current` attribute of the `bookstore:map` tag is set to the default area, w Notice that the `bookstore:area` tags do not contain any of the JavaScript, coordinate, or shape data that is displayed on the HTML page. The JavaScript is generated by the `dukesbookstore.renderers.AreaRenderer` class. The `onmouseover` and `onmouseout` attribute values indicate the image to be loaded when these events occur. -How the JavaScript is generated is explained more in <>. +How the JavaScript is generated is explained more in <<_performing_encoding>>. The coordinate, shape, and alternate text data are obtained through the `value` attribute, whose value refers to an attribute in application scope. The value of this attribute is a bean, which stores the `coords`, `shape`, and `alt` data. @@ -123,7 +123,7 @@ However, the shape and coordinates of a hotspot should be defined together becau Because a component's value can be bound only to one property, the `value` attribute cannot refer to both the shape and the coordinates. To solve this problem, the application encapsulates all of this information in a set of `ImageArea` objects. -These objects are initialized into application scope by the managed bean creation facility (see <>). +These objects are initialized into application scope by the managed bean creation facility (see xref:jsf-configure/jsf-configure.adoc#_using_the_managed_bean_element[Using the managed-bean Element]). Here is part of the managed bean declaration for the `ImageArea` bean corresponding to the South America hotspot: [source,xml] @@ -153,7 +153,7 @@ Here is part of the managed bean declaration for the `ImageArea` bean correspond ---- -For more information on initializing managed beans with the managed bean creation facility, see the section <>. +For more information on initializing managed beans with the managed bean creation facility, see the section xref:jsf-configure/jsf-configure.adoc#_application_configuration_resource_file[Application Configuration Resource File]. The `value` attributes of the `bookstore:area` tags refer to the beans in the application scope, as shown in this `bookstore:area` tag from `index.xhtml`: @@ -176,13 +176,13 @@ ImageArea iarea = (ImageArea) area.getValue(); ---- `ImageArea` is a simple bean, so you can access the shape, coordinates, and alternative text values by calling the appropriate accessor methods of `ImageArea`. -<> explains how to do this in the `AreaRenderer` class. +<<_creating_the_renderer_class>> explains how to do this in the `AreaRenderer` class. === Summary of the Image Map Application Classes -<> summarizes all the classes needed to implement the image map component. +<<_image_map_classes>> summarizes all the classes needed to implement the image map component. -[[image-map-classes]] +[[_image_map_classes]] .Image Map Classes [width="60%",cols="15%,45%"] |=== diff --git a/src/main/antora/modules/web/pages/jsf-custom/jsf-custom004.adoc b/src/main/antora/modules/web/pages/jsf-custom/jsf-custom004.adoc index 6a9b07b3..8bdac431 100644 --- a/src/main/antora/modules/web/pages/jsf-custom/jsf-custom004.adoc +++ b/src/main/antora/modules/web/pages/jsf-custom/jsf-custom004.adoc @@ -14,7 +14,7 @@ You can apply the following steps while developing your own custom component. .. Saves and restores the component state -. [[create-custom-component-step-2, Step 2]] Delegate rendering to a renderer if your component does not handle the rendering. +. [[_create_custom_component_step_2, Step 2]] Delegate rendering to a renderer if your component does not handle the rendering. To do this: .. Create a custom renderer class by extending `jakarta.faces.render.Renderer`. @@ -27,5 +27,5 @@ To do this: . Create a tag library descriptor (TLD) that defines the custom tag. -See <> and <> for information on registering the custom component and the renderer. -The section <> discusses how to use the custom component in a Jakarta Faces page. +See xref:jsf-configure/jsf-configure.adoc#_registering_a_custom_component[Registering a Custom Component] and xref:jsf-configure/jsf-configure.adoc#_registering_a_custom_renderer_with_a_render_kit[Registering a Custom Renderer with a Render Kit] for information on registering the custom component and the renderer. +The section <<_using_a_custom_component>> discusses how to use the custom component in a Jakarta Faces page. diff --git a/src/main/antora/modules/web/pages/jsf-custom/jsf-custom005.adoc b/src/main/antora/modules/web/pages/jsf-custom/jsf-custom005.adoc index 0aafbd54..6cece864 100644 --- a/src/main/antora/modules/web/pages/jsf-custom/jsf-custom005.adoc +++ b/src/main/antora/modules/web/pages/jsf-custom/jsf-custom005.adoc @@ -1,6 +1,6 @@ == Creating Custom Component Classes -As explained in <>, a component class defines the state and behavior of a UI component. +As explained in <<_when_to_use_a_custom_component>>, a component class defines the state and behavior of a UI component. The state information includes the component's type, identifier, and local value. The behavior defined by the component class includes the following: @@ -109,7 +109,7 @@ Its behavior consists of the following actions: `MapComponent` delegates the rendering of the HTML `map` and `input` tags to the `MapRenderer` class. `AreaComponent` is bound to a bean that stores the shape and coordinates of the region of the image map. -You will see how all this data is accessed through the value expression in <>. +You will see how all this data is accessed through the value expression in <<_creating_the_renderer_class>>. The behavior of `AreaComponent` consists of the following: * Retrieving the shape and coordinate data from the bean @@ -119,10 +119,10 @@ The behavior of `AreaComponent` consists of the following: * Rendering the `area` tag, including the JavaScript for the `onmouseover`, `onmouseout`, and `onclick` functions Although these tasks are actually performed by `AreaRenderer`, `AreaComponent` must delegate the tasks to `AreaRenderer`. -See <> for more information. +See <<_delegating_rendering_to_a_renderer>> for more information. The rest of this section describes the tasks that `MapComponent` performs as well as the encoding and decoding that it delegates to `MapRenderer`. -<> details how `MapComponent` handles events. +<<_handling_events_for_custom_components>> details how `MapComponent` handles events. === Specifying the Component Family @@ -137,8 +137,8 @@ public String getFamily() { ---- The component family identifier, `Map`, must match that defined by the `component-family` elements included in the component and renderer configurations in the application configuration resource file. -<> explains how to define the component family in the renderer configuration. -<> explains how to define the component family in the component configuration. +xref:jsf-configure/jsf-configure.adoc#_registering_a_custom_renderer_with_a_render_kit[Registering a Custom Renderer with a Render Kit] explains how to define the component family in the renderer configuration. +xref:jsf-configure/jsf-configure.adoc#_registering_a_custom_component[Registering a Custom Component] explains how to define the component family in the component configuration. === Performing Encoding @@ -316,7 +316,7 @@ public void setAction(MethodExpression action) { === Saving and Restoring State -As described in <>, use of the `StateHelper` interface facilities allows you to save the component's state at the same time you set and retrieve property values. +As described in <<_enabling_component_properties_to_accept_expressions>>, use of the `StateHelper` interface facilities allows you to save the component's state at the same time you set and retrieve property values. The `StateHelper` implementation allows partial state saving; it saves only the changes in the state since the initial request, not the entire state, because the full state can be restored during the Restore View phase. Component classes that implement `StateHolder` may prefer to implement the `saveState(FacesContext)` and `restoreState(FacesContext, Object)` methods to help the Jakarta Faces implementation save and restore the state of components across multiple requests. diff --git a/src/main/antora/modules/web/pages/jsf-custom/jsf-custom006.adoc b/src/main/antora/modules/web/pages/jsf-custom/jsf-custom006.adoc index 6818fb9c..f6ad0f97 100644 --- a/src/main/antora/modules/web/pages/jsf-custom/jsf-custom006.adoc +++ b/src/main/antora/modules/web/pages/jsf-custom/jsf-custom006.adoc @@ -1,14 +1,14 @@ == Delegating Rendering to a Renderer Both `MapComponent` and `AreaComponent` delegate all of their rendering to a separate renderer. -The section <> explains how `MapRenderer` performs the encoding for `MapComponent`. +The section <<_performing_encoding>> explains how `MapRenderer` performs the encoding for `MapComponent`. This section explains in detail the process of delegating rendering to a renderer using `AreaRenderer`, which performs the rendering for `AreaComponent`. To delegate rendering, you perform the tasks described in the following topics: -* <> +* <<_creating_the_renderer_class>> -* <> +* <<_identifying_the_renderer_type>> === Creating the Renderer Class @@ -37,7 +37,7 @@ ImageArea ia = (ImageArea)area.getValue(); ---- The attribute value is the `ImageArea` bean instance, which contains the `shape`, `coords`, and `alt` values associated with the `book203` `AreaComponent` instance. -<> describes how the application stores these values. +<<_configuring_model_data>> describes how the application stores these values. After retrieving the `ImageArea` object, the method renders the values for `shape`, `coords`, and `alt` by simply calling the associated accessor methods and passing the returned values to the `ResponseWriter` instance, as shown by these lines of code, which write out the shape and coordinates: @@ -101,7 +101,7 @@ The annotation identifies the component family as well as the renderer type. === Identifying the Renderer Type -Register the renderer with a render kit by using the `@FacesRenderer` annotation (or by using the application configuration resource file, as explained in <>). +Register the renderer with a render kit by using the `@FacesRenderer` annotation (or by using the application configuration resource file, as explained in xref:jsf-configure/jsf-configure.adoc#_registering_a_custom_renderer_with_a_render_kit[Registering a Custom Renderer with a Render Kit]). During the Render Response phase, the Jakarta Faces implementation calls the `getRendererType` method of the component's tag handler to determine which renderer to invoke, if there is one. You identify the type associated with the renderer in the `rendererType` element of the `@FacesRenderer` annotation for `AreaRenderer` as well as in the `renderer-type` element of the tag library descriptor. diff --git a/src/main/antora/modules/web/pages/jsf-custom/jsf-custom007.adoc b/src/main/antora/modules/web/pages/jsf-custom/jsf-custom007.adoc index 2a9fd6d0..3ec1a387 100644 --- a/src/main/antora/modules/web/pages/jsf-custom/jsf-custom007.adoc +++ b/src/main/antora/modules/web/pages/jsf-custom/jsf-custom007.adoc @@ -15,11 +15,11 @@ Similarly, listeners that handle the value-change events must implement the inte This section explains how to implement the two listener classes. To handle events generated by custom components, you must implement an event listener and an event handler and manually queue the event on the component. -See <> for more information. +See <<_handling_events_for_custom_components>> for more information. [NOTE] You do not need to create an `ActionListener` implementation to handle an event that results solely in navigating to a page and does not perform any other application-specific processing. -See <> for information on how to manage page navigation. +See xref:jsf-develop/jsf-develop.adoc#_writing_a_method_to_handle_navigation[Writing a Method to Handle Navigation] for information on how to manage page navigation. === Implementing Value-Change Listeners @@ -68,7 +68,7 @@ public class NameChanged extends Object implements ValueChangeListener { When the user enters the name in the field, a value-change event is generated, and the `processValueChange(ValueChangeEvent)` method of the `NameChanged` listener implementation is invoked. This method first gets the ID of the component that fired the event from the `ValueChangeEvent` object, and it puts the value, along with an attribute name, into the session map of the `FacesContext` instance. -<> explains how to +xref:jsf-page-core/jsf-page-core.adoc#_registering_a_value_change_listener_on_a_component[Registering a Value-Change Listener on a Component] explains how to register this listener onto a component. === Implementing Action Listeners @@ -78,6 +78,6 @@ The `processAction(ActionEvent)` method processes the specified action event. The Jakarta Faces implementation invokes the `processAction(ActionEvent)` method when the `ActionEvent` occurs. The Duke's Bookstore case study uses two `ActionListener` implementations, `LinkBookChangeListener` and `MapBookChangeListener`. -See <> for details on `MapBookChangeListener`. +See <<_handling_events_for_custom_components>> for details on `MapBookChangeListener`. -<> explains how to register this listener onto a component. +xref:jsf-page-core/jsf-page-core.adoc#_registering_an_action_listener_on_a_component[Registering an Action Listener on a Component] explains how to register this listener onto a component. diff --git a/src/main/antora/modules/web/pages/jsf-custom/jsf-custom008.adoc b/src/main/antora/modules/web/pages/jsf-custom/jsf-custom008.adoc index 9f55223d..0aa5d56e 100644 --- a/src/main/antora/modules/web/pages/jsf-custom/jsf-custom008.adoc +++ b/src/main/antora/modules/web/pages/jsf-custom/jsf-custom008.adoc @@ -1,12 +1,12 @@ == Handling Events for Custom Components -As explained in <>, events are automatically queued on standard components that fire events. +As explained in <<_implementing_an_event_listener>>, events are automatically queued on standard components that fire events. A custom component, on the other hand, must manually queue events from its `decode` method if it fires events. -<> explains how to queue an event on `MapComponent` using its `decode` method. +<<_performing_decoding>> explains how to queue an event on `MapComponent` using its `decode` method. This section explains how to write the class that represents the event of clicking on the map and how to write the method that processes this event. -As explained in <>, the `actionListener` attribute of the `bookstore:map` tag points to the `MapBookChangeListener` class. +As explained in <<_understanding_the_facelets_page>>, the `actionListener` attribute of the `bookstore:map` tag points to the `MapBookChangeListener` class. The listener class's `processAction` method processes the event of clicking the image map. Here is the `processAction` method: @@ -47,5 +47,5 @@ public class AreaSelectedEvent extends ActionEvent { } ---- -As explained in the section <>, in order for `MapComponent` to fire events in the first place, it must implement `ActionSource`. +As explained in the section <<_creating_custom_component_classes>>, in order for `MapComponent` to fire events in the first place, it must implement `ActionSource`. Because `MapComponent` extends `UICommand`, it also implements `ActionSource`. diff --git a/src/main/antora/modules/web/pages/jsf-custom/jsf-custom009.adoc b/src/main/antora/modules/web/pages/jsf-custom/jsf-custom009.adoc index 9bb68213..4d46d696 100644 --- a/src/main/antora/modules/web/pages/jsf-custom/jsf-custom009.adoc +++ b/src/main/antora/modules/web/pages/jsf-custom/jsf-custom009.adoc @@ -37,7 +37,7 @@ Here are the tag definitions for the `area` and `map` components: The `component-type` element specifies the name defined in the `@FacesComponent` annotation, and the `renderer-type` element specifies the `rendererType` defined in the `@FacesRenderer` annotation. The `facelet-taglib` element must also include a `namespace` element, which defines the namespace to be specified in pages that use the custom component. -See <> for information on specifying the namespace in pages. +See <<_using_a_custom_component>> for information on specifying the namespace in pages. The TLD file is located in the `WEB-INF` directory. In addition, an entry is included in the web deployment descriptor (`web.xml`) to identify the custom tag library descriptor file, as follows: diff --git a/src/main/antora/modules/web/pages/jsf-custom/jsf-custom010.adoc b/src/main/antora/modules/web/pages/jsf-custom/jsf-custom010.adoc index 94fa862a..12cad524 100644 --- a/src/main/antora/modules/web/pages/jsf-custom/jsf-custom010.adoc +++ b/src/main/antora/modules/web/pages/jsf-custom/jsf-custom010.adoc @@ -2,7 +2,7 @@ To use a custom component in a page, you add the custom tag associated with the component to the page. -As explained in <>, you must ensure that the TLD that defines any custom tags is packaged in the application if you intend to use the tags in your pages. +As explained in <<_defining_the_custom_component_tag_in_a_tag_library_descriptor>>, you must ensure that the TLD that defines any custom tags is packaged in the application if you intend to use the tags in your pages. TLD files are stored in the `WEB-INF/` directory or subdirectory of the WAR file or in the `META-INF/` directory or subdirectory of a tag library packaged in a JAR file. You also need to include a namespace declaration in the page so that the page has access to the tags. diff --git a/src/main/antora/modules/web/pages/jsf-custom/jsf-custom011.adoc b/src/main/antora/modules/web/pages/jsf-custom/jsf-custom011.adoc index 8367c24d..1519ac8b 100644 --- a/src/main/antora/modules/web/pages/jsf-custom/jsf-custom011.adoc +++ b/src/main/antora/modules/web/pages/jsf-custom/jsf-custom011.adoc @@ -2,10 +2,10 @@ A Jakarta Faces converter class converts strings to objects and objects to strings as required. Several standard converters are provided by Jakarta Faces for this purpose. -See <> for more information on these included converters. +See xref:jsf-page-core/jsf-page-core.adoc#_using_the_standard_converters[Using the Standard Converters] for more information on these included converters. -As explained in <>, if the standard converters included with Jakarta Faces cannot perform the data conversion that you need, you can create a custom converter to perform this specialized conversion. -This implementation, at a minimum, must define how to convert data both ways between the two views of the data described in <>. +As explained in xref:jsf-intro/jsf-intro.adoc#_conversion_model[Conversion Model], if the standard converters included with Jakarta Faces cannot perform the data conversion that you need, you can create a custom converter to perform this specialized conversion. +This implementation, at a minimum, must define how to convert data both ways between the two views of the data described in xref:jsf-intro/jsf-intro.adoc#_conversion_model[Conversion Model]. All custom converters must implement the `jakarta.faces.convert.Converter` interface. This section explains how to implement this interface to perform a custom data conversion. @@ -29,7 +29,7 @@ public class CreditCardConverter implements Converter { ---- The `@FacesConverter` annotation registers the custom converter class as a converter with the name of `ccno` with the Jakarta Faces implementation. -Alternatively, you can register the converter with entries in the application configuration resource file, as shown in <>. +Alternatively, you can register the converter with entries in the application configuration resource file, as shown in xref:jsf-configure/jsf-configure.adoc#_registering_a_custom_converter[Registering a Custom Converter]. To define how the data is converted from the presentation view to the model view, the `Converter` implementation must implement the `getAsObject(FacesContext, UIComponent, String)` method from the `Converter` interface. Here is the implementation of this method from `CreditCardConverter`: @@ -114,7 +114,7 @@ When the Jakarta Faces implementation calls this method, it passes in the curren Because this converter does a `String`-to-`String` conversion, this method can cast the bean value to a `String`. If the value cannot be converted to a `String`, the method throws an exception, passing an error message from the resource bundle that is registered with the application. -<> explains how to register custom error messages with the application. +xref:jsf-configure/jsf-configure.adoc#_registering_application_messages[Registering Application Messages] explains how to register custom error messages with the application. If the value can be converted to a `String`, the method reads the `String` to a character array and loops through the array, adding a space after every four characters. @@ -141,7 +141,7 @@ To apply the data conversion performed by a custom converter to a particular com * Nest an `f:converter` tag inside the component's tag and reference the custom converter from one of the `f:converter` tag's attributes. If you are using the component tag's `converter` attribute, this attribute must reference the `Converter` implementation's identifier or the fully-qualified class name of the converter. -<> explains how to implement a custom converter. +<<_creating_and_using_a_custom_converter>> explains how to implement a custom converter. The identifier for the credit card converter class is `ccno`, the value specified in the `@FacesConverter` annotation: @@ -188,7 +188,7 @@ This method is shown in `bookcashier.xhtml`: ---- -* Bind the `Converter` implementation to a managed bean property using the `f:converter` tag's `binding` attribute, as described in <>. +* Bind the `Converter` implementation to a managed bean property using the `f:converter` tag's `binding` attribute, as described in <<_binding_converters_listeners_and_validators_to_managed_bean_properties>>. The Jakarta Faces implementation calls the converter's `getAsObject` method to strip spaces and hyphens from the input value. The `getAsString` method is called when the `bookcashier.xhtml` page is redisplayed; this happens if the user orders more than $100 worth of books. diff --git a/src/main/antora/modules/web/pages/jsf-custom/jsf-custom012.adoc b/src/main/antora/modules/web/pages/jsf-custom/jsf-custom012.adoc index d7cf6cea..42649ff6 100644 --- a/src/main/antora/modules/web/pages/jsf-custom/jsf-custom012.adoc +++ b/src/main/antora/modules/web/pages/jsf-custom/jsf-custom012.adoc @@ -1,27 +1,27 @@ == Creating and Using a Custom Validator If the standard validators or Bean Validation don't perform the validation checking you need, you can create a custom validator to validate user input. -As explained in <>, there are two ways to implement validation code. +As explained in xref:jsf-intro/jsf-intro.adoc#_validation_model[Validation Model], there are two ways to implement validation code. * Implement a managed bean method that performs the validation. * Provide an implementation of the `jakarta.faces.validator.Validator` interface to perform the validation. -<> explains how to implement a managed bean method to perform validation. +xref:jsf-develop/jsf-develop.adoc#_writing_a_method_to_perform_validation[Writing a Method to Perform Validation] explains how to implement a managed bean method to perform validation. The rest of this section explains how to implement the `Validator` interface. If you choose to implement the `Validator` interface and you want to allow the page author to configure the validator's attributes from the page, you also must specify a custom tag for registering the validator on a component. -If you prefer to configure the attributes in the `Validator` implementation, you can forgo specifying a custom tag and instead let the page author register the validator on a component using the `f:validator` tag, as described in <>. +If you prefer to configure the attributes in the `Validator` implementation, you can forgo specifying a custom tag and instead let the page author register the validator on a component using the `f:validator` tag, as described in <<_using_a_custom_validator>>. -You can also create a managed bean property that accepts and returns the `Validator` implementation you create, as described in <>. +You can also create a managed bean property that accepts and returns the `Validator` implementation you create, as described in xref:jsf-develop/jsf-develop.adoc#_writing_properties_bound_to_converters_listeners_or_validators[Writing Properties Bound to Converters, Listeners, or Validators]. You can use the `f:validator` tag's binding attribute to bind the `Validator` implementation to the managed bean property. Usually, you will want to display an error message when data fails validation. You need to store these error messages in a resource bundle. After creating the resource bundle, you have two ways to make the messages available to the application. -You can queue the error messages onto the `FacesContext` programmatically, or you can register the error messages in the application configuration resource file, as explained in <>. +You can queue the error messages onto the `FacesContext` programmatically, or you can register the error messages in the application configuration resource file, as explained in xref:jsf-configure/jsf-configure.adoc#_registering_application_messages[Registering Application Messages]. For example, an e-commerce application might use a general-purpose custom validator called `FormatValidator.java` to validate input data against a format pattern that is specified in the custom validator tag. This validator would be used with a Credit Card Number field on a Facelets page. @@ -137,7 +137,7 @@ Input must match one of the following patterns: {0} You may wish to save and restore state for your validator, although state saving is not usually necessary. To do so, you will need to implement the `StateHolder` interface as well as the `Validator` interface. To implement `StateHolder`, you would need to implement its four methods: `saveState(FacesContext)`, `restoreState(FacesContext, Object)`, `isTransient`, and `setTransient(boolean)`. -See <> for more information. +See <<_saving_and_restoring_state>> for more information. === Specifying a Custom Tag @@ -145,7 +145,7 @@ If you implemented a `Validator` interface rather than implementing a managed be * Allow the page author to specify the `Validator` implementation to use with the `f:validator` tag. In this case, the `Validator` implementation must define its own properties. -<> explains how to use the `f:validator` tag. +<<_using_a_custom_validator>> explains how to use the `f:validator` tag. * Specify a custom tag that provides attributes for configuring the properties of the validator from the page. @@ -168,7 +168,7 @@ The `tag-name` element defines the name of the tag as it must be used in a Facel The `validator-id` element identifies the custom validator. The `validator-class` element wires the custom tag to its implementation class. -<> explains how to use the custom validator tag on the page. +<<_using_a_custom_validator>> explains how to use the custom validator tag on the page. === Using a Custom Validator @@ -202,7 +202,7 @@ Then the page author needs to do one of the following. * Set the `f:validator` tag's `validatorId` attribute to the ID of the validator that is defined in the application configuration resource file. -* Bind the custom `Validator` implementation to a managed bean property using the `f:validator` tag's `binding` attribute, as described in <>. +* Bind the custom `Validator` implementation to a managed bean property using the `f:validator` tag's `binding` attribute, as described in <<_binding_converters_listeners_and_validators_to_managed_bean_properties>>. The following tag registers a hypothetical validator on a component using an `f:validator` tag and references the ID of the validator: diff --git a/src/main/antora/modules/web/pages/jsf-custom/jsf-custom013.adoc b/src/main/antora/modules/web/pages/jsf-custom/jsf-custom013.adoc index 949fa412..fb62f9fc 100644 --- a/src/main/antora/modules/web/pages/jsf-custom/jsf-custom013.adoc +++ b/src/main/antora/modules/web/pages/jsf-custom/jsf-custom013.adoc @@ -50,9 +50,9 @@ The `value` attribute that references this property must have this value-binding ---- In addition to binding a component's value to a bean property, the `value` attribute can specify a literal value or can map the component's data to any primitive (such as `int`), structure (such as an array), or collection (such as a list), independent of a JavaBeans component. -<> lists some example value-binding expressions that you can use with the `value` attribute. +<<_examples_of_value_binding_expressions>> lists some example value-binding expressions that you can use with the `value` attribute. -[[examples-of-value-binding-expressions]] +[[_examples_of_value_binding_expressions]] .Examples of Value-Binding Expressions [width="60%",cols="30%,30%"] |=== @@ -129,7 +129,7 @@ Although the `bookstore:area` tags on the `index.xhtml` page do not bind to an ` ---- -See <> for information on how to configure beans in the application configuration resource file. +See xref:jsf-configure/jsf-configure.adoc#_configuring_managed_beans[Configuring Managed Beans] for information on how to configure beans in the application configuration resource file. === Binding a Component Value to an Implicit Object @@ -153,10 +153,10 @@ Thank you, Gwen Canigetit, for purchasing your books from us. ---- Retrieving values from other implicit objects is done in a similar way to the example shown in this section. -<> lists the implicit objects to which a value attribute can refer. +<<_implicit_objects>> lists the implicit objects to which a value attribute can refer. All of the implicit objects, except for the scope objects, are read-only and therefore should not be used as values for a `UIInput` component. -[[implicit-objects]] +[[_implicit_objects]] .Implicit Objects [width="75%",cols="15%,60%"] |=== @@ -219,4 +219,4 @@ These tags use component bindings rather than value bindings because the managed If the tags were to use value bindings instead of component bindings, the managed bean would not have direct access to the components and would therefore require additional code to access the components from the `FacesContext` instance to change the components' `rendered` properties. -<> explains how to write the bean properties bound to the example components. +xref:jsf-develop/jsf-develop.adoc#_writing_properties_bound_to_component_instances[Writing Properties Bound to Component Instances] explains how to write the bean properties bound to the example components. diff --git a/src/main/antora/modules/web/pages/jsf-custom/jsf-custom014.adoc b/src/main/antora/modules/web/pages/jsf-custom/jsf-custom014.adoc index 18428f9e..e6064bd1 100644 --- a/src/main/antora/modules/web/pages/jsf-custom/jsf-custom014.adoc +++ b/src/main/antora/modules/web/pages/jsf-custom/jsf-custom014.adoc @@ -1,8 +1,8 @@ == Binding Converters, Listeners, and Validators to Managed Bean Properties -As described in <>, a page author can bind converter, listener, and validator implementations to managed bean properties using the `binding` attributes of the tags that are used to register the implementations on components. +As described in xref:jsf-page/jsf-page.adoc#_adding_components_to_a_page_using_html_tag_library_tags[Adding Components to a Page Using HTML Tag Library Tags], a page author can bind converter, listener, and validator implementations to managed bean properties using the `binding` attributes of the tags that are used to register the implementations on components. -This technique has similar advantages to binding component instances to managed bean properties, as described in <>. +This technique has similar advantages to binding component instances to managed bean properties, as described in <<_binding_component_values_and_instances_to_managed_bean_properties>>. In particular, binding a converter, listener, or validator implementation to a managed bean property yields the following benefits. * The managed bean can instantiate the implementation instead of @@ -45,4 +45,4 @@ public void setConvertDate(DateTimeConverter convertDate) { } ---- -See <> for more information on writing managed bean properties for converter, listener, and validator implementations. +See xref:jsf-develop/jsf-develop.adoc#_writing_properties_bound_to_converters_listeners_or_validators[Writing Properties Bound to Converters, Listeners, or Validators] for more information on writing managed bean properties for converter, listener, and validator implementations. diff --git a/src/main/antora/modules/web/pages/jsf-develop/jsf-develop001.adoc b/src/main/antora/modules/web/pages/jsf-develop/jsf-develop001.adoc index cbaf4dd3..f7a36649 100644 --- a/src/main/antora/modules/web/pages/jsf-develop/jsf-develop001.adoc +++ b/src/main/antora/modules/web/pages/jsf-develop/jsf-develop001.adoc @@ -4,7 +4,7 @@ A typical Jakarta Faces application includes one or more managed beans, each of This section introduces the basic concepts of creating, configuring, and using managed beans in an application. [NOTE] -xref:using-jakarta-faces-technology-in-web-pages[xrefstyle=full] and xref:using-converters-listeners-and-validators[xrefstyle=full] show how to add components to a page and connect them to server-side objects by using component tags and core tags. +xref:jsf-page/jsf-page.adoc#_using_jakarta_faces_technology_in_web_pages[Using Jakarta Faces Technology in Web Pages] and xref:jsf-page-core/jsf-page-core.adoc#_using_converters_listeners_and_validators[Using Converters, Listeners, and Validators] show how to add components to a page and connect them to server-side objects by using component tags and core tags. These chapters also show how to provide additional functionality to the components through converters, listeners, and validators. Developing a Jakarta Faces application also involves the task of programming the server-side objects: managed beans, converters, event handlers, and validators. @@ -47,18 +47,18 @@ public Integer getUserNumber() { When bound to a component's value, a bean property can be any of the basic primitive and numeric types or any Java object type for which the application has access to an appropriate converter. For example, a property can be of type `java.util.Date` if the application has access to a converter that can convert the `Date` type to a `String` and back again. -See <> for information on which types are accepted by which component tags. +See <<_writing_bean_properties>> for information on which types are accepted by which component tags. When a bean property is bound to a component instance, the property's type must be the same as the component object. For example, if a `jakarta.faces.component.UISelectBoolean` component is bound to the property, the property must accept and return a `UISelectBoolean` object. Likewise, if the property is bound to a converter, validator, or listener instance, the property must be of the appropriate converter, validator, or listener type. -For more information on writing beans and their properties, see <>. +For more information on writing beans and their properties, see <<_writing_bean_properties>>. === Using the EL to Reference Managed Beans To bind component values and objects to managed bean properties or to reference managed bean methods from component tags, page authors use the Expression Language syntax. -As explained in <>, the following are some of the features that the EL offers: +As explained in xref:jsf-el/jsf-el.adoc#_overview_of_the_el[Overview of the EL], the following are some of the features that the EL offers: * Deferred evaluation of expressions @@ -108,6 +108,6 @@ A page author does this by referencing the property from the `binding` attribute In addition to using expressions with the standard component tags, you can configure your custom component properties to accept expressions by creating `jakarta.el.ValueExpression` or `jakarta.el.MethodExpression` instances for them. -For information on the EL, see xref:expression-language[xrefstyle=full]. +For information on the EL, see xref:jsf-el/jsf-el.adoc#_expression_language[Expression Language]. -For information on referencing managed bean methods from component tags, see <>. +For information on referencing managed bean methods from component tags, see xref:jsf-page-core/jsf-page-core.adoc#_referencing_a_managed_bean_method[Referencing a Managed Bean Method]. diff --git a/src/main/antora/modules/web/pages/jsf-develop/jsf-develop002.adoc b/src/main/antora/modules/web/pages/jsf-develop/jsf-develop002.adoc index 91f6797c..665624ff 100644 --- a/src/main/antora/modules/web/pages/jsf-develop/jsf-develop002.adoc +++ b/src/main/antora/modules/web/pages/jsf-develop/jsf-develop002.adoc @@ -1,6 +1,6 @@ == Writing Bean Properties -As explained in <>, a managed bean property can be bound to one of the following items: +As explained in <<_managed_beans_in_jakarta_faces_technology>>, a managed bean property can be bound to one of the following items: * A component value @@ -17,7 +17,7 @@ For more information on JavaBeans components, see the JavaBeans Tutorial at http The component's tag binds the component's value to a managed bean property by using its `value` attribute and binds the component's instance to a managed bean property by using its `binding` attribute. Likewise, all the converter, listener, and validator tags use their `binding` attributes to bind their associated implementations to managed bean properties. -See <> and <> for more information. +See xref:jsf-custom/jsf-custom.adoc#_binding_component_values_and_instances_to_managed_bean_properties[Binding Component Values and Instances to Managed Bean Properties] and xref:jsf-custom/jsf-custom.adoc#_binding_converters_listeners_and_validators_to_managed_bean_properties[Binding Converters, Listeners, and Validators to Managed Bean Properties] for more information. To bind a component's value to a managed bean property, the type of the property must match the type of the component's value to which it is bound. For example, if a managed bean property is bound to a `UISelectBoolean` component's value, the property should accept and return a `boolean` value or a `Boolean` wrapper `Object` instance. @@ -28,15 +28,15 @@ For example, if a managed bean property is bound to a `UISelectBoolean` instance Similarly, to bind a converter, listener, or validator implementation to a managed bean property, the property must accept and return the same type of converter, listener, or validator object. For example, if you are using the `convertDateTime` tag to bind a `jakarta.faces.convert.DateTimeConverter` to a property, that property must accept and return a `DateTimeConverter` instance. -The rest of this section explains how to write properties that can be bound to component values, to component instances for the component objects described in <>, and to converter, listener, and validator implementations. +The rest of this section explains how to write properties that can be bound to component values, to component instances for the component objects described in xref:jsf-page/jsf-page.adoc#_adding_components_to_a_page_using_html_tag_library_tags[Adding Components to a Page Using HTML Tag Library Tags], and to converter, listener, and validator implementations. === Writing Properties Bound to Component Values To write a managed bean property that is bound to a component's value, you must match the property type to the component's value. -<> lists the `jakarta.faces.component` classes and the acceptable types of their values. +<<_acceptable_types_of_component_values>> lists the `jakarta.faces.component` classes and the acceptable types of their values. -[[acceptable-types-of-component-values]] +[[_acceptable_types_of_component_values]] .Acceptable Types of Component Values [width="99%",cols="25%,75%"] |=== @@ -84,8 +84,8 @@ public String getName() { } ---- -As described in <>, to convert the value of an input or output component you can either apply a converter or create the bean property bound to the component with the matching type. -Here is the example tag, from <>, that displays the date on which items will be shipped. +As described in xref:jsf-page-core/jsf-page-core.adoc#_using_the_standard_converters[Using the Standard Converters], to convert the value of an input or output component you can either apply a converter or create the bean property bound to the component with the matching type. +Here is the example tag, from xref:jsf-page-core/jsf-page-core.adoc#_using_datetimeconverter[Using DateTimeConverter], that displays the date on which items will be shipped. [source,xml] ---- @@ -113,8 +113,8 @@ public void setShipDate(Date shipDate) { The `UIData` component class is represented by the `h:dataTable` component tag. -`UIData` components must be bound to one of the managed bean property types listed in <>. -Data components are discussed in <>. +`UIData` components must be bound to one of the managed bean property types listed in <<_acceptable_types_of_component_values>>. +Data components are discussed in xref:jsf-page/jsf-page.adoc#_using_data_bound_table_components[Using Data-Bound Table Components]. Here is part of the start tag of `dataTable` from that section: [source,xml] @@ -199,7 +199,7 @@ For UIData and UIRepeat, the supported types are: The `UISelectBoolean` component class is represented by the component tag `h:selectBooleanCheckbox`. Managed bean properties that hold a `UISelectBoolean` component's data must be of `boolean` or `Boolean` type. -The example `selectBooleanCheckbox` tag from the section <> binds a component to a property. +The example `selectBooleanCheckbox` tag from the section xref:jsf-page/jsf-page.adoc#_displaying_components_for_selecting_one_value[Displaying Components for Selecting One Value] binds a component to a property. The following example shows a tag that binds a component value to a `boolean` property: [source,xml] @@ -231,7 +231,7 @@ The `UISelectMany` component class is represented by the component tags that beg Because a `UISelectMany` component allows a user to select one or more items from a list of items, this component must map to a bean property of type `List` or `array`. This bean property represents the set of currently selected items from the list of available items. -The following example of the `selectManyCheckbox` tag comes from <>: +The following example of the `selectManyCheckbox` tag comes from xref:jsf-page/jsf-page.adoc#_displaying_components_for_selecting_multiple_values[Displaying Components for Selecting Multiple Values]: [source,xml] ---- @@ -257,7 +257,7 @@ public String[] getNewsletters() { ---- The `UISelectItem` and `UISelectItems` components are used to represent all the values in a `UISelectMany` component. -See <> for information on writing the bean properties for the `UISelectItem` and `UISelectItems` components. +See <<_uiselectitems_properties>> for information on writing the bean properties for the `UISelectItem` and `UISelectItems` components. ==== UISelectOne Properties @@ -266,7 +266,7 @@ The `UISelectOne` component class is represented by the component tags that begi `UISelectOne` properties accept the same types as `UIInput` and `UIOutput` properties, because a `UISelectOne` component represents the single selected item from a set of items. This item can be any of the primitive types and anything else for which you can apply a converter. -Here is an example of the `h:selectOneMenu` tag from <>: +Here is an example of the `h:selectOneMenu` tag from xref:jsf-page/jsf-page.adoc#_displaying_a_menu_using_the_hselectonemenu_tag[Displaying a Menu Using the h:selectOneMenu Tag]: [source,xml] ---- @@ -299,9 +299,9 @@ public String getShippingOption() { Note that `shippingOption` represents the currently selected item from the list of items in the `UISelectOne` component. The `UISelectItem` and `UISelectItems` components are used to represent all the values in a `UISelectOne` component. -This is explained in <>. +This is explained in xref:jsf-page/jsf-page.adoc#_displaying_a_menu_using_the_hselectonemenu_tag[Displaying a Menu Using the h:selectOneMenu Tag]. -For information on how to write the managed bean properties for the `UISelectItem` and `UISelectItems` components, see <>. +For information on how to write the managed bean properties for the `UISelectItem` and `UISelectItems` components, see <<_uiselectitems_properties>>. ==== UISelectItem Properties @@ -309,7 +309,7 @@ A `UISelectItem` component represents a single value in a set of values in a `UI A `UISelectItem` component must be bound to a managed bean property of type `jakarta.faces.model.SelectItem`. A `SelectItem` object is composed of an `Object` representing the value along with two `Strings` representing the label and the description of the `UISelectItem` object. -The example `selectOneMenu` tag from <> contains `selectItem` tags that set the values of the list of items in the page. +The example `selectOneMenu` tag from <<_uiselectone_properties>> contains `selectItem` tags that set the values of the list of items in the page. Here is an example of a bean property that can set the values for this list in the bean: [source,java] @@ -401,11 +401,11 @@ public void setSpecialOffer(UISelectBoolean specialOffer) { } ---- -For more general information on component binding, see <>. +For more general information on component binding, see <<_managed_beans_in_jakarta_faces_technology>>. -For information on how to reference a managed bean method that performs navigation when a button is clicked, see <>. +For information on how to reference a managed bean method that performs navigation when a button is clicked, see xref:jsf-page-core/jsf-page-core.adoc#_referencing_a_method_that_performs_navigation[Referencing a Method That Performs Navigation]. -For more information on writing managed bean methods that handle navigation, see <>. +For more information on writing managed bean methods that handle navigation, see <<_writing_a_method_to_handle_navigation>>. === Writing Properties Bound to Converters, Listeners, or Validators diff --git a/src/main/antora/modules/web/pages/jsf-develop/jsf-develop003.adoc b/src/main/antora/modules/web/pages/jsf-develop/jsf-develop003.adoc index 1aba1b3e..93f38aaa 100644 --- a/src/main/antora/modules/web/pages/jsf-develop/jsf-develop003.adoc +++ b/src/main/antora/modules/web/pages/jsf-develop/jsf-develop003.adoc @@ -79,8 +79,8 @@ public Object submit(){ } ---- -The section <> explains how a component tag references this method. -The section <> explains how to write the bean properties to which the components are bound. +The section xref:jsf-page-core/jsf-page-core.adoc#_referencing_a_method_that_performs_navigation[Referencing a Method That Performs Navigation] explains how a component tag references this method. +The section <<_writing_properties_bound_to_component_instances>> explains how to write the bean properties to which the components are bound. === Writing a Method to Handle an Action Event @@ -104,7 +104,7 @@ This method gets the component that generated the event from the event object; t The method matches the code against a `HashMap` object that contains the book codes and corresponding book ID values. Finally, the method sets the book ID by using the selected value from the `HashMap` object. -<> explains how a component tag references this method. +xref:jsf-page-core/jsf-page-core.adoc#_referencing_a_method_that_handles_an_action_event[Referencing a Method That Handles an Action Event] explains how a component tag references this method. === Writing a Method to Perform Validation @@ -145,7 +145,7 @@ Then it queues a message onto the `FacesContext` instance, associating the messa * If the user has some remaining guesses, the method then retrieves the local value of the component. If the input value is outside the allowable range, the method again sets the `valid` property of the `UIInput` component to `false`, queues a different message on the `FacesContext` instance, and returns. -See <> for information on how a component tag references this method. +See xref:jsf-page-core/jsf-page-core.adoc#_referencing_a_method_that_performs_validation[Referencing a Method That Performs Validation] for information on how a component tag references this method. === Writing a Method to Handle a Value-Change Event @@ -153,7 +153,7 @@ A managed bean that handles a value-change event must use a public method that a This method is referenced using the component's `valueChangeListener` attribute. This section explains how to write a managed bean method to replace the `jakarta.faces.event.ValueChangeListener` implementation. -The following example tag comes from <>, where the `h:inputText` tag with the `id` of `name` has a `ValueChangeListener` instance registered on it. +The following example tag comes from xref:jsf-page-core/jsf-page-core.adoc#_registering_a_value_change_listener_on_a_component[Registering a Value-Change Listener on a Component], where the `h:inputText` tag with the `id` of `name` has a `ValueChangeListener` instance registered on it. This `ValueChangeListener` instance handles the event of entering a value in the field corresponding to the component. When the user enters a value, a value-change event is generated, and the `processValueChange(ValueChangeEvent)` method of the `ValueChangeListener` class is invoked: @@ -186,4 +186,4 @@ public void processValueChange(ValueChangeEvent event) ---- To make this method handle the `ValueChangeEvent` generated by an input component, reference this method from the component tag's `valueChangeListener` attribute. -See <> for more information. +See xref:jsf-page-core/jsf-page-core.adoc#_referencing_a_method_that_handles_a_value_change_event[Referencing a Method That Handles a Value-Change Event] for more information. diff --git a/src/main/antora/modules/web/pages/jsf-el/jsf-el001.adoc b/src/main/antora/modules/web/pages/jsf-el/jsf-el001.adoc index 3f104acc..898b91ff 100644 --- a/src/main/antora/modules/web/pages/jsf-el/jsf-el001.adoc +++ b/src/main/antora/modules/web/pages/jsf-el/jsf-el001.adoc @@ -10,7 +10,7 @@ For example, the `test` attribute of the following conditional tag is supplied w ---- -See <> for more information on how to use the EL in Jakarta Faces applications. +See xref:jsf-develop/jsf-develop.adoc#_using_the_el_to_reference_managed_beans[Using the EL to Reference Managed Beans] for more information on how to use the EL in Jakarta Faces applications. To summarize, the EL provides a way to use simple expressions to perform the following tasks: diff --git a/src/main/antora/modules/web/pages/jsf-el/jsf-el005.adoc b/src/main/antora/modules/web/pages/jsf-el/jsf-el005.adoc index a83af184..72552d90 100644 --- a/src/main/antora/modules/web/pages/jsf-el/jsf-el005.adoc +++ b/src/main/antora/modules/web/pages/jsf-el/jsf-el005.adoc @@ -1,6 +1,6 @@ == Operators -In addition to the `.` and `[]` operators discussed in <>, the EL provides the following operators, which can be used in rvalue expressions only. +In addition to the `.` and `[]` operators discussed in <<_value_and_method_expressions>>, the EL provides the following operators, which can be used in rvalue expressions only. * Arithmetic: `+`, `-` (binary), `*`, `/` and `div`, `%` and `mod`, `-` (unary). diff --git a/src/main/antora/modules/web/pages/jsf-el/jsf-el007.adoc b/src/main/antora/modules/web/pages/jsf-el/jsf-el007.adoc index d47ea763..3a2dd81e 100644 --- a/src/main/antora/modules/web/pages/jsf-el/jsf-el007.adoc +++ b/src/main/antora/modules/web/pages/jsf-el/jsf-el007.adoc @@ -1,8 +1,8 @@ == Examples of EL Expressions -<> contains example EL expressions and the result of evaluating them. +<<_example_expressions>> contains example EL expressions and the result of evaluating them. -[[example-expressions]] +[[_example_expressions]] .Example Expressions [width="80%",cols="40%,40%"] |=== diff --git a/src/main/antora/modules/web/pages/jsf-facelets/jsf-facelets001.adoc b/src/main/antora/modules/web/pages/jsf-facelets/jsf-facelets001.adoc index d734d934..bfb4360f 100644 --- a/src/main/antora/modules/web/pages/jsf-facelets/jsf-facelets001.adoc +++ b/src/main/antora/modules/web/pages/jsf-facelets/jsf-facelets001.adoc @@ -31,9 +31,9 @@ By convention, web pages built with XHTML have an `.xhtml` extension. Jakarta Faces technology supports various tag libraries to add components to a web page. To support the Jakarta Faces tag library mechanism, Facelets uses XML namespace declarations. -<> lists the tag libraries supported by Facelets. +<<_tag_libraries_supported_by_facelets>> lists the tag libraries supported by Facelets. -[[tag-libraries-supported-by-facelets]] +[[_tag_libraries_supported_by_facelets]] .Tag Libraries Supported by Facelets [width="99%",cols="25%,25%,10%,15%,20%"] |=== @@ -71,10 +71,10 @@ To support the Jakarta Faces tag library mechanism, Facelets uses XML namespace |=== Facelets provides two namespaces to support HTML5-friendly markup. -For details, see <>. +For details, see <<_html5_friendly_markup>>. Facelets supports tags for composite components, for which you can declare custom prefixes. -For more information on composite components, see <>. +For more information on composite components, see <<_composite_components>>. The namespace prefixes shown in the table are conventional, not mandatory. As is always the case when you declare an XML namespace, you can specify any prefix in your Facelets page. @@ -92,4 +92,4 @@ xmlns:cc="http://xmlns.jcp.org/jsf/composite" Based on the Jakarta Faces support for Expression Language (EL) syntax, Facelets uses EL expressions to reference properties and methods of managed beans. EL expressions can be used to bind component objects or values to methods or properties of managed beans that are used as backing beans. -For more information on using EL expressions, see <>. +For more information on using EL expressions, see xref:jsf-develop/jsf-develop.adoc#_using_the_el_to_reference_managed_beans[Using the EL to Reference Managed Beans]. diff --git a/src/main/antora/modules/web/pages/jsf-facelets/jsf-facelets002.adoc b/src/main/antora/modules/web/pages/jsf-facelets/jsf-facelets002.adoc index 6d48ca37..d0cd218d 100644 --- a/src/main/antora/modules/web/pages/jsf-facelets/jsf-facelets002.adoc +++ b/src/main/antora/modules/web/pages/jsf-facelets/jsf-facelets002.adoc @@ -1,12 +1,12 @@ == The Lifecycle of a Facelets Application The Jakarta Faces specification defines the lifecycle of a Jakarta Faces application. -For more information on this lifecycle, see <>. +For more information on this lifecycle, see xref:jsf-intro/jsf-intro.adoc#_the_lifecycle_of_a_jakarta_faces_application[The Lifecycle of a Jakarta Faces Application]. The following steps describe that process as applied to a Facelets-based application. . When a client, such as a browser, makes a new request to a page that is created using Facelets, a new component tree or `jakarta.faces.component.UIViewRoot` is created and placed in the `FacesContext`. -. [[step-2-of-lifecycle-of-facelets, Step 2]] The `UIViewRoot` is applied to the Facelets, and the view is populated with components for rendering. +. [[_step_2_of_lifecycle_of_facelets, Step 2]] The `UIViewRoot` is applied to the Facelets, and the view is populated with components for rendering. . The newly built view is rendered back as a response to the client. diff --git a/src/main/antora/modules/web/pages/jsf-facelets/jsf-facelets003.adoc b/src/main/antora/modules/web/pages/jsf-facelets/jsf-facelets003.adoc index eb755ca7..0d78f9cf 100644 --- a/src/main/antora/modules/web/pages/jsf-facelets/jsf-facelets003.adoc +++ b/src/main/antora/modules/web/pages/jsf-facelets/jsf-facelets003.adoc @@ -165,7 +165,7 @@ An `h:inputText` tag accepts user input and sets the value of the managed bean p The input value is validated for value range by the Jakarta Faces standard validator tag `f:validateLongRange`. The image file, `wave.med.gif`, is added to the page as a resource, as is the style sheet. -For more details about the resources facility, see <>. +For more details about the resources facility, see <<_web_resources>>. An `h:commandButton` tag with the ID `submit` starts validation of the input data when a user clicks the button. Using implicit navigation, the tag redirects the client to another page, `response.xhtml`, which shows the response to your input. diff --git a/src/main/antora/modules/web/pages/jsf-facelets/jsf-facelets004.adoc b/src/main/antora/modules/web/pages/jsf-facelets/jsf-facelets004.adoc index 44026f70..d9d9048d 100644 --- a/src/main/antora/modules/web/pages/jsf-facelets/jsf-facelets004.adoc +++ b/src/main/antora/modules/web/pages/jsf-facelets/jsf-facelets004.adoc @@ -5,9 +5,9 @@ Templating is a useful Facelets feature that allows you to create a page that wi By using templates, you can reuse code and avoid recreating similarly constructed pages. Templating also helps in maintaining a standard look and feel in an application with a large number of pages. -<> lists Facelets tags that are used for templating and their respective functionality. +<<_facelets_templating_tags>> lists Facelets tags that are used for templating and their respective functionality. -[[facelets-templating-tags]] +[[_facelets_templating_tags]] .Facelets Templating Tags [width="99%",cols="20%,80%"] |=== diff --git a/src/main/antora/modules/web/pages/jsf-facelets/jsf-facelets005.adoc b/src/main/antora/modules/web/pages/jsf-facelets/jsf-facelets005.adoc index d2084cfa..4d6614e2 100644 --- a/src/main/antora/modules/web/pages/jsf-facelets/jsf-facelets005.adoc +++ b/src/main/antora/modules/web/pages/jsf-facelets/jsf-facelets005.adoc @@ -13,9 +13,9 @@ This reusable, user-created component has a customized, defined functionality an With Facelets, any XHTML page that contains markup tags and other components can be converted into a composite component. Using the resources facility, the composite component can be stored in a library that is available to the application from the defined resources location. -<> lists the most commonly used composite tags and their functions. +<<_composite_component_tags>> lists the most commonly used composite tags and their functions. -[[composite-component-tags]] +[[_composite_component_tags]] .Composite Component Tags [width="99%",cols="20%,80%"] |=== @@ -71,7 +71,7 @@ The word `cc` in Jakarta Faces is a reserved word for composite components. The `#{cc.attrs._attribute-name_}` expression is used to access the attributes defined for the composite component's interface, which in this case happens to be `value`. The preceding example content is stored as a file named `email.xhtml` in a folder named `resources/emcomp`, under the application web root directory. -This directory is considered a library by Jakarta Faces, and a component can be accessed from such a library. For more information on resources, see <>. +This directory is considered a library by Jakarta Faces, and a component can be accessed from such a library. For more information on resources, see <<_web_resources>>. The web page that uses this composite component is generally called a using page. The using page includes a reference to the composite component, in the `xml` namespace declarations: @@ -105,4 +105,4 @@ When compiled and deployed on a server, it can be accessed with the following UR http://localhost:8080/application-name/emuserpage.xhtml ---- -See xref:composite-components-advanced-topics-and-an-example[xrefstyle=full] for more information and an example. +See xref:jsf-advanced-cc/jsf-advanced-cc.adoc#_composite_components_advanced_topics_and_an_example[Composite Components: Advanced Topics and an Example] for more information and an example. diff --git a/src/main/antora/modules/web/pages/jsf-facelets/jsf-facelets007.adoc b/src/main/antora/modules/web/pages/jsf-facelets/jsf-facelets007.adoc index 8f591e8c..84ad16bc 100644 --- a/src/main/antora/modules/web/pages/jsf-facelets/jsf-facelets007.adoc +++ b/src/main/antora/modules/web/pages/jsf-facelets/jsf-facelets007.adoc @@ -22,4 +22,4 @@ For example, the following `h:outputScript` tag is placed within an `h:form` ele The `h:outputStylesheet` tag also supports resource relocation, in a similar way. Relocatable resources are essential for composite components that use stylesheets and can also be useful for composite components that use JavaScript. -See <> for an example. +See xref:jsf-advanced-cc/jsf-advanced-cc.adoc#_the_compositecomponentexample_example_application[The compositecomponentexample Example Application] for an example. diff --git a/src/main/antora/modules/web/pages/jsf-facelets/jsf-facelets008.adoc b/src/main/antora/modules/web/pages/jsf-facelets/jsf-facelets008.adoc index ba8548d9..f1e270ec 100644 --- a/src/main/antora/modules/web/pages/jsf-facelets/jsf-facelets008.adoc +++ b/src/main/antora/modules/web/pages/jsf-facelets/jsf-facelets008.adoc @@ -57,7 +57,7 @@ You need to use this element only if your application uses more than one contrac === The hello1-rlc Example Application -The `hello1-rlc` example modifies the simple `hello1` example from <> to use two resource library contracts. +The `hello1-rlc` example modifies the simple `hello1` example from xref:webapp/webapp.adoc#_a_web_module_that_uses_jakarta_faces_technology_the_hello1_example[A Web Module That Uses Jakarta Faces Technology: The hello1 Example] to use two resource library contracts. Each of the two pages in the application uses a different contract. The managed bean for `hello1-rlc`, `Hello.java`, is identical to the one for `hello1` (except that it replaces the `@Named` and `@RequestScoped` annotations with `@Model`). diff --git a/src/main/antora/modules/web/pages/jsf-facelets/jsf-facelets009.adoc b/src/main/antora/modules/web/pages/jsf-facelets/jsf-facelets009.adoc index 6216133f..279102b3 100644 --- a/src/main/antora/modules/web/pages/jsf-facelets/jsf-facelets009.adoc +++ b/src/main/antora/modules/web/pages/jsf-facelets/jsf-facelets009.adoc @@ -2,7 +2,7 @@ When you want to produce user interface features for which HTML does not have its own elements, you can create a custom Jakarta Faces component and insert it in your Facelets page. This mechanism can cause a simple element to create complex web code. -However, creating such a component is a significant task (see xref:creating-custom-ui-components-and-other-custom-objects[xrefstyle=full]). +However, creating such a component is a significant task (see xref:jsf-custom/jsf-custom.adoc#_creating_custom_ui_components_and_other_custom_objects[Creating Custom UI Components and Other Custom Objects]). HTML5 offers new elements and attributes that can make it unnecessary to write your own components. It also provides many new capabilities for existing components. @@ -35,11 +35,11 @@ For example, the following code declares the namespace with the short name `jsf` Here, the `jsf` prefix is placed on the `id` attribute so that the HTML5 input tag's attributes are treated as part of the Facelets page. This means that, for example, you can use EL expressions to retrieve managed bean properties. -<> shows how pass-through elements are rendered as Facelets tags. +<<_how_facelets_renders_html5_elements>> shows how pass-through elements are rendered as Facelets tags. The faces implementation uses the element name and the identifying attribute to determine the corresponding Facelets tag that will be used in the server-side processing. The browser, however, interprets the markup that the page author has written. -[[how-facelets-renders-html5-elements]] +[[_how_facelets_renders_html5_elements]] .How Facelets Renders HTML5 Elements [width="60%",cols="20%,20%,20%"] |=== @@ -224,7 +224,7 @@ The namespace declarations in the `html` element of the `reservation.xhtml` page xmlns:jsf="http://xmlns.jcp.org/jsf"> ---- -Next, an empty `h:head` tag followed by an `h:outputStylesheet` tag within the `h:body` tag illustrates the use of a relocatable resource (as described in <>): +Next, an empty `h:head` tag followed by an `h:outputStylesheet` tag within the `h:body` tag illustrates the use of a relocatable resource (as described in <<_relocatable_resources>>): [source,xml] ---- @@ -274,7 +274,7 @@ Here, the `p` prefix on the HTML5 attributes passes them through to the browser ---- The output of the `calculateTotal` method that is specified as the listener for the Ajax event is rendered in the output element whose `id` and `name` value is `total`. -See <>, for more information. +See xref:jsf-ajax/jsf-ajax.adoc#_using_ajax_with_jakarta_faces_technology[Using Ajax with Jakarta Faces Technology], for more information. The second Facelets page, `confirmation.xhtml`, uses a pass-through `output` element to display the values entered by the user and provides a Facelets `h:commandButton` tag to allow the user to return to the `reservation.xhtml` page. diff --git a/src/main/antora/modules/web/pages/jsf-intro/jsf-intro002.adoc b/src/main/antora/modules/web/pages/jsf-intro/jsf-intro002.adoc index d502878d..badc384e 100644 --- a/src/main/antora/modules/web/pages/jsf-intro/jsf-intro002.adoc +++ b/src/main/antora/modules/web/pages/jsf-intro/jsf-intro002.adoc @@ -18,12 +18,12 @@ In a Jakarta Faces application, managed beans serve as backing beans, which defi * Optionally, a set of custom tags for representing custom objects on the page. -<> shows the interaction between client and server in a typical Jakarta Faces application. +<<_responding_to_a_client_request_for_a_jakarta_faces_page>> shows the interaction between client and server in a typical Jakarta Faces application. In response to a client request, a web page is rendered by the web container that implements Jakarta Faces technology. -[[responding-to-a-client-request-for-a-jakarta-faces-page]] +[[_responding_to_a_client_request_for_a_jakarta_faces_page]] .Responding to a Client Request for a Jakarta Faces Page -image::jakartaeett_dt_014.svg["Diagram that shows a browser accessing the myfacelet.xhtml page using an HTTP Request and the server sending the rendered HTML page using an HTTP Response."] +image::common:jakartaeett_dt_014.svg["Diagram that shows a browser accessing the myfacelet.xhtml page using an HTTP Request and the server sending the rendered HTML page using an HTTP Response."] The web page, `myfacelet.xhtml`, is built using Jakarta Faces component tags. Component tags are used to add components to the `view` (represented by `myView` in the diagram), which is the server-side representation of the page. diff --git a/src/main/antora/modules/web/pages/jsf-intro/jsf-intro003.adoc b/src/main/antora/modules/web/pages/jsf-intro/jsf-intro003.adoc index fd999a22..772fb22c 100644 --- a/src/main/antora/modules/web/pages/jsf-intro/jsf-intro003.adoc +++ b/src/main/antora/modules/web/pages/jsf-intro/jsf-intro003.adoc @@ -8,23 +8,23 @@ The separation of logic from presentation also allows each member of a web appli For example, page authors with no programming expertise can use Jakarta Faces technology tags in a web page to link to server-side objects without writing any scripts. Another important goal of Jakarta Faces technology is to leverage familiar component and web-tier concepts without limiting you to a particular scripting technology or markup language. -Jakarta Faces technology APIs are layered directly on top of the Servlet API, as shown in <>. +Jakarta Faces technology APIs are layered directly on top of the Servlet API, as shown in <<_web_application_technologies>>. -[[web-application-technologies]] +[[_web_application_technologies]] .Web Application Technologies -image::jakartaeett_dt_015.svg["Diagram of web application technologies. Jakarta Server Pages, the server pages Standard Tag Library, and Jakarta Faces rest on Jakarta Servlet technology."] +image::common:jakartaeett_dt_015.svg["Diagram of web application technologies. Jakarta Server Pages, the server pages Standard Tag Library, and Jakarta Faces rest on Jakarta Servlet technology."] This layering of APIs enables several important application use cases, such as using different presentation technologies, creating your own custom components directly from the component classes, and generating output for various client devices. Facelets technology, available as part of Jakarta Faces technology, is the preferred presentation technology for building Jakarta Faces technology–based web applications. -For more information on Facelets technology features, see xref:introduction-to-facelets[xrefstyle=full]. +For more information on Facelets technology features, see xref:jsf-facelets/jsf-facelets.adoc#_introduction_to_facelets[Introduction to Facelets]. Facelets technology offers several advantages. * Code can be reused and extended for components through the templating and composite component features. * You can use annotations to automatically register the managed bean as a resource available for Jakarta Faces applications. -In addition, implicit navigation rules allow developers to quickly configure page navigation (see <> for details). +In addition, implicit navigation rules allow developers to quickly configure page navigation (see <<_navigation_model>> for details). These features reduce the manual configuration process for applications. * Most important, Jakarta Faces technology provides a rich architecture for managing component state, processing component data, validating user input, and handling events. diff --git a/src/main/antora/modules/web/pages/jsf-intro/jsf-intro004.adoc b/src/main/antora/modules/web/pages/jsf-intro/jsf-intro004.adoc index 650da758..e796c2e2 100644 --- a/src/main/antora/modules/web/pages/jsf-intro/jsf-intro004.adoc +++ b/src/main/antora/modules/web/pages/jsf-intro/jsf-intro004.adoc @@ -1,7 +1,7 @@ == A Simple Jakarta Faces Application Jakarta Faces technology provides an easy and user-friendly process for creating web applications. -Developing a simple Jakarta Faces application typically requires the following tasks, which have already been described in <>: +Developing a simple Jakarta Faces application typically requires the following tasks, which have already been described in xref:webapp/webapp.adoc#_a_web_module_that_uses_jakarta_faces_technology_the_hello1_example[A Web Module That Uses Jakarta Faces Technology: The hello1 Example]: * Creating web pages using component tags @@ -12,9 +12,9 @@ Developing a simple Jakarta Faces application typically requires the following t The `hello1` example includes a managed bean and two Facelets web pages. When accessed by a client, the first web page asks the user for his or her name, and the second page responds by providing a greeting. -For details on Facelets technology, see xref:introduction-to-facelets[xrefstyle=full]. -For details on using EL expressions, see xref:expression-language[xrefstyle=full]. -For details on the Jakarta Faces programming model and building web pages using Jakarta Faces technology, see xref:using-jakarta-faces-technology-in-web-pages[xrefstyle=full]. +For details on Facelets technology, see xref:jsf-facelets/jsf-facelets.adoc#_introduction_to_facelets[Introduction to Facelets]. +For details on using EL expressions, see xref:jsf-el/jsf-el.adoc#_expression_language[Expression Language]. +For details on the Jakarta Faces programming model and building web pages using Jakarta Faces technology, see xref:jsf-page/jsf-page.adoc#_using_jakarta_faces_technology_in_web_pages[Using Jakarta Faces Technology in Web Pages]. Every web application has a lifecycle. Common tasks, such as handling incoming requests, decoding parameters, modifying and saving state, and rendering web pages to the browser, are all performed during a web application lifecycle. @@ -64,4 +64,4 @@ The `hello1` example application goes through the following stages when it is de . On subsequent (postback) requests, the component tree is rebuilt, and the saved state is applied. -For full details on the lifecycle, see <>. +For full details on the lifecycle, see <<_the_lifecycle_of_a_jakarta_faces_application>>. diff --git a/src/main/antora/modules/web/pages/jsf-intro/jsf-intro005.adoc b/src/main/antora/modules/web/pages/jsf-intro/jsf-intro005.adoc index 0bf91968..31b7e61c 100644 --- a/src/main/antora/modules/web/pages/jsf-intro/jsf-intro005.adoc +++ b/src/main/antora/modules/web/pages/jsf-intro/jsf-intro005.adoc @@ -27,7 +27,7 @@ This section briefly describes each of these pieces of the component architectur Jakarta Faces technology provides a set of UI component classes and associated behavioral interfaces that specify all the UI component functionality, such as holding component state, maintaining a reference to objects, and driving event handling and rendering for a set of standard components. The component classes are completely extensible, allowing component writers to create their own custom components. -See xref:creating-custom-ui-components-and-other-custom-objects[xrefstyle=full] for more information. +See xref:jsf-custom/jsf-custom.adoc#_creating_custom_ui_components_and_other_custom_objects[Creating Custom UI Components and Other Custom Objects] for more information. The abstract base class for all components is `jakarta.faces.component.UIComponent`. Jakarta Faces UI component classes extend the `UIComponentBase` class (a subclass of `UIComponent`), which defines the default state and behavior of a component. @@ -137,7 +137,7 @@ The `Button` or `Link` part of each tag corresponds to a separate `Renderer` cla Each custom tag defined in the standard HTML render kit is composed of the component functionality (defined in the `UIComponent` class) and the rendering attributes (defined by the `Renderer` class). -The section <> lists all supported component tags and illustrates how to use the tags in an example. +The section xref:jsf-page/jsf-page.adoc#_adding_components_to_a_page_using_html_tag_library_tags[Adding Components to a Page Using HTML Tag Library Tags] lists all supported component tags and illustrates how to use the tags in an example. The Jakarta Faces implementation provides a custom tag library for rendering components in HTML. @@ -164,7 +164,7 @@ To facilitate this, Jakarta Faces technology allows you to register a `jakarta.f If you register the `Converter` implementation on a component, the `Converter` implementation converts the component's data between the two views. You can either use the standard converters supplied with the Jakarta Faces implementation or create your own custom converter. -Custom converter creation is covered in xref:creating-custom-ui-components-and-other-custom-objects[xrefstyle=full]. +Custom converter creation is covered in xref:jsf-custom/jsf-custom.adoc#_creating_custom_ui_components_and_other_custom_objects[Creating Custom UI Components and Other Custom Objects]. === Event and Listener Model @@ -190,7 +190,7 @@ An example is selecting a check box, an action that results in the component's v The component types that can generate these types of events are the `UIInput`, `UISelectOne`, `UISelectMany`, and `UISelectBoolean` components. Value-change events are fired only if no validation errors are detected. -Depending on the value of the `immediate` property (see <>) of the component emitting the event, action events can be processed during the Invoke Application phase or the Apply Request Values phase, and value-change events can be processed during the Process Validations phase or the Apply Request Values phase. +Depending on the value of the `immediate` property (see xref:jsf-page/jsf-page.adoc#_the_immediate_attribute[The immediate Attribute]) of the component emitting the event, action events can be processed during the Invoke Application phase or the Apply Request Values phase, and value-change events can be processed during the Process Validations phase or the Apply Request Values phase. System events are generated by an `Object` rather than a `UIComponent`. They are generated during the execution of an application at predefined times. @@ -204,15 +204,15 @@ There are two ways to cause your application to react to action events or value- * Implement a method of a managed bean to handle the event, and refer to the method with a method expression from the appropriate attribute of the component's tag. -See <> for information on how to implement an event listener. -See <> for information on how to register the listener on a component. +See xref:jsf-custom/jsf-custom.adoc#_implementing_an_event_listener[Implementing an Event Listener] for information on how to implement an event listener. +See xref:jsf-page-core/jsf-page-core.adoc#_registering_listeners_on_components[Registering Listeners on Components] for information on how to register the listener on a component. -See <> and <> for information on how to implement managed bean methods that handle these events. +See xref:jsf-develop/jsf-develop.adoc#_writing_a_method_to_handle_an_action_event[Writing a Method to Handle an Action Event] and xref:jsf-develop/jsf-develop.adoc#_writing_a_method_to_handle_a_value_change_event[Writing a Method to Handle a Value-Change Event] for information on how to implement managed bean methods that handle these events. -See <> for information on how to refer to the managed bean method from the component tag. +See xref:jsf-page-core/jsf-page-core.adoc#_referencing_a_managed_bean_method[Referencing a Managed Bean Method] for information on how to refer to the managed bean method from the component tag. When emitting events from custom components, you must implement the appropriate event class and manually queue the event on the component in addition to implementing an event listener class or a managed bean method that handles the event. -<> explains how to do this. +xref:jsf-custom/jsf-custom.adoc#_handling_events_for_custom_components[Handling Events for Custom Components] explains how to do this. === Validation Model @@ -221,13 +221,13 @@ This validation occurs before the corresponding model data is updated to match t Like the conversion model, the validation model defines a set of standard classes for performing common data validation checks. The Jakarta Faces core tag library also defines a set of tags that correspond to the standard `jakarta.faces.validator.Validator` implementations. -See <> for a list of all the standard validation classes and corresponding tags. +See xref:jsf-page-core/jsf-page-core.adoc#_using_the_standard_validators[Using the Standard Validators] for a list of all the standard validation classes and corresponding tags. Most of the tags have a set of attributes for configuring the validator's properties, such as the minimum and maximum allowable values for the component's data. The page author registers the validator on a component by nesting the validator's tag within the component's tag. In addition to validators that are registered on the component, you can declare a default validator that is registered on all `UIInput` components in the application. -For more information on default validators, see <>. +For more information on default validators, see xref:jsf-configure/jsf-configure.adoc#_using_default_validators[Using Default Validators]. The validation model also allows you to create your own custom validator and corresponding tag to perform custom validation. The validation model provides two ways to implement custom validation. @@ -244,4 +244,4 @@ If you are implementing a `Validator` interface, you must also do the following. In the previously described standard validation model, the validator is defined for each input component on a page. The Bean Validation model allows the validator to be applied to all fields in a page. -See xref:introduction-to-jakarta-bean-validation[xrefstyle=full] and xref:bean-validation-advanced-topics[xrefstyle=full] for more information on Bean Validation. +See xref:introduction-to-jakarta-bean-validation[] and xref:bean-validation-advanced-topics[] for more information on Bean Validation. diff --git a/src/main/antora/modules/web/pages/jsf-intro/jsf-intro006.adoc b/src/main/antora/modules/web/pages/jsf-intro/jsf-intro006.adoc index 34362952..df74e4f8 100644 --- a/src/main/antora/modules/web/pages/jsf-intro/jsf-intro006.adoc +++ b/src/main/antora/modules/web/pages/jsf-intro/jsf-intro006.adoc @@ -134,8 +134,8 @@ The return value of `createdStudent` has a corresponding navigation case in the After the student is created, the user is returned to the Administration index page. -For more information on how to define navigation rules, see <>. +For more information on how to define navigation rules, see xref:jsf-configure/jsf-configure.adoc#_configuring_navigation_rules[Configuring Navigation Rules]. -For more information on how to implement action methods to handle navigation, see <>. +For more information on how to implement action methods to handle navigation, see xref:jsf-develop/jsf-develop.adoc#_writing_a_method_to_handle_an_action_event[Writing a Method to Handle an Action Event]. -For more information on how to reference outcomes or action methods from component tags, see <>. +For more information on how to reference outcomes or action methods from component tags, see xref:jsf-page-core/jsf-page-core.adoc#_referencing_a_method_that_performs_navigation[Referencing a Method That Performs Navigation]. diff --git a/src/main/antora/modules/web/pages/jsf-intro/jsf-intro007.adoc b/src/main/antora/modules/web/pages/jsf-intro/jsf-intro007.adoc index 3e4e027b..6472c3a2 100644 --- a/src/main/antora/modules/web/pages/jsf-intro/jsf-intro007.adoc +++ b/src/main/antora/modules/web/pages/jsf-intro/jsf-intro007.adoc @@ -15,10 +15,10 @@ During a web application lifecycle, common tasks are performed, including the fo The Jakarta Faces web application framework manages lifecycle phases automatically for simple applications or allows you to manage them manually for more complex applications as required. Jakarta Faces applications that use advanced features may require interaction with the lifecycle at certain phases. -For example, Ajax applications use partial processing features of the lifecycle (see <>). +For example, Ajax applications use partial processing features of the lifecycle (see <<_partial_processing_and_partial_rendering>>). A clearer understanding of the lifecycle phases is key to creating well-designed components. -A simplified view of the Jakarta Faces lifecycle, consisting of the two main phases of a Jakarta Faces web application, is introduced in <>. +A simplified view of the Jakarta Faces lifecycle, consisting of the two main phases of a Jakarta Faces web application, is introduced in <<_a_simple_jakarta_faces_application>>. This section examines the Jakarta Faces lifecycle in more detail. === Overview of the Jakarta Faces Lifecycle @@ -34,11 +34,11 @@ During the lifecycle, the Jakarta Faces implementation must build the view while When the client requests a page, the Jakarta Faces implementation performs several tasks, such as validating the data input of components in the view and converting input data to types specified on the server side. The Jakarta Faces implementation performs all these tasks as a series of steps in the Jakarta Faces request-response lifecycle. -<> illustrates these steps. +<<_jakarta_faces_standard_request_response_lifecycle>> illustrates these steps. -[[jakarta-faces-standard-request-response-lifecycle]] +[[_jakarta_faces_standard_request_response_lifecycle]] .Jakarta Faces Standard Request-Response Lifecycle -image::jakartaeett_dt_016.svg["Flow diagram of Faces request and Faces response, including event and validation processing, error handling, model updating, application invocation."] +image::common:jakartaeett_dt_016.svg["Flow diagram of Faces request and Faces response, including event and validation processing, error handling, model updating, application invocation."] The request-response lifecycle handles two kinds of requests: initial requests and postbacks. An initial request occurs when a user makes a request for a page for the first time. @@ -49,7 +49,7 @@ Conversely, when the lifecycle handles a postback, it executes all of the phases Usually, the first request for a Jakarta Faces page comes in from a client, as a result of clicking a link or button component on a Jakarta Faces page. To render a response that is another Jakarta Faces page, the application creates a new view and stores it in the `jakarta.faces.context.FacesContext` instance, which represents all of the information associated with processing an incoming request and creating a response. -The application then acquires object references needed by the view and calls the `FacesContext.renderResponse` method, which forces immediate rendering of the view by skipping to the <> of the lifecycle, as is shown by the arrows labelled Render Response in <>. +The application then acquires object references needed by the view and calls the `FacesContext.renderResponse` method, which forces immediate rendering of the view by skipping to the <<_render_response_phase>> of the lifecycle, as is shown by the arrows labelled Render Response in <<_jakarta_faces_standard_request_response_lifecycle>>. Sometimes, an application might need to redirect to a different web application resource, such as a web service, or generate a response that does not contain Jakarta Faces components. In these situations, the developer must skip the Render Response phase by calling the `FacesContext.responseComplete` method. @@ -59,24 +59,24 @@ The most common situation is that a Jakarta Faces component submits a request fo In this case, the Jakarta Faces implementation handles the request and automatically goes through the phases in the lifecycle to perform any necessary conversions, validations, and model updates and to generate the response. There is one exception to the lifecycle described in this section. -When a component's `immediate` attribute is set to `true`, the validation, conversion, and events associated with these components are processed during the <> rather than in a later phase. +When a component's `immediate` attribute is set to `true`, the validation, conversion, and events associated with these components are processed during the <<_apply_request_values_phase>> rather than in a later phase. The details of the lifecycle explained in the following sections are primarily intended for developers who need to know information such as when validations, conversions, and events are usually handled and ways to change how and when they are handled. For more information on each of the lifecycle phases, download the latest Jakarta Faces Specification documentation from https://jakarta.ee/specifications/faces/[^]. The Jakarta Faces application lifecycle Execute phase contains the following subphases: -* <> +* <<_restore_view_phase>> -* <> +* <<_apply_request_values_phase>> -* <> +* <<_process_validations_phase>> -* <> +* <<_update_model_values_phase>> -* <> +* <<_invoke_application_phase>> -* <> +* <<_render_response_phase>> === Restore View Phase @@ -99,7 +99,7 @@ If any `decode` methods or event listeners have called the `renderResponse` meth If any events have been queued during this phase, the Jakarta Faces implementation broadcasts the events to interested listeners. -If some components on the page have their `immediate` attributes (see <>) set to `true`, then the validations, conversions, and events associated with these components will be processed during this phase. +If some components on the page have their `immediate` attributes (see xref:jsf-page/jsf-page.adoc#_the_immediate_attribute[The immediate Attribute]) set to `true`, then the validations, conversions, and events associated with these components will be processed during this phase. If any conversion fails, an error message associated with the component is generated and queued on `FacesContext`. This message will be displayed during the Render Response phase, along with any validation errors resulting from the Process Validations phase. diff --git a/src/main/antora/modules/web/pages/jsf-intro/jsf-intro008.adoc b/src/main/antora/modules/web/pages/jsf-intro/jsf-intro008.adoc index 2f74aee4..5bc05d89 100644 --- a/src/main/antora/modules/web/pages/jsf-intro/jsf-intro008.adoc +++ b/src/main/antora/modules/web/pages/jsf-intro/jsf-intro008.adoc @@ -8,4 +8,4 @@ Once such a partial request enters the Jakarta Faces lifecycle, the information The Jakarta Faces lifecycle is still aware of such Ajax requests and modifies the component tree accordingly. The `execute` and `render` attributes of the `f:ajax` tag are used to identify which components may be executed and rendered. -For more information on these attributes, see xref:using-ajax-with-jakarta-faces-technology[xrefstyle=full]. +For more information on these attributes, see xref:jsf-ajax/jsf-ajax.adoc#_using_ajax_with_jakarta_faces_technology[Using Ajax with Jakarta Faces Technology]. diff --git a/src/main/antora/modules/web/pages/jsf-page-core/jsf-page-core001.adoc b/src/main/antora/modules/web/pages/jsf-page-core/jsf-page-core001.adoc index a9ac5f64..c90e32c3 100644 --- a/src/main/antora/modules/web/pages/jsf-page-core/jsf-page-core001.adoc +++ b/src/main/antora/modules/web/pages/jsf-page-core/jsf-page-core001.adoc @@ -2,14 +2,14 @@ The Jakarta Faces implementation provides a set of `Converter` implementations that you can use to convert component data. The purpose of conversion is to take the String-based data coming in from the Servlet API and convert it to strongly typed Java objects suitable for the business domain. -For more information on the conceptual details of the conversion model, see <>. +For more information on the conceptual details of the conversion model, see xref:jsf-intro/jsf-intro.adoc#_conversion_model[Conversion Model]. The standard `Converter` implementations are located in the `jakarta.faces.convert` package. Normally, converters are implicitly assigned based on the type of the EL expression pointed to by the value of the component. However, these converters can also be accessed by a converter ID. -<> shows the converter classes and their associated converter IDs. +<<_converter_classes_and_converter_ids>> shows the converter classes and their associated converter IDs. -[[converter-classes-and-converter-ids]] +[[_converter_classes_and_converter_ids]] .Converter Classes and Converter IDs [width="60%",cols="30%,30%"] |=== @@ -54,8 +54,8 @@ For example, the following error message appears if `BigIntegerConverter` fails In this case, the `{0}` substitution parameter will be replaced with the name of the input component on which the converter is registered. Two of the standard converters (`DateTimeConverter` and `NumberConverter`) have their own tags, which allow you to configure the format of the component data using the tag attributes. -For more information about using `DateTimeConverter`, see <>. -For more information about using `NumberConverter`, see <>. +For more information about using `DateTimeConverter`, see <<_using_datetimeconverter>>. +For more information about using `NumberConverter`, see <<_using_numberconverter>>. The following section explains how to convert a component's value, including how to register other standard converters with a component. === Converting a Component's Value @@ -64,7 +64,7 @@ To use a particular converter to convert a component's value, you need to regist You can register any of the standard converters in one of the following ways. * Nest one of the standard converter tags inside the component's tag. -These tags are `f:convertDateTime` and `f:convertNumber`, which are described in <>, respectively. +These tags are `f:convertDateTime` and `f:convertNumber`, which are described in <<_using_numberconverter>>, respectively. * Bind the value of the component to a managed bean property of the same type as the converter. This is the most common technique. @@ -90,7 +90,7 @@ If you don't need to specify any formatting instructions using the `f:convertNum You can also nest an `f:converter` tag within the component tag and use either the converter tag's `converterId` attribute or its `binding` attribute to reference the converter. The `converterId` attribute must reference the converter's ID. -Here is an example that uses one of the converter IDs listed in <>: +Here is an example that uses one of the converter IDs listed in <<_converter_classes_and_converter_ids>>: [source,xml] ---- @@ -103,13 +103,13 @@ Instead of using the `converterId` attribute, the `f:converter` tag can use the The `binding` attribute must resolve to a bean property that accepts and returns an appropriate `Converter` instance. You can also create custom converters and register them on components using the `f:converter` tag. -For details, see <>. +For details, see xref:jsf-custom/jsf-custom.adoc#_creating_and_using_a_custom_converter[Creating and Using a Custom Converter]. === Using DateTimeConverter You can convert a component's data to a `java.util.Date` by nesting the `convertDateTime` tag inside the component tag. The `convertDateTime` tag has several attributes that allow you to specify the format and type of the data. -<> lists the attributes. +<<_attributes_for_the_fconvertdatetime_tag>> lists the attributes. Here is a simple example of a `convertDateTime` tag: @@ -157,7 +157,7 @@ jueves 24 de octubre de 2013 15:07:04 GMT Refer to the "Customizing Formats" lesson of the Java Tutorial at https://docs.oracle.com/javase/tutorial/i18n/format/simpleDateFormat.html[^] for more information on how to format the output using the `pattern` attribute of the `convertDateTime` tag. -[[attributes-for-the-fconvertDateTime-tag]] +[[_attributes_for_the_fconvertDateTime_tag]] .Attributes for the f:convertDateTime Tag [width="99%",cols="25%a,25%,50%"] |=== @@ -179,7 +179,7 @@ If not specified, the `Locale` returned by `FacesContext.getLocale` will be used |`pattern` |`String` a| Custom formatting pattern that determines how the date/time string should be formatted and parsed. If this attribute is specified, `dateStyle` and `timeStyle` attributes are ignored. -See <> for the default values when `pattern` is not specified. +See <<_type_attribute_and_default_pattern_values>> for the default values when `pattern` is not specified. |`timeStyle` |`String` a|Defines the format, as specified by `java.text.DateFormat`, of a `time` or the time part of a `date` string. Applied only if `type` is time and `pattern` is not defined. @@ -192,10 +192,10 @@ If no value is specified, `default` is used. Valid values are: `date`, `time`, `both`, `LocalDate`, `LocalTime`, `LocalDateTime`, `OffsetTime`, `OffsetDateTime`, or `ZonedDateTime`. If no value is specified, `date` is used. -See <> for additional information. +See <<_type_attribute_and_default_pattern_values>> for additional information. |=== -[[type-attribute-and-default-pattern-values]] +[[_type_attribute_and_default_pattern_values]] .Type Attribute and Default Pattern Values [width="99%",cols="25%,25%,50%"] |=== @@ -224,7 +224,7 @@ See <> for additional information. You can convert a component's data to a `java.lang.Number` by nesting the `convertNumber` tag inside the component tag. The `convertNumber` tag has several attributes that allow you to specify the format and type of the data. -<> lists the attributes. +<<_attributes_for_the_fconvertnumber_tag>> lists the attributes. The following example uses a `convertNumber` tag to display the total prices of the contents of a shopping cart: @@ -255,7 +255,7 @@ This result can also be displayed by using the following tag in which the curren See the "Customizing Formats" lesson of the Java Tutorial at https://docs.oracle.com/javase/tutorial/i18n/format/decimalFormat.html[^] for more information on how to format the output by using the `pattern` attribute of the `convertNumber` tag. -[[attributes-for-the-fconvertNumber-tag]] +[[_attributes_for_the_fconvertNumber_tag]] .Attributes for the f:convertNumber Tag [width="99%",cols="25%,25%,50%"] |=== diff --git a/src/main/antora/modules/web/pages/jsf-page-core/jsf-page-core002.adoc b/src/main/antora/modules/web/pages/jsf-page-core/jsf-page-core002.adoc index d1368eea..da83584d 100644 --- a/src/main/antora/modules/web/pages/jsf-page-core/jsf-page-core002.adoc +++ b/src/main/antora/modules/web/pages/jsf-page-core/jsf-page-core002.adoc @@ -4,7 +4,7 @@ An application developer can implement listeners as classes or as managed bean m If a listener is a managed bean method, the page author references the method from either the component's `valueChangeListener` attribute or its `actionListener` attribute. If the listener is a class, the page author can reference the listener from either an `f:valueChangeListener` tag or an `f:actionListener` tag and nest the tag inside the component tag to register the listener on the component. -<> and <> explain how a page author uses the `valueChangeListener` and `actionListener` attributes to reference managed bean methods that handle events. +<<_referencing_a_method_that_handles_an_action_event>> and <<_referencing_a_method_that_handles_a_value_change_event>> explain how a page author uses the `valueChangeListener` and `actionListener` attributes to reference managed bean methods that handle events. This section explains how to register a `NameChanged` value-change listener and a `BookChange` action listener implementation on components. The Duke's Bookstore case study includes both of these listeners. @@ -12,9 +12,9 @@ The Duke's Bookstore case study includes both of these listeners. === Registering a Value-Change Listener on a Component A page author can register a `ValueChangeListener` implementation on a component that implements `EditableValueHolder` by nesting an `f:valueChangeListener` tag within the component's tag on the page. -The `f:valueChangeListener` tag supports the attributes shown in <>, one of which must be used. +The `f:valueChangeListener` tag supports the attributes shown in <<_attributes_for_the_fvaluechangelistener_tag>>, one of which must be used. -[[attributes-for-the-fvaluechangelistener-tag]] +[[_attributes_for_the_fvaluechangelistener_tag]] .Attributes for the f:valueChangeListener Tag [width="60%",cols="10%,50%"] |=== @@ -47,7 +47,7 @@ After this component tag is processed and local values have been validated, its The `binding` attribute is used to bind a `ValueChangeListener` implementation to a managed bean property. This attribute works in a similar way to the `binding` attribute supported by the standard converter tags. -See <> for more information. +See xref:jsf-custom/jsf-custom.adoc#_binding_component_values_and_instances_to_managed_bean_properties[Binding Component Values and Instances to Managed Bean Properties] for more information. === Registering an Action Listener on a Component @@ -68,7 +68,7 @@ Here is an example of an `h:commandLink` tag that references an `ActionListener` The `type` attribute of the `f:actionListener` tag specifies the fully qualified class name of the `ActionListener` implementation. Similarly to the `f:valueChangeListener` tag, the `f:actionListener` tag also supports the `binding` attribute. -See <> for more information about binding listeners to managed bean properties. +See xref:jsf-custom/jsf-custom.adoc#_binding_converters_listeners_and_validators_to_managed_bean_properties[Binding Converters, Listeners, and Validators to Managed Bean Properties] for more information about binding listeners to managed bean properties. In addition to the `actionListener` tag that allows you register a custom listener onto a component, the core tag library includes the `f:setPropertyActionListener` tag. You use this tag to register a special action listener onto the `ActionSource` instance associated with a component. diff --git a/src/main/antora/modules/web/pages/jsf-page-core/jsf-page-core003.adoc b/src/main/antora/modules/web/pages/jsf-page-core/jsf-page-core003.adoc index 8c6bff08..30a56e33 100644 --- a/src/main/antora/modules/web/pages/jsf-page-core/jsf-page-core003.adoc +++ b/src/main/antora/modules/web/pages/jsf-page-core/jsf-page-core003.adoc @@ -1,9 +1,9 @@ == Using the Standard Validators Jakarta Faces technology provides a set of standard classes and associated tags that page authors and application developers can use to validate a component's data. -<> lists all the standard validator classes and the tags that allow you to use the validators from the page. +<<_the_validator_classes>> lists all the standard validator classes and the tags that allow you to use the validators from the page. -[[the-validator-classes]] +[[_the_validator_classes]] .The Validator Classes [width="99%",cols="15%,15%,60%"] |=== @@ -41,31 +41,31 @@ For example, the error message that displays when the component's value exceeds In this case, the `{1}` substitution parameter is replaced by the component's label or `id`, and the `{0}` substitution parameter is replaced with the maximum value allowed by the validator. -See <> for information on how to display validation error messages on the page when validation fails. +See <<_displaying_error_messages_with_the_hmessage_and_hmessages_tags>> for information on how to display validation error messages on the page when validation fails. Instead of using the standard validators, you can use Bean Validation to validate data. If you specify bean validation constraints on your managed bean properties, the constraints are automatically placed on the corresponding fields on your applications web pages. -See xref:introduction-to-jakarta-bean-validation[xrefstyle=full] for more information. +See xref:introduction-to-jakarta-bean-validation[] for more information. You do not need to specify the `validateBean` tag to use Bean Validation, but the tag allows you to use more advanced Bean Validation features. For example, you can use the `validationGroups` attribute of the tag to specify constraint groups. You can also create and register custom validators, although Bean Validation has made this feature less useful. -For details, see <>. +For details, see xref:jsf-custom/jsf-custom.adoc#_creating_and_using_a_custom_validator[Creating and Using a Custom Validator]. === Validating a Component's Value To validate a component's value using a particular validator, you need to register that validator on the component. You can do this in one of the following ways. -* Nest the validator's corresponding tag (shown in <>) inside the component's tag. -<> explains how to use the `validateLongRange` tag. +* Nest the validator's corresponding tag (shown in <<_the_validator_classes>>) inside the component's tag. +<<_using_validator_tags>> explains how to use the `validateLongRange` tag. You can use the other standard tags in the same way. * Refer to a method that performs the validation from the component tag's `validator` attribute. * Nest a validator tag inside the component tag, and use either the validator tag's `validatorId` attribute or its `binding` attribute to refer to the validator. -See <> for more information on using the `validator` attribute. +See <<_referencing_a_method_that_performs_validation>> for more information on using the `validator` attribute. The `validatorId` attribute works similarly to the `converterId` attribute of the `converter` tag, as described in <>. diff --git a/src/main/antora/modules/web/pages/jsf-page-core/jsf-page-core004.adoc b/src/main/antora/modules/web/pages/jsf-page-core/jsf-page-core004.adoc index 81aa44e5..55b43d6b 100644 --- a/src/main/antora/modules/web/pages/jsf-page-core/jsf-page-core004.adoc +++ b/src/main/antora/modules/web/pages/jsf-page-core/jsf-page-core004.adoc @@ -1,9 +1,9 @@ == Referencing a Managed Bean Method A component tag has a set of attributes for referencing managed bean methods that can perform certain functions for the component associated with the tag. -These attributes are summarized in <>. +These attributes are summarized in <<_component_tag_attributes_that_reference_managed_bean_methods>>. -[[component-tag-attributes-that-reference-managed-bean-methods]] +[[_component_tag_attributes_that_reference_managed_bean_methods]] .Component Tag Attributes That Reference Managed Bean Methods [width="60%",cols="10%,50%"] |=== @@ -50,7 +50,7 @@ The following example shows how to reference a navigation method: action="#{cashierBean.submit}" /> ---- -See <> for information on how to write such a method. +See xref:jsf-develop/jsf-develop.adoc#_writing_a_method_to_handle_navigation[Writing a Method to Handle Navigation] for information on how to write such a method. === Referencing a Method That Handles an Action Event @@ -66,7 +66,7 @@ The following example shows how such a method could be referenced: The `actionListener` attribute of this component tag references the `chooseBookFromLink` method using a method expression. The `chooseBookFromLink` method handles the event when the user clicks the link rendered by this component. -See <> for information on how to write such a method. +See xref:jsf-develop/jsf-develop.adoc#_writing_a_method_to_handle_an_action_event[Writing a Method to Handle an Action Event] for information on how to write such a method. === Referencing a Method That Performs Validation @@ -85,7 +85,7 @@ The following simplified example from <> shows ---- The managed bean method `validateNumberRange` verifies that the input value is within the valid range, which changes each time another guess is made. -See <> for information on how to write such a method. +See xref:jsf-develop/jsf-develop.adoc#_writing_a_method_to_perform_validation[Writing a Method to Perform Validation] for information on how to write such a method. === Referencing a Method That Handles a Value-Change Event @@ -104,4 +104,4 @@ If you want a component on your page to generate a value-change event and you wa The `valueChangeListener` attribute of this component tag references the `processValueChange` method of `CashierBean` by using a method expression. The `processValueChange` method handles the event of a user entering a name in the input field rendered by this component. -<> describes how to implement a method that handles a `ValueChangeEvent`. +xref:jsf-develop/jsf-develop.adoc#_writing_a_method_to_handle_a_value_change_event[Writing a Method to Handle a Value-Change Event] describes how to implement a method that handles a `ValueChangeEvent`. diff --git a/src/main/antora/modules/web/pages/jsf-page/jsf-page.adoc b/src/main/antora/modules/web/pages/jsf-page/jsf-page.adoc index ff8b7d9a..6dc40986 100644 --- a/src/main/antora/modules/web/pages/jsf-page/jsf-page.adoc +++ b/src/main/antora/modules/web/pages/jsf-page/jsf-page.adoc @@ -6,7 +6,7 @@ The process of creating web pages for a Jakarta Faces application includes using This chapter explains how to create web pages using various types of component and core tags. In the next chapter, you will learn about adding converters, validators, and listeners to component tags to provide additional functionality to components. -Many of the examples in this chapter are taken from xref:dukes-bookstore-case-study-example[xrefstyle=full] +Many of the examples in this chapter are taken from xref:dukes-bookstore-case-study-example[] include::jsf-page001.adoc[] diff --git a/src/main/antora/modules/web/pages/jsf-page/jsf-page001.adoc b/src/main/antora/modules/web/pages/jsf-page/jsf-page001.adoc index 5a724e67..ad98abdd 100644 --- a/src/main/antora/modules/web/pages/jsf-page/jsf-page001.adoc +++ b/src/main/antora/modules/web/pages/jsf-page/jsf-page001.adoc @@ -37,4 +37,4 @@ For example, in the following web page the `form` tag must be referenced using t ---- -The sections <> and <> describe how to use the component tags from the Jakarta Faces standard HTML tag library and the core tags from the Jakarta Faces core tag library. +The sections <<_adding_components_to_a_page_using_html_tag_library_tags>> and <<_using_core_tags>> describe how to use the component tags from the Jakarta Faces standard HTML tag library and the core tags from the Jakarta Faces core tag library. diff --git a/src/main/antora/modules/web/pages/jsf-page/jsf-page002.adoc b/src/main/antora/modules/web/pages/jsf-page/jsf-page002.adoc index 6ae15f76..fbe448e3 100644 --- a/src/main/antora/modules/web/pages/jsf-page/jsf-page002.adoc +++ b/src/main/antora/modules/web/pages/jsf-page/jsf-page002.adoc @@ -3,9 +3,9 @@ The tags defined by the Jakarta Faces standard HTML tag library represent HTML form components and other basic HTML elements. These components display data or accept data from the user. This data is collected as part of a form and is submitted to the server, usually when the user clicks a button. -This section explains how to use each of the component tags shown in <>. +This section explains how to use each of the component tags shown in <<_the_component_tags>>. -[[the-component-tags]] +[[_the_component_tags]] .The Component Tags [width="99%",cols="15%,30%,30%,25%"] |=== @@ -67,18 +67,18 @@ For a standalone radio button, use the `group` attribute. |=== The tags correspond to components in the `jakarta.faces.component` package. -The components are discussed in more detail in xref:developing-with-jakarta-faces-technology[xrefstyle=full] +The components are discussed in more detail in xref:jsf-develop/jsf-develop.adoc#_developing_with_jakarta_faces_technology[Developing with Jakarta Faces Technology] The next section explains the important attributes that are common to most component tags. -For each of the components discussed in the following sections, <> explains how to write a bean property bound to that particular component or its value. +For each of the components discussed in the following sections, xref:jsf-develop/jsf-develop.adoc#_writing_bean_properties[Writing Bean Properties] explains how to write a bean property bound to that particular component or its value. For reference information about the tags and their attributes, see the https://jakarta.ee/specifications/faces/3.0/vdldoc/[Jakarta Faces Facelets Tag Library documentation^]. === Common Component Tag Attributes -Most of the component tags support the attributes shown in <>. +Most of the component tags support the attributes shown in <<_common_tag_attributes>>. -[[common-tag-attributes]] +[[_common_tag_attributes]] .Common Component Tag Attributes [width="80%",cols="20%,60%"] |=== @@ -100,7 +100,7 @@ If the condition is not satisfied, the component is not rendered. |`value` |Specifies the value of the component in the form of a value expression. |=== -All the tag attributes except `id` can accept expressions, as defined by the Expression Language, described in xref:expression-language[xrefstyle=full]. +All the tag attributes except `id` can accept expressions, as defined by the Expression Language, described in xref:jsf-el/jsf-el.adoc#_expression_language[Expression Language]. An attribute such as `rendered` or `value` can be set on the page and then modified in the backing bean for the page. @@ -108,8 +108,8 @@ An attribute such as `rendered` or `value` can be set on the page and then modif The `id` attribute is not usually required for a component tag but is used when another component or a server-side class must refer to the component. If you don't include an `id` attribute, the Jakarta Faces implementation automatically generates a component ID. -Unlike most other Jakarta Faces tag attributes, the `id` attribute takes expressions using only the evaluation syntax described in <>, which uses the `${}` delimiters. -For more information on expression syntax, see <>. +Unlike most other Jakarta Faces tag attributes, the `id` attribute takes expressions using only the evaluation syntax described in xref:jsf-el/jsf-el.adoc#_immediate_evaluation[Immediate Evaluation], which uses the `${}` delimiters. +For more information on expression syntax, see xref:jsf-el/jsf-el.adoc#_value_expressions[Value Expressions]. ==== The immediate Attribute @@ -171,18 +171,18 @@ For example, the `commandLink` component in the following section of a page is n ---- Unlike nearly every other Jakarta Faces tag attribute, the `rendered` attribute is restricted to using rvalue expressions. -As explained in <>, these rvalue expressions can only read data; they cannot write the data back to the data source. +As explained in xref:jsf-el/jsf-el.adoc#_value_and_method_expressions[Value and Method Expressions], these rvalue expressions can only read data; they cannot write the data back to the data source. Therefore, expressions used with `rendered` attributes can use the arithmetic operators and literals that rvalue expressions can use but lvalue expressions cannot use. For example, the expression in the preceding example uses the `>` operator. [NOTE] In this example and others, `bundle` refers to a `java.util.ResourceBundle` file that contains locale-specific strings to be displayed. -Resource bundles are discussed in xref:internationalizing-and-localizing-web-applications[xrefstyle=full]. +Resource bundles are discussed in xref:webi18n/webi18n.adoc#_internationalizing_and_localizing_web_applications[Internationalizing and Localizing Web Applications]. ==== The style and styleClass Attributes The `style` and `styleClass` attributes allow you to specify CSS styles for the rendered output of your tags. -<> describes an example of using the `style` attribute to specify styles directly in the attribute. +<<_displaying_error_messages_with_the_hmessage_and_hmessages_tags>> describes an example of using the `style` attribute to specify styles directly in the attribute. A component tag can instead refer to a CSS class. The following example shows the use of a `dataTable` tag that references the style class `list-background`: @@ -203,7 +203,7 @@ For more information on defining styles, see the Cascading Style Sheets specific A tag representing an output component uses the `value` and `binding` attributes to bind its component's value or instance, respectively, to a data object. The `value` attribute is used more commonly than the `binding` attribute, and examples appear throughout this chapter. -For more information on these attributes, see <>, <>, and <>. +For more information on these attributes, see xref:jsf-develop/jsf-develop.adoc#_creating_a_managed_bean[Creating a Managed Bean], xref:jsf-develop/jsf-develop.adoc#_writing_properties_bound_to_component_values[Writing Properties Bound to Component Values], and xref:jsf-develop/jsf-develop.adoc#_writing_properties_bound_to_component_instances[Writing Properties Bound to Component Instances]. === Adding HTML Head and Body Tags @@ -248,17 +248,17 @@ The following is an example of an XHTML page using `h:head` and `h:body` tags: Both of the preceding example code segments render the same HTML elements. The head and body tags are useful mainly for resource relocation. -For more information on resource relocation, see <>. +For more information on resource relocation, see <<_resource_relocation_using_houtputscript_and_houtputstylesheet_tags>>. === Adding a Form Component An `h:form` tag represents an input form, which includes child components that can contain data that is either presented to the user or submitted with the form. -<> shows a typical login form in which a user enters a user name and password, then submits the form by clicking the Login button. +<<_a_typical_form>> shows a typical login form in which a user enters a user name and password, then submits the form by clicking the Login button. -[[a-typical-form]] +[[_a_typical_form]] .A Typical Form -image::jakartaeett_dt_065_frmcmpnt.svg["Form with User Name and Password text fields and a Login button."] +image::common:jakartaeett_dt_065_frmcmpnt.svg["Form with User Name and Password text fields and a Login button."] The `h:form` tag represents the form on the page and encloses all the components that display or collect data from the user, as shown here: @@ -285,11 +285,11 @@ The basic types of text components are as follows: * Password field, which is a type of field that displays a set of characters, such as asterisks, instead of the password text that the user enters -<> shows examples of these text components. +<<_example_text_components>> shows examples of these text components. -[[example-text-components]] +[[_example_text_components]] .Example Text Components -image::jakartaeett_dt_068_txtcmpnts.svg["A form. "User Name" labels a field. "Password" labels a password field. "Comments" labels a multi-line field."] +image::common:jakartaeett_dt_068_txtcmpnts.svg["A form. "User Name" labels a field. "Password" labels a password field. "Comments" labels a multi-line field."] Text components can be categorized as either input or output. A Jakarta Faces output component, such as a label, is rendered as read-only text. @@ -297,9 +297,9 @@ A Jakarta Faces input component, such as a field, is rendered as editable text. The input and output components can each be rendered in various ways to display more specialized text. -<> lists the tags that represent the input components. +<<_input_tags>> lists the tags that represent the input components. -[[input-tags]] +[[_input_tags]] .Input Tags [width="80%",cols="20%,60%"] |=== @@ -314,18 +314,18 @@ The input and output components can each be rendered in various ways to display |`h:inputTextarea` |The standard multiline field: accepts multiple lines of text |=== -The input tags support the tag attributes shown in <> in addition to those described in <>. +The input tags support the tag attributes shown in <<_input_tag_attributes>> in addition to those described in <<_common_component_tag_attributes>>. Note that this table does not include all the attributes supported by the input tags but just those that are used most often. For the complete list of attributes, refer to the https://jakarta.ee/specifications/faces/3.0/vdldoc/[Jakarta Faces Facelets Tag Library documentation^]. -[[input-tag-attributes]] +[[_input_tag_attributes]] .Input Tag Attributes [width="80%",cols="20%,60%"] |=== |Attribute |Description |`converter` |Identifies a converter that will be used to convert the component's local data. -See <> for more information on how to use this attribute. +See xref:jsf-page-core/jsf-page-core.adoc#_using_the_standard_converters[Using the Standard Converters] for more information on how to use this attribute. |`converterMessage` |Specifies an error message to display when the converter registered on the component fails. @@ -341,17 +341,17 @@ Acceptable values are `ltr`, meaning left to right, and `rtl`, meaning right to |`requiredMessage` |Specifies an error message to display when the user does not enter a value into the component. |`validator` |Identifies a method expression pointing to a managed bean method that performs validation on the component's data. -See <> for an example of using the `f:validator` tag. +See xref:jsf-page-core/jsf-page-core.adoc#_referencing_a_method_that_performs_validation[Referencing a Method That Performs Validation] for an example of using the `f:validator` tag. |`validatorMessage` |Specifies an error message to display when the validator registered on the component fails to validate the component's local value. |`valueChangeListener` |Identifies a method expression that points to a managed bean method that handles the event of entering a value in this component. -See <> for an example of using `valueChangeListener`. +See xref:jsf-page-core/jsf-page-core.adoc#_referencing_a_method_that_handles_a_value_change_event[Referencing a Method That Handles a Value-Change Event] for an example of using `valueChangeListener`. |=== -<> lists the tags that represent the output components. +<<_output_tags>> lists the tags that represent the output components. -[[output-tags]] +[[_output_tags]] .Output Tags [width="80%",cols="20%,60%"] |=== @@ -366,9 +366,9 @@ See <> for an example of |`h:outputText` |Displays a one-line text string |=== -The output tags support the `converter` tag attribute in addition to those listed in <>. +The output tags support the `converter` tag attribute in addition to those listed in <<_common_component_tag_attributes>>. -The rest of this section explains how to use some of the tags listed in <>. +The rest of this section explains how to use some of the tags listed in <<_output_tags>>. The other tags are written in a similar way. ==== Rendering a Field with the h:inputText Tag @@ -526,15 +526,15 @@ These tags are called command component tags because they perform an action when The `h:commandButton` tag is rendered as a button. The `h:commandLink` tag is rendered as a link. -In addition to the tag attributes listed in <>, the `h:commandButton` and `h:commandLink` tags can use the following attributes. +In addition to the tag attributes listed in <<_common_component_tag_attributes>>, the `h:commandButton` and `h:commandLink` tags can use the following attributes. * `action`, which is either a logical outcome `String` or a method expression pointing to a bean method that returns a logical outcome `String`. In either case, the logical outcome `String` is used to determine what page to access when the command component tag is activated. * `actionListener`, which is a method expression pointing to a bean method that processes an action event fired by the command component tag. -See <> for more information on using the `action` attribute. -See <> for details on using the `actionListener` attribute. +See xref:jsf-page-core/jsf-page-core.adoc#_referencing_a_method_that_performs_navigation[Referencing a Method That Performs Navigation] for more information on using the `action` attribute. +See xref:jsf-page-core/jsf-page-core.adoc#_referencing_a_method_that_handles_an_action_event[Referencing a Method That Handles an Action Event] for details on using the `actionListener` attribute. ==== Rendering a Button with the h:commandButton Tag @@ -551,7 +551,7 @@ Clicking the button will cause the `submit` method of `CashierBean` to be invoke The `submit` method performs some processing and returns a logical outcome. The `value` attribute of the example `h:commandButton` tag references the button's label. -For information on how to use the `action` attribute, see <>. +For information on how to use the `action` attribute, see xref:jsf-page-core/jsf-page-core.adoc#_referencing_a_method_that_performs_navigation[Referencing a Method That Performs Navigation]. ==== Rendering a Link with the h:commandLink Tag @@ -595,7 +595,7 @@ In a Jakarta Faces application, use the `h:graphicImage` tag to render an image In this example, the `url` attribute specifies the path to the image. The URL of the example tag begins with a slash (`/`), which adds the relative context path of the web application to the beginning of the path to the image. -Alternatively, you can use the facility described in <> to point to the image location. +Alternatively, you can use the facility described in xref:jsf-facelets/jsf-facelets.adoc#_web_resources[Web Resources] to point to the image location. Here are two examples: [source,xml] @@ -626,9 +626,9 @@ header { In a Jakarta Faces application, you use a panel as a layout container for a set of other components. A panel is rendered as an HTML table. -<> lists the tags used to create panels. +<<_panel_component_tags>> lists the tags used to create panels. -[[panel-component-tags]] +[[_panel_component_tags]] .Panel Component Tags [width="90%",cols="20%,50%,20%"] |=== @@ -707,9 +707,9 @@ Because the `h:panelGrid` tag specifies a `headerClass`, the `h:panelGrid` tag m The example `h:panelGrid` tag uses an `f:facet` tag for the header. Facets can have only one child, so an `h:panelGroup` tag is needed if you want to group more than one component within an `f:facet`. The example `h:panelGrid` tag has only one cell of data, so an `h:panelGroup` tag is not needed. -(For more information about facets, see <>. +(For more information about facets, see <<_using_data_bound_table_components>>. -The `h:panelGroup` tag has an attribute, `layout`, in addition to those listed in <>. +The `h:panelGroup` tag has an attribute, `layout`, in addition to those listed in <<_common_component_tag_attributes>>. If the `layout` attribute has the value `block`, an HTML `div` element is rendered to enclose the row; otherwise, an HTML `span` element is rendered to enclose the row. If you are specifying styles for the `h:panelGroup` tag, you should set the `layout` attribute to `block` in order for the styles to be applied to the components within the `h:panelGroup` tag. You should do this because styles, such as those that set width and height, are not applied to inline elements, which is how content enclosed by the `span` element is defined. @@ -734,11 +734,11 @@ The most common tags for this kind of component are as follows: * An `h:selectOneListbox` tag, displayed as an unscrollable list -<> shows examples of these components. +<<_example_components_for_selecting_one_item>> shows examples of these components. -[[example-components-for-selecting-one-item]] +[[_example_components_for_selecting_one_item]] .Example Components for Selecting One Item -image::jakartaeett_dt_067_slctn.svg["Options, check box, and lists."] +image::common:jakartaeett_dt_067_slctn.svg["Options, check box, and lists."] ==== Displaying a Check Box Using the h:selectBooleanCheckbox Tag @@ -788,7 +788,7 @@ You are not required to provide a value for the currently selected item. If you don't provide a value, the browser determines which one is selected. Like the `h:selectOneRadio` tag, the `h:selectOneMenu` tag must contain either an `f:selectItems` tag or a set of `f:selectItem` tags for representing the items in the list. -<> describes these tags. +<<_using_the_fselectitem_and_fselectitems_tags>> describes these tags. === Displaying Components for Selecting Multiple Values @@ -801,11 +801,11 @@ You can do this using one of the following component tags: * An `h:selectManyListbox` tag, displayed as a box -<> shows examples of these components. +<<_example_components_for_selecting_multiple_values>> shows examples of these components. -[[example-components-for-selecting-multiple-values]] +[[_example_components_for_selecting_multiple_values]] .Example Components for Selecting Multiple Values -image::jakartaeett_dt_066_slctmny.svg["Check box group, scrollable box, and unscrollable box."] +image::common:jakartaeett_dt_066_slctmny.svg["Check box group, scrollable box, and unscrollable box."] These tags allow the user to select zero or more values from a set of values. This section explains the `h:selectManyCheckbox` tag. @@ -868,7 +868,7 @@ The rest of this section shows you how to use the `f:selectItems` and `f:selectI ==== Using the f:selectItems Tag -The following example from <> shows how to use the `h:selectManyCheckbox` tag: +The following example from <<_displaying_components_for_selecting_multiple_values>> shows how to use the `h:selectManyCheckbox` tag: [source,xml] ---- @@ -882,12 +882,12 @@ The following example from <> for information on how to write a managed bean property for one of these tags. +See xref:jsf-develop/jsf-develop.adoc#_uiselectitems_properties[UISelectItems Properties] for information on how to write a managed bean property for one of these tags. ==== Using the f:selectItem Tag The `f:selectItem` tag represents a single item in a list of items. -Here is the example from <> once again: +Here is the example from <<_displaying_a_menu_using_the_hselectonemenu_tag>> once again: [source,xml] ---- @@ -913,7 +913,7 @@ These attributes can also define literal values, as shown in the example `h:sele If you display components that allow a user to select values, you may also want to display the result of the selection. -For example, you might want to thank a user who selected the checkbox to join the Duke Fan Club, as described in <>. +For example, you might want to thank a user who selected the checkbox to join the Duke Fan Club, as described in <<_displaying_a_check_box_using_the_hselectbooleancheckbox_tag>>. Because the checkbox is bound to the `specialOffer` property of `CashierBean`, a `UISelectBoolean` value, you can call the `isSelected` method of the property to determine whether to render a thank-you message: [source,xml] @@ -922,7 +922,7 @@ Because the checkbox is bound to the `specialOffer` property of `CashierBean`, a rendered="#{cashierBean.specialOffer.isSelected()}"/> ---- -Similarly, you might want to acknowledge that a user subscribed to newsletters using the `h:selectManyCheckbox` tag, as described in <>. +Similarly, you might want to acknowledge that a user subscribed to newsletters using the `h:selectManyCheckbox` tag, as described in <<_displaying_components_for_selecting_multiple_values>>. To do so, you can retrieve the value of the `newsletters` property, the `String` array that holds the selected items: [source,xml] @@ -938,7 +938,7 @@ To do so, you can retrieve the value of the `newsletters` property, the `String` An introductory thank-you message is displayed only if the `newsletters` array is not empty. Then a `ui:repeat` tag, a simple way to show values in a loop, displays the contents of the selected items in an itemized list. -(This tag is listed in <>.) +(This tag is listed in xref:jsf-facelets/jsf-facelets.adoc#_facelets_templating_tags[null].) === Using Data-Bound Table Components @@ -1038,7 +1038,7 @@ This data can take the form of any of the following: All data sources for data components have a `DataModel` wrapper. Unless you explicitly construct a `DataModel` wrapper, the Jakarta Faces implementation will create one around data of any of the other acceptable types. -See <> for more information on how to write properties for use with a data component. +See xref:jsf-develop/jsf-develop.adoc#_writing_bean_properties[Writing Bean Properties] for more information on how to write properties for use with a data component. The `var` attribute specifies a name that is used by the components within the `h:dataTable` tag as an alias to the data referenced in the `value` attribute of `h:dataTable`. @@ -1056,9 +1056,9 @@ For example, if you wanted to display records 2 through 10 of the underlying dat When you display a subset of the data in your pages, you might want to consider including a link or button that causes subsequent rows to display when clicked. By default, both `first` and `rows` are set to zero, and this causes all the rows of the underlying data to display. -<> shows the optional attributes for the `h:dataTable` tag. +<<_optional_attributes_for_the_hdatatable_tag>> shows the optional attributes for the `h:dataTable` tag. -[[optional-attributes-for-the-hdatatable-tag]] +[[_optional_attributes_for_the_hdatatable_tag]] .Optional Attributes for the h:dataTable Tag [width="60%",cols="30%,30%"] |=== @@ -1077,7 +1077,7 @@ By default, both `first` and `rows` are set to zero, and this causes all the row |`styleClass` |The entire table |=== -Each of the attributes in <> can specify more than one style. +Each of the attributes in <<_optional_attributes_for_the_hdatatable_tag>> can specify more than one style. If `columnClasses` or `rowClasses` specifies more than one style, the styles are applied to the columns or rows in the order that the styles are listed in the attribute. For example, if `columnClasses` specifies styles `list-column-center` and `list-column-right`, and if the table has two columns, the first column will have style `list-column-center`, and the second column will have style `list-column-right`. @@ -1224,10 +1224,10 @@ The order in which the various parameter values are read is as follows: === The bookmarks Example Application -The `bookmarks` example application modifies the `hello1` application described in <> to use a bookmarkable URL that uses view parameters. +The `bookmarks` example application modifies the `hello1` application described in xref:webapp/webapp.adoc#_a_web_module_that_uses_jakarta_faces_technology_the_hello1_example[A Web Module That Uses Jakarta Faces Technology: The hello1 Example] to use a bookmarkable URL that uses view parameters. Like `hello1`, the application includes the `Hello.java` managed bean, an `index.xhtml` page, and a `response.xhtml` page. -In addition, it includes a `personal.xhtml page`, to which a bookmarkable URL and view parameters are passed from the `response.xhtml` page, as described in <>. +In addition, it includes a `personal.xhtml page`, to which a bookmarkable URL and view parameters are passed from the `response.xhtml` page, as described in <<_using_view_parameters_to_configure_bookmarkable_urls>>. You can use either NetBeans IDE or Maven to build, package, deploy, and run the `bookmarks` example. The source code for this example is in the `_tut-install_/examples/web/jsf/bookmarks/` directory. diff --git a/src/main/antora/modules/web/pages/jsf-page/jsf-page003.adoc b/src/main/antora/modules/web/pages/jsf-page/jsf-page003.adoc index 7672b8f2..e76828fb 100644 --- a/src/main/antora/modules/web/pages/jsf-page/jsf-page003.adoc +++ b/src/main/antora/modules/web/pages/jsf-page/jsf-page003.adoc @@ -2,9 +2,9 @@ The tags included in the Jakarta Faces core tag library are used to perform core actions that are not performed by HTML tags. -<> lists the event-handling core tags. +<<_event_handling_core_tags>> lists the event-handling core tags. -[[event-handling-core-tags]] +[[_event_handling_core_tags]] .Event-Handling Core Tags [width="99%",cols="30%,70%"] |=== @@ -19,9 +19,9 @@ The tags included in the Jakarta Faces core tag library are used to perform core |`f:valueChangeListener` |Adds a value-change listener to a parent component |=== -<> lists the data-conversion core tags. +<<_data_conversion_core_tags>> lists the data-conversion core tags. -[[data-conversion-core-tags]] +[[_data_conversion_core_tags]] .Data-Conversion Core Tags [width="99%",cols="30%,70%"] |=== @@ -34,9 +34,9 @@ The tags included in the Jakarta Faces core tag library are used to perform core |`f:convertNumber` a|Adds a `NumberConverter` instance to the parent component |=== -<> lists the facet core tags. +<<_facet_core_tags>> lists the facet core tags. -[[facet-core-tags]] +[[_facet_core_tags]] .Facet Core Tags [width="99%",cols="30%,70%"] |=== @@ -48,9 +48,9 @@ its enclosing tag |`f:metadata` a|Registers a `facet` on a parent component |=== -<> lists the core tags that represent items in a list. +<<_core_tags_that_represent_items_in_a_list>> lists the core tags that represent items in a list. -[[core-tags-that-represent-items-in-a-list]] +[[_core_tags_that_represent_items_in_a_list]] .Core Tags That Represent Items in a List [width="99%",cols="30%,70%"] |=== @@ -61,9 +61,9 @@ its enclosing tag |`f:selectItems` |Represents a set of items |=== -<> lists the validator core tags. +<<_validator_core_tags>> lists the validator core tags. -[[validator-core-tags]] +[[_validator_core_tags]] .Validator Core Tags [width="99%",cols="30%,70%"] |=== @@ -84,9 +84,9 @@ its enclosing tag |`f:validateRequired` |Enforces the presence of a value in a component |=== -<> lists the core tags that fall into other categories. +<<_miscellaneous_core_tags>> lists the core tags that fall into other categories. -[[miscellaneous-core-tags]] +[[_miscellaneous_core_tags]] .Miscellaneous Core Tags [width="99%",cols="25%,15%,60%"] |=== @@ -107,31 +107,31 @@ its enclosing tag These tags, which are used in conjunction with component tags, are explained in other sections of this tutorial. -<> lists the sections that explain how to use specific core tags. +<<_where_the_core_tags_are_explained>> lists the sections that explain how to use specific core tags. -[[where-the-core-tags-are-explained]] +[[_where_the_core_tags_are_explained]] .Where the Core Tags Are Explained [width="99%",cols="30%,70%"] |=== |Tags |Where Explained -|Event-handling tags | <> +|Event-handling tags | xref:jsf-page-core/jsf-page-core.adoc#_registering_listeners_on_components[Registering Listeners on Components] -|Data-conversion tags | <> +|Data-conversion tags | xref:jsf-page-core/jsf-page-core.adoc#_using_the_standard_converters[Using the Standard Converters] -|`f:facet` |<> and <> +|`f:facet` |<<_using_data_bound_table_components>> and <<_laying_out_components_with_the_hpanelgrid_and_hpanelgroup_tags>> -|`f:loadBundle` | <> +|`f:loadBundle` | xref:webi18n/webi18n.adoc#_setting_the_resource_bundle[Setting the Resource Bundle] -|`f:metadata` | <> +|`f:metadata` | <<_using_view_parameters_to_configure_bookmarkable_urls>> -|`f:param` | <> +|`f:param` | <<_displaying_a_formatted_message_with_the_houtputformat_tag>> -|`f:selectItem` and `f:selectItems` | <> +|`f:selectItem` and `f:selectItems` | <<_using_the_fselectitem_and_fselectitems_tags>> -|Validator tags |<> +|Validator tags |xref:jsf-page-core/jsf-page-core.adoc#_using_the_standard_validators[Using the Standard Validators] -|`f:ajax` | xref:using-ajax-with-jakarta-faces-technology[xrefstyle=full] +|`f:ajax` | xref:jsf-ajax/jsf-ajax.adoc#_using_ajax_with_jakarta_faces_technology[Using Ajax with Jakarta Faces Technology] -|`f:websocket` | xref:using-websockets-with-jakarta-faces-technology[xrefstyle=full] +|`f:websocket` | xref:jsf-ws/jsf-ws.adoc#_using_websockets_with_jakarta_faces_technology[Using WebSockets with Jakarta Faces Technology] |=== diff --git a/src/main/antora/modules/web/pages/jsf-ws/jsf-ws003.adoc b/src/main/antora/modules/web/pages/jsf-ws/jsf-ws003.adoc index 50315b94..5418c341 100644 --- a/src/main/antora/modules/web/pages/jsf-ws/jsf-ws003.adoc +++ b/src/main/antora/modules/web/pages/jsf-ws/jsf-ws003.adoc @@ -1,8 +1,8 @@ == Using the f:websocket Tag -<> describes the attributes of the `f:websocket` tag. +<<_attributes_of_the_fwebsocket_tag>> describes the attributes of the `f:websocket` tag. -[[attributes-of-the-fwebsocket-tag]] +[[_attributes_of_the_fwebsocket_tag]] .Attributes of the `f:websocket` Tag [width="85%",cols="15%,15%,55%"] |=== diff --git a/src/main/antora/modules/web/pages/jsonb/jsonb.adoc b/src/main/antora/modules/web/pages/jsonb/jsonb.adoc index 09885888..adb0f567 100644 --- a/src/main/antora/modules/web/pages/jsonb/jsonb.adoc +++ b/src/main/antora/modules/web/pages/jsonb/jsonb.adoc @@ -2,7 +2,7 @@ This chapter describes the Jakarta JSON Binding. JSON is a data exchange format widely used in web services and other connected applications. -For a brief overview of JSON, see <>. +For a brief overview of JSON, see xref:jsonp/jsonp.adoc#_introduction_to_json[Introduction to JSON]. The https://jakarta.ee/specifications/jsonb/[Jakarta JSON Binding^] specification provides a standard binding layer (metadata and runtime) between Java classes and JSON documents. One Jakarta JSON Binding reference implementation is Yasson, which is developed through Eclipse.org and is included as part of GlassFish Server. diff --git a/src/main/antora/modules/web/pages/jsonb/jsonb001.adoc b/src/main/antora/modules/web/pages/jsonb/jsonb001.adoc index fc5db644..adda6847 100644 --- a/src/main/antora/modules/web/pages/jsonb/jsonb001.adoc +++ b/src/main/antora/modules/web/pages/jsonb/jsonb001.adoc @@ -4,7 +4,7 @@ Jakarta EE includes support for the Jakarta JSON Binding spec, which provides an Jakarta JSON Binding contains the following packages: * The `jakarta.json.bind` package contains the binding interface, the builder interface, and a configuration class. -<> lists the main classes and interfaces in this package. +<<_main_classes_and_interfaces_in_bind>> lists the main classes and interfaces in this package. * The `jakarta.json.bind.adapter` package contains the `JsonbAdapter` interface, which provides methods for binding custom Java types by converting them to known types. @@ -12,15 +12,15 @@ Jakarta JSON Binding contains the following packages: Annotations can be used for field, JavaBean property, type, or package elements. * The `jakarta.json.bind.config` package interfaces and classes for customizing default binding behavior. -<> lists the main classes and interfaces in this package. +<<_main_classes_and_interfaces_in_config>> lists the main classes and interfaces in this package. * The `jakarta.json.bind.serializer` package contains interfaces that are used to create serialization and deserialization routines for custom types that cannot be easily mapped using the `JsonbAdapter` methods. -<> lists the main interfaces in this package. +<<_main_classes_and_interfaces_in_serializer>> lists the main interfaces in this package. * The `jakarta.json.bind.spi` package contains a Service Provider Interface (SPI) for creating JSON Binding implementations. This package contains the `JsonbProvider` class, which contains the methods that a service provider implements. -[[main-classes-and-interfaces-in-bind]] +[[_main_classes_and_interfaces_in_bind]] .Main Classes and Interfaces in jakarta.json.bind [width="99%",cols="25%,75%"] |=== @@ -36,7 +36,7 @@ Properties include binding strategies and properties for configuring custom seri |`JsonbException` | Indicates that a problem occurred during JSON binding. |=== -[[main-classes-and-interfaces-in-config]] +[[_main_classes_and_interfaces_in_config]] .Main Classes and Interfaces in jakarta.json.bind.config [width="99%",cols="25%,75%"] |=== @@ -51,7 +51,7 @@ Properties include binding strategies and properties for configuring custom seri |`PropertyOrderStrategy` | Used to set how properties are ordered during serialization. |=== -[[main-classes-and-interfaces-in-serializer]] +[[_main_classes_and_interfaces_in_serializer]] .Main Classes and Interfaces in jakarta.json.bind.serializer [width="99%",cols="25%,75%"] |=== diff --git a/src/main/antora/modules/web/pages/jsonb/jsonb002.adoc b/src/main/antora/modules/web/pages/jsonb/jsonb002.adoc index 4bdb3a47..f64bf1ff 100644 --- a/src/main/antora/modules/web/pages/jsonb/jsonb002.adoc +++ b/src/main/antora/modules/web/pages/jsonb/jsonb002.adoc @@ -1,7 +1,7 @@ == Overview of the JSON Binding API This section provides basic instructions for using the Jakarta JSON Binding client API. -The instructions provide a basis for understanding the <>. +The instructions provide a basis for understanding the <<_running_the_jsonbbasics_example_application>>. Refer to the http://json-b.net/index.html[Jakarta JSON Binding^] project page for API documentation and a more detailed User Guide. === Creating a jasonb Instance diff --git a/src/main/antora/modules/web/pages/jsonp/jsonp001.adoc b/src/main/antora/modules/web/pages/jsonp/jsonp001.adoc index a8848516..409fd5df 100644 --- a/src/main/antora/modules/web/pages/jsonp/jsonp001.adoc +++ b/src/main/antora/modules/web/pages/jsonp/jsonp001.adoc @@ -72,4 +72,4 @@ Each element can be processed or discarded by the application code, and then the This approach is adequate for local processing, in which the processing of an element does not require information from the rest of the data. The streaming model generates JSON output to a given stream by making a function call with one element at a time. -There are many JSON generators and parsers available for different programming languages and environments. <> describes the functionality provided by Jakarta JSON Processing. +There are many JSON generators and parsers available for different programming languages and environments. <<_json_processing_in_the_jakarta_ee_platform>> describes the functionality provided by Jakarta JSON Processing. diff --git a/src/main/antora/modules/web/pages/jsonp/jsonp002.adoc b/src/main/antora/modules/web/pages/jsonp/jsonp002.adoc index 4a34338c..250862fd 100644 --- a/src/main/antora/modules/web/pages/jsonp/jsonp002.adoc +++ b/src/main/antora/modules/web/pages/jsonp/jsonp002.adoc @@ -1,20 +1,20 @@ == JSON Processing in the Jakarta EE Platform -Jakarta EE includes support for the Jakarta JSON Processing spec, which provides an API to parse, transform, and query JSON data using the object model or the streaming model described in <>. +Jakarta EE includes support for the Jakarta JSON Processing spec, which provides an API to parse, transform, and query JSON data using the object model or the streaming model described in <<_generating_and_parsing_json_data>>. Jakarta JSON Processing contains the following packages: * The `jakarta.json` package contains a reader interface, a writer interface, a model builder interface for the object model, and utility classes and Java types for JSON elements. This package also includes several classes that implement other JSON-related standards: https://tools.ietf.org/html/rfc6901[JSON Pointer^], https://tools.ietf.org/html/rfc6902[JSON Patch^], and https://tools.ietf.org/html/rfc7396[JSON Merge Patch^]. These standards are used to retrieve, transform or manipulate values in an object model. -<> lists the main classes and interfaces in this package. +<<_main_classes_and_interfaces_in_jakarta.json>> lists the main classes and interfaces in this package. * The `jakarta.json.stream` package contains a parser interface and a generator interface for the streaming model. -<> lists the main classes and interfaces in this package. +<<_main_classes_and_interfaces_in_jakarta.json.stream>> lists the main classes and interfaces in this package. * The `jakarta.json.spi` package contains a Service Provider Interface (SPI) to plug in implementations for JSON processing objects. This package contains the `JsonProvider` class, which contains the methods that a service provider implements. -[[main-classes-and-interfaces-in-jakarta.json]] +[[_main_classes_and_interfaces_in_jakarta.json]] .Main Classes and Interfaces in jakarta.json [width=99%,cols="25%,75%"] |=== @@ -52,7 +52,7 @@ These two interfaces are subtypes of `JsonValue`. |`JsonException` | Indicates that a problem occurred during JSON processing. |=== -[[main-classes-and-interfaces-in-jakarta.json.stream]] +[[_main_classes_and_interfaces_in_jakarta.json.stream]] .Main Classes and Interfaces in jakarta.json.stream [width=99%,cols="25%,75%"] |=== diff --git a/src/main/antora/modules/web/pages/jsonp/jsonp003.adoc b/src/main/antora/modules/web/pages/jsonp/jsonp003.adoc index 2123ce33..e137650e 100644 --- a/src/main/antora/modules/web/pages/jsonp/jsonp003.adoc +++ b/src/main/antora/modules/web/pages/jsonp/jsonp003.adoc @@ -69,7 +69,7 @@ JsonObjectBuilder addNull(String name) The `JsonArrayBuilder` class contains similar `add` methods that do not have a name (key) parameter. You can nest arrays and objects by passing a new `JsonArrayBuilder` object or a new `JsonObjectBuilder` object to the corresponding `add` method, as shown in this example. -The resulting tree represents the JSON data from <>. +The resulting tree represents the JSON data from <<_json_syntax>>. === Navigating an Object Model @@ -116,7 +116,7 @@ public static void navigateTree(JsonValue tree, String key) { } ---- -The method `navigateTree` can be used with the models built in <> and <> as follows: +The method `navigateTree` can be used with the models built in <<_creating_an_object_model_from_json_data>> and <<_creating_an_object_model_from_application_code>> as follows: [source,java] ---- @@ -134,7 +134,7 @@ For objects, the `JsonObject.keySet` method returns a set of strings that contai For arrays, `JsonArray` implements the `List` interface. You can use enhanced `for` loops with the `Set` instance returned by `JsonObject.keySet` and with instances of `JsonArray`, as shown in this example. -The `navigateTree` method for the model built in <> produces the following output: +The `navigateTree` method for the model built in <<_creating_an_object_model_from_application_code>> produces the following output: ---- OBJECT @@ -156,7 +156,7 @@ OBJECT === Writing an Object Model to a Stream -The object models created in <> and <> can be written to a stream using the `JsonWriter` class as follows: +The object models created in <<_creating_an_object_model_from_json_data>> and <<_creating_an_object_model_from_application_code>> can be written to a stream using the `JsonWriter` class as follows: [source,java] ---- diff --git a/src/main/antora/modules/web/pages/jsonp/jsonp005.adoc b/src/main/antora/modules/web/pages/jsonp/jsonp005.adoc index 35dc28cb..8a57d522 100644 --- a/src/main/antora/modules/web/pages/jsonp/jsonp005.adoc +++ b/src/main/antora/modules/web/pages/jsonp/jsonp005.adoc @@ -1,9 +1,9 @@ == JSON in Jakarta EE RESTful Web Services This section explains how the Jakarta JSON Processing is related to other Jakarta EE packages that provide JSON support for RESTful web services. -See xref:building-restful-web-services-with-jakarta-rest[xrefstyle=full] for more information on RESTful web services. +See xref:building-restful-web-services-with-jakarta-rest[] for more information on RESTful web services. -Jersey, the Jakarta RESTful Web Services implementation included in GlassFish Server, provides support for binding JSON data from RESTful resource methods to Java objects using Jakarta XML Binding, as described in <> in xref:jakarta-rest-advanced-topics-and-an-example[xrefstyle=full]. +Jersey, the Jakarta RESTful Web Services implementation included in GlassFish Server, provides support for binding JSON data from RESTful resource methods to Java objects using Jakarta XML Binding, as described in <> in xref:jakarta-rest-advanced-topics-and-an-example[]. However, JSON support is not part of Jakarta RESTful Web Services or Jakarta XML Binding, so that procedure may not work for Jakarta EE implementations other than GlassFish Server. You can still use the Jakarta JSON Processing with Jakarta RESTful Web Services resource methods. diff --git a/src/main/antora/modules/web/pages/jsonp/jsonp006.adoc b/src/main/antora/modules/web/pages/jsonp/jsonp006.adoc index 84e92bb0..f250ee57 100644 --- a/src/main/antora/modules/web/pages/jsonp/jsonp006.adoc +++ b/src/main/antora/modules/web/pages/jsonp/jsonp006.adoc @@ -20,9 +20,9 @@ The `jsonpmodel` example application contains the following files. * The `ObjectModelBean.java` managed bean, which is a session-scoped managed bean that stores the data from the form and directs the navigation between the Facelets pages. This file also contains code that uses the JSON object model API. -The code used in `ObjectModelBean.java` to create an object model from the data in the form is similar to the example in <>. -The code to write JSON output from the model is similar to the example in <>. -The code to navigate the object model tree is similar to the example in <>. +The code used in `ObjectModelBean.java` to create an object model from the data in the form is similar to the example in <<_creating_an_object_model_from_application_code>>. +The code to write JSON output from the model is similar to the example in <<_writing_an_object_model_to_a_stream>>. +The code to navigate the object model tree is similar to the example in <<_navigating_an_object_model>>. === Running the jsonpmodel Example Application diff --git a/src/main/antora/modules/web/pages/jsonp/jsonp007.adoc b/src/main/antora/modules/web/pages/jsonp/jsonp007.adoc index 928c4881..c5ccc9c2 100644 --- a/src/main/antora/modules/web/pages/jsonp/jsonp007.adoc +++ b/src/main/antora/modules/web/pages/jsonp/jsonp007.adoc @@ -20,8 +20,8 @@ The `jsonpstreaming` example application contains the following files. * The `StreamingBean.java` managed bean, a session-scoped managed bean that stores the data from the form and directs the navigation between the Facelets pages. This file also contains code that uses the JSON streaming API. -The code used in `StreamingBean.java` to write JSON data to a file is similar to the example in <>. -The code to parse JSON data from a file is similar to the example in <>. +The code used in `StreamingBean.java` to write JSON data to a file is similar to the example in <<_writing_json_data_using_a_generator>>. +The code to parse JSON data from a file is similar to the example in <<_reading_json_data_using_a_parser>>. === Running the jsonpstreaming Example Application diff --git a/src/main/antora/modules/web/pages/servlets/servlets002.adoc b/src/main/antora/modules/web/pages/servlets/servlets002.adoc index 42747fee..1acce945 100644 --- a/src/main/antora/modules/web/pages/servlets/servlets002.adoc +++ b/src/main/antora/modules/web/pages/servlets/servlets002.adoc @@ -9,13 +9,13 @@ When a request is mapped to a servlet, the container performs the following step .. Creates an instance of the servlet class -.. Initializes the servlet instance by calling the `init` method (initialization is covered in <>) +.. Initializes the servlet instance by calling the `init` method (initialization is covered in <<_creating_and_initializing_a_servlet>>) . The container invokes the `service` method, passing request and response objects. -Service methods are discussed in <>. +Service methods are discussed in <<_writing_service_methods>>. If it needs to remove the servlet, the container finalizes the servlet by calling the servlet's `destroy` method. -For more information, see <>. +For more information, see <<_finalizing_a_servlet>>. === Handling Servlet Lifecycle Events @@ -25,11 +25,11 @@ To use these listener objects, you must define and specify the listener class. ==== Defining the Listener Class You define a listener class as an implementation of a listener interface. -<> lists the events that can be monitored and the corresponding interface that must be implemented. +<<_servlet_lifecycle_events>> lists the events that can be monitored and the corresponding interface that must be implemented. When a listener method is invoked, it is passed an event that contains information appropriate to the event. For example, the methods in the `HttpSessionListener` interface are passed an `HttpSessionEvent`, which contains an `HttpSession`. -[[servlet-lifecycle-events]] +[[_servlet_lifecycle_events]] .Servlet Lifecycle Events [width="90%",cols="15%,30%,45%"] |=== diff --git a/src/main/antora/modules/web/pages/servlets/servlets003.adoc b/src/main/antora/modules/web/pages/servlets/servlets003.adoc index 3b94f985..2afc0147 100644 --- a/src/main/antora/modules/web/pages/servlets/servlets003.adoc +++ b/src/main/antora/modules/web/pages/servlets/servlets003.adoc @@ -10,25 +10,25 @@ Web components can do so by doing the following. * Using a database. * Invoking other web resources. -The Jakarta Servlet technology mechanisms that allow a web component to invoke other web resources are described in <>. +The Jakarta Servlet technology mechanisms that allow a web component to invoke other web resources are described in <<_invoking_other_web_resources>>. === Using Scope Objects Collaborating web components share information by means of objects that are maintained as attributes of four scope objects. You access these attributes by using the `getAttribute` and `setAttribute` methods of the class representing the scope. -<> lists the scope objects. +<<_scope_objects>> lists the scope objects. -[[scope-objects]] +[[_scope_objects]] .Scope Objects [width="90%",cols="15%,25%,50%"] |=== |Scope Object |Class |Accessible From |Web context |`jakarta.servlet.ServletContext` |Web components within a web context. -See <>. +See <<_accessing_the_web_context>>. |Session |`jakarta.servlet.http.HttpSession` |Web components handling a request that belongs to the session. -See <>. +See <<_maintaining_client_state>>. |Request |Subtype of `jakarta.servlet.ServletRequest` |Web components handling the request. diff --git a/src/main/antora/modules/web/pages/servlets/servlets005.adoc b/src/main/antora/modules/web/pages/servlets/servlets005.adoc index 92021f08..c2e7f301 100644 --- a/src/main/antora/modules/web/pages/servlets/servlets005.adoc +++ b/src/main/antora/modules/web/pages/servlets/servlets005.adoc @@ -82,11 +82,11 @@ Buffering allows content to be written before anything is sent back to the clien The method must be called before any content is written or before the response is committed. * Set localization information, such as locale and character encoding. -See xref:internationalizing-and-localizing-web-applications[xrefstyle=full] for details. +See xref:webi18n/webi18n.adoc#_internationalizing_and_localizing_web_applications[Internationalizing and Localizing Web Applications] for details. HTTP response objects, `jakarta.servlet.http.HttpServletResponse`, have fields representing HTTP headers, such as the following. * Status codes, which are used to indicate the reason a request is not satisfied or that a request has been redirected. * Cookies, which are used to store application-specific information at the client. -Sometimes, cookies are used to maintain an identifier for tracking a user's session (see <>). +Sometimes, cookies are used to maintain an identifier for tracking a user's session (see <<_session_tracking>>). diff --git a/src/main/antora/modules/web/pages/servlets/servlets006.adoc b/src/main/antora/modules/web/pages/servlets/servlets006.adoc index 90eed15f..bc3bc6ac 100644 --- a/src/main/antora/modules/web/pages/servlets/servlets006.adoc +++ b/src/main/antora/modules/web/pages/servlets/servlets006.adoc @@ -104,11 +104,11 @@ You specify a filter mapping list for a WAR in its deployment descriptor by eith If you want to log every request to a web application, you map the hit counter filter to the URL pattern `/*`. You can map a filter to one or more web resources, and you can map more than one filter to a web resource. -This is illustrated in <>, in which filter F1 is mapped to servlets S1, S2, and S3; filter F2 is mapped to servlet S2; and filter F3 is mapped to servlets S1 and S2. +This is illustrated in <<_filter_to_servlet_mapping>>, in which filter F1 is mapped to servlets S1, S2, and S3; filter F2 is mapped to servlet S2; and filter F3 is mapped to servlets S1 and S2. -[[filter-to-servlet-mapping]] +[[_filter_to_servlet_mapping]] .Filter-to-Servlet Mapping -image::jakartaeett_dt_018.svg["Diagram of filter-to-servlet mapping with filters F1-F3 and servlets S1-S3. F1 filters S1-S3, then F2 filters S2, then F3 filters S1 and S2."] +image::common:jakartaeett_dt_018.svg["Diagram of filter-to-servlet mapping with filters F1-F3 and servlets S1-S3. F1 filters S1-S3, then F2 filters S2, then F3 filters S1 and S2."] Recall that a filter chain is one of the objects passed to the `doFilter` method of a filter. This chain is formed indirectly by means of filter mappings. @@ -157,11 +157,11 @@ REQUEST:: Only when the request comes directly from the client ASYNC:: Only when the asynchronous request comes from the client -FORWARD:: Only when the request has been forwarded to a component (see <>) +FORWARD:: Only when the request has been forwarded to a component (see <<_transferring_control_to_another_web_component>>) -INCLUDE:: Only when the request is being processed by a component that has been included (see <>) +INCLUDE:: Only when the request is being processed by a component that has been included (see <<_including_other_resources_in_the_response>>) -ERROR:: Only when the request is being processed with the error page mechanism (see <>) +ERROR:: Only when the request is being processed with the error page mechanism (see <<_handling_servlet_errors>>) You can direct the filter to be applied to any combination of the preceding situations by selecting multiple dispatcher types. If no types are specified, the default option is *REQUEST*. diff --git a/src/main/antora/modules/web/pages/servlets/servlets009.adoc b/src/main/antora/modules/web/pages/servlets/servlets009.adoc index cd9a3d69..d7e5342e 100644 --- a/src/main/antora/modules/web/pages/servlets/servlets009.adoc +++ b/src/main/antora/modules/web/pages/servlets/servlets009.adoc @@ -16,7 +16,7 @@ This method returns the current session associated with this request; or, if the You can associate object-valued attributes with a session by name. Such attributes are accessible by any web component that belongs to the same web context and is handling a request that is part of the same session. -Recall that your application can notify web context and session listener objects of servlet lifecycle events (<>). +Recall that your application can notify web context and session listener objects of servlet lifecycle events (<<_handling_servlet_lifecycle_events>>). You can also notify objects of certain events related to their association with a session, such as the following. * When the object is added to or removed from a session. diff --git a/src/main/antora/modules/web/pages/servlets/servlets012.adoc b/src/main/antora/modules/web/pages/servlets/servlets012.adoc index ea13d171..35766a9f 100644 --- a/src/main/antora/modules/web/pages/servlets/servlets012.adoc +++ b/src/main/antora/modules/web/pages/servlets/servlets012.adoc @@ -45,9 +45,9 @@ public void doGet(HttpServletRequest req, HttpServletResponse resp) { This call puts the request into asynchronous mode and ensures that the response is not committed after exiting the service method. You have to generate the response in the asynchronous context after the blocking operation completes or dispatch the request to another servlet. -<> describes the basic functionality provided by the `AsyncContext` class. +<<_functionality_provided_by_the_asynccontext_class>> describes the basic functionality provided by the `AsyncContext` class. -[[functionality-provided-by-the-asynccontext-class]] +[[_functionality_provided_by_the_asynccontext_class]] .Functionality Provided by the AsyncContext Class [width="90%",cols="20%,70%"] |=== diff --git a/src/main/antora/modules/web/pages/servlets/servlets013.adoc b/src/main/antora/modules/web/pages/servlets/servlets013.adoc index 17d58527..72f8b555 100644 --- a/src/main/antora/modules/web/pages/servlets/servlets013.adoc +++ b/src/main/antora/modules/web/pages/servlets/servlets013.adoc @@ -2,7 +2,7 @@ Web containers in application servers normally use a server thread per client request. To develop scalable web applications, you must ensure that threads associated with client requests are never sitting idle waiting for a blocking operation to complete. -<> provides a mechanism to execute application-specific blocking operations in a new thread, returning the thread associated with the request immediately to the container. +<<_asynchronous_processing>> provides a mechanism to execute application-specific blocking operations in a new thread, returning the thread associated with the request immediately to the container. Even if you use asynchronous processing for all the application-specific blocking operations inside your service methods, threads associated with client requests can be momentarily sitting idle because of input/output considerations. For example, if a client is submitting a large HTTP POST request over a slow network connection, the server can read the request faster than the client can provide it. @@ -11,7 +11,7 @@ Using traditional I/O, the container thread associated with this request would b Jakarta EE provides nonblocking I/O support for servlets and filters when processing requests in asynchronous mode. The following steps summarize how to use nonblocking I/O to process requests and write responses inside service methods. -. Put the request in asynchronous mode as described in <>. +. Put the request in asynchronous mode as described in <<_asynchronous_processing>>. . Obtain an input stream and/or an output stream from the request and response objects in the service method. @@ -19,10 +19,10 @@ The following steps summarize how to use nonblocking I/O to process requests and . Process the request and the response inside the listener's callback methods. -<> describe the methods available in the servlet input and output streams for nonblocking I/O support. -<> describes the interfaces for read listeners and write listeners. +<<_nonblocking_io_support_in_servletoutputstream>> describe the methods available in the servlet input and output streams for nonblocking I/O support. +<<_listener_interfaces_for_nonblocking_io_support>> describes the interfaces for read listeners and write listeners. -[[nonblocking-io-support-in-servletinputstream]] +[[_nonblocking_io_support_in_servletinputstream]] .Nonblocking I/O Support in jakarta.servlet.ServletInputStream [width="100%",cols="50%,50%"] |=== @@ -36,7 +36,7 @@ You provide the listener object as an anonymous class or use another mechanism t |`boolean isFinished()` |Returns true when all the data has been read. |=== -[[nonblocking-io-support-in-servletoutputstream]] +[[_nonblocking_io_support_in_servletoutputstream]] .Nonblocking I/O Support in jakarta.servlet.ServletOutputStream [width="100%",cols="50%,50%"] |=== @@ -48,7 +48,7 @@ You provide the write listener object as an anonymous class or use another mecha |`boolean isReady()` |Returns true if data can be written without blocking. |=== -[[listener-interfaces-for-nonblocking-io-support]] +[[_listener_interfaces_for_nonblocking_io_support]] .Listener Interfaces for Nonblocking I/O Support [width="100%",cols="20%,30%,50%"] |=== @@ -67,7 +67,7 @@ You provide the write listener object as an anonymous class or use another mecha === Reading a Large HTTP POST Request Using Nonblocking I/O -The code in this section shows how to read a large HTTP POST request inside a servlet by putting the request in asynchronous mode (as described in <>) and using the nonblocking I/O functionality from <> and <>. +The code in this section shows how to read a large HTTP POST request inside a servlet by putting the request in asynchronous mode (as described in <<_asynchronous_processing>>) and using the nonblocking I/O functionality from <<_nonblocking_io_support_in_servletinputstream>> and <<_listener_interfaces_for_nonblocking_io_support>>. [source,java] ---- diff --git a/src/main/antora/modules/web/pages/servlets/servlets014.adoc b/src/main/antora/modules/web/pages/servlets/servlets014.adoc index cea2939e..26e416ac 100644 --- a/src/main/antora/modules/web/pages/servlets/servlets014.adoc +++ b/src/main/antora/modules/web/pages/servlets/servlets014.adoc @@ -29,9 +29,9 @@ OtherHeaderB: Value (XYZP data) ---- -Jakarta EE supports the HTTP protocol upgrade functionality in servlets, as described in <>. +Jakarta EE supports the HTTP protocol upgrade functionality in servlets, as described in <<_protocol_upgrade_support>>. -[[protocol-upgrade-support]] +[[_protocol_upgrade_support]] .Protocol Upgrade Support [width="80%",cols="20%,60%"] |=== diff --git a/src/main/antora/modules/web/pages/servlets/servlets017.adoc b/src/main/antora/modules/web/pages/servlets/servlets017.adoc index f7676c83..fc9a5cf9 100644 --- a/src/main/antora/modules/web/pages/servlets/servlets017.adoc +++ b/src/main/antora/modules/web/pages/servlets/servlets017.adoc @@ -132,7 +132,7 @@ public class PriceVolumeBean { } ---- -See <> in xref:running-the-enterprise-bean-examples[xrefstyle=full] for more information on the timer service. +See <> in xref:running-the-enterprise-bean-examples[] for more information on the timer service. ==== The HTML Page @@ -183,7 +183,7 @@ function makeAjaxRequest() { The `XMLHttpRequest` API is supported by most modern browsers, and it is widely used in Ajax web client development (Asynchronous JavaScript and XML). -See <> in xref:jakarta-websocket-2[xrefstyle=full] for an equivalent version of this example implemented using a WebSocket endpoint. +See xref:websocket/websocket.adoc#_the_dukeetf2_example_application[The dukeetf2 Example Application] in xref:jakarta-websocket-2[] for an equivalent version of this example implemented using a WebSocket endpoint. === Running the dukeetf Example Application diff --git a/src/main/antora/modules/web/pages/webapp/webapp001.adoc b/src/main/antora/modules/web/pages/webapp/webapp001.adoc index e7325a6c..f79878e5 100644 --- a/src/main/antora/modules/web/pages/webapp/webapp001.adoc +++ b/src/main/antora/modules/web/pages/webapp/webapp001.adoc @@ -5,12 +5,12 @@ Web applications are of the following types: Presentation-oriented:: A presentation-oriented web application generates interactive web pages containing various types of markup language (HTML, XHTML, XML, and so on) and dynamic content in response to requests. -Development of presentation-oriented web applications is covered in xref:jakarta-faces-technology-2[xrefstyle=full] through xref:jakarta-servlet-technology-2[xrefstyle=full] +Development of presentation-oriented web applications is covered in xref:jakarta-faces-technology-2[] through xref:jakarta-servlet-technology-2[] Service-oriented:: A service-oriented web application implements the endpoint of a web service. Presentation-oriented applications are often clients of service-oriented web applications. -Development of service-oriented web applications is covered in xref:building-web-services-with-jakarta-xml-web-services[xrefstyle=full] and xref:building-restful-web-services-with-jakarta-rest[xrefstyle=full] in xref:web-services[xrefstyle=full] +Development of service-oriented web applications is covered in xref:building-web-services-with-jakarta-xml-web-services[] and xref:building-restful-web-services-with-jakarta-rest[] in xref:web-services[] In the Jakarta EE platform, web components provide the dynamic extension capabilities for a web server. Web components can be Jakarta servlets, web pages implemented with Jakarta Faces technology, web service endpoints, or Jakarta Server Pages. @@ -22,9 +22,9 @@ The web component can then generate an `HTTPServletResponse` or can pass the req A web component eventually generates a `HTTPServletResponse` object. The web server converts this object to an HTTP response and returns it to the client. -[[jakarta-web-application-request-handling]] +[[_jakarta_web_application_request_handling]] .Jakarta Web Application Request Handling -image::jakartaeett_dt_013.svg["Diagram of web application request handling. Clients and servlets communicate using HttpServletRequest and HttpServletResponse."] +image::common:jakartaeett_dt_013.svg["Diagram of web application request handling. Clients and servlets communicate using HttpServletRequest and HttpServletResponse."] Servlets are Java programming language classes that dynamically process requests and construct responses. Java technologies, such as Jakarta Faces and Facelets, are used for building interactive web applications. diff --git a/src/main/antora/modules/web/pages/webapp/webapp003.adoc b/src/main/antora/modules/web/pages/webapp/webapp003.adoc index 783911f3..7255b6fb 100644 --- a/src/main/antora/modules/web/pages/webapp/webapp003.adoc +++ b/src/main/antora/modules/web/pages/webapp/webapp003.adoc @@ -97,7 +97,7 @@ The response page appears.Even simpler than the greeting page, the response page . Expand the Source Packages node, then the `ee.jakarta.tutorial.hello1` node. -. [[hello1-nb-step-7, Step 7]] Double-click the `Hello.java` file to view it. +. [[_hello1_nb_step_7, Step 7]] Double-click the `Hello.java` file to view it. + The `Hello` class, called a managed bean class, provides getter and setter methods for the `name` property used in the Facelets page expressions. By default, the expression language refers to the class name, with the first letter in lowercase (`hello.name`). @@ -191,7 +191,7 @@ When an application consists of multiple requests and responses where data needs Application (`@ApplicationScoped`):: Application scope persists across all users' interactions with a web application. -For more information on scopes in Jakarta Faces technology, see <>. +For more information on scopes in Jakarta Faces technology, see xref:jsf-configure/jsf-configure.adoc#_using_managed_bean_scopes[Using Managed Bean Scopes]. === Packaging and Deploying the hello1 Web Module diff --git a/src/main/antora/modules/web/pages/webapp/webapp005.adoc b/src/main/antora/modules/web/pages/webapp/webapp005.adoc index 1dda42fa..22b0f7c8 100644 --- a/src/main/antora/modules/web/pages/webapp/webapp005.adoc +++ b/src/main/antora/modules/web/pages/webapp/webapp005.adoc @@ -15,7 +15,7 @@ This section describes the following tasks involved with configuring web applica The web components in a web module share an object that represents their application context. You can pass context parameters to the context, or you can pass initialization parameters to a servlet. Context parameters are available to the entire application. -For information on initialization parameters, see <>. +For information on initialization parameters, see xref:servlets/servlets.adoc#_creating_and_initializing_a_servlet[Creating and Initializing a Servlet]. ==== To Add a Context Parameter Using NetBeans IDE @@ -139,11 +139,11 @@ However, managed beans are managed by the container; therefore, they can accept Components that can accept resource injections are listed in xref:web-components-that-accept-resource-injections[xrefstyle=short]. This section explains how to use a couple of the annotations supported by a web container to inject resources. -xref:running-the-persistence-examples[xrefstyle=full], explains how web applications use annotations supported by Jakarta Persistence. -xref:getting-started-securing-web-applications[xrefstyle=full], explains how to use annotations to specify information about securing web applications. -See xref:resource-adapters-and-contracts[xrefstyle=full], for more information on resources. +xref:running-the-persistence-examples[], explains how web applications use annotations supported by Jakarta Persistence. +xref:getting-started-securing-web-applications[], explains how to use annotations to specify information about securing web applications. +See xref:resource-adapters-and-contracts[], for more information on resources. -[[web-components-that-accept-resource-injections]] +[[_web_components_that_accept_resource_injections]] .Web Components That Accept Resource Injections [width="50%",cols="20%,30%"] |=== diff --git a/src/main/antora/modules/web/pages/webi18n/webi18n001.adoc b/src/main/antora/modules/web/pages/webi18n/webi18n001.adoc index a99bd741..ac8c03be 100644 --- a/src/main/antora/modules/web/pages/webi18n/webi18n001.adoc +++ b/src/main/antora/modules/web/pages/webi18n/webi18n001.adoc @@ -9,7 +9,7 @@ A resource bundle contains key-value pairs, where the keys uniquely identify a l A resource bundle can be backed by a text file (properties resource bundle) or a class (list resource bundle) containing the pairs. You construct a resource bundle instance by appending a locale string representation to a base name. -The Duke's Bookstore application (see xref:dukes-bookstore-case-study-example[xrefstyle=full]) contains resource bundles with the base name `messages.properties` for the locales `de` (German), `es` (Spanish), and `fr` (French). +The Duke's Bookstore application (see xref:dukes-bookstore-case-study-example[]) contains resource bundles with the base name `messages.properties` for the locales `de` (German), `es` (Spanish), and `fr` (French). The default locale, `en` (English), which is specified in the `faces-config.xml` file, uses the resource bundle with the base name, `messages.properties`. For more details on internationalization and localization in the Java platform, see https://docs.oracle.com/javase/tutorial/i18n/index.html[^]. diff --git a/src/main/antora/modules/web/pages/webi18n/webi18n002.adoc b/src/main/antora/modules/web/pages/webi18n/webi18n002.adoc index 2922db3e..4ac4e5ee 100644 --- a/src/main/antora/modules/web/pages/webi18n/webi18n002.adoc +++ b/src/main/antora/modules/web/pages/webi18n/webi18n002.adoc @@ -70,7 +70,7 @@ The setting for Duke's Bookstore looks like this: ---- -After the locale is set, the controller of a web application could retrieve the resource bundle for that locale and save it as a session attribute (see <>) for use by other components or simply be used to return a text string appropriate for the selected locale: +After the locale is set, the controller of a web application could retrieve the resource bundle for that locale and save it as a session attribute (see xref:servlets/servlets.adoc#_associating_objects_with_a_session[Associating Objects with a Session]) for use by other components or simply be used to return a text string appropriate for the selected locale: [source,java] ---- @@ -93,7 +93,7 @@ This tag loads the correct resource bundle according to the locale stored in `Fa Resource bundles containing messages that are explicitly referenced from a Jakarta Faces tag attribute using a value expression must be registered using the `resource-bundle` element of the configuration file. -For more information on using this element, see <>. +For more information on using this element, see xref:jsf-configure/jsf-configure.adoc#_registering_application_messages[Registering Application Messages]. === Retrieving Localized Messages @@ -124,7 +124,7 @@ The following example shows a `message` tag that displays the error message queu id="errors1" for="userNo"/> ---- -For more information on using the `message` or `messages` tags, see <>. +For more information on using the `message` or `messages` tags, see xref:jsf-page/jsf-page.adoc#_displaying_error_messages_with_the_hmessage_and_hmessages_tags[Displaying Error Messages with the h:message and h:messages Tags]. Messages that are not queued on a component and are therefore not loaded automatically are referenced using a value expression. You can reference a localized message from almost any Jakarta Faces tag attribute. diff --git a/src/main/antora/modules/web/pages/webi18n/webi18n003.adoc b/src/main/antora/modules/web/pages/webi18n/webi18n003.adoc index 00dda76a..9d67eda5 100644 --- a/src/main/antora/modules/web/pages/webi18n/webi18n003.adoc +++ b/src/main/antora/modules/web/pages/webi18n/webi18n003.adoc @@ -13,4 +13,4 @@ For example, a shipping date could be converted as follows: ---- -For information on Jakarta Faces converters, see <>. +For information on Jakarta Faces converters, see xref:jsf-page-core/jsf-page-core.adoc#_using_the_standard_converters[Using the Standard Converters]. diff --git a/src/main/antora/modules/web/pages/websocket/websocket004.adoc b/src/main/antora/modules/web/pages/websocket/websocket004.adoc index c1308776..e6d4ba64 100644 --- a/src/main/antora/modules/web/pages/websocket/websocket004.adoc +++ b/src/main/antora/modules/web/pages/websocket/websocket004.adoc @@ -1,6 +1,6 @@ == Annotated Endpoints -The following example shows how to create the same endpoint from <> using annotations instead: +The following example shows how to create the same endpoint from <<_programmatic_endpoints>> using annotations instead: [source,java] ---- @@ -18,11 +18,11 @@ public class EchoEndpoint { The annotated endpoint is simpler than the equivalent programmatic endpoint, and it is deployed automatically with the application to the relative path defined in the `ServerEndpoint` annotation. Instead of having to create an additional class for the message handler, this example uses the `OnMessage` annotation to designate the method invoked to handle messages. -<> lists the annotations available in the `jakarta.websocket` package to designate the methods that handle lifecycle events. +<<_websocket_endpoint_lifecycle_annotations>> lists the annotations available in the `jakarta.websocket` package to designate the methods that handle lifecycle events. The examples in the table show the most common parameters for these methods. See the API reference for details on what combinations of parameters are allowed in each case. -[[websocket-endpoint-lifecycle-annotations]] +[[_websocket_endpoint_lifecycle_annotations]] .WebSocket Endpoint Lifecycle Annotations [width="80%",cols="20%,20%,60%"] |=== diff --git a/src/main/antora/modules/web/pages/websocket/websocket005.adoc b/src/main/antora/modules/web/pages/websocket/websocket005.adoc index 0cbb9ede..ccc5031b 100644 --- a/src/main/antora/modules/web/pages/websocket/websocket005.adoc +++ b/src/main/antora/modules/web/pages/websocket/websocket005.adoc @@ -10,7 +10,7 @@ Follow these steps to send messages in an endpoint. . Obtain the `Session` object from the connection. + -The `Session` object is available as a parameter in the annotated lifecycle methods of the endpoint, like those in <>. +The `Session` object is available as a parameter in the annotated lifecycle methods of the endpoint, like those in <<_websocket_endpoint_lifecycle_annotations>>. When your message is a response to a message from the peer, you have the `Session` object available inside the method that received the message (the method annotated with `@OnMessage`). If you have to send messages that are not responses, store the `Session` object as an instance variable of the endpoint class in the method annotated with `@OnOpen` so that you can access it from other methods. @@ -42,7 +42,7 @@ end a ping frame to the peer. + Send a pong frame to the peer. -The example in <> demonstrates how to use this procedure to reply to every incoming text message. +The example in <<_annotated_endpoints>> demonstrates how to use this procedure to reply to every incoming text message. ==== Sending Messages to All Peers Connected to an Endpoint diff --git a/src/main/antora/modules/web/pages/websocket/websocket012.adoc b/src/main/antora/modules/web/pages/websocket/websocket012.adoc index b5a85833..b8a921d0 100644 --- a/src/main/antora/modules/web/pages/websocket/websocket012.adoc +++ b/src/main/antora/modules/web/pages/websocket/websocket012.adoc @@ -8,15 +8,15 @@ Users can ask simple questions to a bot agent that is always available in the ch The `websocketbot` example application consists of the following elements: -* <> – A CDI bean (`BotBean`) that contains the logic for the bot agent to reply to messages +* <<_the_cdi_bean>> – A CDI bean (`BotBean`) that contains the logic for the bot agent to reply to messages -* <> – A WebSocket endpoint (`BotEndpoint`) that implements the chat room +* <<_the_websocket_endpoint>> – A WebSocket endpoint (`BotEndpoint`) that implements the chat room -* <> – A set of classes (`Message`, `ChatMessage`, `InfoMessage`, `JoinMessage`, and `UsersMessage`) that represent application messages +* <<_the_application_messages>> – A set of classes (`Message`, `ChatMessage`, `InfoMessage`, `JoinMessage`, and `UsersMessage`) that represent application messages -* <> – A set of classes (`ChatMessageEncoder`, `InfoMessageEncoder`, `JoinMessageEncoder`, and `UsersMessageEncoder`) that encode application messages into WebSocket text messages as JSON data +* <<_the_encoder_classes>> – A set of classes (`ChatMessageEncoder`, `InfoMessageEncoder`, `JoinMessageEncoder`, and `UsersMessageEncoder`) that encode application messages into WebSocket text messages as JSON data -* <> – A class (`MessageDecoder`) the parses WebSocket text messages as JSON data and decodes them into `JoinMessage` or `ChatMessage` objects +* <<_the_message_decoder>> – A class (`MessageDecoder`) the parses WebSocket text messages as JSON data and decodes them into `JoinMessage` or `ChatMessage` objects * <> – An HTML page (`index.html`) that uses JavaScript code to implement the client for the chat room @@ -119,7 +119,7 @@ If the message is a join message, the endpoint adds the new user to the list and If the message is a chat message, the endpoint forwards it to all connected clients. If a chat message is for the bot agent, the endpoint obtains a response using the `BotBean` instance and sends it to all connected clients. -The `sendAll` method is similar to the example in <>. +The `sendAll` method is similar to the example in <<_sending_messages_to_all_peers_connected_to_an_endpoint>>. ===== Asynchronous Processing and Concurrency Considerations @@ -132,7 +132,7 @@ This facilitates the development of WebSocket endpoints, because you are guarant When you introduce a new thread in an endpoint, as in this example, you must ensure that variables and methods accessed by more than one thread are thread safe. In this example, the code in `BotBean` is thread safe, and the `BotEndpoint.sendAll` method has been declared `synchronized`. -Refer to xref:jakarta-concurrency-2[xrefstyle=full] for more information on the managed executor service and Concurrency Utilities for Jakarta EE. +Refer to xref:jakarta-concurrency-2[] for more information on the managed executor service and Concurrency Utilities for Jakarta EE. ==== The Application Messages @@ -173,7 +173,7 @@ public class ChatMessageEncoder implements Encoder.Text { } ---- -See xref:json-processing[xrefstyle=full] for more information on the Jakarta JSON Processing. +See xref:jsonp/jsonp.adoc#_json_processing[JSON Processing] for more information on the Jakarta JSON Processing. ==== The Message Decoder @@ -263,7 +263,7 @@ This command builds and packages the application into a WAR file, `websocketbot. http://localhost:8080/websocketbot/ ---- + -See <> for more information. +See <<_to_test_the_websocketbot_example_application>> for more information. ==== To Run the websocketbot Example Application Using Maven @@ -288,7 +288,7 @@ mvn install http://localhost:8080/websocketbot/ ---- + -See <> for more information. +See <<_to_test_the_websocketbot_example_application>> for more information. ==== To Test the websocketbot Example Application From fc820cb5007fb9706faa6a939bf8f5b506d42dd6 Mon Sep 17 00:00:00 2001 From: "Kito D. Mann" Date: Thu, 1 Jun 2023 14:40:39 -0400 Subject: [PATCH 057/247] JETUT-120 Updated README to make jbang optional and give the correct URL. --- antora-conversion/CONVERTING_TO_ANTORA.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/antora-conversion/CONVERTING_TO_ANTORA.adoc b/antora-conversion/CONVERTING_TO_ANTORA.adoc index 09e5c1a2..61891eff 100644 --- a/antora-conversion/CONVERTING_TO_ANTORA.adoc +++ b/antora-conversion/CONVERTING_TO_ANTORA.adoc @@ -4,7 +4,7 @@ As part of the documentation upgrade process, we're migrating the existing conte == Setup -The conversion script is written in Java and requires https://jbang.io[JBang] to run. Install that first. +The conversion script is xref:AntoraConverter.java[]. You can run it with https://jbang.dev[JBang] or just using plain vanilla Java or your favorite IDE. The instructions below use jbang. == Migration Process From 72e3deb038333c2f3d608ec35f45d04ba3c8129c Mon Sep 17 00:00:00 2001 From: Bauke Scholtz Date: Thu, 1 Jun 2023 15:34:03 -0400 Subject: [PATCH 058/247] JETUT-72: simplified wording --- src/main/asciidoc/webapp/webapp002.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/asciidoc/webapp/webapp002.adoc b/src/main/asciidoc/webapp/webapp002.adoc index b301841e..c48f7a0b 100644 --- a/src/main/asciidoc/webapp/webapp002.adoc +++ b/src/main/asciidoc/webapp/webapp002.adoc @@ -25,4 +25,4 @@ This chapter discusses the following simple web applications: * `helloFaces`, a Jakarta Faces based presentation-oriented web application * `helloServlet`, a Jakarta Servlet based service-oriented web application -The web applications are used to illustrate tasks involved in compiling, packaging, deploying, and running a Jakarta Servlet based web application that contains web component code. +They are used to illustrate tasks involved in compiling, packaging, deploying, and running a Jakarta Servlet based web application that contains web component code. From 4526b575e1b02fe1902ade67e0eaf9737dd6d18b Mon Sep 17 00:00:00 2001 From: Bauke Scholtz Date: Thu, 1 Jun 2023 16:17:18 -0400 Subject: [PATCH 059/247] JETUT-72: explain maven project structure --- src/main/asciidoc/webapp/webapp002.adoc | 36 +++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/src/main/asciidoc/webapp/webapp002.adoc b/src/main/asciidoc/webapp/webapp002.adoc index c48f7a0b..76dcbc1d 100644 --- a/src/main/asciidoc/webapp/webapp002.adoc +++ b/src/main/asciidoc/webapp/webapp002.adoc @@ -26,3 +26,39 @@ This chapter discusses the following simple web applications: * `helloServlet`, a Jakarta Servlet based service-oriented web application They are used to illustrate tasks involved in compiling, packaging, deploying, and running a Jakarta Servlet based web application that contains web component code. + +Maven is used to build the example projects. +A Maven WAR project has the following basic structure; not all mentioned resources are required, they are all optional: + +[source] +---- +src + `-- main + |-- java + | `-- com + | `-- example + | `-- Hello.java + |-- resources + | `-- com + | `-- example + | `-- i18n + | |-- text.properties + | |-- text_en.properties + | `-- text_es.properties + `-- webapp + |-- META-INF + | `-- MANIFEST.MF + |-- resources + | |-- css + | | `-- style.css + | |-- img + | | `-- logo.png + | `-- js + | `-- script.js + |-- WEB-INF + | |-- beans.xml + | |-- faces-config.xml + | `-- web.xml + |-- favicon.ico + `-- index.xhtml +---- From 92e714082edf1ca533b8c56d3d0e20bc0b97bcf1 Mon Sep 17 00:00:00 2001 From: Bauke Scholtz Date: Thu, 1 Jun 2023 16:17:31 -0400 Subject: [PATCH 060/247] JETUT-72: rewrite Faces Hello World -- WIP --- src/main/asciidoc/webapp/webapp003.adoc | 186 ++++++++++++++---------- 1 file changed, 111 insertions(+), 75 deletions(-) diff --git a/src/main/asciidoc/webapp/webapp003.adoc b/src/main/asciidoc/webapp/webapp003.adoc index ec1a7066..b50d9e48 100644 --- a/src/main/asciidoc/webapp/webapp003.adoc +++ b/src/main/asciidoc/webapp/webapp003.adoc @@ -1,61 +1,134 @@ -== A Web Module That Uses Jakarta Faces Technology: The hello1 Example +== Hello World Web Application Using Jakarta Faces -The `hello1` application is a web module that uses Jakarta Faces technology to display a greeting and response. -You can use a text editor to view the application files, or you can use NetBeans IDE. +The `helloFaces` application is a web application that uses Jakarta Faces take a name as an HTTP request parameter, generate the greeting and return it as an HTTP response. +The response is represented as a HTML document. +There is an image file as asset. -The source code for this application is in the `_tut-install_/examples/web/faces/hello1/` directory. +The source code for this application is in the `_tut-install_/examples/web/faces/helloFaces/` directory. -=== To View the hello1 Web Module Using NetBeans IDE +Jakarta Faces is a component based MVC framework that provides its own servlet as controller (the "C" part of MVC). +The model and the view are usually provided by you, the web developer. -To view the `hello1` web module using NetBeans IDE: +=== The Model -. From the *File* menu, choose *Open Project*. +In a typical Jakarta Faces application, the model is represented by a JavaBean class. +Such a JavaBean class is in the Jakarta Faces world called a _Backing Bean_. -. In the Open Project dialog box, navigate to: -+ +For this Hello World web application, the backing bean defines a `name` property along with a getter and setter, a `greeting` property along with a getter, and a `submit` action method which creates the `greeting` as output based on `name` as input. + +[source,java] ---- -tut-install/examples/web/faces +package jakartaee.tutorial.faces; + +import jakarta.enterprise.context.RequestScoped; +import jakarta.inject.Named; + +@Named +@RequestScoped +public class Hello { + + private String name; + private String greeting; + + public void submit() { + greeting = "Hello, " + name + "!"; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getGreeting() { + return greeting; + } +} ---- -. Select the `hello1` folder and click *Open Project*. +Note that a getter is required for output and that a setter is only required for input. + +We'll briefly go through the annotations that are used here: + +* `@Named` -- gives the bean a name, which is primarily used to reference it in Expression Language (EL). + Without any attributes this defaults to the simple class name with the first letter in lowercase. + This backing bean will thus be available as `#{hello}` in EL. +* `@RequestScoped` -- gives the bean a scope, which is essentially its lifespan. + In this case that lifespan is the duration of an HTTP request. + When the HTTP request ends, then the bean instance is destroyed. + +=== The View + +In a typical Jakarta Faces application, the view is represented by a XHTML file. +Such a XHTML file is in the Jakarta Faces world called a _Facelets File_ or just _Facelet_. +In Jakarta Faces, the view technology is pluggable and Facelets is used as the default view technology. +XHTML markup is being used because it allows the framework to easily use a XML parser to find components of interest and to generate HTML output. + +For this Hello World web application, the Facelet defines a header with an image and a heading, and a form with a label, input field, messages holder and a command button: -. Expand the *Web Pages* node and double-click the `index.xhtml` file to view it in the editor. -+ -The `index.xhtml` file is the default landing page for a Facelets application. -In a typical Facelets application, web pages are created in XHTML. -For this application, the page uses simple tag markup to display a form with a graphic image, a header, a field, and two command buttons: -+ [source,xml] ---- - - + + - Facelets Hello Greeting + Jakarta Faces Hello World +
+ +

Hello, my name is Duke. What's yours?

+
- -

Hello, my name is Duke. What's yours?

- -

- - - - +
+ + + +
+
+ +
- ... +

#{hello.greeting}

---- + +We'll briefly go through the Jakarta Faces-specific XHTML tags that are used here: + +* `` -- generates the HTML ``. + It gives Jakarta Faces the opportunity to automatically include any necessary JS and CSS files in the generated HTML head. +* `` -- generates the HTML ``. + It gives Jakarta Faces the opportunity to automatically include any necessary JS files in the end of the generated HTML body. +* `` -- generates the HTML `
`. + It gives Jakarta Faces the opportunity to automatically include a hidden field representing the view state. +* `` -- generates the HTML `