From 758153d140c74981ef1a30b74f6223f13be1cfe4 Mon Sep 17 00:00:00 2001 From: Chris Bono Date: Mon, 25 Sep 2023 00:29:05 -0500 Subject: [PATCH] Migrate docs to Antora infrastructure (#460) Resolves #385 --- .github/workflows/deploy-docs-antora.yml | 27 +++++ README.adoc | 2 +- build.gradle | 2 + gradle/antora-docs.gradle | 41 +++++++ spring-pulsar-docs/spring-pulsar-docs.gradle | 94 ++------------- .../src/main/antora/antora-playbook.yml | 46 ++++++++ spring-pulsar-docs/src/main/antora/antora.yml | 12 ++ .../src/main/antora/modules/ROOT/nav.adoc | 19 +++ .../ROOT/pages/appendix}/native-image.adoc | 5 +- .../ROOT/pages/appendix}/non-ga-versions.adoc | 14 ++- .../appendix}/override-boot-dependencies.adoc | 11 +- .../appendix}/version-compatibility.adoc | 5 +- .../attributes}/attributes-variables.adoc | 0 .../ROOT/pages/attributes}/attributes.adoc | 0 .../main/antora/modules/ROOT/pages/index.adoc | 12 ++ .../main/antora/modules/ROOT/pages/intro.adoc | 7 ++ .../modules/ROOT/pages/intro/building.adoc | 25 ++++ .../ROOT/pages/intro}/getting-help.adoc | 3 +- .../ROOT/pages/intro}/project-state.adoc | 2 + .../ROOT/pages/intro/system-requirements.adoc | 12 ++ .../modules/ROOT/pages/other-resources.adoc | 12 ++ .../modules/ROOT/pages/overview}/authors.adoc | 0 .../ROOT/pages/overview}/copyright.adoc | 0 .../ROOT/pages/reference}/authentication.adoc | 18 +-- .../ROOT/pages/reference}/observability.adoc | 12 +- .../ROOT/pages/reference}/pulsar-admin.adoc | 6 +- .../ROOT/pages/reference}/pulsar-binder.adoc | 15 ++- .../pages/reference}/pulsar-function.adoc | 8 +- .../ROOT/pages/reference}/pulsar-header.adoc | 4 +- .../modules/ROOT/pages/reference}/pulsar.adoc | 108 +----------------- .../ROOT/pages/reference}/quick-tour.adoc | 21 +++- .../pages/reference}/reactive-pulsar.adoc | 36 +----- .../pages/reference}/reactive-quick-tour.adoc | 22 +++- .../ROOT/pages/reference/reference.adoc | 4 + .../PulsarListener/listener-snippet.adoc | 2 - .../listener-snippet.adoc | 2 - .../schema-info/custom-schema-mapping.adoc | 2 - .../schema-info/schema-info-listener.adoc | 1 - .../schema-info/schema-info-template.adoc | 0 .../ROOT/pages/reference}/tls-encryption.adoc | 2 +- .../pages/reference}/topic-resolution.adoc | 0 .../src/main/asciidoc/css/stylesheet.css | 31 ----- .../src/main/asciidoc/index.adoc | 55 --------- .../src/main/asciidoc/intro.adoc | 38 ------ .../DefaultReactivePulsarSenderFactory.java | 3 - 45 files changed, 314 insertions(+), 427 deletions(-) create mode 100644 .github/workflows/deploy-docs-antora.yml create mode 100644 gradle/antora-docs.gradle create mode 100644 spring-pulsar-docs/src/main/antora/antora-playbook.yml create mode 100644 spring-pulsar-docs/src/main/antora/antora.yml create mode 100644 spring-pulsar-docs/src/main/antora/modules/ROOT/nav.adoc rename spring-pulsar-docs/src/main/{asciidoc => antora/modules/ROOT/pages/appendix}/native-image.adoc (96%) rename spring-pulsar-docs/src/main/{asciidoc => antora/modules/ROOT/pages/appendix}/non-ga-versions.adoc (93%) rename spring-pulsar-docs/src/main/{asciidoc => antora/modules/ROOT/pages/appendix}/override-boot-dependencies.adoc (95%) rename spring-pulsar-docs/src/main/{asciidoc => antora/modules/ROOT/pages/appendix}/version-compatibility.adoc (91%) rename spring-pulsar-docs/src/main/{asciidoc => antora/modules/ROOT/pages/attributes}/attributes-variables.adoc (100%) rename spring-pulsar-docs/src/main/{asciidoc => antora/modules/ROOT/pages/attributes}/attributes.adoc (100%) create mode 100644 spring-pulsar-docs/src/main/antora/modules/ROOT/pages/index.adoc create mode 100644 spring-pulsar-docs/src/main/antora/modules/ROOT/pages/intro.adoc create mode 100644 spring-pulsar-docs/src/main/antora/modules/ROOT/pages/intro/building.adoc rename spring-pulsar-docs/src/main/{asciidoc => antora/modules/ROOT/pages/intro}/getting-help.adoc (93%) rename spring-pulsar-docs/src/main/{asciidoc => antora/modules/ROOT/pages/intro}/project-state.adoc (98%) create mode 100644 spring-pulsar-docs/src/main/antora/modules/ROOT/pages/intro/system-requirements.adoc create mode 100644 spring-pulsar-docs/src/main/antora/modules/ROOT/pages/other-resources.adoc rename spring-pulsar-docs/src/main/{asciidoc => antora/modules/ROOT/pages/overview}/authors.adoc (100%) rename spring-pulsar-docs/src/main/{asciidoc => antora/modules/ROOT/pages/overview}/copyright.adoc (100%) rename spring-pulsar-docs/src/main/{asciidoc => antora/modules/ROOT/pages/reference}/authentication.adoc (88%) rename spring-pulsar-docs/src/main/{asciidoc => antora/modules/ROOT/pages/reference}/observability.adoc (97%) rename spring-pulsar-docs/src/main/{asciidoc => antora/modules/ROOT/pages/reference}/pulsar-admin.adoc (90%) rename spring-pulsar-docs/src/main/{asciidoc => antora/modules/ROOT/pages/reference}/pulsar-binder.adoc (98%) rename spring-pulsar-docs/src/main/{asciidoc => antora/modules/ROOT/pages/reference}/pulsar-function.adoc (97%) rename spring-pulsar-docs/src/main/{asciidoc => antora/modules/ROOT/pages/reference}/pulsar-header.adoc (98%) rename spring-pulsar-docs/src/main/{asciidoc => antora/modules/ROOT/pages/reference}/pulsar.adoc (99%) rename spring-pulsar-docs/src/main/{asciidoc => antora/modules/ROOT/pages/reference}/quick-tour.adoc (96%) rename spring-pulsar-docs/src/main/{asciidoc => antora/modules/ROOT/pages/reference}/reactive-pulsar.adoc (98%) rename spring-pulsar-docs/src/main/{asciidoc => antora/modules/ROOT/pages/reference}/reactive-quick-tour.adoc (95%) create mode 100644 spring-pulsar-docs/src/main/antora/modules/ROOT/pages/reference/reference.adoc rename spring-pulsar-docs/src/main/{asciidoc => antora/modules/ROOT/pages/reference}/schema-info/PulsarListener/listener-snippet.adoc (94%) rename spring-pulsar-docs/src/main/{asciidoc => antora/modules/ROOT/pages/reference}/schema-info/ReactivePulsarListener/listener-snippet.adoc (94%) rename spring-pulsar-docs/src/main/{asciidoc => antora/modules/ROOT/pages/reference}/schema-info/custom-schema-mapping.adoc (99%) rename spring-pulsar-docs/src/main/{asciidoc => antora/modules/ROOT/pages/reference}/schema-info/schema-info-listener.adoc (99%) rename spring-pulsar-docs/src/main/{asciidoc => antora/modules/ROOT/pages/reference}/schema-info/schema-info-template.adoc (100%) rename spring-pulsar-docs/src/main/{asciidoc => antora/modules/ROOT/pages/reference}/tls-encryption.adoc (97%) rename spring-pulsar-docs/src/main/{asciidoc => antora/modules/ROOT/pages/reference}/topic-resolution.adoc (100%) delete mode 100644 spring-pulsar-docs/src/main/asciidoc/css/stylesheet.css delete mode 100644 spring-pulsar-docs/src/main/asciidoc/index.adoc delete mode 100644 spring-pulsar-docs/src/main/asciidoc/intro.adoc diff --git a/.github/workflows/deploy-docs-antora.yml b/.github/workflows/deploy-docs-antora.yml new file mode 100644 index 00000000..5eada1a0 --- /dev/null +++ b/.github/workflows/deploy-docs-antora.yml @@ -0,0 +1,27 @@ +name: Deploy Docs +on: + push: + branches-ignore: [ gh-pages ] + tags: '**' + workflow_dispatch: +permissions: read-all +jobs: + build: + runs-on: ubuntu-latest + if: github.repository_owner == 'spring-projects' + steps: + - name: Checkout + uses: actions/checkout@v3 + with: + ref: docs-build + fetch-depth: 1 + - name: Dispatch (partial build) + if: github.ref_type == 'branch' + env: + GH_TOKEN: ${{ secrets.GH_ACTIONS_REPO_TOKEN }} + run: gh workflow run deploy-docs-antora.yml -r $(git rev-parse --abbrev-ref HEAD) -f build-refname=${{ github.ref_name }} + - name: Dispatch (full build) + if: github.ref_type == 'tag' + env: + GH_TOKEN: ${{ secrets.GH_ACTIONS_REPO_TOKEN }} + run: gh workflow run deploy-docs-antora.yml -r $(git rev-parse --abbrev-ref HEAD) diff --git a/README.adoc b/README.adoc index 9364537b..3c059c8b 100644 --- a/README.adoc +++ b/README.adoc @@ -6,7 +6,7 @@ Spring for Apache Pulsar provides a basic Spring-friendly API for developing htt **#TIP#**: Most of the ideas in this project are borrowed from the Spring for Apache Kafka project, thus a familiarity with it would help. -include::spring-pulsar-docs/src/main/asciidoc/project-state.adoc[leveloffset=+1] +include::spring-pulsar-docs/src/main/antora/modules/ROOT/pages/intro/project-state.adoc[leveloffset=+1] == Getting Started The {docs}/html/[reference documentation] includes a {docs}/html/#quick-tourhtml[quick tour] section. diff --git a/build.gradle b/build.gradle index f73f565a..1f854018 100644 --- a/build.gradle +++ b/build.gradle @@ -35,6 +35,8 @@ nohttp { source.exclude "**/out/**" source.exclude "**/target/**" source.exclude "**/*.dylib" + source.exclude "**/*.gif" + source.exclude "**/.gradle/**" } check { diff --git a/gradle/antora-docs.gradle b/gradle/antora-docs.gradle new file mode 100644 index 00000000..2d086e17 --- /dev/null +++ b/gradle/antora-docs.gradle @@ -0,0 +1,41 @@ +node { + version = '16.16.0' +} + +antora { + version = '3.2.0-alpha.2' + playbook = file('src/main/antora/antora-playbook.yml') + options = ['to-dir' : project.layout.buildDirectory.dir('site').get().toString(), clean: true, fetch: !project.gradle.startParameter.offline, stacktrace: true] + dependencies = [ + '@antora/atlas-extension': '1.0.0-alpha.1', + '@antora/collector-extension': '1.0.0-alpha.3', + '@asciidoctor/tabs': '1.0.0-beta.3', + '@springio/antora-extensions': '1.4.2', + '@springio/asciidoctor-extensions': '1.0.0-alpha.8', + ] +} + +tasks.named("generateAntoraYml") { + asciidocAttributes = project.provider( { generateAttributes() } ) + baseAntoraYmlFile = file('src/main/antora/antora.yml') +} + +tasks.create(name: 'createAntoraPartials', type: Sync) { + from { project(":spring-pulsar-docs").tasks.generateObservabilityDocs.outputs } + into layout.buildDirectory.dir('generated-antora-resources/modules/ROOT/partials') +} + +tasks.create('generateAntoraResources') { + dependsOn 'createAntoraPartials' + dependsOn 'generateAntoraYml' +} + +def generateAttributes() { + return ['spring-boot-version': project.springBootVersion ?: 'current', + 'spring-framework-version': project.springFrameworkVersion ?: 'current', + 'spring-cloud-stream-version': project.springCloudStreamVersion ?: 'current', + 'spring-pulsar-version': project.version, + 'pulsar-client-version': project.pulsarClientVersion ?: 'current', + 'pulsar-client-reactive-version': project.pulsarClientReactiveVersion ?: 'current', + 'is-snapshot-version': project.version.endsWith("-SNAPSHOT")] +} diff --git a/spring-pulsar-docs/spring-pulsar-docs.gradle b/spring-pulsar-docs/spring-pulsar-docs.gradle index f711198d..e6c99289 100644 --- a/spring-pulsar-docs/spring-pulsar-docs.gradle +++ b/spring-pulsar-docs/spring-pulsar-docs.gradle @@ -1,8 +1,11 @@ plugins { - id 'org.springframework.pulsar.spring-docs-module' - id 'org.asciidoctor.jvm.convert' + id 'org.springframework.pulsar.spring-module' + id 'org.antora' version '1.0.0' + id 'io.spring.antora.generate-antora-yml' version '0.0.1' } +apply from: "${rootDir}/gradle/antora-docs.gradle" + description = 'Spring for Apache Pulsar Docs' ext { @@ -77,96 +80,17 @@ task generateObservabilityDocs(type: JavaExec) { args observationsInputDir, /.+/, observationsOutputDir } -tasks.withType(org.asciidoctor.gradle.jvm.AbstractAsciidoctorTask) { - asciidoctorj { - fatalWarnings = ['^((?!successfully validated).)*$'] - } - forkOptions { - jvmArgs "--add-opens", "java.base/sun.nio.ch=ALL-UNNAMED", "--add-opens", "java.base/java.io=ALL-UNNAMED" - } - doFirst { - attributes "spring-boot-version": project.springBootVersion ?: 'current', - "spring-framework-version": project.springFrameworkVersion ?: 'current', - "spring-cloud-stream-version": project.springCloudStreamVersion ?: 'current', - "spring-pulsar-version": project.version, - "pulsar-client-version": project.pulsarClientVersion ?: 'current', - "pulsar-client-reactive-version": project.pulsarClientReactiveVersion ?: 'current', - "is-snapshot-version": project.version.endsWith("-SNAPSHOT") - } -} - -asciidoctor { - sources { - include "*.singleadoc" - } -} - -task asciidoctorPdf(type: org.asciidoctor.gradle.jvm.AsciidoctorTask) { - sources { - include "*.adoc" - } -} - -task asciidoctorMultipage(type: org.asciidoctor.gradle.jvm.AsciidoctorTask) { - sources { - include "*.adoc" - } -} - -syncDocumentationSourceForAsciidoctor { - dependsOn generateObservabilityDocs - from("${buildDir}/docs/generated") { - into "asciidoc" - } - from("src/main/java") { - into "main/java" - } -} - -syncDocumentationSourceForAsciidoctorMultipage { - dependsOn generateObservabilityDocs - from("${buildDir}/docs/generated") { - into "asciidoc" - } - from("src/main/java") { - into "main/java" - } -} - -syncDocumentationSourceForAsciidoctorPdf { - dependsOn generateObservabilityDocs - from("${buildDir}/docs/generated") { - into "asciidoc" - } - from("src/main/java") { - into "main/java" - } -} - -task asciidocs { - dependsOn asciidoctor, asciidoctorMultipage, asciidoctorPdf -} - -task docsZip(type: Zip) { - dependsOn asciidocs +task docsZip(type: Zip, dependsOn: [':spring-pulsar-docs:antora']) { group = 'Distribution' archiveClassifier = 'docs' description = "Builds docs archive containing api and reference for deployment at static.spring.io/spring-pulsar/docs." duplicatesStrategy "fail" - from(asciidoctor.outputDir) { - into "reference/htmlsingle" - } - from(asciidoctorPdf.outputDir) { - into "reference/pdf" - include "index.pdf" - rename { "spring-pulsar-reference.pdf" } - } - from(asciidoctorMultipage.outputDir) { - into "reference/html" - } from(aggregatedJavadoc) { into "api" } + from ('build/site') { + into 'reference/' + } } artifacts { diff --git a/spring-pulsar-docs/src/main/antora/antora-playbook.yml b/spring-pulsar-docs/src/main/antora/antora-playbook.yml new file mode 100644 index 00000000..ae23ec5b --- /dev/null +++ b/spring-pulsar-docs/src/main/antora/antora-playbook.yml @@ -0,0 +1,46 @@ +antora: + extensions: + - '@springio/antora-extensions/partial-build-extension' + - require: '@springio/antora-extensions/latest-version-extension' + - require: '@springio/antora-extensions/inject-collector-cache-config-extension' + - '@antora/collector-extension' + - '@antora/atlas-extension' + - require: '@springio/antora-extensions/root-component-extension' + root_component_name: 'pulsar' + +site: + title: Spring Pulsar + url: https://docs.spring.io/spring-pulsar/reference/ + +content: + sources: + - url: ./../../../../ + branches: HEAD + start_path: spring-pulsar-docs/src/main/antora + worktrees: true + +asciidoc: + attributes: + page-stackoverflow-url: https://stackoverflow.com/tags/spring-pulsar + page-pagination: '' + hide-uri-scheme: '@' + tabs-sync-option: '@' + chomp: 'all' + listener-class: PulsarListener@ + template-class: PulsarTemplate@ + extensions: + - '@asciidoctor/tabs' + - '@springio/asciidoctor-extensions' + sourcemap: true + +urls: + latest_version_segment: '' + +runtime: + log: + failure_level: warn + format: pretty + +ui: + bundle: + url: https://github.com/spring-io/antora-ui-spring/releases/download/v0.3.5/ui-bundle.zip diff --git a/spring-pulsar-docs/src/main/antora/antora.yml b/spring-pulsar-docs/src/main/antora/antora.yml new file mode 100644 index 00000000..8588186e --- /dev/null +++ b/spring-pulsar-docs/src/main/antora/antora.yml @@ -0,0 +1,12 @@ +name: pulsar +version: true +title: Spring for Apache Pulsar +nav: + - modules/ROOT/nav.adoc +ext: + collector: + run: + command: gradlew :spring-pulsar-docs:generateAntoraResources + local: true + scan: + dir: spring-pulsar-docs/build/generated-antora-resources diff --git a/spring-pulsar-docs/src/main/antora/modules/ROOT/nav.adoc b/spring-pulsar-docs/src/main/antora/modules/ROOT/nav.adoc new file mode 100644 index 00000000..11b1d5be --- /dev/null +++ b/spring-pulsar-docs/src/main/antora/modules/ROOT/nav.adoc @@ -0,0 +1,19 @@ +* xref:index.adoc[Overview] +* xref:intro.adoc[Introduction] +** xref:intro/project-state.adoc[Project Status] +** xref:intro/system-requirements.adoc[System Requirements] +** xref:intro/building.adoc[Building the Project] +** xref:intro/getting-help.adoc[Getting Help] +* xref:reference/reference.adoc[] +** xref:reference/pulsar.adoc[] +** xref:reference/reactive-pulsar.adoc[] +** xref:reference/pulsar-admin.adoc[] +** xref:reference/pulsar-function.adoc[] +** xref:reference/observability.adoc[] +** xref:reference/pulsar-binder.adoc[] +* xref:other-resources.adoc[] +* Appendices +** xref:appendix/version-compatibility.adoc[] +** xref:appendix/override-boot-dependencies.adoc[] +** xref:appendix/non-ga-versions.adoc[] +** xref:appendix/native-image.adoc[] diff --git a/spring-pulsar-docs/src/main/asciidoc/native-image.adoc b/spring-pulsar-docs/src/main/antora/modules/ROOT/pages/appendix/native-image.adoc similarity index 96% rename from spring-pulsar-docs/src/main/asciidoc/native-image.adoc rename to spring-pulsar-docs/src/main/antora/modules/ROOT/pages/appendix/native-image.adoc index 78e33b68..25c9b88f 100644 --- a/spring-pulsar-docs/src/main/asciidoc/native-image.adoc +++ b/spring-pulsar-docs/src/main/antora/modules/ROOT/pages/appendix/native-image.adoc @@ -1,8 +1,7 @@ -[appendix] -[[appendix.native-images]] +[[native-images]] = GraalVM Native Image Support -include::attributes.adoc[] +include::../attributes/attributes.adoc[] https://www.graalvm.org/native-image/[GraalVM Native Images] are standalone executables that can be generated by processing compiled Java applications ahead-of-time. Native Images generally have a smaller memory footprint and start faster than their JVM counterparts. diff --git a/spring-pulsar-docs/src/main/asciidoc/non-ga-versions.adoc b/spring-pulsar-docs/src/main/antora/modules/ROOT/pages/appendix/non-ga-versions.adoc similarity index 93% rename from spring-pulsar-docs/src/main/asciidoc/non-ga-versions.adoc rename to spring-pulsar-docs/src/main/antora/modules/ROOT/pages/appendix/non-ga-versions.adoc index 8270fffb..1c6f3170 100644 --- a/spring-pulsar-docs/src/main/asciidoc/non-ga-versions.adoc +++ b/spring-pulsar-docs/src/main/antora/modules/ROOT/pages/appendix/non-ga-versions.adoc @@ -1,13 +1,15 @@ -[appendix] -[[appendix.non-ga-versions]] +[[non-ga-versions]] = Non-GA Versions -include::attributes.adoc[] +include::../attributes/attributes.adoc[] You can find snapshot or milestone versions of the dependencies in the following repositories: +[tabs] +====== +Maven:: ++ [source,xml,indent=0,subs="verbatim,attributes",role="primary"] -.Maven ---- @@ -37,8 +39,9 @@ You can find snapshot or milestone versions of the dependencies in the following ---- +Gradle:: ++ [source,groovy,indent=0,subs="verbatim,attributes",role="secondary"] -.Gradle ---- repositories { maven { @@ -55,3 +58,4 @@ repositories { } } ---- +====== diff --git a/spring-pulsar-docs/src/main/asciidoc/override-boot-dependencies.adoc b/spring-pulsar-docs/src/main/antora/modules/ROOT/pages/appendix/override-boot-dependencies.adoc similarity index 95% rename from spring-pulsar-docs/src/main/asciidoc/override-boot-dependencies.adoc rename to spring-pulsar-docs/src/main/antora/modules/ROOT/pages/appendix/override-boot-dependencies.adoc index f74de64f..34ede919 100644 --- a/spring-pulsar-docs/src/main/asciidoc/override-boot-dependencies.adoc +++ b/spring-pulsar-docs/src/main/antora/modules/ROOT/pages/appendix/override-boot-dependencies.adoc @@ -1,5 +1,4 @@ -[appendix] -[[appendix.override-boot-deps]] +[[override-boot-deps]] = Override Spring Boot Dependencies When using Spring for Apache Pulsar in a Spring Boot application, the Apache Pulsar dependency versions are determined by Spring Boot's dependency management. @@ -9,7 +8,6 @@ Or, to use a different Spring for Apache Pulsar version with a supported Spring In the following example, snapshot version of the Pulsar clients and Spring for Apache Pulsar are being used. -==== [source, groovy, subs="+attributes", role="secondary"] .Gradle ---- @@ -22,8 +20,11 @@ dependencies { } ---- +[tabs] +====== +Maven:: ++ [source, xml, subs="+attributes", role="primary"] -.Maven ---- 3.1.1-SNAPSHOT @@ -36,5 +37,5 @@ dependencies { spring-boot-starter-pulsar-reactive ---- +====== -==== diff --git a/spring-pulsar-docs/src/main/asciidoc/version-compatibility.adoc b/spring-pulsar-docs/src/main/antora/modules/ROOT/pages/appendix/version-compatibility.adoc similarity index 91% rename from spring-pulsar-docs/src/main/asciidoc/version-compatibility.adoc rename to spring-pulsar-docs/src/main/antora/modules/ROOT/pages/appendix/version-compatibility.adoc index 64e7e7f3..d9ef45b5 100644 --- a/spring-pulsar-docs/src/main/asciidoc/version-compatibility.adoc +++ b/spring-pulsar-docs/src/main/antora/modules/ROOT/pages/appendix/version-compatibility.adoc @@ -1,8 +1,7 @@ -[appendix] -[[appendix.version-compatibility]] +[[version-compatibility]] = Pulsar Clients and Spring Boot Compatibility -include::attributes.adoc[] +include::../attributes/attributes.adoc[] The following is the compatibility matrix: |=== diff --git a/spring-pulsar-docs/src/main/asciidoc/attributes-variables.adoc b/spring-pulsar-docs/src/main/antora/modules/ROOT/pages/attributes/attributes-variables.adoc similarity index 100% rename from spring-pulsar-docs/src/main/asciidoc/attributes-variables.adoc rename to spring-pulsar-docs/src/main/antora/modules/ROOT/pages/attributes/attributes-variables.adoc diff --git a/spring-pulsar-docs/src/main/asciidoc/attributes.adoc b/spring-pulsar-docs/src/main/antora/modules/ROOT/pages/attributes/attributes.adoc similarity index 100% rename from spring-pulsar-docs/src/main/asciidoc/attributes.adoc rename to spring-pulsar-docs/src/main/antora/modules/ROOT/pages/attributes/attributes.adoc diff --git a/spring-pulsar-docs/src/main/antora/modules/ROOT/pages/index.adoc b/spring-pulsar-docs/src/main/antora/modules/ROOT/pages/index.adoc new file mode 100644 index 00000000..a4cf35f5 --- /dev/null +++ b/spring-pulsar-docs/src/main/antora/modules/ROOT/pages/index.adoc @@ -0,0 +1,12 @@ +[[overview]] += Overview +include::attributes/attributes.adoc[] + +include::overview/authors.adoc[] +(v{spring-pulsar-version}) + +include::overview/copyright.adoc[] + +ifeval::[{is-snapshot-version} == true] +CAUTION: You are viewing documentation for a SNAPSHOT version ({spring-pulsar-version}). While it is usually in-sync with the underlying code, it is subject to change and not guaranteed to be up-to-date with the underlying code. +endif::[] diff --git a/spring-pulsar-docs/src/main/antora/modules/ROOT/pages/intro.adoc b/spring-pulsar-docs/src/main/antora/modules/ROOT/pages/intro.adoc new file mode 100644 index 00000000..1ef038d3 --- /dev/null +++ b/spring-pulsar-docs/src/main/antora/modules/ROOT/pages/intro.adoc @@ -0,0 +1,7 @@ +[[introduction]] += Introduction + +This project provides a basic Spring-friendly API for developing https://pulsar.apache.org/[Apache Pulsar] applications. + +On a very high level, Spring for Apache Pulsar provides a `PulsarTemplate` for publishing to a Pulsar topic and a `PulsarListener` annotation for consuming from a Pulsar topic. +In addition, it also provides various convenience APIs for Spring developers to ramp up their development journey into Apache Pulsar. diff --git a/spring-pulsar-docs/src/main/antora/modules/ROOT/pages/intro/building.adoc b/spring-pulsar-docs/src/main/antora/modules/ROOT/pages/intro/building.adoc new file mode 100644 index 00000000..c21a340c --- /dev/null +++ b/spring-pulsar-docs/src/main/antora/modules/ROOT/pages/intro/building.adoc @@ -0,0 +1,25 @@ +[[building-project]] +== Building the Project + +include::../attributes/attributes-variables.adoc[] + +If you have cloned the project locally, follow these steps to build the project from the source code. + +NOTE: Gradle `7.x (7.4 or above)` is required to build. + +Run the following command to do a full build of the project: +[indent=0] +---- +./gradlew clean build +---- +You can build without running tests by using the following command: +[indent=0] +---- +./gradlew clean build -x test +---- + +You can build the reference documentation using this command: +---- +./gradlew :spring-pulsar-docs:antora +---- +You can view the generated HTML in `_docs/build/site_` directory. diff --git a/spring-pulsar-docs/src/main/asciidoc/getting-help.adoc b/spring-pulsar-docs/src/main/antora/modules/ROOT/pages/intro/getting-help.adoc similarity index 93% rename from spring-pulsar-docs/src/main/asciidoc/getting-help.adoc rename to spring-pulsar-docs/src/main/antora/modules/ROOT/pages/intro/getting-help.adoc index 09244f66..5e3a0a07 100644 --- a/spring-pulsar-docs/src/main/asciidoc/getting-help.adoc +++ b/spring-pulsar-docs/src/main/antora/modules/ROOT/pages/intro/getting-help.adoc @@ -1,6 +1,7 @@ [[getting-help]] = Getting Help -include::attributes.adoc[] + +include::../attributes/attributes-variables.adoc[] If you have trouble with Spring for Apache Pulsar, we would like to help. diff --git a/spring-pulsar-docs/src/main/asciidoc/project-state.adoc b/spring-pulsar-docs/src/main/antora/modules/ROOT/pages/intro/project-state.adoc similarity index 98% rename from spring-pulsar-docs/src/main/asciidoc/project-state.adoc rename to spring-pulsar-docs/src/main/antora/modules/ROOT/pages/intro/project-state.adoc index f2322b9b..c6d8d117 100644 --- a/spring-pulsar-docs/src/main/asciidoc/project-state.adoc +++ b/spring-pulsar-docs/src/main/antora/modules/ROOT/pages/intro/project-state.adoc @@ -1,4 +1,6 @@ +[[project-status]] = Project Status + While the code and functionality of the framework is thoroughly tested and ready for production, the project is in a bit of flux while transitioning from experimental GA (`0.2.x`) to GA (`1.0.0`). The evolution of the project (by version) is as follows: diff --git a/spring-pulsar-docs/src/main/antora/modules/ROOT/pages/intro/system-requirements.adoc b/spring-pulsar-docs/src/main/antora/modules/ROOT/pages/intro/system-requirements.adoc new file mode 100644 index 00000000..eaf4a071 --- /dev/null +++ b/spring-pulsar-docs/src/main/antora/modules/ROOT/pages/intro/system-requirements.adoc @@ -0,0 +1,12 @@ +[[system-requirements]] += System Requirements + +include::../attributes/attributes-variables.adoc[] + +Spring for Apache Pulsar `{spring-pulsar-version}` requires the following: + +- https://www.java.com[Java 17] and is compatible up to and including Java 20 +- {spring-framework-docs}[Spring Framework `{spring-framework-version}`] or above +- {apache-pulsar-cient-docs}/[Apache Pulsar Java Client `{pulsar-client-version}`] or above + +The version compatibility matrix (including Spring Boot) can be found in the xref:appendix/version-compatibility.adoc#version-compatibility[appendix]. diff --git a/spring-pulsar-docs/src/main/antora/modules/ROOT/pages/other-resources.adoc b/spring-pulsar-docs/src/main/antora/modules/ROOT/pages/other-resources.adoc new file mode 100644 index 00000000..ee500552 --- /dev/null +++ b/spring-pulsar-docs/src/main/antora/modules/ROOT/pages/other-resources.adoc @@ -0,0 +1,12 @@ +[[other-resources]] += Other Resources + +include::attributes/attributes-variables.adoc[] + +In addition to this reference documentation, we recommend a number of other resources that may help you learn about Spring and Apache Pulsar. + +- {github}[Spring for Apache Pulsar GitHub Repository] +- https://pulsar.apache.org/[Apache Pulsar Project Home Page] +- {apache-pulsar-docs}/client-libraries-java/[Apache Pulsar Java Client] +- https://github.com/apache/pulsar[Apache Pulsar GitHub Repository] +- https://github.com/apache/pulsar-client-reactive[Apache Pulsar Reactive Client GitHub Repository] diff --git a/spring-pulsar-docs/src/main/asciidoc/authors.adoc b/spring-pulsar-docs/src/main/antora/modules/ROOT/pages/overview/authors.adoc similarity index 100% rename from spring-pulsar-docs/src/main/asciidoc/authors.adoc rename to spring-pulsar-docs/src/main/antora/modules/ROOT/pages/overview/authors.adoc diff --git a/spring-pulsar-docs/src/main/asciidoc/copyright.adoc b/spring-pulsar-docs/src/main/antora/modules/ROOT/pages/overview/copyright.adoc similarity index 100% rename from spring-pulsar-docs/src/main/asciidoc/copyright.adoc rename to spring-pulsar-docs/src/main/antora/modules/ROOT/pages/overview/copyright.adoc diff --git a/spring-pulsar-docs/src/main/asciidoc/authentication.adoc b/spring-pulsar-docs/src/main/antora/modules/ROOT/pages/reference/authentication.adoc similarity index 88% rename from spring-pulsar-docs/src/main/asciidoc/authentication.adoc rename to spring-pulsar-docs/src/main/antora/modules/ROOT/pages/reference/authentication.adoc index aa7c354d..a06038b7 100644 --- a/spring-pulsar-docs/src/main/asciidoc/authentication.adoc +++ b/spring-pulsar-docs/src/main/antora/modules/ROOT/pages/reference/authentication.adoc @@ -1,5 +1,5 @@ -include::attributes.adoc[] +include::../attributes/attributes.adoc[] To connect to a Pulsar cluster that requires authentication, you need to specify which authentication plugin to use and any parameters required by the specified plugin. When **using Spring Boot** auto-configuration, you can set the plugin and the plugin parameters via configuration properties (in most cases). @@ -21,7 +21,6 @@ The following listings show how to configure each of the supported authenticatio [[Athenz]] .[.underline]#Click ##here## for **Athenz**# [%collapsible] -==== [source, yaml] ---- spring: @@ -36,13 +35,11 @@ spring: privateKey: ... keyId: ... ---- -NOTE: This also requires TLS encryption as described in <>. -==== +NOTE: This also requires xref:reference/pulsar.adoc#tls-encryption[TLS encryption]. [[Token]] .[.underline]#Click ##here## for **Token**# [%collapsible] -==== [source, yaml] ---- spring: @@ -53,12 +50,10 @@ spring: param: token: some-token-goes-here ---- -==== [[Basic]] .[.underline]#Click ##here## for **Basic**# [%collapsible] -==== [source, yaml] ---- spring: @@ -70,12 +65,10 @@ spring: userId: ... password: ... ---- -==== [[OAuth2]] .[.underline]#Click ##here## for **OAuth2**# [%collapsible] -==== [source, yaml] ---- spring: @@ -89,12 +82,10 @@ spring: audience: ... scope: ... ---- -==== [[Sasl]] .[.underline]#Click ##here## for **Sasl**# [%collapsible] -==== [source, yaml] ---- spring: @@ -106,13 +97,12 @@ spring: saslJaasClientSectionName: ... serverType: ... ---- -==== [[mTlS-pem]] .[.underline]#Click ##here## for **mTLS (PEM)**# [%collapsible] ==== -NOTE: Because this option requires TLS encryption, which already requires you to <>, it is recommended to simply add the authentication directly on the client builder in your provided TLS customizer. +NOTE: Because this option requires TLS encryption, which already requires you to xref:reference/pulsar.adoc#tls-encryption[provide a client builder customizer], it is recommended to simply add the authentication directly on the client builder in your provided TLS customizer. You can use the `org.apache.pulsar.client.api.AuthenticationFactory` to help create the authentication object as follows: [source,java] ---- @@ -125,7 +115,7 @@ See the official Pulsar documentation on {apache-pulsar-docs}/security-tls-authe .[.underline]#Click ##here## for **mTLS (JKS)**# [%collapsible] ==== -NOTE: Because this option requires TLS encryption, which already requires you to <>, it is recommended to simply add the authentication directly on the client builder in your provided TLS customizer. +NOTE: Because this option requires TLS encryption, which already requires you to xref:reference/pulsar.adoc#tls-encryption[provide a client builder customizer], it is recommended to simply add the authentication directly on the client builder in your provided TLS customizer. You can use the `org.apache.pulsar.client.api.AuthenticationFactory` to help create the authentication object as follows: [source,java] ---- diff --git a/spring-pulsar-docs/src/main/asciidoc/observability.adoc b/spring-pulsar-docs/src/main/antora/modules/ROOT/pages/reference/observability.adoc similarity index 97% rename from spring-pulsar-docs/src/main/asciidoc/observability.adoc rename to spring-pulsar-docs/src/main/antora/modules/ROOT/pages/reference/observability.adoc index 004eab7c..b6ddfc23 100644 --- a/spring-pulsar-docs/src/main/asciidoc/observability.adoc +++ b/spring-pulsar-docs/src/main/antora/modules/ROOT/pages/reference/observability.adoc @@ -19,9 +19,9 @@ To add other tags to timers and traces, configure a custom `PulsarTemplateObserv TIP: You can subclass either `DefaultPulsarTemplateObservationConvention` or `DefaultPulsarListenerObservationConvention` or provide completely new implementations. -include::observation/_metrics.adoc[] +include::partial$_metrics.adoc[] -include::observation/_spans.adoc[] +include::partial$_spans.adoc[] See https://micrometer.io/docs/tracing[Micrometer Tracing] for more information. @@ -39,8 +39,11 @@ The following example shows the steps to configure your Spring Boot application . Add the required dependencies to your application (in Maven or Gradle, respectively): + +[tabs] +====== +Maven:: ++ [source,xml,indent=0,subs="verbatim,attributes",role="primary"] -.Maven ---- @@ -61,6 +64,7 @@ The following example shows the steps to configure your Spring Boot application ---- +====== + [source,groovy,indent=0,subs="verbatim,attributes",role="secondary"] .Gradle @@ -74,9 +78,7 @@ dependencies { ---- + NOTE -==== You need the `'io.zipkin.reporter2:zipkin-sender-urlconnection'` dependency only if your application does not have a configured WebClient or RestTemplate. -==== . Add the required properties to your application: + [source,yaml,indent=0,subs="verbatim"] diff --git a/spring-pulsar-docs/src/main/asciidoc/pulsar-admin.adoc b/spring-pulsar-docs/src/main/antora/modules/ROOT/pages/reference/pulsar-admin.adoc similarity index 90% rename from spring-pulsar-docs/src/main/asciidoc/pulsar-admin.adoc rename to spring-pulsar-docs/src/main/antora/modules/ROOT/pages/reference/pulsar-admin.adoc index f62419f2..4c47edff 100644 --- a/spring-pulsar-docs/src/main/asciidoc/pulsar-admin.adoc +++ b/spring-pulsar-docs/src/main/antora/modules/ROOT/pages/reference/pulsar-admin.adoc @@ -1,6 +1,6 @@ [[pulsar-admin]] = Pulsar Administration -include::attributes.adoc[] +include::../attributes/attributes.adoc[] [[pulsar-admin-client]] == Pulsar Admin Client @@ -18,7 +18,7 @@ See the {spring-boot-pulsar-config-props}[`spring.pulsar.admin.*`] application p [[pulsar-admin-authentication]] === Authentication When accessing a Pulsar cluster that requires authentication, the admin client requires the same security configuration as the regular Pulsar client. -You can use the aforementioned <> by replacing `spring.pulsar.client` with `spring.pulsar.admin`. +You can use the aforementioned xref:reference/pulsar.adoc#client-authentication[security configuration] by replacing `spring.pulsar.client` with `spring.pulsar.admin`. [[pulsar-auto-topic-creation]] == Automatic Topic Creation @@ -28,7 +28,6 @@ For all such beans, the `PulsarAdministration` either creates the corresponding The following example shows how to add `PulsarTopic` beans to let the `PulsarAdministration` auto-create topics for you: -==== [source,java] ---- @Bean @@ -43,4 +42,3 @@ PulsarTopic partitionedTopic { return PulsarTopic.builder("persistent://my-tenant/my-namespace/partitioned-topic", 3).build(); } ---- -==== diff --git a/spring-pulsar-docs/src/main/asciidoc/pulsar-binder.adoc b/spring-pulsar-docs/src/main/antora/modules/ROOT/pages/reference/pulsar-binder.adoc similarity index 98% rename from spring-pulsar-docs/src/main/asciidoc/pulsar-binder.adoc rename to spring-pulsar-docs/src/main/antora/modules/ROOT/pages/reference/pulsar-binder.adoc index 8b8ac855..ce771793 100644 --- a/spring-pulsar-docs/src/main/asciidoc/pulsar-binder.adoc +++ b/spring-pulsar-docs/src/main/antora/modules/ROOT/pages/reference/pulsar-binder.adoc @@ -1,6 +1,6 @@ [[pulsar-binder]] = Spring Cloud Stream Binder for Apache Pulsar -include::attributes.adoc[] +include::../attributes/attributes.adoc[] Spring for Apache Pulsar provides a binder for Spring Cloud Stream that we can use to build event-driven microservices using pub-sub paradigms. In this section, we will go through the basic details of this binder. @@ -11,8 +11,11 @@ TIP: For those unfamiliar with the concepts in Spring Cloud Stream, go through t We need to include the following dependency on your application to use Apache Pulsar binder for Spring Cloud Stream. +[tabs] +====== +Maven:: ++ [source,xml,indent=0,subs="verbatim,attributes",role="primary"] -.Maven ---- @@ -23,13 +26,15 @@ We need to include the following dependency on your application to use Apache Pu ---- +Gradle:: ++ [source,groovy,indent=0,subs="verbatim,attributes",role="secondary"] -.Gradle ---- dependencies { implementation 'org.springframework.cloud:spring-cloud-stream-binder-pulsar:{spring-cloud-stream-version}' } ---- +====== == Overview @@ -40,7 +45,6 @@ Applications can start from a middleware-neutral manner and then map Pulsar topi Spring Cloud Stream is built on top of Spring Boot, and when writing an event-driven microservice using Spring Cloud Stream, you are essentially writing a Boot application. Here is a straightforward Spring Cloud Stream application. -==== [source, java] ---- @SpringBootApplication @@ -80,7 +84,6 @@ public class SpringPulsarBinderSampleApp { } ---- -==== The above sample application, a full-blown Spring Boot application, deserves a few explanations. However, on a first pass, you can see that this is just plain Java and a few Spring and Spring Boot annotations. We have three `Bean` methods here - a `java.util.function.Supplier`, a `java.util.function.Function`, and finally, a `java.util.function.Consumer`. @@ -191,7 +194,7 @@ This information is provided as extended binding properties. As you can see above in the configuration, the properties are - `spring.cloud.stream.pulsar.bindings..producer|consumer.schema-type` for schema information and `spring.cloud.stream.pulsar.bindings..producer|consumer.message-type` for the actual target type. If you have both keys and values on the message, you can use `message-key-type` and `message-value-type` to specify their target types. -TIP: Any configured <> will be consulted when the `schema-type` property is omitted. +TIP: Any configured xref:reference/pulsar.adoc#schema-info-template-imperative[custom schema mappings] will be consulted when the `schema-type` property is omitted. === Message Header Conversion Each message typically has header information that needs to be carried along as the message traverses between Pulsar and Spring Messaging via Spring Cloud Stream input and output bindings. diff --git a/spring-pulsar-docs/src/main/asciidoc/pulsar-function.adoc b/spring-pulsar-docs/src/main/antora/modules/ROOT/pages/reference/pulsar-function.adoc similarity index 97% rename from spring-pulsar-docs/src/main/asciidoc/pulsar-function.adoc rename to spring-pulsar-docs/src/main/antora/modules/ROOT/pages/reference/pulsar-function.adoc index 7d2af5ad..584590bb 100644 --- a/spring-pulsar-docs/src/main/asciidoc/pulsar-function.adoc +++ b/spring-pulsar-docs/src/main/antora/modules/ROOT/pages/reference/pulsar-function.adoc @@ -1,6 +1,6 @@ [[pulsar-function]] = Pulsar Functions -include::attributes.adoc[] +include::../attributes/attributes.adoc[] Spring for Apache Pulsar provides basic suppport for {apache-pulsar-io-docs}/[Pulsar IO] (connectors) and {apache-pulsar-function-docs}[Pulsar Functions] which allow users to define stream processing pipelines made up of `sources`, `processors`, and `sinks`. The `sources` and `sinks` are modeled by _Pulsar IO (connectors)_ and the `processors` are represented by _Pulsar Functions_. @@ -24,7 +24,7 @@ The framework provides the `PulsarFunctionAdministration` component to manage Pu When you use the Pulsar Spring Boot starter, you get the `PulsarFunctionAdministration` auto-configured. By default, the application tries to connect to a local Pulsar instance at `http://localhost:8080`. -However, because it leverages the already configured `PulsarAdministration`, see <> for available client options (including authentication). +However, because it leverages the already configured `PulsarAdministration`, see xref:reference/pulsar-admin.adoc#pulsar-admin-client[Pulsar Admin Client] for available client options (including authentication). Additional configuration options are available with the {spring-boot-pulsar-config-props}[`spring.pulsar.function.*`] application properties. == Automatic Function Management @@ -99,7 +99,6 @@ The jar file can be uploaded to the Pulsar package manager and then referenced v Here are some examples that show how to configure a `PulsarSource` bean which results in the `PulsarFunctionAdministration` auto-creating the backing Pulsar source connector. .PulsarSource using built-in Rabbit connector -==== [source,java] ---- @Bean @@ -122,12 +121,10 @@ PulsarSource rabbitSource() { return new PulsarSource(sourceConfig, null); } ---- -==== This next example is the same as the previous, except that it uses the Spring Boot auto-configured `RabbitProperties` to ease the configuration burden. This of course requires the application to be using Spring Boot with Rabbit auto-configuration enabled. .PulsarSource using built-in Rabbit connector and Spring Boot RabbitProperties -==== [source,java] ---- @Bean @@ -150,6 +147,5 @@ PulsarSource rabbitSourceWithBootProps(RabbitProperties props) { return new PulsarSource(sourceConfig, null); } ---- -==== TIP: For a more elaborate example see the link:{github}/blob/main/spring-pulsar-sample-apps/sample-pulsar-functions/README.adoc[Sample Stream Pipeline with Pulsar Functions] sample app diff --git a/spring-pulsar-docs/src/main/asciidoc/pulsar-header.adoc b/spring-pulsar-docs/src/main/antora/modules/ROOT/pages/reference/pulsar-header.adoc similarity index 98% rename from spring-pulsar-docs/src/main/asciidoc/pulsar-header.adoc rename to spring-pulsar-docs/src/main/antora/modules/ROOT/pages/reference/pulsar-header.adoc index 5b1a0f4d..0af63873 100644 --- a/spring-pulsar-docs/src/main/asciidoc/pulsar-header.adoc +++ b/spring-pulsar-docs/src/main/antora/modules/ROOT/pages/reference/pulsar-header.adoc @@ -1,5 +1,5 @@ -include::attributes-variables.adoc[] +include::../attributes/attributes-variables.adoc[] === Pulsar Headers Pulsar does not have a first-class "`header`" concept but instead provides a map for custom user properties as well as methods to access the message metadata typically stored in a message header (eg. `id` and `event-time`). @@ -13,7 +13,6 @@ Spring Messaging provides first-class "`header`" support via its `MessageHeaders The `PulsarHeaderMapper` strategy is provided to map headers to and from Pulsar user properties and Spring `MessageHeaders`. Its interface definition is as follows: -==== [source, java] ---- public interface PulsarHeaderMapper { @@ -23,7 +22,6 @@ public interface PulsarHeaderMapper { MessageHeaders toSpringHeaders(Message pulsarMessage); } ---- -==== The framework provides a couple of mapper implementations. diff --git a/spring-pulsar-docs/src/main/asciidoc/pulsar.adoc b/spring-pulsar-docs/src/main/antora/modules/ROOT/pages/reference/pulsar.adoc similarity index 99% rename from spring-pulsar-docs/src/main/asciidoc/pulsar.adoc rename to spring-pulsar-docs/src/main/antora/modules/ROOT/pages/reference/pulsar.adoc index e1d568c4..3571c58b 100644 --- a/spring-pulsar-docs/src/main/asciidoc/pulsar.adoc +++ b/spring-pulsar-docs/src/main/antora/modules/ROOT/pages/reference/pulsar.adoc @@ -1,6 +1,6 @@ [[pulsar]] = Using Spring for Apache Pulsar -include::attributes.adoc[] +include::../attributes/attributes.adoc[] == Preface @@ -58,14 +58,12 @@ The template provides a {javadocs}/org/springframework/pulsar/core/PulsarOperati ==== Message customization You can specify a `TypedMessageBuilderCustomizer` to configure the outgoing message. For example, the following code shows how to send a keyed message: -==== [source, java] ---- template.newMessage(msg) .withMessageCustomizer((mb) -> mb.key("foo-msg-key")) .send(); ---- -==== ==== Producer customization You can specify a `ProducerBuilderCustomizer` to configure the underlying Pulsar producer builder that ultimately constructs the producer used to send the outgoing message. @@ -73,37 +71,31 @@ You can specify a `ProducerBuilderCustomizer` to configure the underlying Pulsar WARNING: Use with caution as this gives full access to the producer builder and invoking some of its methods (such as `create`) may have unintended side effects. For example, the following code shows how to disable batching and enable chunking: -==== [source, java] ---- template.newMessage(msg) .withProducerCustomizer((pb) -> pb.enableChunking(true).enableBatching(false)) .send(); ---- -==== This other example shows how to use custom routing when publishing records to partitioned topics. Specify your custom `MessageRouter` implementation on the `Producer` builder such as: -==== [source, java] ---- template.newMessage(msg) .withProducerCustomizer((pb) -> pb.messageRouter(messageRouter)) .send(); ---- -==== TIP: Note that, when using a `MessageRouter`, the only valid setting for `spring.pulsar.producer.message-routing-mode` is `custom`. This other example shows how to add a `ProducerInterceptor` that will intercept and mutate messages received by the producer before being published to the brokers: -==== [source, java] ---- template.newMessage(msg) .withProducerCustomizer((pb) -> pb.intercept(interceptor)) .send(); ---- -==== [[schema-info-template-imperative]] :template-class: PulsarTemplate @@ -131,7 +123,6 @@ If you use Spring Boot auto-configuration, you can specify the interceptors as B They are passed automatically to the `PulsarTemplate`. Ordering of the interceptors is achieved by using the `@Order` annotation as follows: -==== [source, java] ---- @Bean @@ -146,7 +137,6 @@ ProducerInterceptor secondInterceptor() { ... } ---- -==== NOTE: If you are not using the starter, you will need to configure and register the aforementioned components yourself. @@ -165,7 +155,6 @@ Spring Boot auto-configuration also provides this consumer factory which you can Let us revisit the `PulsarListener` code snippet we saw in the quick-tour section: -==== [source, java] ---- @PulsarListener(subscriptionName = "hello-pulsar-subscription", topics = "hello-pulsar") @@ -173,11 +162,9 @@ public void listen(String message) { System.out.println("Message Received: " + message); } ---- -==== You can further simplify this method: -==== [source, java] ---- @PulsarListener @@ -185,7 +172,6 @@ public void listen(String message) { System.out.println("Message Received: " + message); } ---- -==== In this most basic form, you must provide the following two properties with their corresponding values: @@ -208,7 +194,6 @@ For any complex types (such as JSON, AVRO, and others), the framework cannot do The following example shows another `PulsarListener` method, which takes an `Integer`: -==== [source, java] ---- @PulsarListener(subscriptionName = "my-subscription-1", topics = "my-topic-1") @@ -216,11 +201,9 @@ public void listen(Integer message) { System.out.println(message); } ---- -==== The following `PulsarListener` method shows how we can consume complex types from a topic: -==== [source, java] ---- @PulsarListener(subscriptionName = "my-subscription-2", topics = "my-topic-2", schemaType = SchemaType.JSON) @@ -228,7 +211,6 @@ public void listen(Foo message) { System.out.println(message); } ---- -==== Note the addition of a `schemaType` property on `PulsarListener`. That is because the library is not capable of inferring the schema type from the provided type: `Foo`. We must tell the framework what schema to use. @@ -237,7 +219,6 @@ Let us look at a few more ways. You can consume the Pulsar message directly: -==== [source, java] ---- @PulsarListener(subscriptionName = "my-subscription", topics = "my-topic") @@ -245,11 +226,9 @@ public void listen(org.apache.pulsar.client.api.Message message) { System.out.println(message.getValue()); } ---- -==== The following example consumes the record by using the Spring messaging envelope: -==== [source, java] ---- @PulsarListener(subscriptionName = "my-subscription", topics = "my-topic") @@ -257,12 +236,10 @@ public void listen(org.springframework.messaging.Message message) { System.out.println(message.getPayload()); } ---- -==== Now let us see how we can consume records in batches. The following example uses `PulsarListener` to consume records in batches as POJOs: -==== [source, java] ---- @PulsarListener(subscriptionName = "hello-batch-subscription", topics = "hello-batch", schemaType = SchemaType.JSON, batch = true) @@ -271,7 +248,6 @@ public void listen(List messages) { messages.forEach((message) -> System.out.println("record : " + message)); } ---- -==== Note that, in this example, we receive the records as a collection (`List`) of objects. In addition, to enable batch consumption at the `PulsarListener` level, you need to set the `batch` property on the annotation to `true`. @@ -281,7 +257,6 @@ If the `List` contains a complex type, you still need to provide the `schemaType The following uses the `Message` envelope provided by the Pulsar Java client: -==== [source, java] ---- @PulsarListener(subscriptionName = "hello-batch-subscription", topics = "hello-batch", schemaType = SchemaType.JSON, batch = true) @@ -290,11 +265,9 @@ public void listen(List> messages) { messages.forEach((message) -> System.out.println("record : " + message.getValue())); } ---- -==== The following example consumes batch records with an envelope of the Spring messaging `Message` type: -==== [source, java] ---- @PulsarListener(subscriptionName = "hello-batch-subscription", topics = "hello-batch", schemaType = SchemaType.JSON, batch = true) @@ -303,11 +276,9 @@ public void listen(List> messages) { messages.forEach((message) -> System.out.println("record : " + message.getPayload())); } ---- -==== Finally, you can also use the `Messages` holder object from Pulsar for the batch listener: -==== [source, java] ---- @PulsarListener(subscriptionName = "hello-batch-subscription", topics = "hello-batch", schemaType = SchemaType.JSON, batch = true) @@ -316,21 +287,18 @@ public void listen(org.apache.pulsar.client.api.Messages> messages) { messages.forEach((message) -> System.out.println("record : " + message.getValue())); } ---- -==== When you use `PulsarListener`, you can provide Pulsar consumer properties directly on the annotation itself. This is convenient if you do not want to use the Boot configuration properties mentioned earlier or have multiple `PulsarListener` methods. The following example uses Pulsar consumer properties directly on `PulsarListener`: -==== [source, java] ---- @PulsarListener(properties = { "subscriptionName=subscription-1", "topicNames=foo-1", "receiverQueueSize=5000" }) void listen(String message) { } ---- -==== TIP: The properties used are direct Pulsar consumer properties, not the `spring.pulsar.consumer` application configuration properties @@ -342,7 +310,6 @@ include::schema-info/schema-info-listener.adoc[leveloffset=+1] Sometimes, you need direct access to the Pulsar Consumer object. The following example shows how to get it: -==== [source, java] ---- @PulsarListener(subscriptionName = "hello-pulsar-subscription", topics = "hello-pulsar") @@ -352,7 +319,6 @@ public void listen(String message, org.apache.pulsar.client.api.Consumer ... } ---- -==== CAUTION: When accessing the `Consumer` object this way, do NOT invoke any operations that would change the Consumer's cursor position by invoking any receive methods. All such operations must be done by the container. @@ -394,31 +360,26 @@ Before doing so, however, let us take a closer look at the container itself. This is a single consumer-based message listener container. The following listing shows its constructor: -==== [source, java] ---- public DefaultPulsarMessageListenerContainer(PulsarConsumerFactory pulsarConsumerFactory, PulsarContainerProperties pulsarContainerProperties) } ---- -==== It receives a `PulsarConsumerFactory` (which it uses to create the consumer) and a `PulsarContainerProperties` object (which contains information about the container properties). `PulsarContainerProperties` has the following constructors: -==== [source, java] ---- public PulsarContainerProperties(String... topics) public PulsarContainerProperties(Pattern topicPattern) ---- -==== You can provide the topic information through `PulsarContainerProperties` or as a consumer property that is provided to the consumer factory. The following example uses the `DefaultPulsarMessageListenerContainer`: -==== [source, java] ---- Map config = new HashMap<>(); @@ -435,7 +396,6 @@ DefaultPulsarMessageListenerContainer pulsarListenerContainer = new Defa return pulsarListenerContainer; ---- -==== NOTE: If topic information is not specified when using the listener containers directly, the same <> used by the `PulsarListener` is used with the one exception that the "Message type default" step is **omitted**. @@ -446,13 +406,11 @@ If you want to have multiple consumers managed through multiple threads, you nee `ConcurrentPulsarMessageListenerContainer` has the following constructor: -==== [source, java] ---- public ConcurrentPulsarMessageListenerContainer(PulsarConsumerFactory pulsarConsumerFactory, PulsarContainerProperties pulsarContainerProperties) ---- -==== `ConcurrentPulsarMessageListenerContainer` lets you specify a `concurrency` property through a setter. Concurrency of more than `1` is allowed only on non-exclusive subscriptions (`failover`, `shared`, and `key-shared`). @@ -460,7 +418,6 @@ You can only have the default `1` for concurrency when you have an exclusive sub The following example enables `concurrency` through the `PulsarListener` annotation for a `failover` subscription. -==== [source, java] ---- @PulsarListener(topics = "my-topic", subscriptionName = "subscription-1", @@ -471,7 +428,6 @@ void listen(String message, Consumer consumer) { System.out.println("Current Consumer: " + consumer.getConsumerName()); } ---- -==== In the preceding listener, it is assumed that the topic `my-topic` has three partitions. If it is a non-partitioned topic, having concurrency set to `3` does nothing. You get two idle consumers in addition to the main active one. @@ -482,7 +438,6 @@ NOTE: When you use the `Failover` subscription this way on partitioned topics, P The following listing shows another example of `PulsarListener`, but with `Shared` subscription and `concurrency` enabled. -==== [source, java] ---- @PulsarListener(topics = "my-topic", subscriptionName = "subscription-1", @@ -491,7 +446,6 @@ void listen(String message) { ... } ---- -==== In the preceding example, the `PulsarListener` creates five different consumers (this time, we assume that the topic has five partitions). @@ -507,7 +461,6 @@ Let us take a look at how the message listener container enables both single-rec ==== Single Record Consumption Let us revisit our basic `PulsarListener` for the sake of this discussion: -==== [source, java] ---- @PulsarListener(subscriptionName = "hello-pulsar-subscription", topics = "hello-pulsar") @@ -515,7 +468,6 @@ public void listen(String message) { System.out.println("Message Received: " + message); } ---- -==== With this `PulsarListener` method, we essential ask Spring for Apache Pulsar to invoke the listener method with a single record each time. We mentioned that the message listener container consumes the data in batches using the `batchReceive` method on the consumer. @@ -527,7 +479,6 @@ As you can see in the previous section, `PulsarRecordMessageListener` extends fr ==== Batch Consumption The following example shows the `PulsarListener` consuming records in batches: -==== [source, java] ---- @PulsarListener(subscriptionName = "hello-batch-subscription", topics = "hello-batch", schemaType = SchemaType.JSON, batch = true) @@ -536,7 +487,6 @@ public void listen4(List messages) { messages.forEach((message) -> System.out.println("record : " + message)); } ---- -==== When you use this type of `PulsarListener`, the framework detects that you are in batch mode. Since it already received the data in batches by using the Consumer's `batchReceive` method, it hands off the entire batch to the listener method through an adapter for `PulsarBatchMessageListener`. @@ -550,7 +500,6 @@ The list of available headers can be found in {github}/blob/main/spring-pulsar/s The following example shows how you can access the various Pulsar Headers in an application that uses the single record mode of consuming: -==== [source,java] ---- @PulsarListener(topics = "simpleListenerWithHeaders") @@ -560,7 +509,6 @@ void simpleListenerWithHeaders(String data, @Header(PulsarHeaders.MESSAGE_ID) Me } ---- -==== In the preceding example, we access the values for the `messageId` and `rawData` message metadata as well as a custom message property named `foo`. The Spring `@Header` annotation is used for each header field. @@ -574,7 +522,6 @@ Note that you can also use the Spring messaging `Message` envelope to carry the In this section, we see how to access the various Pulsar Headers in an application that uses a batch consumer: -==== [source,java] ---- @PulsarListener(topics = "simpleBatchListenerWithHeaders", batch = true) @@ -584,7 +531,6 @@ void simpleBatchListenerWithHeaders(List data, } ---- -==== In the preceding example, we consume the data as a `List`. When extracting the various headers, we do so as a `List<>` as well. @@ -613,7 +559,6 @@ In the following sections, we see how acknowledgment works when you use both sin Let us revisit our basic single message based `PulsarListener`: -==== [source, java] ---- @PulsarListener(subscriptionName = "hello-pulsar-subscription", topics = "hello-pulsar") @@ -621,7 +566,6 @@ public void listen(String message) { System.out.println("Message Received: " + message); } ---- -==== It is natural to wonder, how acknowledgment works when you use `PulsarListener`, especially if you are familiar with using Pulsar consumer directly. The answer comes down to the message listener container, as that is the central place in Spring for Apache Pulsar that coordinates all the consumer related activities. @@ -641,7 +585,6 @@ If the application wants the acknowledgment or negative acknowledgment to occur In that case, after handling each record, the message is acknowledged if no error and negatively acknowledged if there was an error. The following example enables `RECORD` ack mode on the Pulsar listener: -==== [source, java] ---- @PulsarListener(subscriptionName = "hello-pulsar-subscription", topics = "hello-pulsar", ackMode = AckMode.RECORD) @@ -649,7 +592,6 @@ public void listen(String message) { System.out.println("Message Received: " + message); } ---- -==== You can also set the listener property, `spring.pulsar.listner.ack-mode`, to set the ack mode application-wide. When doing this, you need not set this on the `PulsarListener` annotation. @@ -660,7 +602,6 @@ In that case, all the `PulsarListener` methods in the application acquire that p You might not always want the framework to send acknowledgments but, rather, do that directly from the application itself. Spring for Apache Pulsar provides a couple of ways to enable manual message acknowledgments. The following example shows one of them: -==== [source, java] ---- @PulsarListener(subscriptionName = "hello-pulsar-subscription", topics = "hello-pulsar", ackMode = AckMode.MANUAL) @@ -669,7 +610,6 @@ public void listen(Message message, Acknowledgment acknowledgment) { acknowledgment.acknowledge(); } ---- -==== A few things merit explanation here. First, we enablE manual ack mode by setting `ackMode` on `PulsarListener`. When enabling manual ack mode, Spring for Apache Pulsar lets the application inject an `Acknowledgment` object. @@ -677,7 +617,6 @@ The framework achieves this by selecting a compatible message listener container The `Acknowledgment` object provides the following API methods: -==== [source, java] ---- void acknowledge(); @@ -690,7 +629,6 @@ void nack(); void nack(MessageId messageId); ---- -==== You can inject this `Acknowledgment` object into your `PulsarListener` while using `MANUAL` ack mode and then call one of the corresponding methods. @@ -705,7 +643,6 @@ See the nack methods shown earlier. You can also call `acknowledge` directly on the Pulsar consumer: -==== [source, java] ---- @PulsarListener(subscriptionName = "hello-pulsar-subscription", topics = "hello-pulsar", ackMode = AckMode.MANUAL) @@ -719,7 +656,6 @@ public void listen(Message message, Consumer consumer) { } } ---- -==== When calling `acknowledge` directly on the underlying consumer, you need to do error handling by yourself. Using the `Acknowledgment` does not require that, as the framework can do that for you. @@ -736,7 +672,6 @@ Note that this may not be the same batch that was batched on the producer side. Consider the following batch listener: -==== [source, java] ---- @PulsarListener(subscriptionName = "hello-pulsar-subscription", topics = "hello-pulsar", batch = true) @@ -746,7 +681,6 @@ public void batchListen(List messages) { } } ---- -==== When all the messages in the incoming collection (`messages` in this example) are processed, the framework acknowledges all of them. @@ -761,7 +695,6 @@ It is entirely up to the application to take care of such concerns. When `MANUAL` ack mode is set, Spring for Apache Pulsar selects a compatible message listener container: `PulsarBatchAcknowledgingMessageListener` for batch consumption, which gives you access to an `Acknowledgment` object. The following are the methods available in the `Acknowledgment` API: -==== [source, java] ---- void acknowledge(); @@ -774,12 +707,10 @@ void nack(); void nack(MessageId messageId); ---- -==== You can inject this `Acknowledgment` object into your `PulsarListener` while using `MANUAL` ack mode. The following listing shows a basic example for a batch based listener: -==== [source, java] ---- @PulsarListener(subscriptionName = "hello-pulsar-subscription", topics = "hello-pulsar") @@ -795,7 +726,6 @@ public void listen(List> messgaes, Acknowlegement acknowledgment } } ---- -==== When you use a batch listener, the message listener container cannot know which record it is currently operating upon. Therefore, to manually acknowledge, you need to use one of the overloaded `acknowledge` method that takes a `MessageId` or a `List`. @@ -814,7 +744,6 @@ If this property has a value above zero and if the Pulsar consumer does not ackn You can also specify this property directly as a Pulsar consumer property on the `PulsarListener` itself: -==== [source, java] ---- @PulsarListener(subscriptionName = "subscription-1", topics = "topic-1" @@ -823,13 +752,11 @@ public void listen(String s) { ... } ---- -==== When you specify `ackTimeout` (as seen in the preceding `PulsarListener` method), if the consumer does not send an acknowledgement within 60 seconds, the message is redelivered by Pulsar to the consumer. If you want to specify some advanced backoff options for ack timeout with different delays, you can do the following: -==== [source, java] ---- @EnablePulsar @@ -852,7 +779,6 @@ class AckTimeoutRedeliveryConfig { } ---- -==== In the preceding example, we specify a bean for Pulsar's `RedeliveryBackoff` with a minimum delay of 1 second, a maximum delay of 10 seconds, and a backoff multiplier of 2. After the initial ack timeout occurs, the message redeliveries are controlled through this backoff bean. @@ -864,7 +790,6 @@ When acknowledging negatively, Pulsar consumer lets you specify how the applicat The default is to redeliver the message in one minute, but you can change it by setting `spring.pulsar.consumer.negative-ack-redelivery-delay`. You can also set it as a consumer property directly on `PulsarListener`, as follows: -==== [source, java] ---- @PulsarListener(subscriptionName = "subscription-1", topics = "topic-1" @@ -873,11 +798,9 @@ public void listen(String s) { ... } ---- -==== You can also specify different delays and backoff mechanisms with a multiplier by providing a `RedeliveryBackoff` bean and providing the bean name as the `negativeAckRedeliveryBackoff` property on the PulsarProducer, as follows: -==== [source, java] ---- @EnablePulsar @@ -899,7 +822,6 @@ class NegativeAckRedeliveryConfig { } ---- -==== ==== Using Dead Letter Topic from Apache Pulsar for Message Redelivery and Error Handling @@ -908,7 +830,6 @@ For the `Exclusive` and `Failover` subscription types, this feature is not avail The basic idea is that, if a message is retried a certain number of times (maybe due to an ack timeout or nack redelivery), once the number of retries are exhausted, the message can be sent to a special topic called the dead letter queue (DLQ). Let us see some details around this feature in action by inspecting some code snippets: -==== [source, java] ---- @EnablePulsar @@ -934,7 +855,6 @@ class DeadLetterPolicyConfig { } ---- -==== First, we have a special bean for `DeadLetterPolicy`, and it is named as `deadLetterPolicy` (it can be any name as you wish). This bean specifies a number of things, such as the max delivery (10, in this case) and the name of the dead letter topic -- `my-dlq-topic`, in this case. @@ -967,7 +887,6 @@ When you use `PulsarConsumerErrorHandler` from Spring for Apache Pulsar, make su Let us see some details by examining a few code snippets: -==== [source, java] ---- @EnablePulsar @@ -995,14 +914,12 @@ class PulsarConsumerErrorHandlerConfig { } ---- -==== Consider the `pulsarConsumerErrorHandler` bean. This creates a bean of type `PulsarConsumerErrorHandler` and uses the default implementation provided out of the box by Spring for Apache Pulsar: `DefaultPulsarConsumerErrorHandler`. `DefaultPulsarConsumerErrorHandler` has a constructor that takes a `PulsarMessageRecovererFactory` and a `org.springframework.util.backoff.Backoff`. `PulsarMessageRecovererFactory` is a functional interface with the following API: -==== [source, java] ---- @FunctionalInterface @@ -1018,12 +935,10 @@ public interface PulsarMessageRecovererFactory { } ---- -==== The `recovererForConsumer` method takes a Pulsar consumer and returns a `PulsarMessageRecoverer`, which is another functional interface. Here is the API of `PulsarMessageRecoverer`: -==== [source, java] ---- public interface PulsarMessageRecoverer { @@ -1037,7 +952,6 @@ public interface PulsarMessageRecoverer { } ---- -==== Spring for Apache Pulsar provides an implementation for `PulsarMessageRecovererFactory` called `PulsarDeadLetterPublishingRecoverer` that provides a default implementation that can recover the message by sending it to a Dead Letter Topic (DLT). We provide this implementation to the constructor for the preceding `DefaultPulsarConsumerErrorHandler`. @@ -1054,7 +968,6 @@ In most cases, the same auto-configured `PulsarTemplate` from Spring Boot is suf When using partitioned topics and using custom message routing for the main topic, you must use a different `PulsarTemplate` that does not take the auto-configured `PulsarProducerFactory` that is populated with a value of `custompartition` for `message-routing-mode`. You can use a `PulsarConsumerErrorHandler` with the following blueprint: -==== [source, java] ---- @Bean @@ -1072,7 +985,6 @@ PulsarConsumerErrorHandler pulsarConsumerErrorHandler(PulsarClient puls new FixedBackOff(100, 5)); } ---- -==== Note that we are provide a destination resolver to the `PulsarDeadLetterPublishingRecoverer` as the second constructor argument. If not provided, `PulsarDeadLetterPublishingRecoverer` uses `--DLT>` as the DLT topic name. @@ -1090,7 +1002,6 @@ Next, we look at how you can use this on batch listeners. First, let us look at a batch `PulsarListener` method: -==== [source, java] ---- @PulsarListener(subscriptionName = "batch-demo-5-sub", topics = "batch-demo-4", batch = true, concurrency = "3", @@ -1118,7 +1029,6 @@ void dltReceiver(Message message) { } ---- -==== Once again, we provide the `pulsarConsumerErrorHandler` property with the `PulsarConsumerErrorHandler` bean name. When you use a batch listener (as shown in the preceding example) and want to use the `PulsarConsumerErrorHandler` from Spring for Apache Pulsar, you need to use manual acknowledgment. @@ -1134,7 +1044,6 @@ At that point, the message is acknowledged by the container, and the listener is Spring for Apache Pulsar provides a convenient way to customize the consumer created by the container used by the `PulsarListener`. Applications can provide a bean for `ConsumerBuilderCustomizer`. Here is an example. -==== [source, java] ---- @Bean @@ -1144,11 +1053,9 @@ public ConsumerBuilderCustomizer myCustomizer() { }; } ---- -==== Then this customizer bean name can be provided as an attribute on the `PuslarListener` annotation as shown below. -==== [source, java] ---- @PulsarListener(subscriptionName = "my-subscription", @@ -1157,7 +1064,6 @@ void listen(String message) { } ---- -==== The framework detects the provided bean through the `PulsarListener` and applies this customizer on the Consumer builder before creating the Pulsar Consumer. @@ -1172,7 +1078,6 @@ When the Pulsar message listener container is paused, any polling done by the co Similarly, when the container is resumed, the next poll starts returning data if the topic has any new records added while paused. To pause or resume a listener container, first obtain the container instance via the `PulsarListenerEndpointRegistry` bean and then invoke the pause/resume API on the container instance - as shown in the snippet below: -==== [source, java] ---- @Autowired @@ -1183,7 +1088,6 @@ void someMethod() { container.pause(); } ---- -==== TIP: The id parameter passed to `getListenerContainer` is the container id - which will be the value of the `@PulsarListener` id attribute when pausing/resuming a `@PulsarListener`. @@ -1199,7 +1103,6 @@ While it is possible to use `PulsarReaderFactory` directly, Spring for Apache Pu This is similar to the same ideas behind `PulsarListener.` Here is a quick example. -==== [source, java] ---- @PulsarReader(id = "pulsar-reader-demo-id", subscriptionName = "pulsar-reader-demo-subscription", @@ -1208,7 +1111,6 @@ void read(String message) { //... } ---- -==== As you can see from the above example, `PulsarReader` is a quick way to read from a Pulsar topic. The `id` and `subscriptionName` attributes are optional, but always a best practice to provide them. @@ -1223,7 +1125,6 @@ Suppose you want the reader to start reading messages arbitrarily from a topic o You can customize any fields available through `ReaderBuilder` using a `ReaderBuilderCustomizer` in Spring for Apache Pulsar. You can provide a `@Bean` from `ReaderBuilderCustomizer` and then make it available to the `PulsarReader` as below. -==== [source, java] ---- @PulsarReader(id = "with-customizer-reader", subscriptionName = "with-customizer-reader-subscription", @@ -1240,7 +1141,6 @@ public ReaderBuilderCustomizer myCustomizer() { }; } ---- -==== [[topic-resolution-process-imperative]] == Topic Resolution @@ -1251,7 +1151,6 @@ include::topic-resolution.adoc[leveloffset=+1] In the following example, we publish to a topic called `hello-pulsar-partitioned`. It is a topic that is partitioned, and, for this sample, we assume that the topic is already created with three partitions. -==== [source, java] ---- @SpringBootApplication @@ -1304,7 +1203,6 @@ public class PulsarBootPartitioned { } ---- -==== In the preceding example, we publish to a partitioned topic, and we would like to publish some data segment to a specific partition. If you leave it to Pulsar's default, it follows a round-robin mode of partition assignments, and we would like to override that. @@ -1320,7 +1218,6 @@ This means that data from all the partitions ends up in the same consumer and th What can we do if we want each partition to be consumed by a single distinct consumer? We can switch to the `failover` subscription mode and add three separate consumers: -==== [source, java] ---- @PulsarListener(subscriptionName = "hello-pulsar-partitioned-subscription", topics = "hello-pulsar-partitioned", subscriptionType = SubscriptionType.Failover) @@ -1338,7 +1235,6 @@ public void listen3(String foo) { System.out.println("Message Received 3: " + foo); } ---- -==== When you follow this approach, a single partition always gets consumed by a dedicated consumer. @@ -1347,7 +1243,6 @@ However, when you use the `shared` mode, you lose any ordering guarantees, as a Consider the following example: -==== [source, java] ---- @PulsarListener(subscriptionName = "hello-pulsar-shared-subscription", topics = "hello-pulsar-partitioned", subscriptionType = SubscriptionType.Shared) @@ -1360,4 +1255,3 @@ public void listen2(String foo) { System.out.println("Message Received 2: " + foo); } ---- -==== diff --git a/spring-pulsar-docs/src/main/asciidoc/quick-tour.adoc b/spring-pulsar-docs/src/main/antora/modules/ROOT/pages/reference/quick-tour.adoc similarity index 96% rename from spring-pulsar-docs/src/main/asciidoc/quick-tour.adoc rename to spring-pulsar-docs/src/main/antora/modules/ROOT/pages/reference/quick-tour.adoc index 56bc402e..f63296fd 100644 --- a/spring-pulsar-docs/src/main/asciidoc/quick-tour.adoc +++ b/spring-pulsar-docs/src/main/antora/modules/ROOT/pages/reference/quick-tour.adoc @@ -1,6 +1,6 @@ [[quick-tour]] = Quick Tour -include::attributes.adoc[] +include::../attributes/attributes.adoc[] We will take a quick tour of Spring for Apache Pulsar by showing a sample Spring Boot application that produces and consumes. This is a complete application and does not require any additional configuration, as long as you have a Pulsar cluster running on the default location - `localhost:6650`. @@ -8,8 +8,11 @@ This is a complete application and does not require any additional configuration == Dependencies Spring Boot applications need only the `spring-pulsar-spring-boot-starter` dependency. The following listings show how to define the dependency for Maven and Gradle, respectively: +[tabs] +====== +Maven:: ++ [source,xml,indent=0,subs="verbatim,attributes",role="primary"] -.Maven ---- @@ -20,20 +23,25 @@ Spring Boot applications need only the `spring-pulsar-spring-boot-starter` depen ---- +Gradle:: ++ [source,groovy,indent=0,subs="verbatim,attributes",role="secondary"] -.Gradle ---- dependencies { implementation 'org.springframework.boot:spring-boot-starter-pulsar:{spring-boot-version}' } ---- +====== [CAUTION] ==== When using `Version 0.2.x` the above coordinates change as follows: +[tabs] +====== +Maven:: ++ [source,xml,indent=0,subs="verbatim,attributes",role="primary"] -.Maven ---- @@ -43,13 +51,16 @@ When using `Version 0.2.x` the above coordinates change as follows: ---- + +Gradle:: ++ [source,groovy,indent=0,subs="verbatim,attributes",role="secondary"] -.Gradle ---- dependencies { implementation 'org.springframework.pulsar:spring-pulsar-spring-boot-starter:0.2.0' } ---- +====== ==== == Application Code diff --git a/spring-pulsar-docs/src/main/asciidoc/reactive-pulsar.adoc b/spring-pulsar-docs/src/main/antora/modules/ROOT/pages/reference/reactive-pulsar.adoc similarity index 98% rename from spring-pulsar-docs/src/main/asciidoc/reactive-pulsar.adoc rename to spring-pulsar-docs/src/main/antora/modules/ROOT/pages/reference/reactive-pulsar.adoc index ae6f32fb..6a1be8db 100644 --- a/spring-pulsar-docs/src/main/asciidoc/reactive-pulsar.adoc +++ b/spring-pulsar-docs/src/main/antora/modules/ROOT/pages/reference/reactive-pulsar.adoc @@ -1,6 +1,6 @@ [[reactive-pulsar]] = Reactive Support -include::attributes.adoc[] +include::../attributes/attributes.adoc[] The framework provides a Reactive counterpart for almost all supported features. @@ -56,7 +56,7 @@ See the {spring-boot-pulsar-config-props}[`spring.pulsar.client.*`] application [[reactive-client-authentication]] === Authentication -To connect to a Pulsar cluster that requires authentication, follow <> as the imperative client. +To connect to a Pulsar cluster that requires authentication, follow xref:reference/pulsar.adoc#client-authentication[the same steps] as the imperative client. Again, this is because the reactive client adapts the imperative client which handles all security configuration. [[reactive-message-production]] @@ -76,14 +76,12 @@ The template provides a {javadocs}/org/springframework/pulsar/reactive/core/Reac ==== Message customization You can specify a `MessageSpecBuilderCustomizer` to configure the outgoing message. For example, the following code shows how to send a keyed message: -==== [source, java] ---- template.newMessage(msg) .withMessageCustomizer((mc) -> mc.key("foo-msg-key")) .send(); ---- -==== ==== Sender customization You can specify a `ReactiveMessageSenderBuilderCustomizer` to configure the underlying Pulsar sender builder that ultimately constructs the sender used to send the outgoing message. @@ -91,25 +89,21 @@ You can specify a `ReactiveMessageSenderBuilderCustomizer` to configure the unde WARNING: Use with caution as this gives full access to the sender builder and invoking some of its methods (such as `create`) may have unintended side effects. For example, the following code shows how to disable batching and enable chunking: -==== [source, java] ---- template.newMessage(msg) .withSenderCustomizer((sc) -> sc.enableChunking(true).enableBatching(false)) .send(); ---- -==== This other example shows how to use custom routing when publishing records to partitioned topics. Specify your custom `MessageRouter` implementation on the sender builder such as: -==== [source, java] ---- template.newMessage(msg) .withSenderCustomizer((sc) -> sc.messageRouter(messageRouter)) .send(); ---- -==== TIP: Note that, when using a `MessageRouter`, the only valid setting for `spring.pulsar.reactive.sender.message-routing-mode` is `custom`. @@ -144,7 +138,6 @@ When you use Spring Boot support, it automatically enables this annotation and c Let us revisit the `ReactivePulsarListener` code snippet we saw in the quick-tour section: -==== [source, java] ---- @ReactivePulsarListener(subscriptionName = "hello-pulsar-sub", topics = "hello-pulsar-topic") @@ -153,12 +146,10 @@ Mono listen(String message) { return Mono.empty(); } ---- -==== NOTE: The listener method returns a `Mono` to signal whether the message was successfully processed. `Mono.empty()` indicates success (acknowledgment) and `Mono.error()` indicates failure (negative acknowledgment). You can also further simplify this method: -==== [source, java] ---- @ReactivePulsarListener @@ -167,7 +158,6 @@ Mono listen(String message) { return Mono.empty(); } ---- -==== In this most basic form, you must still provide the topic name by setting the following property: @@ -190,7 +180,6 @@ For all the primitive types in Java, the framework does this inference. For any complex types (such as JSON, AVRO, and others), the framework cannot do this inference and the user needs to provide the schema type on the annotation using the `schemaType` property. This example shows how we can consume complex types from a topic: -==== [source, java] ---- @ReactivePulsarListener(topics = "my-topic-2", schemaType = SchemaType.JSON) @@ -199,7 +188,6 @@ Mono listen(Foo message) { return Mono.empty(); } ---- -==== Note the addition of a `schemaType` property on `ReactivePulsarListener`. That is because the library is not capable of inferring the schema type from the provided type: `Foo`. We must tell the framework what schema to use. @@ -207,7 +195,6 @@ That is because the library is not capable of inferring the schema type from the Let us look at a few more ways we can consume. This example consumes the Pulsar message directly: -==== [source, java] ---- @ReactivePulsarListener(topics = "my-topic") @@ -216,10 +203,8 @@ Mono listen(org.apache.pulsar.client.api.Message message) { return Mono.empty(); } ---- -==== This example consumes the record wrapped in a Spring messaging envelope: -==== [source, java] ---- @ReactivePulsarListener(topics = "my-topic") @@ -228,7 +213,6 @@ Mono listen(org.springframework.messaging.Message message) { return Mono.empty(); } ---- -==== ==== Streaming All of the above are examples of consuming a single record one-by-one. @@ -236,7 +220,6 @@ However, one of the compelling reasons to use Reactive is for the streaming capa The following example uses `ReactivePulsarListener` to consume a stream of POJOs: -==== [source, java] ---- @ReactivePulsarListener(topics = "streaming-1", stream = true) @@ -245,7 +228,6 @@ Flux> listen(Flux> messages) { .doOnNext((msg) -> System.out.println("Received: " + msg.getValue())) .map(MessageResult::acknowledge); ---- -==== Here we receive the records as a `Flux` of messages. In addition, to enable stream consumption at the `ReactivePulsarListener` level, you need to set the `stream` property on the annotation to `true`. @@ -255,7 +237,6 @@ Based on the actual type of the messages in the `Flux`, the framework tries to i If it contains a complex type, you still need to provide the `schemaType` on `ReactivePulsarListener`. The following listener uses the Spring messaging `Message` envelope with a complex type : -==== [source, java] ---- @ReactivePulsarListener(topics = "streaming-2", stream = true, schemaType = SchemaType.JSON) @@ -265,7 +246,6 @@ Flux> listen2(Flux myConsumerCustomizer() { return b -> b.subscriptionInitialPosition(SubscriptionInitialPosition.Earliest); } ---- -==== You can also use the customizer to provide direct Pulsar consumer properties to the consumer builder. This is convenient if you do not want to use the Boot configuration properties mentioned earlier or have multiple `ReactivePulsarListener` methods whose configuration varies. The following customizer example uses direct Pulsar consumer properties: -==== [source, java] ---- @Bean @@ -310,7 +287,6 @@ ReactiveMessageConsumerBuilderCustomizer directConsumerPropsCustomizer() return b -> b.property("subscriptionName", "subscription-1").property("topicNames", "foo-1"); } ---- -==== CAUTION: The properties used are direct Pulsar consumer properties, not the `spring.pulsar.reactive.consumer` Spring Boot configuration properties @@ -368,7 +344,6 @@ The list of available headers can be found in {github}/blob/main/spring-pulsar/s ==== Accessing In OneByOne Listener The following example shows how you can access Pulsar Headers when using a one-by-one message listener: -==== [source,java] ---- @ReactivePulsarListener(topics = "some-topic") @@ -379,7 +354,6 @@ Mono listen(String data, return Mono.empty(); } ---- -==== In the preceding example, we access the values for the `messageId` message metadata as well as a custom message property named `foo`. The Spring `@Header` annotation is used for each header field. @@ -421,7 +395,6 @@ If this property has a value above zero and if the Pulsar consumer does not ackn You can also specify this property directly as a Pulsar consumer property via a <> such as: -==== [source, java] ---- @Bean @@ -429,7 +402,6 @@ ReactiveMessageConsumerBuilderCustomizer consumerCustomizer() { return b -> b.property("ackTimeout", "60s"); } ---- -==== ==== Negative Acknowledgment Redelivery Delay When acknowledging negatively, Pulsar consumer lets you specify how the application wants the message to be re-delivered. @@ -437,7 +409,6 @@ The default is to redeliver the message in one minute, but you can change it by You can also set it directly as a Pulsar consumer property via a <> such as: -==== [source, java] ---- @Bean @@ -445,7 +416,6 @@ ReactiveMessageConsumerBuilderCustomizer consumerCustomizer() { return b -> b.property("negativeAckRedeliveryDelay", "10ms"); } ---- -==== ==== Dead Letter Topic Apache Pulsar lets applications use a dead letter topic on consumers with a `Shared` subscription type. @@ -453,7 +423,6 @@ For the `Exclusive` and `Failover` subscription types, this feature is not avail The basic idea is that, if a message is retried a certain number of times (maybe due to an ack timeout or nack redelivery), once the number of retries are exhausted, the message can be sent to a special topic called the dead letter queue (DLQ). Let us see some details around this feature in action by inspecting some code snippets: -==== [source, java] ---- @Configuration(proxyBeanMethods = false) @@ -484,7 +453,6 @@ class DeadLetterPolicyConfig { } } ---- -==== First, we have a special bean for `DeadLetterPolicy`, and it is named as `deadLetterPolicy` (it can be any name as you wish). This bean specifies a number of things, such as the max delivery (10, in this case) and the name of the dead letter topic -- `my-dlq-topic`, in this case. diff --git a/spring-pulsar-docs/src/main/asciidoc/reactive-quick-tour.adoc b/spring-pulsar-docs/src/main/antora/modules/ROOT/pages/reference/reactive-quick-tour.adoc similarity index 95% rename from spring-pulsar-docs/src/main/asciidoc/reactive-quick-tour.adoc rename to spring-pulsar-docs/src/main/antora/modules/ROOT/pages/reference/reactive-quick-tour.adoc index a0419ddc..9468a975 100644 --- a/spring-pulsar-docs/src/main/asciidoc/reactive-quick-tour.adoc +++ b/spring-pulsar-docs/src/main/antora/modules/ROOT/pages/reference/reactive-quick-tour.adoc @@ -1,6 +1,6 @@ [[quick-tour-reactive]] = Quick Tour -include::attributes.adoc[] +include::../attributes/attributes.adoc[] We will take a quick tour of the Reactive support in Spring for Apache Pulsar by showing a sample Spring Boot application that produces and consumes in a Reactive fashion. This is a complete application and does not require any additional configuration, as long as you have a Pulsar cluster running on the default location - `localhost:6650`. @@ -9,8 +9,11 @@ This is a complete application and does not require any additional configuration Spring Boot applications need only the `spring-pulsar-reactive-spring-boot-starter` dependency. The following listings show how to define the dependency for Maven and Gradle, respectively: +[tabs] +====== +Maven:: ++ [source,xml,indent=0,subs="verbatim,attributes",role="primary"] -.Maven ---- @@ -20,20 +23,26 @@ Spring Boot applications need only the `spring-pulsar-reactive-spring-boot-start ---- + +Gradle:: ++ [source,groovy,indent=0,subs="verbatim,attributes",role="secondary"] -.Gradle ---- dependencies { implementation 'org.springframework.boot:spring-boot-starter-pulsar-reactive:{spring-boot-version}' } ---- +====== [CAUTION] ==== When using `Version 0.2.x` the above coordinates change as follows: +[tabs] +====== +Maven:: ++ [source,xml,indent=0,subs="verbatim,attributes",role="primary"] -.Maven ---- @@ -43,13 +52,16 @@ When using `Version 0.2.x` the above coordinates change as follows: ---- + +Gradle:: ++ [source,groovy,indent=0,subs="verbatim,attributes",role="secondary"] -.Gradle ---- dependencies { implementation 'org.springframework.pulsar:spring-pulsar-reactive-spring-boot-starter:0.2.0' } ---- +====== ==== diff --git a/spring-pulsar-docs/src/main/antora/modules/ROOT/pages/reference/reference.adoc b/spring-pulsar-docs/src/main/antora/modules/ROOT/pages/reference/reference.adoc new file mode 100644 index 00000000..8f1b9786 --- /dev/null +++ b/spring-pulsar-docs/src/main/antora/modules/ROOT/pages/reference/reference.adoc @@ -0,0 +1,4 @@ +[[reference]] += Reference + +This part of the reference documentation details the various components that comprise Spring for Apache Pulsar. diff --git a/spring-pulsar-docs/src/main/asciidoc/schema-info/PulsarListener/listener-snippet.adoc b/spring-pulsar-docs/src/main/antora/modules/ROOT/pages/reference/schema-info/PulsarListener/listener-snippet.adoc similarity index 94% rename from spring-pulsar-docs/src/main/asciidoc/schema-info/PulsarListener/listener-snippet.adoc rename to spring-pulsar-docs/src/main/antora/modules/ROOT/pages/reference/schema-info/PulsarListener/listener-snippet.adoc index 183880d3..12879669 100644 --- a/spring-pulsar-docs/src/main/asciidoc/schema-info/PulsarListener/listener-snippet.adoc +++ b/spring-pulsar-docs/src/main/antora/modules/ROOT/pages/reference/schema-info/PulsarListener/listener-snippet.adoc @@ -1,4 +1,3 @@ -==== [source,java,subs="attributes,verbatim"] ---- @PulsarListener(subscriptionName = "user-sub", topics = "user-topic") @@ -6,4 +5,3 @@ public void listen(User user) { System.out.println(user); } ---- -==== diff --git a/spring-pulsar-docs/src/main/asciidoc/schema-info/ReactivePulsarListener/listener-snippet.adoc b/spring-pulsar-docs/src/main/antora/modules/ROOT/pages/reference/schema-info/ReactivePulsarListener/listener-snippet.adoc similarity index 94% rename from spring-pulsar-docs/src/main/asciidoc/schema-info/ReactivePulsarListener/listener-snippet.adoc rename to spring-pulsar-docs/src/main/antora/modules/ROOT/pages/reference/schema-info/ReactivePulsarListener/listener-snippet.adoc index c8ca46a1..4bc732c8 100644 --- a/spring-pulsar-docs/src/main/asciidoc/schema-info/ReactivePulsarListener/listener-snippet.adoc +++ b/spring-pulsar-docs/src/main/antora/modules/ROOT/pages/reference/schema-info/ReactivePulsarListener/listener-snippet.adoc @@ -1,4 +1,3 @@ -==== [source,java,subs="attributes,verbatim"] ---- @ReactivePulsarListener(topics = "user-topic") @@ -7,4 +6,3 @@ Mono listen(User user) { return Mono.empty(); } ---- -==== diff --git a/spring-pulsar-docs/src/main/asciidoc/schema-info/custom-schema-mapping.adoc b/spring-pulsar-docs/src/main/antora/modules/ROOT/pages/reference/schema-info/custom-schema-mapping.adoc similarity index 99% rename from spring-pulsar-docs/src/main/asciidoc/schema-info/custom-schema-mapping.adoc rename to spring-pulsar-docs/src/main/antora/modules/ROOT/pages/reference/schema-info/custom-schema-mapping.adoc index 7fee39b9..c3755707 100644 --- a/spring-pulsar-docs/src/main/asciidoc/schema-info/custom-schema-mapping.adoc +++ b/spring-pulsar-docs/src/main/antora/modules/ROOT/pages/reference/schema-info/custom-schema-mapping.adoc @@ -22,7 +22,6 @@ However, if more control is needed you can provide a schema resolver customizer The following example uses a schema resolver customizer to add mappings for the `User` and `Address` complex objects using `AVRO` and `JSON` schemas, respectively: -==== [source, java] ---- @Bean @@ -33,4 +32,3 @@ public SchemaResolverCustomizer schemaResolverCustomizer( } } ---- -==== diff --git a/spring-pulsar-docs/src/main/asciidoc/schema-info/schema-info-listener.adoc b/spring-pulsar-docs/src/main/antora/modules/ROOT/pages/reference/schema-info/schema-info-listener.adoc similarity index 99% rename from spring-pulsar-docs/src/main/asciidoc/schema-info/schema-info-listener.adoc rename to spring-pulsar-docs/src/main/antora/modules/ROOT/pages/reference/schema-info/schema-info-listener.adoc index 4f2830bd..c2e83517 100644 --- a/spring-pulsar-docs/src/main/asciidoc/schema-info/schema-info-listener.adoc +++ b/spring-pulsar-docs/src/main/antora/modules/ROOT/pages/reference/schema-info/schema-info-listener.adoc @@ -1,5 +1,4 @@ == Specifying Schema Information - As indicated earlier, for Java primitives, the Spring for Apache Pulsar framework can infer the proper Schema to use on the `{listener-class}`. For non-primitive types, if the Schema is not explicitly specified on the annotation, the Spring for Apache Pulsar framework will try to build a `Schema.JSON` from the type. diff --git a/spring-pulsar-docs/src/main/asciidoc/schema-info/schema-info-template.adoc b/spring-pulsar-docs/src/main/antora/modules/ROOT/pages/reference/schema-info/schema-info-template.adoc similarity index 100% rename from spring-pulsar-docs/src/main/asciidoc/schema-info/schema-info-template.adoc rename to spring-pulsar-docs/src/main/antora/modules/ROOT/pages/reference/schema-info/schema-info-template.adoc diff --git a/spring-pulsar-docs/src/main/asciidoc/tls-encryption.adoc b/spring-pulsar-docs/src/main/antora/modules/ROOT/pages/reference/tls-encryption.adoc similarity index 97% rename from spring-pulsar-docs/src/main/asciidoc/tls-encryption.adoc rename to spring-pulsar-docs/src/main/antora/modules/ROOT/pages/reference/tls-encryption.adoc index ad443962..18123604 100644 --- a/spring-pulsar-docs/src/main/asciidoc/tls-encryption.adoc +++ b/spring-pulsar-docs/src/main/antora/modules/ROOT/pages/reference/tls-encryption.adoc @@ -1,5 +1,5 @@ -include::attributes.adoc[] +include::../attributes/attributes.adoc[] By default, Pulsar clients communicate with Pulsar services in plain text. The following section describes how to configure Pulsar clients to use TLS encryption (SSL). diff --git a/spring-pulsar-docs/src/main/asciidoc/topic-resolution.adoc b/spring-pulsar-docs/src/main/antora/modules/ROOT/pages/reference/topic-resolution.adoc similarity index 100% rename from spring-pulsar-docs/src/main/asciidoc/topic-resolution.adoc rename to spring-pulsar-docs/src/main/antora/modules/ROOT/pages/reference/topic-resolution.adoc diff --git a/spring-pulsar-docs/src/main/asciidoc/css/stylesheet.css b/spring-pulsar-docs/src/main/asciidoc/css/stylesheet.css deleted file mode 100644 index ad1f1bd0..00000000 --- a/spring-pulsar-docs/src/main/asciidoc/css/stylesheet.css +++ /dev/null @@ -1,31 +0,0 @@ -@import 'css/spring.css'; - -.listingblock .switch { - border-style: none; - display: inline-block; - position: relative; - bottom: -3px; -} - -.listingblock .switch--item { - padding: 10px; - background-color: #e6e1dc; - color: #282c34; - display: inline-block; - cursor: pointer; - border-top-left-radius: 4px; - border-top-right-radius: 4px; -} - -.listingblock .switch--item:not(:first-child) { - border-style: none; -} - -.listingblock .switch--item.selected { - background-color: #282c34; - color: #e6e1dc; -} - -.listingblock pre.highlightjs { - padding: 0; -} diff --git a/spring-pulsar-docs/src/main/asciidoc/index.adoc b/spring-pulsar-docs/src/main/asciidoc/index.adoc deleted file mode 100644 index 2b80a22b..00000000 --- a/spring-pulsar-docs/src/main/asciidoc/index.adoc +++ /dev/null @@ -1,55 +0,0 @@ -[[spring-pulsar-reference]] -= Spring for Apache Pulsar -include::attributes.adoc[] - -include::authors.adoc[] -(v{spring-pulsar-version}) - -include::copyright.adoc[] - -ifeval::[{is-snapshot-version} == true] -CAUTION: You are viewing documentation for a SNAPSHOT version ({spring-pulsar-version}). While it is usually in-sync with the underlying code, it is subject to change and not guaranteed to be up-to-date with the underlying code. -endif::[] - -include::intro.adoc[leveloffset=+1] - -include::getting-help.adoc[leveloffset=+2] - -[[reference]] -== Reference -This part of the reference documentation goes through the details of the various components in Spring for Apache Pulsar. - -include::pulsar.adoc[leveloffset=+2] - -include::reactive-pulsar.adoc[leveloffset=+2] - -include::pulsar-admin.adoc[leveloffset=+2] - -include::pulsar-function.adoc[leveloffset=+2] - -include::observability.adoc[leveloffset=+2] - -include::pulsar-binder.adoc[leveloffset=+2] - -:sectnums!: -[[other-resources]] -== Other Resources - -In addition to this reference documentation, we recommend a number of other resources that may help you learn about Spring and Apache Pulsar. - -- {github}[Spring for Apache Pulsar GitHub Repository] -- https://pulsar.apache.org/[Apache Pulsar Project Home Page] -- {apache-pulsar-docs}/client-libraries-java/[Apache Pulsar Java Client] -- https://github.com/apache/pulsar[Apache Pulsar GitHub Repository] -- https://github.com/apache/pulsar-client-reactive[Apache Pulsar Reactive Client GitHub Repository] - -[[appendix]] -== Appendices - -include::version-compatibility.adoc[leveloffset=+2] - -include::override-boot-dependencies.adoc[leveloffset=+2] - -include::non-ga-versions.adoc[leveloffset=+2] - -include::native-image.adoc[leveloffset=+2] diff --git a/spring-pulsar-docs/src/main/asciidoc/intro.adoc b/spring-pulsar-docs/src/main/asciidoc/intro.adoc deleted file mode 100644 index bcec2a47..00000000 --- a/spring-pulsar-docs/src/main/asciidoc/intro.adoc +++ /dev/null @@ -1,38 +0,0 @@ - -include::attributes-variables.adoc[] - -= Introduction -This project provides a basic Spring-friendly API for developing https://pulsar.apache.org/[Apache Pulsar] applications. - -On a very high level, Spring for Apache Pulsar provides a `PulsarTemplate` for publishing to a Pulsar topic and a `PulsarListener` annotation for consuming from a Pulsar topic. -In addition, it also provides various convenience APIs for Spring developers to ramp up their development journey into Apache Pulsar. - -include::project-state.adoc[leveloffset=+1] - -== System Requirements - -Spring for Apache Pulsar `{spring-pulsar-version}` requires the following: - -- https://www.java.com[Java 17] and is compatible up to and including Java 20 -- {spring-framework-docs}[Spring Framework `{spring-framework-version}`] or above -- {apache-pulsar-cient-docs}/[Apache Pulsar Java Client `{pulsar-client-version}`] or above - -==== -The version compatibility matrix (including Spring Boot) can be found in the <>. -==== - -== Building the Project -If you have cloned the project locally, follow these steps to build the project from the source code. - -NOTE: Gradle `7.x (7.4 or above)` is required to build. - -Run the following command to do a full build of the project: -[indent=0] ----- -./gradlew clean build ----- -You can build without running tests by using the following command: -[indent=0] ----- -./gradlew clean build -x test ----- diff --git a/spring-pulsar-reactive/src/main/java/org/springframework/pulsar/reactive/core/DefaultReactivePulsarSenderFactory.java b/spring-pulsar-reactive/src/main/java/org/springframework/pulsar/reactive/core/DefaultReactivePulsarSenderFactory.java index 23209ef5..a58f10eb 100644 --- a/spring-pulsar-reactive/src/main/java/org/springframework/pulsar/reactive/core/DefaultReactivePulsarSenderFactory.java +++ b/spring-pulsar-reactive/src/main/java/org/springframework/pulsar/reactive/core/DefaultReactivePulsarSenderFactory.java @@ -117,9 +117,6 @@ public final class DefaultReactivePulsarSenderFactory private ReactiveMessageSender doCreateReactiveMessageSender(Schema schema, @Nullable String topic, @Nullable List> customizers) { Objects.requireNonNull(schema, "Schema must be specified"); - - this.logger.warn(() -> "**** Du CreateMessageSender for topic=" + topic); - String resolvedTopic = this.topicResolver.resolveTopic(topic, () -> getDefaultTopic()).orElseThrow(); this.logger.trace(() -> "Creating reactive message sender for '%s' topic".formatted(resolvedTopic));