This is an automated email from the ASF dual-hosted git repository.

davsclaus pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel.git


The following commit(s) were added to refs/heads/main by this push:
     new 1795c8c91816 CAMEL-23531: Fix Jackson 2.x/3.x dataformat doc 
collisions (#23257)
1795c8c91816 is described below

commit 1795c8c918164084905acf9574c1351527ea8ad1
Author: Adriano Machado <[email protected]>
AuthorDate: Sun May 17 02:46:22 2026 -0400

    CAMEL-23531: Fix Jackson 2.x/3.x dataformat doc collisions (#23257)
    
    The Jackson 2.x and 3.x dataformat lines share the same DSL `name`
    (`jackson`, `jacksonXml`, `avroJackson`, `protobufJackson`) so a runtime
    can drop in either variant transparently. The doc pipeline flattened
    both variants to the same destination filename, so the second symlink
    silently overwrote the first and only one entry appeared in the
    dataformats nav.
    
    Disambiguate at the doc layer only — runtime catalog and DSL behaviour
    are unchanged:
    
    - Rename the per-module `<name>-dataformat.adoc` source files with a
      `2` / `3` suffix in all eight Jackson modules.
    - Append the major-version suffix to the rendered `.adoc` title in
      `UpdateReadmeMojo` (driven by the artifactId), and look up the
      renamed page filename via the same suffix. The dataformat JSON
      `title` stays unsuffixed, so the catalog and `dataFormatJSonSchema`
      API keep their existing values.
    - Detect destination-basename collisions in `PrepareDocSymlinksMojo`
      and disambiguate Jackson-family `.json` symlinks via the same
      artifact rule. Any unresolvable collision now fails the build
      loudly instead of silently overwriting one source.
    - Regenerate the dataformats nav, page symlinks, JSON example
      symlinks, and per-module readme headers; both variants now appear
      with distinct titles (e.g. `JSON Jackson 2` / `JSON Jackson 3`).
    - Document the page renames in the 4.21 upgrade guide.
    
    Co-Authored-By: Claude Opus 4.7 <[email protected]>
    
    rh-pre-commit.version: 2.3.2
    rh-pre-commit.check-secrets: ENABLED
---
 ...ataformat.adoc => avroJackson2-dataformat.adoc} |  6 +-
 ...ormat.adoc => protobufJackson2-dataformat.adoc} |  6 +-
 ...on-dataformat.adoc => jackson2-dataformat.adoc} |  6 +-
 ...ataformat.adoc => avroJackson3-dataformat.adoc} |  6 +-
 ...ormat.adoc => protobufJackson3-dataformat.adoc} |  6 +-
 ...on-dataformat.adoc => jackson3-dataformat.adoc} |  6 +-
 ...dataformat.adoc => jacksonXml3-dataformat.adoc} |  6 +-
 ...dataformat.adoc => jacksonXml2-dataformat.adoc} |  6 +-
 .../dataformats/examples/json/avroJackson2.json    |  1 +
 .../json/{avroJackson.json => avroJackson3.json}   |  0
 .../dataformats/examples/json/jackson2.json        |  1 +
 .../examples/json/{jackson.json => jackson3.json}  |  0
 .../json/{jacksonXml.json => jacksonXml2.json}     |  0
 .../dataformats/examples/json/jacksonXml3.json     |  1 +
 .../examples/json/protobufJackson2.json            |  1 +
 ...{protobufJackson.json => protobufJackson3.json} |  0
 docs/components/modules/dataformats/nav.adoc       | 12 ++-
 .../dataformats/pages/avroJackson-dataformat.adoc  |  1 -
 .../dataformats/pages/avroJackson2-dataformat.adoc |  1 +
 .../dataformats/pages/avroJackson3-dataformat.adoc |  1 +
 .../dataformats/pages/jackson-dataformat.adoc      |  1 -
 .../dataformats/pages/jackson2-dataformat.adoc     |  1 +
 .../dataformats/pages/jackson3-dataformat.adoc     |  1 +
 .../dataformats/pages/jacksonXml-dataformat.adoc   |  1 -
 .../dataformats/pages/jacksonXml2-dataformat.adoc  |  1 +
 .../dataformats/pages/jacksonXml3-dataformat.adoc  |  1 +
 .../pages/protobufJackson-dataformat.adoc          |  1 -
 .../pages/protobufJackson2-dataformat.adoc         |  1 +
 .../pages/protobufJackson3-dataformat.adoc         |  1 +
 .../ROOT/pages/camel-4x-upgrade-guide-4_21.adoc    | 27 +++++-
 .../maven/packaging/PackageDataFormatMojo.java     | 14 +++-
 .../maven/packaging/PrepareDocSymlinksMojo.java    | 97 +++++++++++++++++++---
 .../camel/maven/packaging/UpdateReadmeMojo.java    | 24 +++++-
 .../packaging/PrepareDocSymlinksMojoTest.java      | 41 +++++++++
 34 files changed, 228 insertions(+), 51 deletions(-)

diff --git 
a/components/camel-jackson-avro/src/main/docs/avroJackson-dataformat.adoc 
b/components/camel-jackson-avro/src/main/docs/avroJackson2-dataformat.adoc
similarity index 96%
rename from 
components/camel-jackson-avro/src/main/docs/avroJackson-dataformat.adoc
rename to 
components/camel-jackson-avro/src/main/docs/avroJackson2-dataformat.adoc
index 8934ea86ed22..7e3143ace3ab 100644
--- a/components/camel-jackson-avro/src/main/docs/avroJackson-dataformat.adoc
+++ b/components/camel-jackson-avro/src/main/docs/avroJackson2-dataformat.adoc
@@ -1,6 +1,6 @@
-= Avro Jackson DataFormat
-:doctitle: Avro Jackson
-:shortname: avroJackson
+= Avro Jackson 2 DataFormat
+:doctitle: Avro Jackson 2
+:shortname: avroJackson2
 :artifactid: camel-jackson-avro
 :description: Marshal POJOs to Avro and back using Jackson.
 :since: 3.10
diff --git 
a/components/camel-jackson-protobuf/src/main/docs/protobufJackson-dataformat.adoc
 
b/components/camel-jackson-protobuf/src/main/docs/protobufJackson2-dataformat.adoc
similarity index 96%
rename from 
components/camel-jackson-protobuf/src/main/docs/protobufJackson-dataformat.adoc
rename to 
components/camel-jackson-protobuf/src/main/docs/protobufJackson2-dataformat.adoc
index c6e1ff5969f9..82f1183fcecb 100644
--- 
a/components/camel-jackson-protobuf/src/main/docs/protobufJackson-dataformat.adoc
+++ 
b/components/camel-jackson-protobuf/src/main/docs/protobufJackson2-dataformat.adoc
@@ -1,6 +1,6 @@
-= Protobuf Jackson DataFormat
-:doctitle: Protobuf Jackson
-:shortname: protobufJackson
+= Protobuf Jackson 2 DataFormat
+:doctitle: Protobuf Jackson 2
+:shortname: protobufJackson2
 :artifactid: camel-jackson-protobuf
 :description: Marshal POJOs to Protobuf and back using Jackson.
 :since: 3.10
diff --git a/components/camel-jackson/src/main/docs/jackson-dataformat.adoc 
b/components/camel-jackson/src/main/docs/jackson2-dataformat.adoc
similarity index 97%
rename from components/camel-jackson/src/main/docs/jackson-dataformat.adoc
rename to components/camel-jackson/src/main/docs/jackson2-dataformat.adoc
index 91e6ce4e2b92..f27ec430faf9 100644
--- a/components/camel-jackson/src/main/docs/jackson-dataformat.adoc
+++ b/components/camel-jackson/src/main/docs/jackson2-dataformat.adoc
@@ -1,6 +1,6 @@
-= JSON Jackson DataFormat
-:doctitle: JSON Jackson
-:shortname: jackson
+= JSON Jackson 2 DataFormat
+:doctitle: JSON Jackson 2
+:shortname: jackson2
 :artifactid: camel-jackson
 :description: Marshal POJOs to JSON and back using Jackson.
 :since: 2.0
diff --git 
a/components/camel-jackson3-avro/src/main/docs/avroJackson-dataformat.adoc 
b/components/camel-jackson3-avro/src/main/docs/avroJackson3-dataformat.adoc
similarity index 96%
rename from 
components/camel-jackson3-avro/src/main/docs/avroJackson-dataformat.adoc
rename to 
components/camel-jackson3-avro/src/main/docs/avroJackson3-dataformat.adoc
index 9fcab72f31f8..ad27efe00c7b 100644
--- a/components/camel-jackson3-avro/src/main/docs/avroJackson-dataformat.adoc
+++ b/components/camel-jackson3-avro/src/main/docs/avroJackson3-dataformat.adoc
@@ -1,6 +1,6 @@
-= Avro Jackson DataFormat
-:doctitle: Avro Jackson
-:shortname: avroJackson
+= Avro Jackson 3 DataFormat
+:doctitle: Avro Jackson 3
+:shortname: avroJackson3
 :artifactid: camel-jackson3-avro
 :description: Marshal POJOs to Avro and back using Jackson.
 :since: 4.19
diff --git 
a/components/camel-jackson3-protobuf/src/main/docs/protobufJackson-dataformat.adoc
 
b/components/camel-jackson3-protobuf/src/main/docs/protobufJackson3-dataformat.adoc
similarity index 96%
rename from 
components/camel-jackson3-protobuf/src/main/docs/protobufJackson-dataformat.adoc
rename to 
components/camel-jackson3-protobuf/src/main/docs/protobufJackson3-dataformat.adoc
index e7a3eb37ccdd..29afb5d69bae 100644
--- 
a/components/camel-jackson3-protobuf/src/main/docs/protobufJackson-dataformat.adoc
+++ 
b/components/camel-jackson3-protobuf/src/main/docs/protobufJackson3-dataformat.adoc
@@ -1,6 +1,6 @@
-= Protobuf Jackson DataFormat
-:doctitle: Protobuf Jackson
-:shortname: protobufJackson
+= Protobuf Jackson 3 DataFormat
+:doctitle: Protobuf Jackson 3
+:shortname: protobufJackson3
 :artifactid: camel-jackson3-protobuf
 :description: Marshal POJOs to Protobuf and back using Jackson.
 :since: 4.19
diff --git a/components/camel-jackson3/src/main/docs/jackson-dataformat.adoc 
b/components/camel-jackson3/src/main/docs/jackson3-dataformat.adoc
similarity index 98%
rename from components/camel-jackson3/src/main/docs/jackson-dataformat.adoc
rename to components/camel-jackson3/src/main/docs/jackson3-dataformat.adoc
index 089b5ea4fe82..1a68e4814f01 100644
--- a/components/camel-jackson3/src/main/docs/jackson-dataformat.adoc
+++ b/components/camel-jackson3/src/main/docs/jackson3-dataformat.adoc
@@ -1,6 +1,6 @@
-= JSON Jackson DataFormat
-:doctitle: JSON Jackson
-:shortname: jackson
+= JSON Jackson 3 DataFormat
+:doctitle: JSON Jackson 3
+:shortname: jackson3
 :artifactid: camel-jackson3
 :description: Marshal POJOs to JSON and back using Jackson.
 :since: 4.19
diff --git 
a/components/camel-jackson3xml/src/main/docs/jacksonXml-dataformat.adoc 
b/components/camel-jackson3xml/src/main/docs/jacksonXml3-dataformat.adoc
similarity index 99%
rename from 
components/camel-jackson3xml/src/main/docs/jacksonXml-dataformat.adoc
rename to components/camel-jackson3xml/src/main/docs/jacksonXml3-dataformat.adoc
index dbc5e23422c2..f257a2cfcee8 100644
--- a/components/camel-jackson3xml/src/main/docs/jacksonXml-dataformat.adoc
+++ b/components/camel-jackson3xml/src/main/docs/jacksonXml3-dataformat.adoc
@@ -1,6 +1,6 @@
-= Jackson XML DataFormat
-:doctitle: Jackson XML
-:shortname: jacksonXml
+= Jackson XML 3 DataFormat
+:doctitle: Jackson XML 3
+:shortname: jacksonXml3
 :artifactid: camel-jackson3xml
 :description: Unmarshal an XML payloads to POJOs and back using XMLMapper 
extension of Jackson.
 :since: 4.19
diff --git 
a/components/camel-jacksonxml/src/main/docs/jacksonXml-dataformat.adoc 
b/components/camel-jacksonxml/src/main/docs/jacksonXml2-dataformat.adoc
similarity index 99%
rename from components/camel-jacksonxml/src/main/docs/jacksonXml-dataformat.adoc
rename to components/camel-jacksonxml/src/main/docs/jacksonXml2-dataformat.adoc
index 0c753ed98b17..78cdee962deb 100644
--- a/components/camel-jacksonxml/src/main/docs/jacksonXml-dataformat.adoc
+++ b/components/camel-jacksonxml/src/main/docs/jacksonXml2-dataformat.adoc
@@ -1,6 +1,6 @@
-= Jackson XML DataFormat
-:doctitle: Jackson XML
-:shortname: jacksonXml
+= Jackson XML 2 DataFormat
+:doctitle: Jackson XML 2
+:shortname: jacksonXml2
 :artifactid: camel-jacksonxml
 :description: Unmarshal an XML payloads to POJOs and back using XMLMapper 
extension of Jackson.
 :since: 2.16
diff --git 
a/docs/components/modules/dataformats/examples/json/avroJackson2.json 
b/docs/components/modules/dataformats/examples/json/avroJackson2.json
new file mode 120000
index 000000000000..11c449c9ffa4
--- /dev/null
+++ b/docs/components/modules/dataformats/examples/json/avroJackson2.json
@@ -0,0 +1 @@
+../../../../../../components/camel-jackson-avro/src/generated/resources/META-INF/org/apache/camel/component/jackson/avro/avroJackson.json
\ No newline at end of file
diff --git a/docs/components/modules/dataformats/examples/json/avroJackson.json 
b/docs/components/modules/dataformats/examples/json/avroJackson3.json
similarity index 100%
rename from docs/components/modules/dataformats/examples/json/avroJackson.json
rename to docs/components/modules/dataformats/examples/json/avroJackson3.json
diff --git a/docs/components/modules/dataformats/examples/json/jackson2.json 
b/docs/components/modules/dataformats/examples/json/jackson2.json
new file mode 120000
index 000000000000..fac90c7ac8b4
--- /dev/null
+++ b/docs/components/modules/dataformats/examples/json/jackson2.json
@@ -0,0 +1 @@
+../../../../../../components/camel-jackson/src/generated/resources/META-INF/org/apache/camel/component/jackson/jackson.json
\ No newline at end of file
diff --git a/docs/components/modules/dataformats/examples/json/jackson.json 
b/docs/components/modules/dataformats/examples/json/jackson3.json
similarity index 100%
rename from docs/components/modules/dataformats/examples/json/jackson.json
rename to docs/components/modules/dataformats/examples/json/jackson3.json
diff --git a/docs/components/modules/dataformats/examples/json/jacksonXml.json 
b/docs/components/modules/dataformats/examples/json/jacksonXml2.json
similarity index 100%
rename from docs/components/modules/dataformats/examples/json/jacksonXml.json
rename to docs/components/modules/dataformats/examples/json/jacksonXml2.json
diff --git a/docs/components/modules/dataformats/examples/json/jacksonXml3.json 
b/docs/components/modules/dataformats/examples/json/jacksonXml3.json
new file mode 120000
index 000000000000..d632a302eea5
--- /dev/null
+++ b/docs/components/modules/dataformats/examples/json/jacksonXml3.json
@@ -0,0 +1 @@
+../../../../../../components/camel-jackson3xml/src/generated/resources/META-INF/org/apache/camel/component/jackson3xml/jacksonXml.json
\ No newline at end of file
diff --git 
a/docs/components/modules/dataformats/examples/json/protobufJackson2.json 
b/docs/components/modules/dataformats/examples/json/protobufJackson2.json
new file mode 120000
index 000000000000..af16c2935aef
--- /dev/null
+++ b/docs/components/modules/dataformats/examples/json/protobufJackson2.json
@@ -0,0 +1 @@
+../../../../../../components/camel-jackson-protobuf/src/generated/resources/META-INF/org/apache/camel/component/jackson/protobuf/protobufJackson.json
\ No newline at end of file
diff --git 
a/docs/components/modules/dataformats/examples/json/protobufJackson.json 
b/docs/components/modules/dataformats/examples/json/protobufJackson3.json
similarity index 100%
rename from 
docs/components/modules/dataformats/examples/json/protobufJackson.json
rename to 
docs/components/modules/dataformats/examples/json/protobufJackson3.json
diff --git a/docs/components/modules/dataformats/nav.adoc 
b/docs/components/modules/dataformats/nav.adoc
index a25bc3bf9508..9d9e3b2e92ba 100644
--- a/docs/components/modules/dataformats/nav.adoc
+++ b/docs/components/modules/dataformats/nav.adoc
@@ -4,7 +4,8 @@
 * xref:dataformats:index.adoc[Data Formats]
 ** xref:asn1-dataformat.adoc[ASN.1 File]
 ** xref:avro-dataformat.adoc[Avro]
-** xref:avroJackson-dataformat.adoc[Avro Jackson]
+** xref:avroJackson2-dataformat.adoc[Avro Jackson 2]
+** xref:avroJackson3-dataformat.adoc[Avro Jackson 3]
 ** xref:barcode-dataformat.adoc[Barcode]
 ** xref:base64-dataformat.adoc[Base64]
 ** xref:beanio-dataformat.adoc[BeanIO]
@@ -24,11 +25,13 @@
 ** xref:hl7-dataformat.adoc[HL7]
 ** xref:ical-dataformat.adoc[iCal]
 ** xref:iso8583-dataformat.adoc[ISO-8583]
-** xref:jacksonXml-dataformat.adoc[Jackson XML]
+** xref:jacksonXml2-dataformat.adoc[Jackson XML 2]
+** xref:jacksonXml3-dataformat.adoc[Jackson XML 3]
 ** xref:jaxb-dataformat.adoc[JAXB]
 ** xref:fastjson-dataformat.adoc[JSON Fastjson]
 ** xref:gson-dataformat.adoc[JSON Gson]
-** xref:jackson-dataformat.adoc[JSON Jackson]
+** xref:jackson2-dataformat.adoc[JSON Jackson 2]
+** xref:jackson3-dataformat.adoc[JSON Jackson 3]
 ** xref:jsonb-dataformat.adoc[JSON JSON-B]
 ** xref:jsonApi-dataformat.adoc[JSonApi]
 ** xref:lzf-dataformat.adoc[LZF Deflate Compression]
@@ -38,7 +41,8 @@
 ** xref:pgp-dataformat.adoc[PGP (Pretty Good Privacy Cryptographic)]
 ** xref:pqc-dataformat.adoc[PQC (Post-Quantum Cryptography)]
 ** xref:protobuf-dataformat.adoc[Protobuf]
-** xref:protobufJackson-dataformat.adoc[Protobuf Jackson]
+** xref:protobufJackson2-dataformat.adoc[Protobuf Jackson 2]
+** xref:protobufJackson3-dataformat.adoc[Protobuf Jackson 3]
 ** xref:rss-dataformat.adoc[RSS]
 ** xref:smooks-dataformat.adoc[Smooks]
 ** xref:soap-dataformat.adoc[SOAP]
diff --git 
a/docs/components/modules/dataformats/pages/avroJackson-dataformat.adoc 
b/docs/components/modules/dataformats/pages/avroJackson-dataformat.adoc
deleted file mode 120000
index 466bbc8671ee..000000000000
--- a/docs/components/modules/dataformats/pages/avroJackson-dataformat.adoc
+++ /dev/null
@@ -1 +0,0 @@
-../../../../../components/camel-jackson3-avro/src/main/docs/avroJackson-dataformat.adoc
\ No newline at end of file
diff --git 
a/docs/components/modules/dataformats/pages/avroJackson2-dataformat.adoc 
b/docs/components/modules/dataformats/pages/avroJackson2-dataformat.adoc
new file mode 120000
index 000000000000..18d553cc0688
--- /dev/null
+++ b/docs/components/modules/dataformats/pages/avroJackson2-dataformat.adoc
@@ -0,0 +1 @@
+../../../../../components/camel-jackson-avro/src/main/docs/avroJackson2-dataformat.adoc
\ No newline at end of file
diff --git 
a/docs/components/modules/dataformats/pages/avroJackson3-dataformat.adoc 
b/docs/components/modules/dataformats/pages/avroJackson3-dataformat.adoc
new file mode 120000
index 000000000000..810aa15e16a1
--- /dev/null
+++ b/docs/components/modules/dataformats/pages/avroJackson3-dataformat.adoc
@@ -0,0 +1 @@
+../../../../../components/camel-jackson3-avro/src/main/docs/avroJackson3-dataformat.adoc
\ No newline at end of file
diff --git a/docs/components/modules/dataformats/pages/jackson-dataformat.adoc 
b/docs/components/modules/dataformats/pages/jackson-dataformat.adoc
deleted file mode 120000
index 22c23f26c7ec..000000000000
--- a/docs/components/modules/dataformats/pages/jackson-dataformat.adoc
+++ /dev/null
@@ -1 +0,0 @@
-../../../../../components/camel-jackson3/src/main/docs/jackson-dataformat.adoc
\ No newline at end of file
diff --git a/docs/components/modules/dataformats/pages/jackson2-dataformat.adoc 
b/docs/components/modules/dataformats/pages/jackson2-dataformat.adoc
new file mode 120000
index 000000000000..e7c2d90ba488
--- /dev/null
+++ b/docs/components/modules/dataformats/pages/jackson2-dataformat.adoc
@@ -0,0 +1 @@
+../../../../../components/camel-jackson/src/main/docs/jackson2-dataformat.adoc
\ No newline at end of file
diff --git a/docs/components/modules/dataformats/pages/jackson3-dataformat.adoc 
b/docs/components/modules/dataformats/pages/jackson3-dataformat.adoc
new file mode 120000
index 000000000000..8d66dbfa0589
--- /dev/null
+++ b/docs/components/modules/dataformats/pages/jackson3-dataformat.adoc
@@ -0,0 +1 @@
+../../../../../components/camel-jackson3/src/main/docs/jackson3-dataformat.adoc
\ No newline at end of file
diff --git 
a/docs/components/modules/dataformats/pages/jacksonXml-dataformat.adoc 
b/docs/components/modules/dataformats/pages/jacksonXml-dataformat.adoc
deleted file mode 120000
index d6be7b6e95ad..000000000000
--- a/docs/components/modules/dataformats/pages/jacksonXml-dataformat.adoc
+++ /dev/null
@@ -1 +0,0 @@
-../../../../../components/camel-jacksonxml/src/main/docs/jacksonXml-dataformat.adoc
\ No newline at end of file
diff --git 
a/docs/components/modules/dataformats/pages/jacksonXml2-dataformat.adoc 
b/docs/components/modules/dataformats/pages/jacksonXml2-dataformat.adoc
new file mode 120000
index 000000000000..49b2823f6593
--- /dev/null
+++ b/docs/components/modules/dataformats/pages/jacksonXml2-dataformat.adoc
@@ -0,0 +1 @@
+../../../../../components/camel-jacksonxml/src/main/docs/jacksonXml2-dataformat.adoc
\ No newline at end of file
diff --git 
a/docs/components/modules/dataformats/pages/jacksonXml3-dataformat.adoc 
b/docs/components/modules/dataformats/pages/jacksonXml3-dataformat.adoc
new file mode 120000
index 000000000000..bf15da44fa84
--- /dev/null
+++ b/docs/components/modules/dataformats/pages/jacksonXml3-dataformat.adoc
@@ -0,0 +1 @@
+../../../../../components/camel-jackson3xml/src/main/docs/jacksonXml3-dataformat.adoc
\ No newline at end of file
diff --git 
a/docs/components/modules/dataformats/pages/protobufJackson-dataformat.adoc 
b/docs/components/modules/dataformats/pages/protobufJackson-dataformat.adoc
deleted file mode 120000
index d67bf758d66f..000000000000
--- a/docs/components/modules/dataformats/pages/protobufJackson-dataformat.adoc
+++ /dev/null
@@ -1 +0,0 @@
-../../../../../components/camel-jackson3-protobuf/src/main/docs/protobufJackson-dataformat.adoc
\ No newline at end of file
diff --git 
a/docs/components/modules/dataformats/pages/protobufJackson2-dataformat.adoc 
b/docs/components/modules/dataformats/pages/protobufJackson2-dataformat.adoc
new file mode 120000
index 000000000000..2ed770cc8b23
--- /dev/null
+++ b/docs/components/modules/dataformats/pages/protobufJackson2-dataformat.adoc
@@ -0,0 +1 @@
+../../../../../components/camel-jackson-protobuf/src/main/docs/protobufJackson2-dataformat.adoc
\ No newline at end of file
diff --git 
a/docs/components/modules/dataformats/pages/protobufJackson3-dataformat.adoc 
b/docs/components/modules/dataformats/pages/protobufJackson3-dataformat.adoc
new file mode 120000
index 000000000000..82d696b8dcc0
--- /dev/null
+++ b/docs/components/modules/dataformats/pages/protobufJackson3-dataformat.adoc
@@ -0,0 +1 @@
+../../../../../components/camel-jackson3-protobuf/src/main/docs/protobufJackson3-dataformat.adoc
\ No newline at end of file
diff --git 
a/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_21.adoc 
b/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_21.adoc
index 28cfa8a627df..46a19e9348fb 100644
--- a/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_21.adoc
+++ b/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_21.adoc
@@ -467,7 +467,31 @@ to work without changes. Routes that set the header by its 
literal string value
 (for example `setHeader("JGROUPSRAFT_SET_TIMEOUT", ...)`) must be updated to
 use the new value (`setHeader("CamelJGroupsRaftSetTimeout", ...)`).
 
-=== Deprecation of camel-ironmqThe library used had no stable release since 
2007. There is no Java library very active for this protocol.
+=== Jackson dataformat documentation pages renamed
+
+The Jackson 2.x and Jackson 3.x lines ship the same dataformat names 
(`jackson`, `jacksonXml`,
+`avroJackson`, `protobufJackson`) for DSL drop-in compatibility, but their 
documentation pages
+previously shared the same filename and silently overwrote each other when the 
doc site was
+built (CAMEL-23531). The pages have been split and now carry an explicit `2` 
or `3` suffix:
+
+[options="header"]
+|===
+| Module | Old page | New page
+| `camel-jackson` | `jackson-dataformat.adoc` | `jackson2-dataformat.adoc`
+| `camel-jacksonxml` | `jacksonXml-dataformat.adoc` | 
`jacksonXml2-dataformat.adoc`
+| `camel-jackson-avro` | `avroJackson-dataformat.adoc` | 
`avroJackson2-dataformat.adoc`
+| `camel-jackson-protobuf` | `protobufJackson-dataformat.adoc` | 
`protobufJackson2-dataformat.adoc`
+| `camel-jackson3` | `jackson-dataformat.adoc` | `jackson3-dataformat.adoc`
+| `camel-jackson3xml` | `jacksonXml-dataformat.adoc` | 
`jacksonXml3-dataformat.adoc`
+| `camel-jackson3-avro` | `avroJackson-dataformat.adoc` | 
`avroJackson3-dataformat.adoc`
+| `camel-jackson3-protobuf` | `protobufJackson-dataformat.adoc` | 
`protobufJackson3-dataformat.adoc`
+|===
+
+The page titles are likewise disambiguated (`JSON Jackson 2` / `JSON Jackson 
3`, etc.) and both
+variants now appear in the dataformats navigation. Update any external `xref:` 
links that point
+at the old filenames; routes referencing the dataformats by `name` are 
unaffected.
+
+=== Deprecation of camel-ironmq
 
 The component camel-ironmq is deprecated. The official library used has been 
unmaintained since 2017
 All the other client libraries (in other languages) are unmaintained since the 
same amount of time.
@@ -484,4 +508,3 @@ The component camel-irc is deprecated. The library used had 
no stable release si
 === Deprecation of camel-iec-60870
 
 The component camel-iec-60870 is deprecated. The library used to implement it 
NeoScada is no more maintained since 2021. There are no alternatives in Java 
with compatible license.
-
diff --git 
a/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/PackageDataFormatMojo.java
 
b/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/PackageDataFormatMojo.java
index e1c11e65ff84..e556ce530233 100644
--- 
a/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/PackageDataFormatMojo.java
+++ 
b/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/PackageDataFormatMojo.java
@@ -546,13 +546,14 @@ public class PackageDataFormatMojo extends 
AbstractGeneratorMojo {
     }
 
     private static String asModelTitle(String name, String title) {
+        // The Jackson 2.x and 3.x lines deliberately share the same 
dataformat name (and therefore the same
+        // catalog title) so the runtime DSL resolves either variant 
transparently. Doc-side disambiguation
+        // is applied by UpdateReadmeMojo at .adoc-rendering time, not here. 
See CAMEL-23531.
         // special for some data formats
         if ("gson".equals(name)) {
             return "JSON Gson";
         } else if ("jackson".equals(name)) {
             return "JSON Jackson";
-        } else if ("jackson3".equals(name)) {
-            return "JSON Jackson3";
         } else if ("avroJackson".equals(name)) {
             return "Avro Jackson";
         } else if ("protobufJackson".equals(name)) {
@@ -575,6 +576,15 @@ public class PackageDataFormatMojo extends 
AbstractGeneratorMojo {
         return title;
     }
 
+    /**
+     * Returns the major-version suffix to append to a Jackson-family 
dataformat title. Jackson 3.x lives in artifacts
+     * whose name contains {@code jackson3}; everything else in the family 
(the original {@code camel-jackson},
+     * {@code camel-jacksonxml}, {@code camel-jackson-avro}, {@code 
camel-jackson-protobuf}) is the 2.x line.
+     */
+    static String jacksonFamilySuffix(String artifactId) {
+        return artifactId != null && artifactId.contains("jackson3") ? "3" : 
"2";
+    }
+
     private static String schemaSubDirectory(String javaType) {
         int idx = javaType.lastIndexOf('.');
         String pckName = javaType.substring(0, idx);
diff --git 
a/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/PrepareDocSymlinksMojo.java
 
b/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/PrepareDocSymlinksMojo.java
index b5775453ec0d..ccd69dd1134b 100644
--- 
a/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/PrepareDocSymlinksMojo.java
+++ 
b/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/PrepareDocSymlinksMojo.java
@@ -141,7 +141,7 @@ public class PrepareDocSymlinksMojo extends AbstractMojo {
         }
     }
 
-    private void runGroup(Path base, Path root, DocGroup group) throws 
IOException {
+    private void runGroup(Path base, Path root, DocGroup group) throws 
IOException, MojoFailureException {
         // Both includes and destinations are repo-root-relative; resolve 
against root for consistency.
         if (group.asciidoc != null && !group.asciidoc.includes().isEmpty()) {
             Path dest = root.resolve(group.asciidoc.destination()).normalize();
@@ -211,28 +211,103 @@ public class PrepareDocSymlinksMojo extends AbstractMojo 
{
     /**
      * Walk the spec's includes/excludes under {@code root}, optionally 
JSON-filter, then create one relative symlink
      * per match at {@code destination/<basename>}.
+     *
+     * <p>
+     * If two distinct sources flatten to the same {@code 
destination/<basename>} they are passed through
+     * {@link #disambiguate(Path, List)} so the build fails loudly rather than 
silently overwriting the first symlink
+     * with the second (the bug behind CAMEL-23531).
      */
-    private void createSymlinks(Path root, KindSpec spec, Path destination) 
throws IOException {
+    private void createSymlinks(Path root, KindSpec spec, Path destination) 
throws IOException, MojoFailureException {
         Files.createDirectories(destination);
-        // Track unique destination paths so the log surfaces basename 
collisions: if two distinct sources
-        // flatten to the same `dest/<basename>`, the second 
`createRelativeSymlink` overwrites the first
-        // and only one symlink remains on disk. The "(from N sources)" suffix 
is the signal.
-        Set<Path> uniqueLinks = new LinkedHashSet<>();
-        int sources = 0;
         String jsonRootKey = spec.jsonRootKey();
+
+        // Group matches by their default destination basename so we can 
detect and resolve collisions
+        // before any symlink is written.
+        Map<String, List<Path>> bySrcName = new LinkedHashMap<>();
         for (Path src : walk(root, spec.includes(), spec.excludes())) {
             if (jsonRootKey != null && !matchesJsonFilter(src, jsonRootKey)) {
                 continue;
             }
-            Path link = destination.resolve(src.getFileName().toString());
-            createRelativeSymlink(link, src);
-            uniqueLinks.add(link);
-            sources++;
+            bySrcName.computeIfAbsent(src.getFileName().toString(), k -> new 
ArrayList<>()).add(src);
+        }
+
+        Set<Path> uniqueLinks = new LinkedHashSet<>();
+        int sources = 0;
+        for (Map.Entry<String, List<Path>> entry : bySrcName.entrySet()) {
+            List<Path> srcs = entry.getValue();
+            List<String> linkNames = srcs.size() == 1
+                    ? List.of(entry.getKey())
+                    : disambiguate(destination, srcs);
+            for (int i = 0; i < srcs.size(); i++) {
+                Path link = destination.resolve(linkNames.get(i));
+                createRelativeSymlink(link, srcs.get(i));
+                uniqueLinks.add(link);
+                sources++;
+            }
         }
         getLog().info("  → linked " + countSuffix(uniqueLinks.size(), sources, 
"files") + " to "
                       + relativize(destination));
     }
 
+    /**
+     * Resolve a basename collision by inserting a per-source discriminator 
before the file extension.
+     *
+     * <p>
+     * The only known collisions are the Jackson 2.x / 3.x dataformat pairs 
(CAMEL-23531): both lines register the same
+     * dataformat {@code name} for DSL drop-in compatibility, so their 
generated descriptors share a basename (e.g.
+     * {@code jackson.json}). We disambiguate by appending {@code 2} or {@code 
3} based on the artifact directory the
+     * source lives in (see {@link 
PackageDataFormatMojo#jacksonFamilySuffix(String)}).
+     *
+     * <p>
+     * Any future collision that doesn't match this rule fails the build 
rather than silently overwriting one of the
+     * sources.
+     */
+    static List<String> disambiguate(Path destination, List<Path> srcs) throws 
MojoFailureException {
+        String baseName = srcs.get(0).getFileName().toString();
+        int dot = baseName.lastIndexOf('.');
+        String stem = dot < 0 ? baseName : baseName.substring(0, dot);
+        String ext = dot < 0 ? "" : baseName.substring(dot);
+
+        List<String> names = new ArrayList<>(srcs.size());
+        Set<String> seen = new LinkedHashSet<>();
+        for (Path src : srcs) {
+            String artifact = artifactDirName(src);
+            if (artifact == null || !artifact.contains("jackson")) {
+                throw new MojoFailureException(collisionMessage(destination, 
baseName, srcs));
+            }
+            String name = stem + 
PackageDataFormatMojo.jacksonFamilySuffix(artifact) + ext;
+            if (!seen.add(name)) {
+                throw new MojoFailureException(collisionMessage(destination, 
baseName, srcs));
+            }
+            names.add(name);
+        }
+        return names;
+    }
+
+    /**
+     * Returns the artifact directory name (the segment immediately under 
{@code components/}) for the given source
+     * path, or {@code null} if the path doesn't live under {@code 
components/}.
+     */
+    private static String artifactDirName(Path src) {
+        for (int i = 0; i < src.getNameCount() - 1; i++) {
+            if ("components".equals(src.getName(i).toString())) {
+                return src.getName(i + 1).toString();
+            }
+        }
+        return null;
+    }
+
+    private static String collisionMessage(Path destination, String baseName, 
List<Path> srcs) {
+        StringBuilder sb = new StringBuilder("Doc symlink collision: 
").append(srcs.size())
+                .append(" sources flatten to 
").append(destination).append('/').append(baseName).append(":\n");
+        for (Path s : srcs) {
+            sb.append("  - ").append(s).append('\n');
+        }
+        sb.append("Resolve by giving the sources distinct basenames or by 
extending "
+                  + "PrepareDocSymlinksMojo.disambiguate() with a rule that 
produces unique destination names.");
+        return sb.toString();
+    }
+
     // ----- example symlinks (preserves repo-relative directory hierarchy) 
-------------------------------------------
 
     private void createExampleSymlinks(Path root, KindSpec spec, Path 
destination) throws IOException {
diff --git 
a/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/UpdateReadmeMojo.java
 
b/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/UpdateReadmeMojo.java
index 7d750e6cca10..db66a67c1cb1 100644
--- 
a/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/UpdateReadmeMojo.java
+++ 
b/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/UpdateReadmeMojo.java
@@ -276,7 +276,7 @@ public class UpdateReadmeMojo extends AbstractGeneratorMojo 
{
                 String json = loadJsonFrom(jsonFiles, kind, dataFormatName);
                 if (json != null) {
                     // special for some data formats
-                    dataFormatName = asDataFormatName(dataFormatName);
+                    dataFormatName = asDataFormatName(dataFormatName, 
project.getArtifactId());
 
                     File file = new File(dataformatDocDir, dataFormatName + 
"-" + kind + ".adoc");
 
@@ -289,7 +289,7 @@ public class UpdateReadmeMojo extends AbstractGeneratorMojo 
{
                                 .forEach(o -> o.setDefaultValue(null));
                     }
 
-                    String title = asDataFormatTitle(model.getName(), 
model.getTitle());
+                    String title = asDataFormatTitle(model.getName(), 
model.getTitle(), project.getArtifactId());
                     model.setTitle(title);
 
                     boolean exists = file.exists();
@@ -456,24 +456,40 @@ public class UpdateReadmeMojo extends 
AbstractGeneratorMojo {
                 || name.equals("smtps");
     }
 
-    private static String asDataFormatName(String name) {
+    private static String asDataFormatName(String name, String artifactId) {
         // special for some dataformats which share the same readme file
         if (name.startsWith("bindy")) {
             return "bindy";
         }
+        // Jackson 2.x and 3.x ship the same dataformat `name` but live in 
separate artifacts;
+        // disambiguate the doc filename by appending the major-version 
suffix. See CAMEL-23531.
+        if (isJacksonFamily(name)) {
+            return name + 
PackageDataFormatMojo.jacksonFamilySuffix(artifactId);
+        }
 
         return name;
     }
 
-    private static String asDataFormatTitle(String name, String title) {
+    private static String asDataFormatTitle(String name, String title, String 
artifactId) {
         // special for some dataformats which share the same readme file
         if (name.startsWith("bindy")) {
             return "Bindy";
         }
+        // The catalog title for the Jackson family is intentionally 
unsuffixed (the dataformat `name` is the
+        // same for 2.x and 3.x so the runtime DSL resolves either variant 
transparently). Doc pages must
+        // disambiguate visually, so we add a "2" / "3" suffix when rendering 
the .adoc title. See CAMEL-23531.
+        if (isJacksonFamily(name)) {
+            return title + " " + 
PackageDataFormatMojo.jacksonFamilySuffix(artifactId);
+        }
 
         return title;
     }
 
+    private static boolean isJacksonFamily(String name) {
+        return "jackson".equals(name) || "jacksonXml".equals(name)
+                || "avroJackson".equals(name) || 
"protobufJackson".equals(name);
+    }
+
     private boolean updateHeader(
             String name, final File file, final BaseModel<? extends 
BaseOptionModel> model, String titleSuffix)
             throws MojoExecutionException {
diff --git 
a/tooling/maven/camel-package-maven-plugin/src/test/java/org/apache/camel/maven/packaging/PrepareDocSymlinksMojoTest.java
 
b/tooling/maven/camel-package-maven-plugin/src/test/java/org/apache/camel/maven/packaging/PrepareDocSymlinksMojoTest.java
index 4c2fe9d6aabf..290b333ded42 100644
--- 
a/tooling/maven/camel-package-maven-plugin/src/test/java/org/apache/camel/maven/packaging/PrepareDocSymlinksMojoTest.java
+++ 
b/tooling/maven/camel-package-maven-plugin/src/test/java/org/apache/camel/maven/packaging/PrepareDocSymlinksMojoTest.java
@@ -24,6 +24,7 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
+import org.apache.maven.plugin.MojoFailureException;
 import org.junit.jupiter.api.Test;
 
 import static org.assertj.core.api.Assertions.assertThat;
@@ -156,6 +157,46 @@ class PrepareDocSymlinksMojoTest {
         assertThat(entries).containsExactly(a1, a2, b1);
     }
 
+    // ----- disambiguate (CAMEL-23531) 
-------------------------------------------------------------------------------
+
+    @Test
+    void disambiguate_jacksonFamilyAppendsMajorVersionSuffix() throws 
Exception {
+        Path dest = 
Paths.get("docs/components/modules/dataformats/examples/json");
+        // Simulate the canonical Jackson 2.x vs 3.x collision: both artifacts 
produce `jackson.json`.
+        List<Path> srcs = List.of(
+                
Paths.get("/repo/components/camel-jackson/src/generated/resources/META-INF/jackson.json"),
+                
Paths.get("/repo/components/camel-jackson3/src/generated/resources/META-INF/jackson.json"));
+        assertThat(PrepareDocSymlinksMojo.disambiguate(dest, srcs))
+                .containsExactly("jackson2.json", "jackson3.json");
+    }
+
+    @Test
+    void disambiguate_failsLoudWhenSourceIsNotInTheJacksonFamily() {
+        // Two non-jackson components flattening to the same basename: no rule 
applies, must fail rather than
+        // silently overwrite.
+        Path dest = 
Paths.get("docs/components/modules/dataformats/examples/json");
+        List<Path> srcs = List.of(
+                
Paths.get("/repo/components/camel-foo/src/generated/resources/META-INF/foo.json"),
+                
Paths.get("/repo/components/camel-bar/src/generated/resources/META-INF/foo.json"));
+        assertThatThrownBy(() -> PrepareDocSymlinksMojo.disambiguate(dest, 
srcs))
+                .isInstanceOf(MojoFailureException.class)
+                .hasMessageContaining("collision")
+                .hasMessageContaining("foo.json");
+    }
+
+    @Test
+    void disambiguate_failsLoudWhenJacksonRuleStillProducesDuplicates() {
+        // Two 3.x sources with the same basename ⇒ the jackson rule maps both 
to "...3.json", so the disambiguator
+        // can't resolve it. Must fail rather than write one symlink twice.
+        Path dest = 
Paths.get("docs/components/modules/dataformats/examples/json");
+        List<Path> srcs = List.of(
+                
Paths.get("/repo/components/camel-jackson3/src/generated/resources/META-INF/jackson.json"),
+                
Paths.get("/repo/components/camel-jackson3-extra/src/generated/resources/META-INF/jackson.json"));
+        assertThatThrownBy(() -> PrepareDocSymlinksMojo.disambiguate(dest, 
srcs))
+                .isInstanceOf(MojoFailureException.class)
+                .hasMessageContaining("collision");
+    }
+
     @Test
     void navComparator_isReflexivelyConsistentForRandomInput() {
         // Sort-then-sort-reverse-then-sort-again must converge and not throw 
IllegalArgumentException;


Reply via email to